From 288d78ef48a9309b3a4fb14c134f28eaa786a136 Mon Sep 17 00:00:00 2001 From: Tilo Palfner Date: Tue, 9 Jun 2026 02:27:56 +0100 Subject: [PATCH 1/2] refactor to zkcompression --- README.md | 4 +- ai-tools/agent-skills.mdx | 14 +- ai-tools/prompts.mdx | 2 +- api-reference/anchor.mdx | 194 -- api-reference/json-rpc-methods/overview.mdx | 4 +- api-reference/overview.mdx | 7 +- api-reference/sdk.mdx | 2 +- api-reference/solana-to-light-comparison.mdx | 1581 ----------------- .../guides.mdx | 2 +- .../guides/client-guide.mdx | 2 +- .../how-to-burn-compressed-accounts.mdx | 6 +- .../how-to-close-compressed-accounts.mdx | 8 +- .../how-to-create-compressed-accounts.mdx | 6 +- ...ow-to-reinitialize-compressed-accounts.mdx | 6 +- .../how-to-update-compressed-accounts.mdx | 6 +- .../nullifier-pda.mdx | 2 +- .../overview.mdx | 18 +- .../program-examples.mdx | 2 +- .../solana-attestation-service.mdx | 0 compressed-tokens/combine-instructions.mdx | 198 +++ compressed-tokens/guides.mdx | 9 + .../add-token-pools-to-mint-accounts.mdx | 112 ++ .../guides/compress-decompress.mdx | 217 +++ .../guides/compress-spl-token-account.mdx | 189 ++ .../create-compressed-token-accounts.mdx | 20 + .../guides/create-mint-with-token-pool.mdx | 99 ++ compressed-tokens/guides/delegate.mdx | 166 ++ .../merge-compressed-token-accounts.mdx | 145 ++ .../guides/mint-compressed-tokens.mdx | 155 ++ .../guides/transfer-compressed-tokens.mdx | 190 ++ compressed-tokens/overview.mdx | 86 + compressed-tokens/privy.mdx | 170 ++ compressed-tokens/token-2022.mdx | 277 +++ .../token-distribution.mdx | 4 +- compressed-tokens/wallet-integration.mdx | 640 +++++++ docs.json | 582 +----- faq.mdx | 286 --- home.mdx | 62 +- .../compressed-account-model.mdx | 4 +- learn/{core-concepts => }/considerations.mdx | 30 +- learn/core-concepts.mdx | 75 - learn/light-token-standard.mdx | 353 ---- .../merkle-trees-validity-proofs.mdx | 4 +- learn/overview.mdx | 101 +- .../transaction-lifecycle.mdx | 4 +- light-token/cookbook/add-interface-pda.mdx | 55 - light-token/cookbook/approve-revoke.mdx | 355 ---- light-token/cookbook/burn.mdx | 156 -- light-token/cookbook/close-token-account.mdx | 163 -- light-token/cookbook/create-ata.mdx | 352 ---- light-token/cookbook/create-mint.mdx | 579 ------ light-token/cookbook/create-token-account.mdx | 287 --- light-token/cookbook/freeze-thaw.mdx | 246 --- light-token/cookbook/load-ata.mdx | 58 - light-token/cookbook/mint-to.mdx | 227 --- light-token/cookbook/transfer-checked.mdx | 117 -- light-token/cookbook/transfer-delegated.mdx | 56 - light-token/cookbook/transfer-interface.mdx | 365 ---- light-token/cookbook/wrap-unwrap.mdx | 172 -- light-token/defi/programs-pinocchio.mdx | 525 ------ light-token/defi/programs.mdx | 556 ------ light-token/defi/routers.mdx | 320 ---- light-token/examples/client.mdx | 16 - light-token/examples/program.mdx | 16 - light-token/extensions/overview.mdx | 29 - light-token/payments/basic-payment.mdx | 225 --- light-token/payments/batch-payments.mdx | 113 -- light-token/payments/overview.mdx | 127 -- light-token/payments/payment-with-memo.mdx | 135 -- light-token/payments/production-readiness.mdx | 73 - light-token/payments/receive-payments.mdx | 30 - light-token/payments/spend-permissions.mdx | 221 --- light-token/payments/verify-payments.mdx | 127 -- .../payments/verify-recipient-address.mdx | 94 - light-token/payments/wrap-unwrap.mdx | 168 -- light-token/quickstart.mdx | 41 - light-token/streaming/mints.mdx | 269 --- light-token/streaming/tokens.mdx | 276 --- light-token/wallets/gasless-transactions.mdx | 218 --- light-token/wallets/overview.mdx | 490 ----- light-token/wallets/privy.mdx | 418 ----- light-token/wallets/wallet-adapter.mdx | 289 --- light-token/welcome.mdx | 294 --- llms.txt | 206 +-- pda/light-pda/overview.mdx | 209 --- pda/overview.mdx | 42 - resources/addresses-and-urls.mdx | 2 +- resources/cli.mdx | 304 ---- resources/legacy-compressed-tokens.mdx | 16 +- resources/migration-v1-to-v2.mdx | 2 +- resources/terminology.mdx | 74 +- resources/whitepaper.mdx | 212 --- scripts/generate-llms-txt.js | 172 +- skill.md | 248 +-- .../close-account-infos-accounts-list.mdx | 57 - .../light-mint-system-accounts-list.mdx | 46 - ...ight-mint-to-light-token-accounts-list.mdx | 61 - ...ight-token-create-accounts-list-client.mdx | 117 -- .../light-token-create-accounts-list.mdx | 41 - .../light-token-create-ata-accounts-list.mdx | 65 - ...-interface-accounts-list-light-token-1.mdx | 56 - ...transfer-interface-accounts-list-spl-2.mdx | 2 +- snippets/ai-prompts/all-prompts.mdx | 106 +- .../ai-prompts/anchor-program-template.mdx | 57 - .../anchor-programs/defi-anchor.mdx | 117 -- snippets/ai-prompts/cpi-program-template.mdx | 57 - snippets/ai-prompts/cpi-programs/burn.mdx | 4 +- .../ai-prompts/cpi-programs/client-guide.mdx | 4 +- snippets/ai-prompts/cpi-programs/close.mdx | 4 +- snippets/ai-prompts/cpi-programs/create.mdx | 4 +- .../ai-prompts/cpi-programs/reinitialize.mdx | 4 +- snippets/ai-prompts/cpi-programs/update.mdx | 4 +- snippets/ai-prompts/defi/defi-anchor.mdx | 217 --- snippets/ai-prompts/defi/defi-pinocchio.mdx | 117 -- snippets/ai-prompts/defi/routers.mdx | 125 -- snippets/ai-prompts/light-token-prompts.mdx | 89 - snippets/ai-prompts/light-token-recipes.mdx | 197 -- .../program-cookbook/approve-revoke.mdx | 117 -- snippets/ai-prompts/program-cookbook/burn.mdx | 115 -- .../program-cookbook/close-token-account.mdx | 115 -- .../program-cookbook/create-ata-cpi.mdx | 115 -- .../program-cookbook/create-ata-macros.mdx | 113 -- .../program-cookbook/create-mint-cpi.mdx | 117 -- .../program-cookbook/create-mint-macros.mdx | 115 -- .../create-token-account-cpi.mdx | 115 -- .../create-token-account-macros.mdx | 113 -- .../program-cookbook/freeze-thaw.mdx | 117 -- .../ai-prompts/program-cookbook/light-pda.mdx | 115 -- .../ai-prompts/program-cookbook/mint-to.mdx | 115 -- .../program-cookbook/transfer-checked.mdx | 121 -- .../program-cookbook/transfer-interface.mdx | 117 -- .../rust-cookbook/approve-revoke.mdx | 115 -- snippets/ai-prompts/rust-cookbook/burn.mdx | 115 -- .../rust-cookbook/close-token-account.mdx | 115 -- .../ai-prompts/rust-cookbook/create-ata.mdx | 115 -- .../ai-prompts/rust-cookbook/create-mint.mdx | 115 -- .../rust-cookbook/create-token-account.mdx | 115 -- .../ai-prompts/rust-cookbook/freeze-thaw.mdx | 123 -- snippets/ai-prompts/rust-cookbook/mint-to.mdx | 115 -- .../rust-cookbook/transfer-checked.mdx | 119 -- .../rust-cookbook/transfer-interface.mdx | 125 -- .../ai-prompts/rust-cookbook/wrap-unwrap.mdx | 121 -- snippets/ai-prompts/rust-template.mdx | 57 - snippets/ai-prompts/streaming/mints.mdx | 117 -- snippets/ai-prompts/streaming/tokens.mdx | 123 -- snippets/ai-prompts/template.mdx | 55 - snippets/ai-prompts/toolkits/airdrop.mdx | 4 +- snippets/ai-prompts/toolkits/nullifiers.mdx | 4 +- snippets/ai-prompts/toolkits/payments.mdx | 209 --- snippets/ai-prompts/toolkits/wallets.mdx | 141 -- .../ts-cookbook/add-interface-pda.mdx | 111 -- .../ai-prompts/ts-cookbook/approve-revoke.mdx | 111 -- .../ai-prompts/ts-cookbook/create-ata.mdx | 111 -- .../ai-prompts/ts-cookbook/create-mint.mdx | 111 -- snippets/ai-prompts/ts-cookbook/mint-to.mdx | 111 -- .../ts-cookbook/transfer-interface.mdx | 127 -- .../ai-prompts/ts-cookbook/wrap-unwrap.mdx | 113 -- .../wallets/gasless-transactions.mdx | 147 -- snippets/ai-prompts/wallets/privy.mdx | 141 -- .../ai-prompts/wallets/wallet-adapter.mdx | 137 -- .../compressed-token/approve/action.mdx | 39 + .../compress-spl-account/action.mdx | 51 + .../compressed-token/compress/action.mdx | 39 + .../create-mint}/action.mdx | 24 +- .../create-mint/instruction.mdx | 23 +- .../create-token-pool/action.mdx | 36 + .../compressed-token/decompress/action.mdx | 37 + .../merge-token-accounts/action.mdx | 38 + .../compressed-token/mint-to/action.mdx | 36 + .../mint-to/instruction.mdx | 19 +- .../compressed-token/revoke/action.mdx | 40 + .../compressed-token/transfer/action.mdx | 38 + .../approve-revoke/approve-action.mdx | 48 - .../approve-revoke/revoke-action.mdx | 53 - .../rust-client/approve-action.mdx | 35 - .../rust-client/approve-full.mdx | 35 - .../rust-client/approve-instruction.mdx | 40 - .../rust-client/revoke-action.mdx | 31 - .../rust-client/revoke-full.mdx | 30 - .../rust-client/revoke-instruction.mdx | 35 - .../token-interface-approve-instruction.mdx | 29 - .../token-interface-revoke-instruction.mdx | 26 - .../approve/anchor-program/full-example.mdx | 88 - .../approve/native-program/full-example.mdx | 137 -- .../burn-checked/rust-client/instruction.mdx | 44 - .../burn/anchor-program/full-example.mdx | 87 - .../burn/native-program/full-example.mdx | 170 -- .../burn/rust-client/instruction.mdx | 40 - .../anchor-program/full-example.mdx | 83 - .../native-program/full-example.mdx | 116 -- .../rust-client/instruction.mdx | 28 - .../counter/anchor-macro/full-example.mdx | 266 --- .../light-token/create-ata/action.mdx | 32 - .../create-ata/anchor-macro/full-example.mdx | 179 -- .../anchor-program/full-example.mdx | 172 -- .../light-token/create-ata/instruction.mdx | 52 - .../native-program/full-example.mdx | 172 -- .../create-ata/rust-client/action.mdx | 33 - .../create-ata/rust-client/idempotent.mdx | 11 - .../create-ata/rust-client/instruction.mdx | 31 - .../token-interface-instruction.mdx | 24 - .../light-token/create-mint/action.mdx | 44 - .../create-mint/anchor-macro/full-example.mdx | 343 ---- .../anchor-program/full-example.mdx | 232 --- .../native-program/full-example.mdx | 483 ----- .../create-mint/rust-client/action.mdx | 31 - .../create-mint/rust-client/instruction.mdx | 97 - .../token-interface-instruction.mdx | 38 - .../create-spl-mint/instruction.mdx | 77 - .../token-interface-instruction.mdx | 24 - .../light-token/create-t22-mint/action.mdx | 40 - .../create-t22-mint/instruction.mdx | 79 - .../token-interface-instruction.mdx | 24 - .../anchor-macro/full-example.mdx | 178 -- .../anchor-program/full-example.mdx | 161 -- .../native-program/full-example.mdx | 170 -- .../rust-client/instruction.mdx | 36 - .../light-token/create-token-pool/action.mdx | 29 - .../create-token-pool/instruction.mdx | 42 - .../token-interface-instruction.mdx | 22 - .../light-token/delegate-transfer/action.mdx | 65 - .../freeze-thaw/rust-client/freeze-full.mdx | 32 - .../rust-client/freeze-instruction.mdx | 37 - .../freeze-thaw/rust-client/thaw-full.mdx | 32 - .../rust-client/thaw-instruction.mdx | 36 - .../freeze/anchor-program/full-example.mdx | 75 - .../freeze/native-program/full-example.mdx | 118 -- .../gasless-transactions/rust-instruction.mdx | 53 - .../gasless-transactions/ts-instruction.mdx | 104 -- .../light-token/load-ata/action.mdx | 44 - .../light-token/load-ata/instruction.mdx | 61 - .../load-ata/token-interface-instruction.mdx | 25 - .../light-token/mint-spl-and-wrap/action.mdx | 96 - .../anchor-program/full-example.mdx | 88 - .../native-program/full-example.mdx | 145 -- .../light-token/mint-to/action.mdx | 47 - .../mint-to/anchor-program/full-example.mdx | 84 - .../mint-to/native-program/full-example.mdx | 187 -- .../mint-to/rust-client/action.mdx | 46 - .../mint-to/rust-client/instruction.mdx | 40 - .../mint-to/token-interface-instruction.mdx | 36 - .../revoke/anchor-program/full-example.mdx | 97 - .../revoke/native-program/full-example.mdx | 107 -- .../thaw/anchor-program/full-example.mdx | 89 - .../thaw/native-program/full-example.mdx | 111 -- .../anchor-program/full-example.mdx | 106 -- .../native-program/full-example.mdx | 180 -- .../transfer-checked/rust-client/action.mdx | 51 - .../rust-client/instruction.mdx | 62 - .../light-token/transfer-interface/action.mdx | 54 - .../create-and-transfer-example.mdx | 249 --- .../anchor-program/full-example.mdx | 297 ---- .../transfer-interface/instruction.mdx | 64 - .../native-program/full-example.mdx | 185 -- .../transfer-interface/rust-client/action.mdx | 50 - .../rust-client/instruction.mdx | 74 - .../token-interface-instruction.mdx | 30 - .../light-token/unwrap/action.mdx | 65 - .../light-token/unwrap/instruction.mdx | 83 - .../light-token/unwrap/rust-client/action.mdx | 40 - .../unwrap/token-interface-instruction.mdx | 32 - .../code-snippets/light-token/wrap/action.mdx | 64 - .../light-token/wrap/instruction.mdx | 92 - .../light-token/wrap/rust-client/action.mdx | 39 - .../wrap/token-interface-instruction.mdx | 47 - .../payments/interop/register-spl-mint.mdx | 2 +- .../code-snippets/payments/interop/unwrap.mdx | 4 +- .../code-snippets/payments/interop/wrap.mdx | 4 +- .../code-snippets/privy/balances/nodejs.mdx | 176 +- .../code-snippets/privy/balances/react.mdx | 177 -- .../code-snippets/privy/compress/nodejs.mdx | 89 + .../code-snippets/privy/decompress/nodejs.mdx | 81 + .../privy/helpers/sign-and-send-batches.mdx | 46 - .../code-snippets/privy/receive/nodejs.mdx | 63 - .../code-snippets/privy/receive/react.mdx | 61 - .../privy/transaction-history/nodejs.mdx | 43 +- .../privy/transaction-history/react.mdx | 65 - .../code-snippets/privy/transfer/nodejs.mdx | 96 +- .../code-snippets/privy/transfer/react.mdx | 71 - .../code-snippets/privy/unwrap/nodejs.mdx | 74 - snippets/code-snippets/privy/unwrap/react.mdx | 78 - snippets/code-snippets/privy/wrap/nodejs.mdx | 87 - snippets/code-snippets/privy/wrap/react.mdx | 99 -- .../streaming/find-closed-accounts.mdx | 3 - .../wallet-adapter/balances/react.mdx | 177 -- .../helpers/sign-and-send-batches.mdx | 36 - .../wallet-adapter/receive/react.mdx | 57 - .../transaction-history/react.mdx | 65 - .../wallet-adapter/transfer/react.mdx | 65 - .../wallet-adapter/unwrap/react.mdx | 72 - .../wallet-adapter/wrap/react.mdx | 90 - snippets/compressible-vs-solana-rent.mdx | 2 +- snippets/cost-tables/cu-performance.mdx | 5 - snippets/cost-tables/light-pda-cost.mdx | 3 - snippets/cost-tables/mint-account-cost.mdx | 3 - snippets/cost-tables/token-account-cost.mdx | 3 - snippets/cost-tables/token-creation-cost.mdx | 5 +- .../jsx/light-token-vs-spl-calculator.jsx | 156 -- snippets/light-token-configure-rent.mdx | 61 - snippets/light-token-guides/cata-intro.mdx | 11 - .../client-custom-rent-config.mdx | 67 - snippets/light-token-guides/close-intro.mdx | 5 - .../light-token-client-prerequisites.mdx | 12 - .../light-token-guides/light-token-intro.mdx | 10 - .../light-token-program-prerequisites.mdx | 99 -- .../light-token-ts-client-prerequisites.mdx | 14 - .../token-interface-sdk2-callout.mdx | 5 - .../transfer-interface-intro.mdx | 35 - .../migration-reference/macros/light-pda.mdx | 29 - .../compressed-pdas-guides-table.mdx | 12 +- ...ompressed-tokens-advanced-guides-table.mdx | 4 +- .../overview-tables/cookbook-guides-table.mdx | 98 - .../overview-tables/examples-guides-table.mdx | 26 - .../integrate-light-token-guides-table.mdx | 6 - .../light-mint-guides-table.mdx | 4 - .../light-token-client-examples-table.mdx | 66 - .../light-token-guides-table.mdx | 6 - .../light-token-program-examples-table.mdx | 40 - snippets/overview-tables/sdk-reference.mdx | 12 +- snippets/setup/agent-skill-payments.mdx | 2 +- snippets/setup/payments-setup-helper.mdx | 2 +- snippets/setup/register-spl-mint.mdx | 2 +- support.mdx | 2 +- zk/overview.mdx | 2 +- 324 files changed, 3827 insertions(+), 29462 deletions(-) delete mode 100644 api-reference/anchor.mdx delete mode 100644 api-reference/solana-to-light-comparison.mdx rename {pda/compressed-pdas => compressed-pdas}/guides.mdx (96%) rename {pda/compressed-pdas => compressed-pdas}/guides/client-guide.mdx (99%) rename {pda/compressed-pdas => compressed-pdas}/guides/how-to-burn-compressed-accounts.mdx (96%) rename {pda/compressed-pdas => compressed-pdas}/guides/how-to-close-compressed-accounts.mdx (95%) rename {pda/compressed-pdas => compressed-pdas}/guides/how-to-create-compressed-accounts.mdx (98%) rename {pda/compressed-pdas => compressed-pdas}/guides/how-to-reinitialize-compressed-accounts.mdx (96%) rename {pda/compressed-pdas => compressed-pdas}/guides/how-to-update-compressed-accounts.mdx (96%) rename {pda/compressed-pdas => compressed-pdas}/nullifier-pda.mdx (99%) rename {pda/compressed-pdas => compressed-pdas}/overview.mdx (91%) rename {pda/compressed-pdas => compressed-pdas}/program-examples.mdx (99%) rename {pda/compressed-pdas => compressed-pdas}/solana-attestation-service.mdx (100%) create mode 100644 compressed-tokens/combine-instructions.mdx create mode 100644 compressed-tokens/guides.mdx create mode 100644 compressed-tokens/guides/add-token-pools-to-mint-accounts.mdx create mode 100644 compressed-tokens/guides/compress-decompress.mdx create mode 100644 compressed-tokens/guides/compress-spl-token-account.mdx create mode 100644 compressed-tokens/guides/create-compressed-token-accounts.mdx create mode 100644 compressed-tokens/guides/create-mint-with-token-pool.mdx create mode 100644 compressed-tokens/guides/delegate.mdx create mode 100644 compressed-tokens/guides/merge-compressed-token-accounts.mdx create mode 100644 compressed-tokens/guides/mint-compressed-tokens.mdx create mode 100644 compressed-tokens/guides/transfer-compressed-tokens.mdx create mode 100644 compressed-tokens/overview.mdx create mode 100644 compressed-tokens/privy.mdx create mode 100644 compressed-tokens/token-2022.mdx rename token-distribution.mdx => compressed-tokens/token-distribution.mdx (99%) create mode 100644 compressed-tokens/wallet-integration.mdx delete mode 100644 faq.mdx rename learn/{core-concepts => }/compressed-account-model.mdx (98%) rename learn/{core-concepts => }/considerations.mdx (73%) delete mode 100644 learn/core-concepts.mdx delete mode 100644 learn/light-token-standard.mdx rename learn/{core-concepts => }/merkle-trees-validity-proofs.mdx (98%) rename learn/{core-concepts => }/transaction-lifecycle.mdx (97%) delete mode 100644 light-token/cookbook/add-interface-pda.mdx delete mode 100644 light-token/cookbook/approve-revoke.mdx delete mode 100644 light-token/cookbook/burn.mdx delete mode 100644 light-token/cookbook/close-token-account.mdx delete mode 100644 light-token/cookbook/create-ata.mdx delete mode 100644 light-token/cookbook/create-mint.mdx delete mode 100644 light-token/cookbook/create-token-account.mdx delete mode 100644 light-token/cookbook/freeze-thaw.mdx delete mode 100644 light-token/cookbook/load-ata.mdx delete mode 100644 light-token/cookbook/mint-to.mdx delete mode 100644 light-token/cookbook/transfer-checked.mdx delete mode 100644 light-token/cookbook/transfer-delegated.mdx delete mode 100644 light-token/cookbook/transfer-interface.mdx delete mode 100644 light-token/cookbook/wrap-unwrap.mdx delete mode 100644 light-token/defi/programs-pinocchio.mdx delete mode 100644 light-token/defi/programs.mdx delete mode 100644 light-token/defi/routers.mdx delete mode 100644 light-token/examples/client.mdx delete mode 100644 light-token/examples/program.mdx delete mode 100644 light-token/extensions/overview.mdx delete mode 100644 light-token/payments/basic-payment.mdx delete mode 100644 light-token/payments/batch-payments.mdx delete mode 100644 light-token/payments/overview.mdx delete mode 100644 light-token/payments/payment-with-memo.mdx delete mode 100644 light-token/payments/production-readiness.mdx delete mode 100644 light-token/payments/receive-payments.mdx delete mode 100644 light-token/payments/spend-permissions.mdx delete mode 100644 light-token/payments/verify-payments.mdx delete mode 100644 light-token/payments/verify-recipient-address.mdx delete mode 100644 light-token/payments/wrap-unwrap.mdx delete mode 100644 light-token/quickstart.mdx delete mode 100644 light-token/streaming/mints.mdx delete mode 100644 light-token/streaming/tokens.mdx delete mode 100644 light-token/wallets/gasless-transactions.mdx delete mode 100644 light-token/wallets/overview.mdx delete mode 100644 light-token/wallets/privy.mdx delete mode 100644 light-token/wallets/wallet-adapter.mdx delete mode 100644 light-token/welcome.mdx delete mode 100644 pda/light-pda/overview.mdx delete mode 100644 pda/overview.mdx delete mode 100644 resources/cli.mdx delete mode 100644 resources/whitepaper.mdx delete mode 100644 snippets/accounts-list/close-account-infos-accounts-list.mdx delete mode 100644 snippets/accounts-list/light-mint-system-accounts-list.mdx delete mode 100644 snippets/accounts-list/light-mint-to-light-token-accounts-list.mdx delete mode 100644 snippets/accounts-list/light-token-create-accounts-list-client.mdx delete mode 100644 snippets/accounts-list/light-token-create-accounts-list.mdx delete mode 100644 snippets/accounts-list/light-token-create-ata-accounts-list.mdx delete mode 100644 snippets/accounts-list/transfer-interface-accounts-list-light-token-1.mdx delete mode 100644 snippets/ai-prompts/anchor-program-template.mdx delete mode 100644 snippets/ai-prompts/anchor-programs/defi-anchor.mdx delete mode 100644 snippets/ai-prompts/cpi-program-template.mdx delete mode 100644 snippets/ai-prompts/defi/defi-anchor.mdx delete mode 100644 snippets/ai-prompts/defi/defi-pinocchio.mdx delete mode 100644 snippets/ai-prompts/defi/routers.mdx delete mode 100644 snippets/ai-prompts/light-token-prompts.mdx delete mode 100644 snippets/ai-prompts/light-token-recipes.mdx delete mode 100644 snippets/ai-prompts/program-cookbook/approve-revoke.mdx delete mode 100644 snippets/ai-prompts/program-cookbook/burn.mdx delete mode 100644 snippets/ai-prompts/program-cookbook/close-token-account.mdx delete mode 100644 snippets/ai-prompts/program-cookbook/create-ata-cpi.mdx delete mode 100644 snippets/ai-prompts/program-cookbook/create-ata-macros.mdx delete mode 100644 snippets/ai-prompts/program-cookbook/create-mint-cpi.mdx delete mode 100644 snippets/ai-prompts/program-cookbook/create-mint-macros.mdx delete mode 100644 snippets/ai-prompts/program-cookbook/create-token-account-cpi.mdx delete mode 100644 snippets/ai-prompts/program-cookbook/create-token-account-macros.mdx delete mode 100644 snippets/ai-prompts/program-cookbook/freeze-thaw.mdx delete mode 100644 snippets/ai-prompts/program-cookbook/light-pda.mdx delete mode 100644 snippets/ai-prompts/program-cookbook/mint-to.mdx delete mode 100644 snippets/ai-prompts/program-cookbook/transfer-checked.mdx delete mode 100644 snippets/ai-prompts/program-cookbook/transfer-interface.mdx delete mode 100644 snippets/ai-prompts/rust-cookbook/approve-revoke.mdx delete mode 100644 snippets/ai-prompts/rust-cookbook/burn.mdx delete mode 100644 snippets/ai-prompts/rust-cookbook/close-token-account.mdx delete mode 100644 snippets/ai-prompts/rust-cookbook/create-ata.mdx delete mode 100644 snippets/ai-prompts/rust-cookbook/create-mint.mdx delete mode 100644 snippets/ai-prompts/rust-cookbook/create-token-account.mdx delete mode 100644 snippets/ai-prompts/rust-cookbook/freeze-thaw.mdx delete mode 100644 snippets/ai-prompts/rust-cookbook/mint-to.mdx delete mode 100644 snippets/ai-prompts/rust-cookbook/transfer-checked.mdx delete mode 100644 snippets/ai-prompts/rust-cookbook/transfer-interface.mdx delete mode 100644 snippets/ai-prompts/rust-cookbook/wrap-unwrap.mdx delete mode 100644 snippets/ai-prompts/rust-template.mdx delete mode 100644 snippets/ai-prompts/streaming/mints.mdx delete mode 100644 snippets/ai-prompts/streaming/tokens.mdx delete mode 100644 snippets/ai-prompts/template.mdx delete mode 100644 snippets/ai-prompts/toolkits/payments.mdx delete mode 100644 snippets/ai-prompts/toolkits/wallets.mdx delete mode 100644 snippets/ai-prompts/ts-cookbook/add-interface-pda.mdx delete mode 100644 snippets/ai-prompts/ts-cookbook/approve-revoke.mdx delete mode 100644 snippets/ai-prompts/ts-cookbook/create-ata.mdx delete mode 100644 snippets/ai-prompts/ts-cookbook/create-mint.mdx delete mode 100644 snippets/ai-prompts/ts-cookbook/mint-to.mdx delete mode 100644 snippets/ai-prompts/ts-cookbook/transfer-interface.mdx delete mode 100644 snippets/ai-prompts/ts-cookbook/wrap-unwrap.mdx delete mode 100644 snippets/ai-prompts/wallets/gasless-transactions.mdx delete mode 100644 snippets/ai-prompts/wallets/privy.mdx delete mode 100644 snippets/ai-prompts/wallets/wallet-adapter.mdx create mode 100644 snippets/code-snippets/compressed-token/approve/action.mdx create mode 100644 snippets/code-snippets/compressed-token/compress-spl-account/action.mdx create mode 100644 snippets/code-snippets/compressed-token/compress/action.mdx rename snippets/code-snippets/{light-token/create-spl-mint => compressed-token/create-mint}/action.mdx (56%) rename snippets/code-snippets/{light-token => compressed-token}/create-mint/instruction.mdx (79%) create mode 100644 snippets/code-snippets/compressed-token/create-token-pool/action.mdx create mode 100644 snippets/code-snippets/compressed-token/decompress/action.mdx create mode 100644 snippets/code-snippets/compressed-token/merge-token-accounts/action.mdx create mode 100644 snippets/code-snippets/compressed-token/mint-to/action.mdx rename snippets/code-snippets/{light-token => compressed-token}/mint-to/instruction.mdx (82%) create mode 100644 snippets/code-snippets/compressed-token/revoke/action.mdx create mode 100644 snippets/code-snippets/compressed-token/transfer/action.mdx delete mode 100644 snippets/code-snippets/light-token/approve-revoke/approve-action.mdx delete mode 100644 snippets/code-snippets/light-token/approve-revoke/revoke-action.mdx delete mode 100644 snippets/code-snippets/light-token/approve-revoke/rust-client/approve-action.mdx delete mode 100644 snippets/code-snippets/light-token/approve-revoke/rust-client/approve-full.mdx delete mode 100644 snippets/code-snippets/light-token/approve-revoke/rust-client/approve-instruction.mdx delete mode 100644 snippets/code-snippets/light-token/approve-revoke/rust-client/revoke-action.mdx delete mode 100644 snippets/code-snippets/light-token/approve-revoke/rust-client/revoke-full.mdx delete mode 100644 snippets/code-snippets/light-token/approve-revoke/rust-client/revoke-instruction.mdx delete mode 100644 snippets/code-snippets/light-token/approve-revoke/token-interface-approve-instruction.mdx delete mode 100644 snippets/code-snippets/light-token/approve-revoke/token-interface-revoke-instruction.mdx delete mode 100644 snippets/code-snippets/light-token/approve/anchor-program/full-example.mdx delete mode 100644 snippets/code-snippets/light-token/approve/native-program/full-example.mdx delete mode 100644 snippets/code-snippets/light-token/burn-checked/rust-client/instruction.mdx delete mode 100644 snippets/code-snippets/light-token/burn/anchor-program/full-example.mdx delete mode 100644 snippets/code-snippets/light-token/burn/native-program/full-example.mdx delete mode 100644 snippets/code-snippets/light-token/burn/rust-client/instruction.mdx delete mode 100644 snippets/code-snippets/light-token/close-token-account/anchor-program/full-example.mdx delete mode 100644 snippets/code-snippets/light-token/close-token-account/native-program/full-example.mdx delete mode 100644 snippets/code-snippets/light-token/close-token-account/rust-client/instruction.mdx delete mode 100644 snippets/code-snippets/light-token/counter/anchor-macro/full-example.mdx delete mode 100644 snippets/code-snippets/light-token/create-ata/action.mdx delete mode 100644 snippets/code-snippets/light-token/create-ata/anchor-macro/full-example.mdx delete mode 100644 snippets/code-snippets/light-token/create-ata/anchor-program/full-example.mdx delete mode 100644 snippets/code-snippets/light-token/create-ata/instruction.mdx delete mode 100644 snippets/code-snippets/light-token/create-ata/native-program/full-example.mdx delete mode 100644 snippets/code-snippets/light-token/create-ata/rust-client/action.mdx delete mode 100644 snippets/code-snippets/light-token/create-ata/rust-client/idempotent.mdx delete mode 100644 snippets/code-snippets/light-token/create-ata/rust-client/instruction.mdx delete mode 100644 snippets/code-snippets/light-token/create-ata/token-interface-instruction.mdx delete mode 100644 snippets/code-snippets/light-token/create-mint/action.mdx delete mode 100644 snippets/code-snippets/light-token/create-mint/anchor-macro/full-example.mdx delete mode 100644 snippets/code-snippets/light-token/create-mint/anchor-program/full-example.mdx delete mode 100644 snippets/code-snippets/light-token/create-mint/native-program/full-example.mdx delete mode 100644 snippets/code-snippets/light-token/create-mint/rust-client/action.mdx delete mode 100644 snippets/code-snippets/light-token/create-mint/rust-client/instruction.mdx delete mode 100644 snippets/code-snippets/light-token/create-mint/token-interface-instruction.mdx delete mode 100644 snippets/code-snippets/light-token/create-spl-mint/instruction.mdx delete mode 100644 snippets/code-snippets/light-token/create-spl-mint/token-interface-instruction.mdx delete mode 100644 snippets/code-snippets/light-token/create-t22-mint/action.mdx delete mode 100644 snippets/code-snippets/light-token/create-t22-mint/instruction.mdx delete mode 100644 snippets/code-snippets/light-token/create-t22-mint/token-interface-instruction.mdx delete mode 100644 snippets/code-snippets/light-token/create-token-account/anchor-macro/full-example.mdx delete mode 100644 snippets/code-snippets/light-token/create-token-account/anchor-program/full-example.mdx delete mode 100644 snippets/code-snippets/light-token/create-token-account/native-program/full-example.mdx delete mode 100644 snippets/code-snippets/light-token/create-token-account/rust-client/instruction.mdx delete mode 100644 snippets/code-snippets/light-token/create-token-pool/action.mdx delete mode 100644 snippets/code-snippets/light-token/create-token-pool/instruction.mdx delete mode 100644 snippets/code-snippets/light-token/create-token-pool/token-interface-instruction.mdx delete mode 100644 snippets/code-snippets/light-token/delegate-transfer/action.mdx delete mode 100644 snippets/code-snippets/light-token/freeze-thaw/rust-client/freeze-full.mdx delete mode 100644 snippets/code-snippets/light-token/freeze-thaw/rust-client/freeze-instruction.mdx delete mode 100644 snippets/code-snippets/light-token/freeze-thaw/rust-client/thaw-full.mdx delete mode 100644 snippets/code-snippets/light-token/freeze-thaw/rust-client/thaw-instruction.mdx delete mode 100644 snippets/code-snippets/light-token/freeze/anchor-program/full-example.mdx delete mode 100644 snippets/code-snippets/light-token/freeze/native-program/full-example.mdx delete mode 100644 snippets/code-snippets/light-token/gasless-transactions/rust-instruction.mdx delete mode 100644 snippets/code-snippets/light-token/gasless-transactions/ts-instruction.mdx delete mode 100644 snippets/code-snippets/light-token/load-ata/action.mdx delete mode 100644 snippets/code-snippets/light-token/load-ata/instruction.mdx delete mode 100644 snippets/code-snippets/light-token/load-ata/token-interface-instruction.mdx delete mode 100644 snippets/code-snippets/light-token/mint-spl-and-wrap/action.mdx delete mode 100644 snippets/code-snippets/light-token/mint-to-checked/anchor-program/full-example.mdx delete mode 100644 snippets/code-snippets/light-token/mint-to-checked/native-program/full-example.mdx delete mode 100644 snippets/code-snippets/light-token/mint-to/action.mdx delete mode 100644 snippets/code-snippets/light-token/mint-to/anchor-program/full-example.mdx delete mode 100644 snippets/code-snippets/light-token/mint-to/native-program/full-example.mdx delete mode 100644 snippets/code-snippets/light-token/mint-to/rust-client/action.mdx delete mode 100644 snippets/code-snippets/light-token/mint-to/rust-client/instruction.mdx delete mode 100644 snippets/code-snippets/light-token/mint-to/token-interface-instruction.mdx delete mode 100644 snippets/code-snippets/light-token/revoke/anchor-program/full-example.mdx delete mode 100644 snippets/code-snippets/light-token/revoke/native-program/full-example.mdx delete mode 100644 snippets/code-snippets/light-token/thaw/anchor-program/full-example.mdx delete mode 100644 snippets/code-snippets/light-token/thaw/native-program/full-example.mdx delete mode 100644 snippets/code-snippets/light-token/transfer-checked/anchor-program/full-example.mdx delete mode 100644 snippets/code-snippets/light-token/transfer-checked/native-program/full-example.mdx delete mode 100644 snippets/code-snippets/light-token/transfer-checked/rust-client/action.mdx delete mode 100644 snippets/code-snippets/light-token/transfer-checked/rust-client/instruction.mdx delete mode 100644 snippets/code-snippets/light-token/transfer-interface/action.mdx delete mode 100644 snippets/code-snippets/light-token/transfer-interface/anchor-program/create-and-transfer-example.mdx delete mode 100644 snippets/code-snippets/light-token/transfer-interface/anchor-program/full-example.mdx delete mode 100644 snippets/code-snippets/light-token/transfer-interface/instruction.mdx delete mode 100644 snippets/code-snippets/light-token/transfer-interface/native-program/full-example.mdx delete mode 100644 snippets/code-snippets/light-token/transfer-interface/rust-client/action.mdx delete mode 100644 snippets/code-snippets/light-token/transfer-interface/rust-client/instruction.mdx delete mode 100644 snippets/code-snippets/light-token/transfer-interface/token-interface-instruction.mdx delete mode 100644 snippets/code-snippets/light-token/unwrap/action.mdx delete mode 100644 snippets/code-snippets/light-token/unwrap/instruction.mdx delete mode 100644 snippets/code-snippets/light-token/unwrap/rust-client/action.mdx delete mode 100644 snippets/code-snippets/light-token/unwrap/token-interface-instruction.mdx delete mode 100644 snippets/code-snippets/light-token/wrap/action.mdx delete mode 100644 snippets/code-snippets/light-token/wrap/instruction.mdx delete mode 100644 snippets/code-snippets/light-token/wrap/rust-client/action.mdx delete mode 100644 snippets/code-snippets/light-token/wrap/token-interface-instruction.mdx delete mode 100644 snippets/code-snippets/privy/balances/react.mdx create mode 100644 snippets/code-snippets/privy/compress/nodejs.mdx create mode 100644 snippets/code-snippets/privy/decompress/nodejs.mdx delete mode 100644 snippets/code-snippets/privy/helpers/sign-and-send-batches.mdx delete mode 100644 snippets/code-snippets/privy/receive/nodejs.mdx delete mode 100644 snippets/code-snippets/privy/receive/react.mdx delete mode 100644 snippets/code-snippets/privy/transaction-history/react.mdx delete mode 100644 snippets/code-snippets/privy/transfer/react.mdx delete mode 100644 snippets/code-snippets/privy/unwrap/nodejs.mdx delete mode 100644 snippets/code-snippets/privy/unwrap/react.mdx delete mode 100644 snippets/code-snippets/privy/wrap/nodejs.mdx delete mode 100644 snippets/code-snippets/privy/wrap/react.mdx delete mode 100644 snippets/code-snippets/wallet-adapter/balances/react.mdx delete mode 100644 snippets/code-snippets/wallet-adapter/helpers/sign-and-send-batches.mdx delete mode 100644 snippets/code-snippets/wallet-adapter/receive/react.mdx delete mode 100644 snippets/code-snippets/wallet-adapter/transaction-history/react.mdx delete mode 100644 snippets/code-snippets/wallet-adapter/transfer/react.mdx delete mode 100644 snippets/code-snippets/wallet-adapter/unwrap/react.mdx delete mode 100644 snippets/code-snippets/wallet-adapter/wrap/react.mdx delete mode 100644 snippets/cost-tables/cu-performance.mdx delete mode 100644 snippets/cost-tables/light-pda-cost.mdx delete mode 100644 snippets/cost-tables/mint-account-cost.mdx delete mode 100644 snippets/cost-tables/token-account-cost.mdx delete mode 100644 snippets/jsx/light-token-vs-spl-calculator.jsx delete mode 100644 snippets/light-token-configure-rent.mdx delete mode 100644 snippets/light-token-guides/cata-intro.mdx delete mode 100644 snippets/light-token-guides/client-custom-rent-config.mdx delete mode 100644 snippets/light-token-guides/close-intro.mdx delete mode 100644 snippets/light-token-guides/light-token-client-prerequisites.mdx delete mode 100644 snippets/light-token-guides/light-token-intro.mdx delete mode 100644 snippets/light-token-guides/light-token-program-prerequisites.mdx delete mode 100644 snippets/light-token-guides/light-token-ts-client-prerequisites.mdx delete mode 100644 snippets/light-token-guides/token-interface-sdk2-callout.mdx delete mode 100644 snippets/light-token-guides/transfer-interface-intro.mdx delete mode 100644 snippets/migration-reference/macros/light-pda.mdx delete mode 100644 snippets/overview-tables/cookbook-guides-table.mdx delete mode 100644 snippets/overview-tables/examples-guides-table.mdx delete mode 100644 snippets/overview-tables/integrate-light-token-guides-table.mdx delete mode 100644 snippets/overview-tables/light-mint-guides-table.mdx delete mode 100644 snippets/overview-tables/light-token-client-examples-table.mdx delete mode 100644 snippets/overview-tables/light-token-guides-table.mdx delete mode 100644 snippets/overview-tables/light-token-program-examples-table.mdx diff --git a/README.md b/README.md index 3f35c311..b1ffe37b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ Resources for developers to learn and build: -- **Light-Token Program**: High performance token program that reduces the cost of account creations by 200x, while being more CU efficient than SPL on hot paths. +- **Compressed Tokens**: Rent-free token accounts that reduce the cost of account creation by ~99% compared to SPL. - **ZK Compression Core**: Solana account primitive that lets you create tokens and PDAs without rent-exemption cost with L1 performance and security. --- @@ -9,5 +9,5 @@ Find more resources here: - Documentation: [zkcompression.com](https://www.zkcompression.com). - Index for LLMs and Agents: [llms.txt](https://www.zkcompression.com/llms.txt) -- [Examples](https://github.com/Lightprotocol/examples-light-token) +- [Examples](https://github.com/Lightprotocol/examples-zk-compression) - [Agent Skills](https://github.com/Lightprotocol/skills/tree/main) diff --git a/ai-tools/agent-skills.mdx b/ai-tools/agent-skills.mdx index f02d718a..ef43a17b 100644 --- a/ai-tools/agent-skills.mdx +++ b/ai-tools/agent-skills.mdx @@ -1,7 +1,7 @@ --- title: "Agent skills" description: "Install structured agent skill files for Token APIs and PDA accounts. Skills tell AI coding agents what they can do with ZK Compression." -keywords: ["agent skills light protocol", "AI coding agent solana", "claude code solana skills", "cursor solana skills", "light sdk agent skill", "light token agent skill", "AI agent solana development"] +keywords: ["agent skills light protocol", "AI coding agent solana", "claude code solana skills", "cursor solana skills", "compressed token agent skill", "compressed pda agent skill", "AI agent solana development"] --- ## Agent Skill for Orchestration @@ -39,16 +39,12 @@ Add the marketplace and install: | Use case | Skill | | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------- | -| For stablecoin payment flows and wallet integrations on Solana. | [payments](https://github.com/Lightprotocol/skills/tree/main/skills/payments) | -| For client development with Light Token APIs on Solana. | [light-token-client](https://github.com/Lightprotocol/skills/tree/main/skills/light-token-client) | -| For Solana program development with tokens and PDAs. | [light-sdk](https://github.com/Lightprotocol/skills/tree/main/skills/light-sdk) | -| For data pipelines, aggregators, or indexers, real-time account state streaming on Solana with light account hot/cold lifecycle tracking | [data-streaming](https://github.com/Lightprotocol/skills/tree/main/skills/data-streaming) | -| For token distribution on Solana 5000x cheaper than SPL (rewards, airdrops, depins, ...) | [token-distribution](https://github.com/Lightprotocol/skills/tree/main/skills/token-distribution) | -| For custom ZK Solana programs and privacy-preserving applications to prevent double spending | [zk-nullifier](https://github.com/Lightprotocol/skills/tree/main/skills/zk-nullifier) | -| For program development on Solana with infrequently accessed state, such as per-user state, DePIN registrations, ... | [solana-compression](https://github.com/Lightprotocol/skills/tree/main/skills/solana-compression) | +| For token use cases on Solana, such as token distribution, stablecoin payments and more. Works with Token-2022, Privy, Wallet Adapter similarly to SPL. | [compressed-token](https://github.com/Lightprotocol/skills/tree/main/skills/compressed-token) | +| For program development on Solana with infrequently accessed state, such as per-user state, DePIN registrations, nullifiers, or custom compressed accounts | [compressed-pda](https://github.com/Lightprotocol/skills/tree/main/skills/compressed-pda) | +| For custom ZK Solana programs and privacy-preserving applications to prevent double spending | [zk](https://github.com/Lightprotocol/skills/tree/main/skills/zk) | | For testing with Light Protocol programs and clients on localnet, devnet, and mainnet validation | [testing](https://github.com/Lightprotocol/skills/tree/main/skills/testing) | | For questions about compressed accounts, Light SDK, Solana development, Claude Code features, or agent skills | [ask-mcp](https://github.com/Lightprotocol/skills/tree/main/skills/ask-mcp) | > View all skills here: https://github.com/Lightprotocol/skills. -All skills are included and are auto-discovered based on context. Ask about light-token, defi, payments, or program migration and the agent uses the relevant skill automatically. +All skills are included and are auto-discovered based on context. Ask about compressed tokens, compressed PDAs, ZK programs, or testing and the agent uses the relevant skill automatically. diff --git a/ai-tools/prompts.mdx b/ai-tools/prompts.mdx index 17948846..a661a4b7 100644 --- a/ai-tools/prompts.mdx +++ b/ai-tools/prompts.mdx @@ -1,7 +1,7 @@ --- title: "AI Prompts" description: "Ready-to-use AI prompts for Light Protocol. Copy a prompt, paste into your AI coding agent, and let it implement the recipe in your project." -keywords: ["AI prompts solana", "AI coding prompts light protocol", "solana agent prompts", "cursor prompts solana", "claude code solana prompts", "light token AI prompts"] +keywords: ["AI prompts solana", "AI coding prompts light protocol", "solana agent prompts", "cursor prompts solana", "claude code solana prompts", "compressed token AI prompts"] --- import AllPrompts from "/snippets/ai-prompts/all-prompts.mdx"; diff --git a/api-reference/anchor.mdx b/api-reference/anchor.mdx deleted file mode 100644 index cbb19cca..00000000 --- a/api-reference/anchor.mdx +++ /dev/null @@ -1,194 +0,0 @@ ---- -title: "Anchor Constraints LightAccount" -description: "Syntax reference for #[light_account] constraints with sponsored rent-exemption." ---- - -- [`#[light_account(init)]`](#light_accountinit) creates a PDA -- [`#[light_account(init, token::...)]`](#light_accountinit-token) creates a token account via CPI -- [`#[light_account(init, associated_token::...)]`](#light_accountinit-associated_token) creates an ATA via CPI -- [`#[light_account(init, mint::...)]`](#light_accountinit-mint) creates a mint via CPI -- [Required accounts](#required-accounts) per account type - -Place `#[light_account]` below standard Anchor `#[account]` on the same field. -Anchor handles seeds, space, and payer; LightAccount handles rent-free creation. - ---- - -### `#[light_account(init)]` - -Creates a rent-free PDA. No additional parameters — uses Anchor `#[account]` seeds and space. - -**attribute** - -``` -#[light_account(init)] -``` - -```rust -#[account( // ← Anchor: seeds, space, payer - init, - payer = fee_payer, - space = 8 + ::INIT_SPACE, - seeds = [COUNTER_SEED, owner.key().as_ref()], - bump, -)] -#[light_account(init)] // ← Light: register for rent-free creation -pub counter: Account<'info, Counter>, -``` - -Examples: [Github](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-macros/counter) - ---- - -### `#[light_account(init, token::...)]` - -Creates a rent-free token account via CPI to the Light Token program. The account type is `UncheckedAccount` because Light Token program initializes it via CPI. - -**attribute** - -``` -#[light_account(init, - token::authority = , - token::mint = , - token::owner = , - token::bump = -)] -``` - -```rust -#[account( - mut, - seeds = [VAULT_SEED, mint.key().as_ref()], - bump, -)] -#[light_account(init, - token::authority = [VAULT_SEED, self.mint.key()], - token::mint = mint, - token::owner = vault_authority, - token::bump = params.vault_bump -)] -pub vault: UncheckedAccount<'info>, -``` - -Examples: [Github](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-macros/create-token-account) - ---- - -### `#[light_account(init, associated_token::...)]` - -Creates a rent-free associated token account via CPI. - -**attribute** - -``` -#[light_account(init, - associated_token::authority = , - associated_token::mint = , - associated_token::bump = -)] -``` - -```rust -#[account(mut)] -#[light_account(init, - associated_token::authority = associated_token_account_owner, - associated_token::mint = associated_token_account_mint, - associated_token::bump = params.associated_token_account_bump -)] -pub associated_token_account: UncheckedAccount<'info>, -``` - -Examples: [Github](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-macros/create-associated-token-account) - ---- - -### `#[light_account(init, mint::...)]` - -Creates a rent-free mint via CPI. - -**attribute (required)** - -``` -#[light_account(init, mint, - mint::signer = , - mint::authority = , - mint::decimals = , - mint::seeds = , -)] -``` - -**attribute (optional)** - -``` -mint::bump = -mint::freeze_authority = -mint::authority_seeds = -mint::name = // requires symbol + uri -mint::symbol = // requires name + uri -mint::uri = // requires name + symbol -mint::update_authority = // requires name, symbol, uri -mint::additional_metadata = // requires name, symbol, uri -``` - -```rust -#[account(mut)] -#[light_account(init, mint, - mint::signer = mint_signer, - mint::authority = fee_payer, - mint::decimals = 9, - mint::seeds = &[MINT_SIGNER_SEED, self.authority.to_account_info().key.as_ref()], -)] -pub mint: UncheckedAccount<'info>, -``` - - - -```rust -#[account(mut)] -#[light_account(init, mint, - mint::signer = mint_signer, - mint::authority = fee_payer, - mint::decimals = 9, - mint::seeds = &[MINT_SIGNER_SEED, self.authority.to_account_info().key.as_ref()], - mint::bump = params.mint_signer_bump, - mint::name = params.name.clone(), - mint::symbol = params.symbol.clone(), - mint::uri = params.uri.clone(), - mint::update_authority = authority, - mint::additional_metadata = params.additional_metadata.clone() -)] -pub mint: UncheckedAccount<'info>, -``` - - - -Examples: [Github](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-macros/create-mint) - ---- - -## Required accounts - -Add these to your `init` struct alongside the fields above. The `LightAccounts` derive macro appends additional protocol accounts to the instruction at runtime — you don't add those manually. - - - - -| Account | Description | -|:-|:-| -| `compression_config` | Per-program PDA. Stores rent sponsor address and compression settings. Initialize once via `InitializeRentFreeConfig`. | -| `pda_rent_sponsor` | Per-program PDA. Receives rent-exemption lamports when accounts compress. Must be mutable. | -| `system_program` | Solana System Program. Transfers lamports for rent-exemption. | - - - - -| Account | Description | -|:-|:-| -| `light_token_compressible_config` | Protocol PDA. Stores rent-config for Light Token accounts. | -| `light_token_rent_sponsor` | Protocol PDA. Holds the lamport pool that sponsors rent-exemption. Reclaims lamports when accounts compress. | -| `light_token_program` | Light Token program. CPI target for token, ATA, and mint creation. | -| `light_token_cpi_authority` | Signer PDA. Authorizes CPI calls from your program to the Light Token program. | -| `system_program` | Solana System Program. Transfers lamports for rent-exemption. | - - - \ No newline at end of file diff --git a/api-reference/json-rpc-methods/overview.mdx b/api-reference/json-rpc-methods/overview.mdx index 496c0cd6..0d2b4a1c 100644 --- a/api-reference/json-rpc-methods/overview.mdx +++ b/api-reference/json-rpc-methods/overview.mdx @@ -5,7 +5,7 @@ sidebarTitle: "Overview" --- -The Light Token SDK calls these methods internally via interface functions +The compressed token SDK calls these methods internally via interface functions like `transferInterface` and `getAtaInterface`. You rarely need to call them directly. @@ -71,7 +71,7 @@ const connection: Rpc = createRpc(RPC_ENDPOINT, RPC_ENDPOINT); ## Methods -These methods are called internally by the Light Token SDK. Call them +These methods are called internally by the compressed token SDK. Call them directly for custom indexing, block explorers, or debugging. diff --git a/api-reference/overview.mdx b/api-reference/overview.mdx index aa6876bf..f695374b 100644 --- a/api-reference/overview.mdx +++ b/api-reference/overview.mdx @@ -1,14 +1,11 @@ --- title: API Reference Overview -description: Reference documentation for Light Protocol SDKs, Anchor constraints, and JSON RPC methods. +description: Reference documentation for Light Protocol SDKs and JSON RPC methods. --- - TypeScript and Rust client SDKs for Light Token and ZK Compression. - - - Syntax reference for #[light_account] constraints: init PDAs, token accounts, ATAs, and mints. + TypeScript and Rust client SDKs for Compressed Tokens and ZK Compression. Photon indexer methods for querying compressed state on Solana. diff --git a/api-reference/sdk.mdx b/api-reference/sdk.mdx index b8f2200e..2db41324 100644 --- a/api-reference/sdk.mdx +++ b/api-reference/sdk.mdx @@ -1,7 +1,7 @@ --- title: SDK Reference sidebarTitle: Reference -description: Client and program SDKs for Light Token and ZK Compression. +description: Client and program SDKs for Compressed Tokens and ZK Compression. --- import SdkReference from "/snippets/overview-tables/sdk-reference.mdx"; diff --git a/api-reference/solana-to-light-comparison.mdx b/api-reference/solana-to-light-comparison.mdx deleted file mode 100644 index e6200681..00000000 --- a/api-reference/solana-to-light-comparison.mdx +++ /dev/null @@ -1,1581 +0,0 @@ ---- -title: Solana to Light Reference -sidebarTitle: Reference -description: Side-by-side mapping of every Light Token instruction against its SPL/Solana equivalent. Covers RPC, TypeScript client, Rust client, program CPI, and Anchor macros. -keywords: ["rent-exemption on solana", "solana rent-exemption", "expensive rent solana", "spl to light token migration", "solana spl token vs light token", "light token API reference", "solana token comparison", "spl token alternative solana", "light token typescript SDK", "light token rust SDK", "anchor light token"] ---- - -import LightCreateConnection from "/snippets/migration-reference/rpc/create-connection.mdx"; -import LightCreateConnectionRust from "/snippets/migration-reference/rpc/create-connection-rust.mdx"; -import LightLoadAtaTs from "/snippets/migration-reference/ts/load-ata.mdx"; -import LightGetBalanceTs from "/snippets/migration-reference/ts/get-balance.mdx"; -import LightGetHistoryTs from "/snippets/migration-reference/ts/get-history.mdx"; -import LightApproveTs from "/snippets/migration-reference/ts/approve.mdx"; -import LightRevokeTs from "/snippets/migration-reference/ts/revoke.mdx"; -import LightCreateTokenAccountRust from "/snippets/migration-reference/rust/create-token-account.mdx"; -import LightBurnRust from "/snippets/migration-reference/rust/burn.mdx"; -import LightFreezeRust from "/snippets/migration-reference/rust/freeze.mdx"; -import LightThawRust from "/snippets/migration-reference/rust/thaw.mdx"; -import LightCloseRust from "/snippets/migration-reference/rust/close.mdx"; -import LightWrapRust from "/snippets/migration-reference/rust/wrap.mdx"; -import LightUnwrapRust from "/snippets/migration-reference/rust/unwrap.mdx"; -import LightCreateMintCpi from "/snippets/migration-reference/cpi/create-mint.mdx"; -import LightCreateAtaCpi from "/snippets/migration-reference/cpi/create-ata.mdx"; -import LightCreateTokenAccountCpi from "/snippets/migration-reference/cpi/create-token-account.mdx"; -import LightMintToCpi from "/snippets/migration-reference/cpi/mint-to.mdx"; -import LightTransferCheckedCpi from "/snippets/migration-reference/cpi/transfer-checked.mdx"; -import LightTransferInterfaceCpi from "/snippets/migration-reference/cpi/transfer-interface.mdx"; -import LightBurnCpi from "/snippets/migration-reference/cpi/burn.mdx"; -import LightFreezeCpi from "/snippets/migration-reference/cpi/freeze.mdx"; -import LightThawCpi from "/snippets/migration-reference/cpi/thaw.mdx"; -import LightApproveCpi from "/snippets/migration-reference/cpi/approve.mdx"; -import LightRevokeCpi from "/snippets/migration-reference/cpi/revoke.mdx"; -import LightCloseCpi from "/snippets/migration-reference/cpi/close.mdx"; -import LightCreateMintMacro from "/snippets/migration-reference/macros/create-mint.mdx"; -import LightCreateMintMetadataMacro from "/snippets/migration-reference/macros/create-mint-metadata.mdx"; -import LightCreateAtaMacro from "/snippets/migration-reference/macros/create-ata.mdx"; -import LightCreateTokenAccountMacro from "/snippets/migration-reference/macros/create-token-account.mdx"; -import LightPdaMacro from "/snippets/migration-reference/macros/light-pda.mdx"; -import PromptTsCreateMint from "/snippets/ai-prompts/ts-cookbook/create-mint.mdx"; -import PromptTsCreateAta from "/snippets/ai-prompts/ts-cookbook/create-ata.mdx"; -import PromptTsMintTo from "/snippets/ai-prompts/ts-cookbook/mint-to.mdx"; -import PromptTsTransfer from "/snippets/ai-prompts/ts-cookbook/transfer-interface.mdx"; -import PromptTsApproveRevoke from "/snippets/ai-prompts/ts-cookbook/approve-revoke.mdx"; -import PromptTsWrapUnwrap from "/snippets/ai-prompts/ts-cookbook/wrap-unwrap.mdx"; -import PromptRustCreateMint from "/snippets/ai-prompts/rust-cookbook/create-mint.mdx"; -import PromptRustCreateAta from "/snippets/ai-prompts/rust-cookbook/create-ata.mdx"; -import PromptRustMintTo from "/snippets/ai-prompts/rust-cookbook/mint-to.mdx"; -import PromptRustTransfer from "/snippets/ai-prompts/rust-cookbook/transfer-interface.mdx"; -import PromptRustApproveRevoke from "/snippets/ai-prompts/rust-cookbook/approve-revoke.mdx"; -import PromptRustWrapUnwrap from "/snippets/ai-prompts/rust-cookbook/wrap-unwrap.mdx"; -import PromptRustCreateTokenAccount from "/snippets/ai-prompts/rust-cookbook/create-token-account.mdx"; -import PromptRustBurn from "/snippets/ai-prompts/rust-cookbook/burn.mdx"; -import PromptRustFreezeThaw from "/snippets/ai-prompts/rust-cookbook/freeze-thaw.mdx"; -import PromptRustClose from "/snippets/ai-prompts/rust-cookbook/close-token-account.mdx"; -import PromptCpiCreateMint from "/snippets/ai-prompts/program-cookbook/create-mint-cpi.mdx"; -import PromptCpiCreateAta from "/snippets/ai-prompts/program-cookbook/create-ata-cpi.mdx"; -import PromptCpiCreateTokenAccount from "/snippets/ai-prompts/program-cookbook/create-token-account-cpi.mdx"; -import PromptCpiMintTo from "/snippets/ai-prompts/program-cookbook/mint-to.mdx"; -import PromptCpiTransferChecked from "/snippets/ai-prompts/program-cookbook/transfer-checked.mdx"; -import PromptCpiTransferInterface from "/snippets/ai-prompts/program-cookbook/transfer-interface.mdx"; -import PromptCpiBurn from "/snippets/ai-prompts/program-cookbook/burn.mdx"; -import PromptCpiFreezeThaw from "/snippets/ai-prompts/program-cookbook/freeze-thaw.mdx"; -import PromptCpiApproveRevoke from "/snippets/ai-prompts/program-cookbook/approve-revoke.mdx"; -import PromptCpiClose from "/snippets/ai-prompts/program-cookbook/close-token-account.mdx"; -import PromptMacrosCreateMint from "/snippets/ai-prompts/program-cookbook/create-mint-macros.mdx"; -import PromptMacrosCreateAta from "/snippets/ai-prompts/program-cookbook/create-ata-macros.mdx"; -import PromptMacrosCreateTokenAccount from "/snippets/ai-prompts/program-cookbook/create-token-account-macros.mdx"; -import PromptMacrosLightPda from "/snippets/ai-prompts/program-cookbook/light-pda.mdx"; -import AgentSkillGeneric from "/snippets/setup/agent-skill-generic.mdx"; - - - - -### Create an RPC connection - -Helius exposes Solana and Photon RPC endpoints through a single URL. -It's a thin wrapper extending Solana's `Connection` class that allows you to query cold Light Token balances. - - - - - -```typescript title="SPL" -import { Connection } from "@solana/web3.js"; - -const connection = new Connection(RPC_ENDPOINT); -``` - - - - - -```rust title="SPL" -use solana_client::rpc_client::RpcClient; - -let client = RpcClient::new(rpc_url.to_string()); -``` - - - - - -The Light Token SDK calls RPC methods internally via interface functions like `transferInterface` and `getAtaInterface`. Call them directly for custom indexing, block explorers, or debugging. -See [JSON RPC Methods](/api-reference/json-rpc-methods/overview). - - - -Fetch the parsed state of a light token account, including hot and cold balances. - -> [Guide](/light-token/payments/overview) | -> [Example](https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/verify/get-balance.ts) - - - -```typescript title="SPL" -import { getAccount } from "@solana/spl-token"; - -const account = await getAccount(connection, ata); - -console.log(account.amount); -``` - - - - -Fetch merged and deduplicated transaction history across on-chain and compressed transactions. - -> [Guide](/light-token/payments/overview) | -> [Example](https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/verify/get-history.ts) - - - -```typescript title="SPL" -const signatures = await connection.getSignaturesForAddress(ata); -``` - - - ---- - -## Client - -Both `@lightprotocol/compressed-token` (TypeScript) and `light_token_client` (Rust) are a superset of the SPL Token API. Every SPL operation has a 1:1 equivalent. The SDKs add unified balance queries (`getAtaInterface`), automatic load/decompress for cold state, wrap/unwrap for SPL and Token 2022 interop, and cross-program dispatch via `Interface` methods like `transferInterface` that auto-detect the token program. - -### Create mint - -Create a mint account with optional token metadata. - -> [Guide](/light-token/cookbook/create-mint) | -> [Example (TS)](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/actions/create-mint.ts) | -> [Example (Rust)](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/actions/create_mint.rs) - - - - - -```typescript Light Action -import { createMintInterface } from "@lightprotocol/compressed-token"; - -const { mint } = await createMintInterface( - rpc, - payer, - mintAuthority, - freezeAuthority, - decimals, - mintKeypair -); -``` - -```typescript Light Instruction -import { createMintInstruction } from "@lightprotocol/compressed-token"; - -const ix = createMintInstruction( - mintSigner.publicKey, - decimals, - payer.publicKey, - freezeAuthority, - payer.publicKey, - validityProof, - addressTreeInfo, - stateTreeInfo, - tokenMetadata -); -``` - - -```typescript SPL Action -import { createMint } from "@solana/spl-token"; - -const mint = await createMint( - connection, - payer, - mintAuthority, - freezeAuthority, - decimals -); -``` - -```typescript SPL Instruction -import { createInitializeMint2Instruction } from "@solana/spl-token"; - -const ix = createInitializeMint2Instruction( - mint.publicKey, - decimals, - mintAuthority, - freezeAuthority, - TOKEN_PROGRAM_ID -); -``` - - - - - - -```rust Light Instruction -use light_token::instruction::CreateMint; - -let ix = CreateMint::new( - params, - mint_seed.pubkey(), - payer.pubkey(), - address_tree.tree, - output_queue, -) -.instruction()?; -``` - -```rust Light Action -use light_token_client::actions::CreateMint; - -let (sig, mint) = CreateMint { - decimals: 9, - freeze_authority: Some(payer.pubkey()), - token_metadata: None, - seed: None, -} -.execute(&mut rpc, &payer, &mint_authority) -.await?; -``` - -```rust title="SPL" -use spl_token::instruction::initialize_mint; - -let ix = initialize_mint( - &spl_token::id(), - &mint.pubkey(), - &mint_authority, - Some(&freeze_authority), - decimals, -)?; -``` - - - - - - - - - - - - - - - -### Create associated token account - -Associated light token accounts can hold balances of light, SPL, or Token 2022 mints. - -> [Guide](/light-token/cookbook/create-ata) | -> [Example (TS)](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/actions/create-ata.ts) | -> [Example (Rust)](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/actions/create_associated_token_account.rs) - - - - - -```typescript Light Action -import { getOrCreateAtaInterface } from "@lightprotocol/compressed-token/unified"; - -const ata = await getOrCreateAtaInterface( - rpc, - payer, - mint, - owner -); -``` - -```typescript Light Instruction -import { createAssociatedTokenAccountInterfaceInstruction } from "@lightprotocol/compressed-token"; - -const ix = createAssociatedTokenAccountInterfaceInstruction( - payer.publicKey, - ata, - owner.publicKey, - mint -); -``` - - -```typescript SPL Action -import { getOrCreateAssociatedTokenAccount } from "@solana/spl-token"; - -const ata = await getOrCreateAssociatedTokenAccount( - connection, - payer, - mint, - owner -); -``` - -```typescript SPL Instruction -import { createAssociatedTokenAccountInstruction } from "@solana/spl-token"; - -const ix = createAssociatedTokenAccountInstruction( - payer.publicKey, - ata, - owner.publicKey, - mint -); -``` - - - - - - -```rust Light Instruction -use light_token::instruction::CreateAssociatedTokenAccount; - -let ix = CreateAssociatedTokenAccount::new( - payer.pubkey(), - owner.pubkey(), - mint, -) -.instruction()?; -``` - -```rust Light Action -use light_token_client::actions::CreateAta; - -let (sig, ata) = CreateAta { - mint, - owner: owner.pubkey(), - idempotent: false, -} -.execute(&mut rpc, &payer) -.await?; -``` - -```rust title="SPL" -use spl_associated_token_account::instruction::create_associated_token_account; - -let ix = create_associated_token_account( - &payer.pubkey(), - &owner.pubkey(), - &mint, - &spl_token::id(), -); -``` - - - - - - - - - - - - - - - -### Mint tokens - -Mint Light, SPL and Token 2022 tokens to a destination account. The SDK auto-detects the token program based on the mint address you pass. -When no programId is passed, all three token programs are queried in parallel and returns the first successful result. The priority - order is SPL Token → Token 2022 → Light Token. - -> [Guide](/light-token/cookbook/mint-to) | -> [Example (TS)](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/actions/mint-to.ts) | -> [Example (Rust)](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/actions/mint_to.rs) - - - - - -```typescript Light Action -import { mintToInterface } from "@lightprotocol/compressed-token"; - -const tx = await mintToInterface( - rpc, - payer, - mint, - destination, - mintAuthority, - amount -); -``` - -```typescript Light Instruction -import { createMintToInterfaceInstruction } from "@lightprotocol/compressed-token"; - -const ix = createMintToInterfaceInstruction( - mintInterface, - destination, - authority.publicKey, - payer.publicKey, - amount -); -``` - - -```typescript SPL Action -import { mintTo } from "@solana/spl-token"; - -const tx = await mintTo( - connection, - payer, - mint, - destination, - mintAuthority, - amount -); -``` - -```typescript SPL Instruction -import { createMintToInstruction } from "@solana/spl-token"; - -const ix = createMintToInstruction( - mint, - destination, - mintAuthority.publicKey, - amount -); -``` - - - - - - -```rust Light Instruction -use light_token::instruction::MintTo; - -let ix = MintTo { - mint, - destination, - amount, - authority: payer.pubkey(), - fee_payer: payer.pubkey(), -} -.instruction()?; -``` - -```rust Light Action -use light_token_client::actions::MintTo; - -let sig = MintTo { - mint, - destination, - amount, -} -.execute(&mut rpc, &payer, &authority) -.await?; -``` - -```rust title="SPL" -use spl_token::instruction::mint_to; - -let ix = mint_to( - &spl_token::id(), - &mint, - &destination, - &mint_authority, - &[], - amount, -)?; -``` - - - - - - - - - - - - - - - -### Transfer tokens with Transferinterface - -The interface detects account types and invokes the right programs. - -
- - - - - - - - - - - - - - -
**Light Token -> Light Token Account** -
    -
  • Transfers tokens between Light Token accounts
  • -
-
**SPL token -> Light Token Account** -
    -
  • Transfers SPL tokens to Light Token accounts
  • -
  • SPL tokens are locked in interface PDA
  • -
  • Tokens are minted to Light Token account
  • -
-
**Light Token -> SPL Account** -
    -
  • Releases SPL tokens from interface PDA to SPL account
  • -
  • Burns tokens in source Light Token account
  • -
-
- -> [Guide](/light-token/cookbook/transfer-interface) | -> [Example (TS)](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/actions/transfer-interface.ts) | -> [Example (Rust)](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/actions/transfer_interface.rs) - - - - - -```typescript Light Action -import { transferInterface } from "@lightprotocol/compressed-token/unified"; - -const tx = await transferInterface( - rpc, - payer, - sourceAta, - mint, - recipient, - owner.publicKey, - owner, - amount -); -``` - -```typescript Light Instruction -import { createLightTokenTransferInstruction } from "@lightprotocol/compressed-token"; - -const ix = createLightTokenTransferInstruction( - source, - destination, - owner.publicKey, - amount -); -``` - - -```typescript SPL Action -import { transfer } from "@solana/spl-token"; - -const tx = await transfer( - connection, - payer, - sourceAta, - destinationAta, - owner, - amount -); -``` - -```typescript SPL Instruction -import { createTransferInstruction } from "@solana/spl-token"; - -const ix = createTransferInstruction( - sourceAta, - destinationAta, - owner.publicKey, - amount -); -``` - - - - - - -```rust Light Instruction -use light_token::instruction::TransferInterface; - -let ix = TransferInterface { - source, - destination, - amount, - decimals, - authority: payer.pubkey(), - payer: payer.pubkey(), - mint, - spl_interface: None, - source_owner: LIGHT_TOKEN_PROGRAM_ID, - destination_owner: LIGHT_TOKEN_PROGRAM_ID, -} -.instruction()?; -``` - -```rust Light Action -use light_token_client::actions::TransferInterface; - -let sig = TransferInterface { - source, - mint, - destination, - amount, - decimals, - spl_token_program: None, - restricted: false, -} -.execute(&mut rpc, &payer, &authority) -.await?; -``` - -```rust title="SPL" -use spl_token::instruction::transfer; - -let ix = transfer( - &spl_token::id(), - &source, - &destination, - &authority, - &[], - amount, -)?; -``` - - - - -For payment flows, `createTransferInterfaceInstructions` returns -`TransactionInstruction[][]` — handles loading cold state and -transferring in one call: - -> [Guide](/light-token/payments/overview) | -> [Example (instruction)](https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/send/basic-send-instruction.ts) | -> [Example (action)](https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/send/basic-send-action.ts) - -```typescript -import { Transaction } from "@solana/web3.js"; -import { createTransferInterfaceInstructions } from "@lightprotocol/compressed-token/unified"; - -// Returns TransactionInstruction[][]. -// Each inner array is one transaction. -// Almost always returns just one. -const instructions = await createTransferInterfaceInstructions( - rpc, - payer.publicKey, - mint, - amount, - owner.publicKey, - recipient -); - -for (const ixs of instructions) { - const tx = new Transaction().add(...ixs); - - // sign and send ... -} -``` - -Your app logic may require you to create a single sign request for your user: - - - -```typescript -const transactions = instructions.map((ixs) => new Transaction().add(...ixs)); - -// One approval for all -const signed = await wallet.signAllTransactions(transactions); - -for (const tx of signed) { - // send... - await sendAndConfirmTransaction(rpc, tx); -} -``` - - - -While almost always you will have only one transfer transaction, you can -optimize sending in the rare cases where you have multiple transactions. -Parallelize the loads, confirm them, and then send the transfer instruction -after. - - - -```typescript -import { - createTransferInterfaceInstructions, - sliceLast, -} from "@lightprotocol/compressed-token/unified"; - -const instructions = await createTransferInterfaceInstructions( - rpc, - payer.publicKey, - mint, - amount, - owner.publicKey, - recipient -); -const { rest: loadInstructions, last: transferInstructions } = sliceLast(instructions); -// empty = nothing to load, will no-op. -await Promise.all( - loadInstructions.map((ixs) => { - const tx = new Transaction().add(...ixs); - tx.sign(payer, owner); - return sendAndConfirmTransaction(rpc, tx); - }) -); - -const transferTx = new Transaction().add(...transferInstructions); -transferTx.sign(payer, owner); -await sendAndConfirmTransaction(rpc, transferTx); -``` - - - - -Load creates the ATA if needed and loads any compressed state into it. Light Token accounts auto-compress inactive accounts. Before any action, the SDK detects cold balances and adds instructions to load them. - -> [Guide](/light-token/cookbook/load-ata) | -> [Example](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/actions/load-ata.ts) | -> [Source](https://github.com/Lightprotocol/light-protocol/blob/main/js/compressed-token/src/v3/actions/load-ata.ts) - - - - - - - - - - - - - - - -### Wrap and unwrap - -**Wrap** moves tokens from an SPL/Token 2022 account to a Light Token associated token account - (hot balance). **Unwrap** moves tokens back to SPL. Use this to compose with applications that do not yet support light-token. - -> [Guide](/light-token/cookbook/wrap-unwrap) | -> [Example (wrap)](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/actions/wrap.ts) | -> [Example (unwrap)](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/actions/unwrap.ts) - - - - -```typescript Action -import { getAssociatedTokenAddressSync } from "@solana/spl-token"; -import { - wrap, - unwrap, - getAssociatedTokenAddressInterface, -} from "@lightprotocol/compressed-token/unified"; - -const splAta = getAssociatedTokenAddressSync(mint, owner.publicKey); -const tokenAta = getAssociatedTokenAddressInterface(mint, owner.publicKey); - -// Wrap: SPL → Light -await wrap(rpc, payer, splAta, tokenAta, owner, mint, amount); - -// Unwrap: Light → SPL -await unwrap(rpc, payer, splAta, owner, mint, amount); -``` - -```typescript Instruction -import { createWrapInstruction, createUnwrapInstruction } from "@lightprotocol/compressed-token"; - -const wrapIx = createWrapInstruction( - source, destination, owner.publicKey, mint, amount, splInterfaceInfo, decimals -); - -const unwrapIx = createUnwrapInstruction( - source, destination, owner.publicKey, mint, amount, splInterfaceInfo, decimals -); -``` - - - - - - - - - - - - - - - - - - - -### Approve delegate - -Approve a delegate to spend tokens up to a specified amount. - -> [Guide](/light-token/cookbook/approve-revoke) | -> [Example (TS)](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/actions/delegate-approve.ts) | -> [Example (Rust)](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/actions/approve.rs) - - - - - -```typescript title="SPL" -import { approve } from "@solana/spl-token"; - -const tx = await approve( - connection, - payer, - source, - delegate, - owner, - amount -); -``` - - - - - -```rust Light Instruction -use light_token::instruction::Approve; - -let ix = Approve { - token_account: ata, - delegate: delegate.pubkey(), - owner: payer.pubkey(), - amount, - fee_payer: payer.pubkey(), -} -.instruction()?; -``` - -```rust Light Action -use light_token_client::actions::Approve; - -let sig = Approve { - token_account: ata, - delegate: delegate.pubkey(), - amount, - owner: None, -} -.execute(&mut rpc, &payer) -.await?; -``` - -```rust title="SPL" -use spl_token::instruction::approve; - -let ix = approve( - &spl_token::id(), - &source, - &delegate, - &owner, - &[], - amount, -)?; -``` - - - - - - - - - - - - - - - -### Delegated transfer - -Transfer tokens as an approved delegate. The delegate is the transaction authority; the owner's signature is not required. - -> [Guide](/light-token/payments/spend-permissions) - - - - -```typescript title="Light" -import { transferInterface } from "@lightprotocol/compressed-token/unified"; - -const tx = await transferInterface( - rpc, - payer, - sourceAta, - mint, - recipient, - owner.publicKey, - delegate, - amount -); -``` -```typescript title="SPL" -import { transfer } from "@solana/spl-token"; - -// delegate signs instead of owner -const tx = await transfer( - connection, - payer, - sourceAta, - destinationAta, - delegate, - amount -); -``` - - - - -### Revoke delegate - -Remove all delegate permissions. - -> [Guide](/light-token/cookbook/approve-revoke) | -> [Example (TS)](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/actions/delegate-revoke.ts) | -> [Example (Rust)](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/actions/revoke.rs) - - - - - -```typescript title="SPL" -import { revoke } from "@solana/spl-token"; - -const tx = await revoke( - connection, - payer, - source, - owner -); -``` - - - - - -```rust Light Instruction -use light_token::instruction::Revoke; - -let ix = Revoke { - token_account: ata, - owner: payer.pubkey(), - fee_payer: payer.pubkey(), -} -.instruction()?; -``` - -```rust Light Action -use light_token_client::actions::Revoke; - -let sig = Revoke { - token_account: ata, - owner: None, -} -.execute(&mut rpc, &payer) -.await?; -``` - -```rust title="SPL" -use spl_token::instruction::revoke; - -let ix = revoke( - &spl_token::id(), - &source, - &owner, - &[], -)?; -``` - - - - - - - - - - - - - - - -### Create token account - -> [Guide](/light-token/cookbook/create-token-account) | -> [Example](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/instructions/create_token_account.rs) - - - -```rust title="SPL" -use spl_token::instruction::initialize_account; - -let ix = initialize_account( - &spl_token::id(), - &account, - &mint, - &owner, -)?; -``` - - - - - - -### Burn - -Permanently destroy tokens and reduce mint supply. - -> [Guide](/light-token/cookbook/burn) | -> [Example](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/instructions/burn.rs) - - - -```rust title="SPL" -use spl_token::instruction::burn; - -let ix = burn( - &spl_token::id(), - &source, - &mint, - &authority, - &[], - amount, -)?; -``` - - - - - - -### Freeze and thaw - -Freeze prevents all transfers, burns, or closes. Only the freeze authority can freeze or thaw. - -> [Guide](/light-token/cookbook/freeze-thaw) | -> [Example (freeze)](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/instructions/freeze.rs) | -> [Example (thaw)](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/instructions/thaw.rs) - - -
- - -
-```rust title="SPL" -use spl_token::instruction::{freeze_account, thaw_account}; - -let ix = freeze_account( - &spl_token::id(), - &account, - &mint, - &freeze_authority, - &[], -)?; - -let ix = thaw_account( - &spl_token::id(), - &account, - &mint, - &freeze_authority, - &[], -)?; -``` -
- - - - - -### Close token account - -Close an empty token account and reclaim lamports. - -> [Guide](/light-token/cookbook/close-token-account) | -> [Example](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/instructions/close.rs) - - - -```rust title="SPL" -use spl_token::instruction::close_account; - -let ix = close_account( - &spl_token::id(), - &account, - &destination, - &owner, - &[], -)?; -``` - - - - - - ---- - -## Program CPI - -`light_token::instruction::*Cpi` structs map 1:1 to `spl_token::instruction::*`. Use `.invoke()` for external signers or `.invoke_signed()` for PDA signers. Add `.rent_free()` to sponsor rent-exemption on account creation. - -### CreateMintCpi - -Create a rent-free mint account via CPI. - -> [Guide](/light-token/cookbook/create-mint) | -> [Example](https://github.com/Lightprotocol/examples-light-token/blob/main/programs/anchor/basic-instructions/create-mint/src/lib.rs) | -> [Source](https://docs.rs/light-token) - - - -```rust title="SPL" -use spl_token::instruction::initialize_mint; - -let ix = initialize_mint( - &spl_token::id(), - &mint.pubkey(), - &mint_authority, - Some(&freeze_authority), - decimals, -)?; - -invoke(&ix, &[mint, rent_sysvar])?; -``` - - - - - - -### CreateAssociatedAccountCpi - -Create a rent-free associated token account via CPI. - -> [Guide](/light-token/cookbook/create-ata) | -> [Example](https://github.com/Lightprotocol/examples-light-token/blob/main/programs/anchor/basic-instructions/create-associated-token-account/src/lib.rs) | -> [Source](https://docs.rs/light-token) - - - -```rust title="SPL" -use spl_associated_token_account::instruction::create_associated_token_account; - -let ix = create_associated_token_account( - &payer.pubkey(), - &owner.pubkey(), - &mint, - &spl_token::id(), -); - -invoke(&ix, &[payer, owner, mint])?; -``` - - - - - - -### CreateTokenAccountCpi - -Create a rent-free token account via CPI. - -> [Guide](/light-token/cookbook/create-token-account) | -> [Example](https://github.com/Lightprotocol/examples-light-token/blob/main/programs/anchor/basic-instructions/create-token-account/src/lib.rs) | -> [Source](https://docs.rs/light-token) - - - -```rust title="SPL" -use spl_token::instruction::initialize_account; - -let ix = initialize_account( - &spl_token::id(), - &account, - &mint, - &owner, -)?; - -invoke(&ix, &[account, mint, owner])?; -``` - - - - - - -### MintToCpi - -Mint tokens to a destination account via CPI. - -> [Guide](/light-token/cookbook/mint-to) | -> [Example](https://github.com/Lightprotocol/examples-light-token/blob/main/programs/anchor/basic-instructions/mint-to/src/lib.rs) | -> [Source](https://docs.rs/light-token) - - - -```rust title="SPL" -use spl_token::instruction::mint_to; - -let ix = mint_to( - &spl_token::id(), - &mint, - &destination, - &mint_authority, - &[], - amount, -)?; - -invoke(&ix, &[mint, destination, authority])?; -``` - - - - - - -### Transfer - -Transfer with decimal validation via CPI. - -> [Guide](/light-token/cookbook/transfer-interface) | -> [Example](https://github.com/Lightprotocol/examples-light-token/blob/main/programs/anchor/basic-instructions/transfer-checked/src/lib.rs) | -> [Source](https://docs.rs/light-token) - - - -```rust title="SPL" -use spl_token::instruction::transfer_checked; - -let ix = transfer_checked( - &spl_token::id(), - &source, - &mint, - &destination, - &authority, - &[], - amount, - decimals, -)?; - -invoke(&ix, &[source, mint, destination, authority])?; -``` - - - - - - -### TransferInterfaceCpi - -Transfer tokens across SPL, Token 2022, and Light Token accounts via CPI. The interface auto-detects the token type and routes to the correct program. - -> [Guide](/light-token/cookbook/transfer-interface) | -> [Example](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-instructions/transfer-interface) | -> [Source](https://docs.rs/light-token) - - - -```rust title="SPL" -use spl_token::instruction::transfer_checked; - -let ix = transfer_checked( - &spl_token::id(), - &source, - &mint, - &destination, - &authority, - &[], - amount, - decimals, -)?; - -invoke(&ix, &[source, mint, destination, authority])?; -``` - - - - - - -### BurnCpi - -Burn tokens via CPI. - -> [Guide](/light-token/cookbook/burn) | -> [Example](https://github.com/Lightprotocol/examples-light-token/blob/main/programs/anchor/basic-instructions/burn/src/lib.rs) | -> [Source](https://docs.rs/light-token) - - - -```rust title="SPL" -use spl_token::instruction::burn; - -let ix = burn( - &spl_token::id(), - &source, - &mint, - &authority, - &[], - amount, -)?; - -invoke(&ix, &[source, mint, authority])?; -``` - - - - - - -### FreezeCpi and ThawCpi - -Freeze or thaw a token account via CPI. - -> [Guide](/light-token/cookbook/freeze-thaw) | -> [Example (freeze)](https://github.com/Lightprotocol/examples-light-token/blob/main/programs/anchor/basic-instructions/freeze/src/lib.rs) | -> [Example (thaw)](https://github.com/Lightprotocol/examples-light-token/blob/main/programs/anchor/basic-instructions/thaw/src/lib.rs) | -> [Source](https://docs.rs/light-token) - - -
- - -
-```rust title="SPL" -use spl_token::instruction::{freeze_account, thaw_account}; - -let ix = freeze_account( - &spl_token::id(), &account, &mint, &freeze_authority, &[], -)?; -invoke(&ix, &[account, mint, freeze_authority])?; - -let ix = thaw_account( - &spl_token::id(), &account, &mint, &freeze_authority, &[], -)?; -invoke(&ix, &[account, mint, freeze_authority])?; -``` -
- - - - - -### ApproveCpi and RevokeCpi - -Approve a delegate or revoke permissions via CPI. - -> [Guide](/light-token/cookbook/approve-revoke) | -> [Example (approve)](https://github.com/Lightprotocol/examples-light-token/blob/main/programs/anchor/basic-instructions/approve/src/lib.rs) | -> [Example (revoke)](https://github.com/Lightprotocol/examples-light-token/blob/main/programs/anchor/basic-instructions/revoke/src/lib.rs) | -> [Source](https://docs.rs/light-token) - - -
- - -
-```rust title="SPL" -use spl_token::instruction::{approve, revoke}; - -let ix = approve( - &spl_token::id(), &source, &delegate, &owner, &[], amount, -)?; -invoke(&ix, &[source, delegate, owner])?; - -let ix = revoke( - &spl_token::id(), &source, &owner, &[], -)?; -invoke(&ix, &[source, owner])?; -``` -
- - - - - -### CloseAccountCpi - -Close a token account and reclaim lamports via CPI. - -> [Guide](/light-token/cookbook/close-token-account) | -> [Example](https://github.com/Lightprotocol/examples-light-token/blob/main/programs/anchor/basic-instructions/close/src/lib.rs) | -> [Source](https://docs.rs/light-token) - - - -```rust title="SPL" -use spl_token::instruction::close_account; - -let ix = close_account( - &spl_token::id(), &account, &destination, &owner, &[], -)?; -invoke(&ix, &[account, destination, owner])?; -``` - - - - - - ---- - -## Anchor macros - -`#[light_account(...)]` replaces `#[account(...)]` for rent-free account initialization. Add `#[light_program]` above `#[program]` to enable compression. - -### Create mint - -> [Guide](/light-token/cookbook/create-mint) | -> [Example](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-macros/create-mint) | -> [Source](https://docs.rs/light-token) - - - -```rust title="Anchor" -#[account( - init, - payer = fee_payer, - mint::decimals = 9, - mint::authority = fee_payer, -)] -pub mint: InterfaceAccount<'info, Mint>, -``` - - - - - - -### Create mint with metadata - -Metadata fields are declared inline instead of requiring a separate CPI. - -> [Guide](/light-token/cookbook/create-mint) | -> [Example](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-macros/create-mint) | -> [Source](https://docs.rs/light-token) - - - -```rust title="Anchor" -#[account( - init, - payer = fee_payer, - mint::decimals = 9, - mint::authority = fee_payer, - extensions::metadata_pointer::authority = fee_payer, - extensions::metadata_pointer::metadata_address = mint_account, -)] -pub mint_account: InterfaceAccount<'info, Mint>, - -// Metadata requires a separate CPI: -token_metadata_initialize( - cpi_ctx, - params.name, - params.symbol, - params.uri, -)?; -``` - - - - - - -### Create associated token account - -> [Guide](/light-token/cookbook/create-ata) | -> [Example](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-macros/create-associated-token-account) | -> [Source](https://docs.rs/light-token) - - - -```rust title="Anchor" -#[account( - init, - payer = fee_payer, - associated_token::mint = mint, - associated_token::authority = owner, -)] -pub ata: Account<'info, TokenAccount>, -``` - - - - - - -### Create token account (vault) - -> [Guide](/light-token/cookbook/create-token-account) | -> [Example](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-macros/create-token-account) | -> [Source](https://docs.rs/light-token) - - - -```rust title="Anchor" -#[account( - init, - payer = fee_payer, - token::mint = mint, - token::authority = authority, -)] -pub vault: Account<'info, TokenAccount>, -``` - - - - - - -### Light-PDA init - -Add `#[light_program]` above `#[program]`, derive `LightAccount` on state structs with a `compression_info` field, and derive `LightAccounts` on the accounts struct. - -> [Guide](/pda/light-pda/overview) | -> [Example](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-macros/counter) | -> [Source](https://docs.rs/light-account) - - - -```rust title="Anchor" -#[program] -pub mod my_program { - // instruction logic unchanged -} - -#[account] -pub struct MyState { - pub authority: Pubkey, - pub data: u64, -} - -#[derive(Accounts)] -pub struct Initialize<'info> { - #[account( - init, - payer = payer, - space = 8 + MyState::INIT_SPACE, - )] - pub state: Account<'info, MyState>, - #[account(mut)] - pub payer: Signer<'info>, - pub system_program: Program<'info, System>, -} -``` - - - - - diff --git a/pda/compressed-pdas/guides.mdx b/compressed-pdas/guides.mdx similarity index 96% rename from pda/compressed-pdas/guides.mdx rename to compressed-pdas/guides.mdx index 3980e92d..a8d89412 100644 --- a/pda/compressed-pdas/guides.mdx +++ b/compressed-pdas/guides.mdx @@ -79,6 +79,6 @@ Here is the complete flow to create, or interact with compressed accounts: title="Create a program with compressed accounts" icon="chevron-right" color="#0066ff" - href="/pda/compressed-pdas/guides/how-to-create-compressed-accounts" + href="/compressed-pdas/guides/how-to-create-compressed-accounts" horizontal /> \ No newline at end of file diff --git a/pda/compressed-pdas/guides/client-guide.mdx b/compressed-pdas/guides/client-guide.mdx similarity index 99% rename from pda/compressed-pdas/guides/client-guide.mdx rename to compressed-pdas/guides/client-guide.mdx index 9552672b..2707d59d 100644 --- a/pda/compressed-pdas/guides/client-guide.mdx +++ b/compressed-pdas/guides/client-guide.mdx @@ -1118,7 +1118,7 @@ For help with debugging, see the [Error Cheatsheet](/resources/error-cheatsheet) title="Get an overview to Compressed PDA guides and build a program." icon="chevron-right" color="#0066ff" - href="/pda/compressed-pdas/guides" + href="/compressed-pdas/guides" horizontal > diff --git a/pda/compressed-pdas/guides/how-to-burn-compressed-accounts.mdx b/compressed-pdas/guides/how-to-burn-compressed-accounts.mdx similarity index 96% rename from pda/compressed-pdas/guides/how-to-burn-compressed-accounts.mdx rename to compressed-pdas/guides/how-to-burn-compressed-accounts.mdx index 05b2a02f..53917798 100644 --- a/pda/compressed-pdas/guides/how-to-burn-compressed-accounts.mdx +++ b/compressed-pdas/guides/how-to-burn-compressed-accounts.mdx @@ -20,7 +20,7 @@ Burning a compressed account * A burned account cannot be reinitialized. -Find [full code examples at the end](/pda/compressed-pdas/guides/how-to-burn-compressed-accounts#full-code-example) for Anchor and native Rust. +Find [full code examples at the end](/compressed-pdas/guides/how-to-burn-compressed-accounts#full-code-example) for Anchor and native Rust. # Implementation Guide @@ -283,14 +283,14 @@ Find the source code [here](https://github.com/Lightprotocol/program-examples/tr title="Build a client for your program" icon="chevron-right" color="#0066ff" - href="/pda/compressed-pdas/guides/client-guide" + href="/compressed-pdas/guides/client-guide" horizontal /> diff --git a/pda/compressed-pdas/guides/how-to-close-compressed-accounts.mdx b/compressed-pdas/guides/how-to-close-compressed-accounts.mdx similarity index 95% rename from pda/compressed-pdas/guides/how-to-close-compressed-accounts.mdx rename to compressed-pdas/guides/how-to-close-compressed-accounts.mdx index 78484ff9..681a4609 100644 --- a/pda/compressed-pdas/guides/how-to-close-compressed-accounts.mdx +++ b/compressed-pdas/guides/how-to-close-compressed-accounts.mdx @@ -17,10 +17,10 @@ Closing a compressed account * consumes the existing account hash, and * produces a new account hash with zero values to mark it as closed. -* A closed compressed account [can be reinitialized](/pda/compressed-pdas/guides/how-to-reinitialize-compressed-accounts). +* A closed compressed account [can be reinitialized](/compressed-pdas/guides/how-to-reinitialize-compressed-accounts). -Find [full code examples at the end](/pda/compressed-pdas/guides/how-to-close-compressed-accounts#full-code-example) for Anchor and native Rust. +Find [full code examples at the end](/compressed-pdas/guides/how-to-close-compressed-accounts#full-code-example) for Anchor and native Rust. # Implementation Guide @@ -290,14 +290,14 @@ Find the source code [here](https://github.com/Lightprotocol/program-examples/tr title="Build a client for your program" icon="chevron-right" color="#0066ff" - href="/pda/compressed-pdas/guides/client-guide" + href="/compressed-pdas/guides/client-guide" horizontal /> diff --git a/pda/compressed-pdas/guides/how-to-create-compressed-accounts.mdx b/compressed-pdas/guides/how-to-create-compressed-accounts.mdx similarity index 98% rename from pda/compressed-pdas/guides/how-to-create-compressed-accounts.mdx rename to compressed-pdas/guides/how-to-create-compressed-accounts.mdx index 28e9e85d..1ea316da 100644 --- a/pda/compressed-pdas/guides/how-to-create-compressed-accounts.mdx +++ b/compressed-pdas/guides/how-to-create-compressed-accounts.mdx @@ -17,7 +17,7 @@ Compressed accounts and addresses are created via CPI to the Light System Progra * The account hash is not persistent and changes with every write to the account. * For Solana PDA like behavior your compressed account needs an address as persistent identifier. -Find [full code examples at the end](/pda/compressed-pdas/guides/how-to-create-compressed-accounts#full-code-example) for Anchor and native Rust. +Find [full code examples at the end](/compressed-pdas/guides/how-to-create-compressed-accounts#full-code-example) for Anchor and native Rust. # Implementation Guide @@ -431,14 +431,14 @@ Find the source code [here](https://github.com/Lightprotocol/program-examples/tr title="Build a client for your program" icon="chevron-right" color="#0066ff" - href="/pda/compressed-pdas/guides/client-guide" + href="/compressed-pdas/guides/client-guide" horizontal /> diff --git a/pda/compressed-pdas/guides/how-to-reinitialize-compressed-accounts.mdx b/compressed-pdas/guides/how-to-reinitialize-compressed-accounts.mdx similarity index 96% rename from pda/compressed-pdas/guides/how-to-reinitialize-compressed-accounts.mdx rename to compressed-pdas/guides/how-to-reinitialize-compressed-accounts.mdx index a5776fda..17e11562 100644 --- a/pda/compressed-pdas/guides/how-to-reinitialize-compressed-accounts.mdx +++ b/compressed-pdas/guides/how-to-reinitialize-compressed-accounts.mdx @@ -19,7 +19,7 @@ An empty compressed account can be reinitialized * to create a new account hash at the same address with new values. -Find [full code examples at the end](/pda/compressed-pdas/guides/how-to-reinitialize-compressed-accounts#full-code-example) for Anchor and native Rust. +Find [full code examples at the end](/compressed-pdas/guides/how-to-reinitialize-compressed-accounts#full-code-example) for Anchor and native Rust. # Implementation Guide @@ -275,14 +275,14 @@ Find the source code [here](https://github.com/Lightprotocol/program-examples/tr title="Build a client for your program" icon="chevron-right" color="#0066ff" - href="/pda/compressed-pdas/guides/client-guide" + href="/compressed-pdas/guides/client-guide" horizontal /> diff --git a/pda/compressed-pdas/guides/how-to-update-compressed-accounts.mdx b/compressed-pdas/guides/how-to-update-compressed-accounts.mdx similarity index 96% rename from pda/compressed-pdas/guides/how-to-update-compressed-accounts.mdx rename to compressed-pdas/guides/how-to-update-compressed-accounts.mdx index 96d8fb87..116a866e 100644 --- a/pda/compressed-pdas/guides/how-to-update-compressed-accounts.mdx +++ b/compressed-pdas/guides/how-to-update-compressed-accounts.mdx @@ -20,7 +20,7 @@ The update of a compressed account follows a UTXO pattern, unlike regular Solana * The existing account hash is nullified to prevent double spending. -Find [full code examples at the end](/pda/compressed-pdas/guides/how-to-update-compressed-accounts#full-code-example) for Anchor and native Rust. +Find [full code examples at the end](/compressed-pdas/guides/how-to-update-compressed-accounts#full-code-example) for Anchor and native Rust. # Implementation Guide @@ -292,14 +292,14 @@ Find the source code [here](https://github.com/Lightprotocol/program-examples/tr title="Build a client for your program" icon="chevron-right" color="#0066ff" - href="/pda/compressed-pdas/guides/client-guide" + href="/compressed-pdas/guides/client-guide" horizontal /> diff --git a/pda/compressed-pdas/nullifier-pda.mdx b/compressed-pdas/nullifier-pda.mdx similarity index 99% rename from pda/compressed-pdas/nullifier-pda.mdx rename to compressed-pdas/nullifier-pda.mdx index c34750a3..05372f6d 100644 --- a/pda/compressed-pdas/nullifier-pda.mdx +++ b/compressed-pdas/nullifier-pda.mdx @@ -1,6 +1,6 @@ --- title: Create Nullifier PDAs -sidebarTitle: Nullifiers +sidebarTitle: Nullifier PDAs description: For some use cases, such as sending payments, you might want to prevent your on chain instruction from being executed more than once. keywords: ["nullifiers on solana", "prevent double spending", "compressed pdas", "rent-free nullifiers"] --- diff --git a/pda/compressed-pdas/overview.mdx b/compressed-pdas/overview.mdx similarity index 91% rename from pda/compressed-pdas/overview.mdx rename to compressed-pdas/overview.mdx index ff4db3ca..845e57c6 100644 --- a/pda/compressed-pdas/overview.mdx +++ b/compressed-pdas/overview.mdx @@ -10,24 +10,22 @@ import CompressedPdasGuidesTable from '/snippets/overview-tables/compressed-pdas import SdkReferenceCompressedPdas from '/snippets/overview-tables/sdk-reference-compressed-pdas.mdx'; import CompressedPdaCost from "/snippets/cost-tables/compressed-pda-cost.mdx"; +## What are Compressed PDAs +Compressed PDAs are compressed accounts with a unique address. +Programs invoke the Light System program to create and update compressed accounts, instead of the System program. +Fully compatible with existing Solana programs, but requires custom logic. -Compressed PDAs are derived using a specific program address and seed, like regular PDAs. -Custom programs invoke the Light System program -to create and update compressed accounts, instead of the System program. -Compressed PDAs are compressed accounts with an address. - - +## Use Cases Compressed PDAs are suited for: - Per-user state (profiles, preferences, credentials) - DePIN node accounts and stake accounts - Nullifiers to prevent an on-chain instruction from -being executed twice (little implementation overhead and useful e.g. for [payments](/pda/compressed-pdas/nullifier-pda) or [ZK programs](zk/overview)) +being executed twice (little implementation overhead and useful e.g. for [payments](/compressed-pdas/nullifier-pda) or [ZK programs](zk/overview)) - App state that is written to and read from infrequently -For DeFi pools, vaults, shared state, pool accounts, or config accounts, use [Light-PDA](/pda/light-pda/overview) with minimal code changes. - +## How it Works @@ -254,6 +252,6 @@ Caused by: title="Build a client for your program." icon="chevron-right" color="#0066ff" - href="/pda/compressed-pdas/guides/client-guide" + href="/compressed-pdas/guides/client-guide" horizontal /> diff --git a/pda/compressed-pdas/program-examples.mdx b/compressed-pdas/program-examples.mdx similarity index 99% rename from pda/compressed-pdas/program-examples.mdx rename to compressed-pdas/program-examples.mdx index e47944f1..7bdf37fc 100644 --- a/pda/compressed-pdas/program-examples.mdx +++ b/compressed-pdas/program-examples.mdx @@ -62,6 +62,6 @@ Full compressed account lifecycle (create, increment, decrement, reset, close): title="Follow our guides to these program examples" icon="chevron-right" color="#0066ff" - href="/pda/compressed-pdas/guides" + href="/compressed-pdas/guides" horizontal /> \ No newline at end of file diff --git a/pda/compressed-pdas/solana-attestation-service.mdx b/compressed-pdas/solana-attestation-service.mdx similarity index 100% rename from pda/compressed-pdas/solana-attestation-service.mdx rename to compressed-pdas/solana-attestation-service.mdx diff --git a/compressed-tokens/combine-instructions.mdx b/compressed-tokens/combine-instructions.mdx new file mode 100644 index 00000000..180eca8d --- /dev/null +++ b/compressed-tokens/combine-instructions.mdx @@ -0,0 +1,198 @@ +--- +title: Combine Instructions in One Transaction +description: Guide to combine multiple instructions in a single transaction. Full code example for interface PDA creation and for first-time compression of existing SPL tokens. +keywords: ["batch token operations solana", "combine transactions solana"] +--- + +import InstallDependencies from '/snippets/setup/install-dependencies-codegroup.mdx'; +import SetupEnvironment from '/snippets/setup/setup-environment-tabs.mdx'; + +The SDK provides instruction-level APIs that return instructions without sending transactions. Combine these instructions to build custom transactions with multiple instructions. + +This guide demonstrates creating an interface PDA and compressing existing SPL tokens in a single transaction. + +# Full Code Example + + + +### Prerequisites + +Make sure you have dependencies and developer environment set up! + + + +**Dependencies** + + + +**Developer Environment** + + + + + + +### Create Interface PDA + Compress + +```typescript create-pool-and-compress.ts highlight={26,71} expandable +// 1. Setup: Create regular SPL token and mint to ATA +// 2. Build instructions for create interface PDA and compress +// 3. Combine instructions in one transaction +// 4. Verify compressed balance + +import { + Keypair, + ComputeBudgetProgram, +} from '@solana/web3.js'; +import { + createRpc, + buildAndSignTx, + sendAndConfirmTx, + selectStateTreeInfo, +} from '@lightprotocol/stateless.js'; +import { CompressedTokenProgram } from '@lightprotocol/compressed-token'; +import { + createMint, + getOrCreateAssociatedTokenAccount, + mintTo, + TOKEN_PROGRAM_ID, +} from '@solana/spl-token'; +import BN from 'bn.js'; + +async function createPoolAndCompress() { + // Step 1: Setup - Create regular SPL token and mint to ATA + const rpc = createRpc(); + const payer = Keypair.generate(); + const airdropSignature = await rpc.requestAirdrop(payer.publicKey, 1000000000); + await rpc.confirmTransaction(airdropSignature); + + // Create regular SPL token mint + const mint = await createMint( + rpc, + payer, + payer.publicKey, + null, + 9, + undefined, + undefined, + TOKEN_PROGRAM_ID + ); + + // Create ATA and mint tokens to it + const ata = await getOrCreateAssociatedTokenAccount( + rpc, + payer, + mint, + payer.publicKey, + undefined, + undefined, + undefined, + TOKEN_PROGRAM_ID + ); + + await mintTo( + rpc, + payer, + mint, + ata.address, + payer, + 1_000_000_000, // 1 token with 9 decimals + undefined, + undefined, + TOKEN_PROGRAM_ID + ); + + console.log("Regular SPL token created:", mint.toBase58()); + console.log("ATA balance:", 1, "token"); + + // Step 2: Build instructions for create interface PDA and compress + const outputStateTreeInfo = selectStateTreeInfo(await rpc.getStateTreeInfos()); + + // Derive interface PDA + const tokenPoolPda = CompressedTokenProgram.deriveTokenPoolPda(mint); + + // Create interface PDA instruction + const createTokenPoolIx = await CompressedTokenProgram.createTokenPool({ + feePayer: payer.publicKey, + mint, + tokenProgram: TOKEN_PROGRAM_ID, + }); + + // Manually construct TokenPoolInfo for first-time compression + const tokenPoolInfo = { + mint: mint, + tokenPoolPda: tokenPoolPda, + tokenProgram: TOKEN_PROGRAM_ID, + isInitialized: true, // Set to true even though pool will be created in this tx + balance: new BN(0), + poolIndex: 0, + bump: 0, // Placeholder value + }; + + // Create compress instruction + const compressIx = await CompressedTokenProgram.compress({ + outputStateTreeInfo, + tokenPoolInfo, + payer: payer.publicKey, + owner: payer.publicKey, + source: ata.address, + toAddress: payer.publicKey, + amount: new BN(1_000_000_000), + mint, + }); + + // Step 3: Combine instructions in one transaction + const { blockhash } = await rpc.getLatestBlockhash(); + + const allInstructions = [ + ComputeBudgetProgram.setComputeUnitLimit({ units: 1_000_000 }), + createTokenPoolIx, + compressIx, + ]; + + const tx = buildAndSignTx( + allInstructions, + payer, + blockhash, + [] + ); + + const txId = await sendAndConfirmTx(rpc, tx); + + console.log("Interface PDA created and tokens compressed"); + console.log("Transaction:", txId); + + // Step 4: Verify compressed balance + const compressedAccounts = await rpc.getCompressedTokenAccountsByOwner( + payer.publicKey, + { mint } + ); + + const compressedBalance = compressedAccounts.items.reduce( + (sum, account) => sum.add(account.parsed.amount), + new BN(0) + ); + + console.log("Compressed balance:", compressedBalance.toNumber() / 1_000_000_000, "tokens"); + + return { + transactionSignature: txId, + mint, + compressedBalance: compressedBalance.toNumber(), + }; +} + +createPoolAndCompress().catch(console.error); +``` + + + +# Next Steps + + diff --git a/compressed-tokens/guides.mdx b/compressed-tokens/guides.mdx new file mode 100644 index 00000000..16a44ebd --- /dev/null +++ b/compressed-tokens/guides.mdx @@ -0,0 +1,9 @@ +--- +title: Guides +description: "Overview of guides to compressed token operations and reference table with descriptions. Guides include full code examples, troubleshooting, and advanced configurations." +sidebarTitle: "Overview" +--- + +import GuidesTable from '/snippets/overview-tables/compressed-tokens-guides-table.mdx'; + + diff --git a/compressed-tokens/guides/add-token-pools-to-mint-accounts.mdx b/compressed-tokens/guides/add-token-pools-to-mint-accounts.mdx new file mode 100644 index 00000000..4bc914a0 --- /dev/null +++ b/compressed-tokens/guides/add-token-pools-to-mint-accounts.mdx @@ -0,0 +1,112 @@ +--- +title: Create Interface PDAs for Compression to Existing Mints +description: "Create an interface PDA for an existing SPL mint. Requires only fee_payer with no mint authority constraint." +keywords: ["compressed interface PDAs", "interface PDA on solana"] +--- + +import FullSetup from "/snippets/setup/full-setup.mdx"; +import ActionCode from '/snippets/code-snippets/compressed-token/create-token-pool/action.mdx'; + +Create an interface PDA for compression for an existing SPL mint. `createTokenPool()` requires only `fee_payer` and has no mint authority constraint. + + +The interface PDA itself requires rent, but individual compressed token accounts are rent-free. + + + +```typescript function-create-token-pool.ts +// Creates interface PDA for existing SPL mint +const transactionSignature = await createTokenPool( + rpc, + payer, + mint, +); +``` + + + +**Best Practice:** Each mint supports a maximum of 4 interface PDAs total. During compression/decompression operations, interface PDAs get write-locked. Use `addTokenPools()` to create additional PDAs that increase per-block write-lock capacity. + + +## Get Started + + + +### Create Interface PDA + + + + + + + +# Troubleshooting + + + + +You're trying to access an interface PDA that doesn't exist. + +```typescript +// Create the missing interface PDA +const poolTx = await createTokenPool(rpc, payer, mint); +console.log("Interface PDA created:", poolTx); +``` + + + + +# Advanced Configuration + + + + +Create pools for multiple mints: + +```typescript +const mints = [ + new PublicKey("MINT_1_ADDRESS"), + new PublicKey("MINT_2_ADDRESS"), + new PublicKey("MINT_3_ADDRESS"), +]; + +for (const mint of mints) { + try { + const poolTx = await createTokenPool(rpc, payer, mint); + console.log(`Pool created for ${mint.toBase58()}:`, poolTx); + } catch (error) { + console.log(`Failed for ${mint.toBase58()}:`, error.message); + } +} +``` + + + + + +Create interface PDAs for Token-2022 mints: + +```typescript +import { TOKEN_2022_PROGRAM_ID } from '@solana/spl-token'; + +const poolTx = await createTokenPool( + rpc, + payer, + mint, // Token-2022 mint + undefined, + TOKEN_2022_PROGRAM_ID, +); +``` + + + + +# Next Steps + + diff --git a/compressed-tokens/guides/compress-decompress.mdx b/compressed-tokens/guides/compress-decompress.mdx new file mode 100644 index 00000000..6388187b --- /dev/null +++ b/compressed-tokens/guides/compress-decompress.mdx @@ -0,0 +1,217 @@ +--- +title: Compress and Decompress SPL Tokens +description: "Convert SPL tokens between compressed and regular format with compress() and decompress()." +keywords: ["compress spl tokens", "decompress tokens on solana"] +--- + +import FullSetup from "/snippets/setup/full-setup.mdx"; +import MintPrereq from '/snippets/setup/compressed-tokens-mint-prereq.mdx'; +import CompressActionCode from '/snippets/code-snippets/compressed-token/compress/action.mdx'; +import DecompressActionCode from '/snippets/code-snippets/compressed-token/decompress/action.mdx'; + + +```typescript compress() +// Compress SPL tokens to compressed tokens +const compressionSignature = await compress( + rpc, + payer, + mint, // SPL mint with interface PDA for compression + amount, + payer, // owner of SPL tokens + tokenAccount.address, // source SPL token account (sourceTokenAccount parameter) + recipient, // recipient owner address (toAddress parameter) +); +``` + +```typescript decompress() +// Decompress compressed tokens to SPL tokens +const transactionSignature = await decompress( + rpc, + payer, + mint, // SPL mint with interface PDA for compression + amount, + payer, // owner of compressed tokens + tokenAccount.address, // destination token account (toAddress parameter) +); +``` + + + +**Function Difference and Best Practice:** + +* `compress(amount, sourceTokenAccount, toAddress)` compresses specific amounts from source to a specified recipient. Use for transfers and precise amounts. +* `compressSplTokenAccount(tokenAccount, remainingAmount)` compresses the entire SPL token account balance minus optional remaining amount only to the same owner. Use to migrate complete token accounts with optional partial retention. [Here is how](/compressed-tokens/guides/compress-spl-token-account). + + +## Get Started + + + +### Compress / Decompress Tokens + + + + +Before we can compress or decompresss, we need: + +* An SPL mint with a token pool for compression. This token pool can be created for new SPL mints via [`createMint()`](/compressed-tokens/guides/create-mint-with-token-pool) or added to existing SPL mints via [`createTokenPool()`](/compressed-tokens/guides/add-token-pools-to-mint-accounts). +* For `compress()` SPL tokens in an Associated Token Account, or +* For `decompress()` compressed token accounts with sufficient balance. + + + + + + + + + + + + + + +# Troubleshooting + + + + +Check your balances before operations: + +```typescript +// For decompression - check compressed balance +const compressedAccounts = await rpc.getCompressedTokenAccountsByOwner( + owner.publicKey, + { mint } +); +const compressedBalance = compressedAccounts.items.reduce( + (sum, account) => sum.add(account.parsed.amount), + new BN(0) +); + +// For compression - check SPL token balance +const tokenBalance = await rpc.getTokenAccountBalance(tokenAccount); +const splBalance = new BN(tokenBalance.value.amount); + +console.log("Can decompress up to:", compressedBalance.toString()); +console.log("Can compress up to:", splBalance.toString()); +``` + + + + + +Ensure the signer owns the tokens being decompressed/compressed: + +```typescript +// The owner parameter must be the actual owner +const decompressTx = await decompress( + rpc, + payer, // can be different (pays fees) + mint, + amount, + actualOwner, // must own compressed tokens + destinationAta, +); + +const compressTx = await compress( + rpc, + payer, // can be different (pays fees) + mint, + amount, + actualOwner, // must own SPL tokens + sourceAta, + recipient, +); +``` + + + + +# Advanced Configuration + + + + +Compress tokens directly to someone else: + +```typescript +const recipientWallet = new PublicKey("RECIPIENT_WALLET_ADDRESS"); + +// Compress your SPL tokens to recipient +const compressTx = await compress( + rpc, + payer, + mint, + amount, + tokenOwner, // current owner signs + tokenAccount, // your token account + recipientWallet, // recipient gets compressed tokens +); +``` + + + + + +Compress multiple token accounts: + +```typescript +// Compress to multiple recipients at once +const recipients = [recipient1.publicKey, recipient2.publicKey, recipient3.publicKey]; +const amounts = [1_000_000_000, 2_000_000_000, 500_000_000]; // Different amounts + +const batchCompressTx = await compress( + rpc, + payer, + mint, + amounts, // Array of amounts + owner, + tokenAccount, + recipients, // Array of recipients +); + +console.log("Batch compression completed:", batchCompressTx); +``` + + + + + +Decompress tokens using delegate authority: + +```typescript +import { decompressDelegated } from '@lightprotocol/compressed-token'; +import { getAssociatedTokenAddress, TOKEN_PROGRAM_ID } from '@solana/spl-token'; + +// Get ATA for decompressed tokens +const ataAddress = await getAssociatedTokenAddress( + mint, + recipient, + false, + TOKEN_PROGRAM_ID +); + +// Delegate decompresses tokens +await decompressDelegated( + rpc, + payer, + mint, + amount, + delegate, // Signer - owner of compressed tokens + ataAddress, // Uncompressed token account (ATA) +); +``` + + + + +# Next Steps + + diff --git a/compressed-tokens/guides/compress-spl-token-account.mdx b/compressed-tokens/guides/compress-spl-token-account.mdx new file mode 100644 index 00000000..1a43ba27 --- /dev/null +++ b/compressed-tokens/guides/compress-spl-token-account.mdx @@ -0,0 +1,189 @@ +--- +title: Compress Complete SPL Token Accounts +description: "Compress the entire balance of an SPL token account to reclaim rent. Optionally leave some tokens in SPL format." +keywords: ["compress spl token accounts", "migrate spl to compressed"] +--- + +import FullSetup from "/snippets/setup/full-setup.mdx"; +import MintPrereq from '/snippets/setup/compressed-tokens-mint-prereq.mdx'; +import ActionCode from '/snippets/code-snippets/compressed-token/compress-spl-account/action.mdx'; + + +```typescript compressSplTokenAccount() +// Compress entire SPL token account balance +const transactionSignature = await compressSplTokenAccount( + rpc, + payer, + mint, // SPL mint with interface PDA for compression + owner, + tokenAccount, // SPL token account to compress +); +``` + +```typescript partialCompression() +// Compress account while keeping some tokens in SPL format +const transactionSignature = await compressSplTokenAccount( + rpc, + payer, + mint, // SPL mint with interface PDA for compression + owner, + tokenAccount, // SPL token account to compress + remainingAmount, // amount to keep in SPL format +); +``` + + + +After compression, empty token accounts can now be closed to reclaim rent with [`closeAccount()`](https://solana.com/developers/cookbook/tokens/close-token-accounts). + + + +**Function Difference and Best Practice:** + +* `compressSplTokenAccount(tokenAccount, remainingAmount)` compresses the entire SPL token account balance minus optional remaining amount only to the same owner. Use to migrate complete token accounts with optional partial retention. +* `compress(amount, sourceTokenAccount, toAddress)` compresses specific amounts from source to a specified recipient. Use for transfers and precise amounts. [Here is how](/compressed-tokens/guides/compress-decompress). + + +## Get Started + + + +### Compress SPL Token Accounts + + + + + + + + + + +# Troubleshooting + + + + +The token account doesn't have enough tokens for the operation. + +```typescript +// Check token account balance before compression +const balance = await rpc.getTokenAccountBalance(tokenAccount); + +if (Number(balance.value.amount) === 0) { + console.log("Token account is empty"); + return; +} + +console.log("Available balance:", Number(balance.value.amount)); + +// Proceed with compression +const compressTx = await compressSplTokenAccount( + rpc, + payer, + mint, + owner, + tokenAccount, +); +``` + + + + + +The `remainingAmount` parameter exceeds the current account balance. + +```typescript +const balance = await rpc.getTokenAccountBalance(tokenAccount); +const availableAmount = Number(balance.value.amount); +const remainingAmount = bn(500_000_000); // 0.5 tokens + +if (remainingAmount.gt(bn(availableAmount))) { + console.log(`Cannot leave ${remainingAmount.toString()} tokens`); + console.log(`Available balance: ${availableAmount}`); + throw new Error("Remaining amount exceeds balance"); +} + +// Use valid remaining amount +const compressTx = await compressSplTokenAccount( + rpc, + payer, + mint, + owner, + tokenAccount, + remainingAmount, // must be <= balance +); +``` + + + + +# Advanced Configuration + + + + +Compress most tokens while leaving some in SPL format: + +```typescript +import { bn } from '@lightprotocol/stateless.js'; + +// Leave 100 tokens (0.1 with 9 decimals) in SPL account +const remainingAmount = bn(100_000_000); + +const compressTx = await compressSplTokenAccount( + rpc, + payer, + mint, + owner, + tokenAccount, + remainingAmount, // amount to keep in SPL format +); + +// Account will retain remainingAmount tokens +``` + + + + + +Compress several token accounts for the same mint: + +```typescript +const tokenAccounts = [ + { account: new PublicKey("ACCOUNT_1"), owner: owner1 }, + { account: new PublicKey("ACCOUNT_2"), owner: owner2 }, + { account: new PublicKey("ACCOUNT_3"), owner: owner3 }, +]; + +// Compress each account +for (const { account, owner } of tokenAccounts) { + console.log(`Compressing account: ${account.toBase58()}`); + + try { + const compressTx = await compressSplTokenAccount( + rpc, + payer, + mint, + owner, + account, + ); + console.log(`Compressed: ${compressTx}`); + } catch (error) { + console.log(`Failed: ${error.message}`); + } +} +``` + + + + +# Next Steps + + diff --git a/compressed-tokens/guides/create-compressed-token-accounts.mdx b/compressed-tokens/guides/create-compressed-token-accounts.mdx new file mode 100644 index 00000000..28eecd3f --- /dev/null +++ b/compressed-tokens/guides/create-compressed-token-accounts.mdx @@ -0,0 +1,20 @@ +--- +title: Create Compressed Token Accounts +description: Short guide to compressed token account creation with ZK Compression on Solana and difference to regular token accounts. +keywords: ["create compressed token account", "rent free token accounts on solana"] +--- + +Compressed token accounts store ownership information for compressed tokens like regular token accounts with two core differences. Compressed Tokens + +* do not require an Associated Token Accounts (ATAs), and +* do not require a rent-exempt balance. + +Compressed token accounts are created in the following scenarios: + +1. `mintTo()` creates compressed token accounts for recipients. + +How to Mint Compressed Tokens + +2. `transfer()` consumes existing accounts of the sender as input, and creates new compressed token accounts with updated balances as output for the sender and recipient(s). + +Transfer Compressed Tokens \ No newline at end of file diff --git a/compressed-tokens/guides/create-mint-with-token-pool.mdx b/compressed-tokens/guides/create-mint-with-token-pool.mdx new file mode 100644 index 00000000..db3ba7ab --- /dev/null +++ b/compressed-tokens/guides/create-mint-with-token-pool.mdx @@ -0,0 +1,99 @@ +--- +title: Create a Mint Account with Interface PDA for Compression +description: "Create an SPL token mint with an interface PDA for compression. The interface PDA locks tokens while compressed and releases them when decompressed." +keywords: ["register mint for compression", "compressed mint account"] +--- + +import FullSetup from "/snippets/setup/full-setup.mdx"; +import ActionCode from '/snippets/code-snippets/compressed-token/create-mint/action.mdx'; +import InstructionCode from '/snippets/code-snippets/compressed-token/create-mint/instruction.mdx'; + +The mint account itself requires rent (like regular SPL mints), but individual compressed token accounts are rent-free. +Create an interface PDA for an existing SPL mint with [`createTokenPool()`](/compressed-tokens/guides/add-token-pools-to-mint-accounts) or use `createMint()` to create a new one from scratch. + + +```typescript createMint() +// Create SPL mint with interface PDA for compression +const { mint, transactionSignature } = await createMint( + rpc, + payer, + mintAuthority.publicKey, + decimals, +); +``` + + + +**Best Practice:** Each mint supports a maximum of 4 interface PDAs total. During compression/decompression, interface PDAs get write-locked. Use `addTokenPools()` to create additional PDAs that increase per-block write-lock capacity. + + +## Get Started + + + +### Create a Mint Account with Interface PDA for Compression + + + + + + + + + + + + + + +# Advanced Configuration + + + + +Customize who can mint new compressed tokens. + +```typescript +const mintAuthority = Keypair.generate(); + +const { mint, transactionSignature } = await createMint( + rpc, + payer, + mintAuthority.publicKey, + 9, +); +``` + + + + + +Customize who can freeze/thaw compressed token accounts. + +```typescript +const freezeAuthority = Keypair.generate(); + +const { mint, transactionSignature } = await createMint( + rpc, + payer, + payer.publicKey, // mint authority + 9, // decimals + Keypair.generate(), // mint keypair + undefined, // confirm options + undefined, // token program ID + freezeAuthority.publicKey, // freeze authority +); +``` + + + + +# Next Steps + + diff --git a/compressed-tokens/guides/delegate.mdx b/compressed-tokens/guides/delegate.mdx new file mode 100644 index 00000000..1a507f08 --- /dev/null +++ b/compressed-tokens/guides/delegate.mdx @@ -0,0 +1,166 @@ +--- +title: Approve and Revoke Delegate Authority +description: "Grant and remove delegate spending authority for compressed tokens with approve() and revoke(). Only the token owner can perform these operations." +keywords: ["delegate authority on solana", "token delegation compressed"] +--- + +import FullSetup from "/snippets/setup/full-setup.mdx"; +import ApproveActionCode from '/snippets/code-snippets/compressed-token/approve/action.mdx'; +import RevokeActionCode from '/snippets/code-snippets/compressed-token/revoke/action.mdx'; + +The `approve()` and `revoke()` functions grant and remove delegate spending authority for compressed tokens. Only the token owner can perform these instructions. + + +```typescript approve() +// Approve delegate for spending up to the specified amount +const approveSignature = await approve( + rpc, + payer, + mint, // SPL mint with interface PDA for compression + amount, + owner, + delegate.publicKey, // delegate account +); +``` + +```typescript revoke() +// Get delegated accounts for revocation +const delegatedAccounts = await rpc.getCompressedTokenAccountsByDelegate( + delegate.publicKey, + { mint } +); + +// Revoke delegate authority +const revokeSignature = await revoke( + rpc, + payer, + delegatedAccounts.items, // delegated compressed token accounts + owner, +); +``` + + +## Get Started + + + +### Approve / Revoke Delegates + + + + + + + + + + + + + +Before we approve or revoke delegates, we need: + +* compressed token accounts to delegate or revoke delegation from, and +* an SPL mint with a token pool for compression. This token pool can be created for new SPL mints via [`createMint()`](/compressed-tokens/guides/create-mint-with-token-pool) or added to existing SPL mints via [`createTokenPool()`](/compressed-tokens/guides/add-token-pools-to-mint-accounts). + + + + + +# Troubleshooting + + + + +Attempting to revoke non-delegated accounts. + +```typescript +/// Verify accounts are delegated before revocation. +const delegateAccounts = await rpc.getCompressedTokenAccountsByDelegate( + delegate.publicKey, + { mint } +); + +if (delegateAccounts.items.length === 0) { + console.log("No delegated accounts to revoke"); + return; +} +``` + + + + +# Advanced Configuration + + + + +```typescript +const delegates = [ + Keypair.generate().publicKey, + Keypair.generate().publicKey, +]; + +const amounts = [ + 200_000_000, // 0.2 tokens to first delegate + 300_000_000, // 0.3 tokens to second delegate +]; + +// Approve each delegate +for (let i = 0; i < delegates.length; i++) { + const approveTx = await approve( + rpc, + payer, + mint, + amounts[i], + tokenOwner, + delegates[i], + ); + + console.log(`Delegate ${i + 1} approved:`, approveTx); +} +``` + + + + + +```typescript +const delegates = [ + new PublicKey("DELEGATE_1_ADDRESS"), + new PublicKey("DELEGATE_2_ADDRESS"), +]; + +// Revoke each delegate +for (const delegate of delegates) { + // Get delegated accounts for this delegate + const delegateAccounts = await rpc.getCompressedTokenAccountsByDelegate( + delegate, + { mint } + ); + + if (delegateAccounts.items.length > 0) { + const revokeTx = await revoke( + rpc, + payer, + delegateAccounts.items, + tokenOwner, + ); + + console.log(`Delegate ${delegate.toBase58()} revoked:`, revokeTx); + } +} +``` + + + + +# Next Steps + + diff --git a/compressed-tokens/guides/merge-compressed-token-accounts.mdx b/compressed-tokens/guides/merge-compressed-token-accounts.mdx new file mode 100644 index 00000000..bd1346ae --- /dev/null +++ b/compressed-tokens/guides/merge-compressed-token-accounts.mdx @@ -0,0 +1,145 @@ +--- +title: Merge Compressed Token Accounts +description: "Consolidate multiple compressed token accounts of the same mint into a single account to reduce fragmentation." +keywords: ["merge compressed token accounts", "consolidate token accounts"] +--- + +import FullSetup from "/snippets/setup/full-setup.mdx"; +import ActionCode from '/snippets/code-snippets/compressed-token/merge-token-accounts/action.mdx'; + +The `mergeTokenAccounts()` function consolidates multiple compressed accounts of the same mint into a single compressed account. + +The function + +1. consumes multiple compressed token accounts (up to 8 accounts), and +2. creates a single output compressed token account with combined balance for the owner. + + +State trees where compressed account's are stored, are append only. `mergeTokenAccounts()` reduces account fragmentation to simplify balance calculations from `getCompressedTokenAccountsByOwner`. + + + +```typescript function-merge-accounts.ts +// Combines multiple compressed token accounts into single compressed account +const transactionSignature = await mergeTokenAccounts( + rpc, + payer, + mint, // SPL mint with interface PDA for compression + owner, +); +``` + + +## Get Started + + + +### Merge Compressed Accounts + + + + + + +Before we merge compressed accounts, we need + +* Multiple compressed token accounts of the same mint owned by the same wallet, and +* an SPL mint with a token pool for compression. This token pool can be created for new SPL mints via [`createMint()`](/compressed-tokens/guides/create-mint-with-token-pool) or added to existing SPL mints via [`createTokenPool()`](/compressed-tokens/guides/add-token-pools-to-mint-accounts). + + + + + +# Troubleshooting + + + + +The owner has no compressed token accounts for the specified mint: + +```typescript +// Check if accounts exist before merging +const accounts = await rpc.getCompressedTokenAccountsByOwner( + owner.publicKey, + { mint } +); + +if (accounts.items.length === 0) { + console.log("No compressed token accounts found for this mint"); + console.log("Mint address:", mint.toBase58()); + console.log("Owner address:", owner.publicKey.toBase58()); + return; +} + +console.log(`Found ${accounts.items.length} accounts to merge`); +``` + + + + +# Advanced Configuration + + + + +```typescript +// Get account count +const accounts = await rpc.getCompressedTokenAccountsByOwner( + owner.publicKey, + { mint } +); + +// Only merge if more than 2 accounts +if (accounts.items.length > 2) { + console.log(`Merging ${accounts.items.length} accounts...`); + + const mergeTx = await mergeTokenAccounts( + rpc, + payer, + mint, + tokenOwner, + ); + + console.log("Merge completed:", mergeTx); +} else { + console.log("Merge not needed - optimal account structure"); +} +``` + + + + + +```typescript +const mints = [ + new PublicKey("MINT_1_ADDRESS"), + new PublicKey("MINT_2_ADDRESS"), +]; + +// Merge accounts for each mint +for (const mint of mints) { + console.log(`Merging accounts for mint: ${mint.toBase58()}`); + + const mergeTx = await mergeTokenAccounts( + rpc, + payer, + mint, + tokenOwner, + ); + + console.log(`Merge completed: ${mergeTx}`); +} +``` + + + + +# Next Steps + + diff --git a/compressed-tokens/guides/mint-compressed-tokens.mdx b/compressed-tokens/guides/mint-compressed-tokens.mdx new file mode 100644 index 00000000..cdef2a46 --- /dev/null +++ b/compressed-tokens/guides/mint-compressed-tokens.mdx @@ -0,0 +1,155 @@ +--- +title: Mint Compressed Tokens +description: "Mint tokens to compressed token accounts for recipients and increases a mint's token supply. Only the mint authority can perform this operation. +" +keywords: ["mint compressed tokens on solana", "scalable token minting"] +--- + +import FullSetup from "/snippets/setup/full-setup.mdx"; +import MintPrereq from '/snippets/setup/compressed-tokens-mint-prereq.mdx'; +import ActionCode from '/snippets/code-snippets/compressed-token/mint-to/action.mdx'; +import InstructionCode from '/snippets/code-snippets/compressed-token/mint-to/instruction.mdx'; + +```typescript +// Mint compressed tokens - mints SPL tokens to pool, creates compressed token accounts +const transactionSignature = await mintTo( + rpc, + payer, + mint, // SPL mint with interface PDA for compression + recipient, // recipient address (toPubkey parameter) + payer, // mint authority + amount, +); +``` + +## Get Started + + + +### Mint Compressed Tokens + + + + + + + + + + + + + + + + +# Troubleshooting + + + + + +```typescript +// Error message: "TokenPool not found. Please create a compressed token +// pool for mint: [ADDRESS] via createTokenPool(). +``` + +The mint does not have an interface PDA for compression. Ensure you created the mint using `createMint`. + +```typescript +// Create mint with interface PDA for compression +import { createMint } from '@lightprotocol/compressed-token'; +const { mint } = await createMint(rpc, payer, payer.publicKey, 9); +``` + + + + + +The interface PDA info doesn't correspond to the mint address. Ensure you're fetching the correct PDA: + +```typescript +// Get the correct interface PDA for your mint +const tokenPoolInfo = await getTokenPoolInfos(rpc, mint); +``` + + + + + +When minting to multiple recipients, ensure arrays are the same size. + +```typescript +// Wrong: Mismatched array lengths +const recipients = [addr1, addr2, addr3]; +const amounts = [100, 200]; // Only 2 amounts for 3 recipients + +// Correct: Same length arrays +const recipients = [addr1, addr2, addr3]; +const amounts = [100, 200, 300]; // 3 amounts for 3 recipients +``` + + + + +# Advanced Configuration + + + + +```typescript +// Mint different amounts to multiple recipients +const recipients = [ + Keypair.generate().publicKey, + Keypair.generate().publicKey, + Keypair.generate().publicKey, +]; + +const amounts = [ + 1_000_000_000, // 1 token + 2_000_000_000, // 2 tokens + 500_000_000, // 0.5 tokens +]; + +const transactionSignature = await mintTo( + rpc, + payer, + mint, // SPL mint with interface PDA for compression + recipients, // array of recipients (toPubkey parameter) + payer, // mint authority + amounts, // array of amounts (amount parameter) +); +``` + + + + + +Mint tokens using a custom mint authority with `approveAndMintTo()`: + +```typescript +import { approveAndMintTo } from '@lightprotocol/compressed-token'; + +// Mint tokens with a separate mint authority +const transactionSignature = await approveAndMintTo( + rpc, + payer, + mint, // SPL mint with interface PDA for compression + recipient.publicKey, // recipient of minted tokens (toPubkey parameter) + mintAuthority, // mint authority + mintAmount, +); +``` + + + + +# Next Steps + + \ No newline at end of file diff --git a/compressed-tokens/guides/transfer-compressed-tokens.mdx b/compressed-tokens/guides/transfer-compressed-tokens.mdx new file mode 100644 index 00000000..6c047b12 --- /dev/null +++ b/compressed-tokens/guides/transfer-compressed-tokens.mdx @@ -0,0 +1,190 @@ +--- +title: Transfer Compressed Tokens +description: "Transfer compressed tokens between accounts. Transfers consume input accounts and create new output accounts with updated balances." +keywords: ["transfer compressed tokens", "token transfer on solana"] +--- + +import FullSetup from "/snippets/setup/full-setup.mdx"; +import MintPrereq from '/snippets/setup/compressed-tokens-mint-prereq.mdx'; +import ActionCode from '/snippets/code-snippets/compressed-token/transfer/action.mdx'; + +The `transfer()` function moves compressed tokens between accounts. +* SPL token transfers that update the existing account +* Compressed token transfers consume input accounts from the sender and create new output accounts for sender and recipient with updated balances. + +SPL token accounts can be compressed in the same transaction with `compress_or_decompress_amount`, if needed. + + + +```typescript function-transfer-compressed-tokens.ts +// Transfer compressed tokens +const transactionSignature = await transfer( + rpc, + payer, + mint, // SPL mint with interface PDA for compression + amount, + payer, + recipient, // destination address (toAddress parameter) +) +``` + +## Get Started + + + +### Transfer Compressed Tokens + + + + + + + + + +# Troubleshooting + + + + +The sender doesn't have enough compressed tokens for the requested transfer amount. + +```typescript +// Check current balance first +const tokenAccounts = await rpc.getCompressedTokenAccountsByOwner( + owner.publicKey, + { mint } +); + +if (tokenAccounts.items.length === 0) { + throw new Error("No compressed token accounts found"); +} + +// Calculate total balance across all accounts +const totalBalance = tokenAccounts.items.reduce( + (sum, account) => sum.add(account.parsed.amount), + new BN(0) +); + +console.log("Available balance:", totalBalance.toString()); + +// Ensure transfer amount doesn't exceed balance +if (new BN(transferAmount).gt(totalBalance)) { + throw new Error(`Transfer amount ${transferAmount} exceeds balance ${totalBalance.toString()}`); +} +``` + + + + + +The transfer requires more than 4 compressed accounts, which exceeds the transaction limit. + +```typescript +// Error message: "Account limit exceeded: max X (4 accounts) per transaction. +// Total balance: Y (Z accounts). Consider multiple transfers to spend full balance." + +// Split into multiple smaller transfers +const maxTransferPerTx = 1_000_000_000; // Adjust based on your account sizes + +if (transferAmount > maxTransferPerTx) { + console.log("Large transfer detected, splitting into multiple transactions..."); + + let remainingAmount = transferAmount; + while (remainingAmount > 0) { + const currentTransfer = Math.min(remainingAmount, maxTransferPerTx); + + await transfer( + rpc, + payer, + mint, + currentTransfer, + owner, + recipient + ); + + remainingAmount -= currentTransfer; + console.log(`Transferred ${currentTransfer}, remaining: ${remainingAmount}`); + } +} +``` + + + + +# Advanced Configuration + + + + +Transfer to multiple recipients in separate transactions: + +```typescript +const recipients = [ + Keypair.generate().publicKey, + Keypair.generate().publicKey, + Keypair.generate().publicKey, +]; + +const amounts = [ + 100_000_000, // 0.1 tokens + 200_000_000, // 0.2 tokens + 150_000_000, // 0.15 tokens +]; + +for (let i = 0; i < recipients.length; i++) { + const transactionSignature = await transfer( + rpc, + payer, + mint, + amounts[i], + owner, + recipients[i], + ); + + console.log(`Transfer ${i + 1} completed:`, transactionSignature); +} +``` + + + + + +Transfer tokens using delegate authority: + +```typescript +import { approve, transferDelegated } from '@lightprotocol/compressed-token'; + +// 1. Owner approves delegate +await approve( + rpc, + payer, + mint, + amount, + owner, // Signer + delegate.publicKey, // PublicKey +); + +// 2. Delegate transfers tokens +await transferDelegated( + rpc, + payer, + mint, + transferAmount, + delegate, // Signer - named "owner" in SDK + recipient, +); +``` + + + + +# Next Steps + + diff --git a/compressed-tokens/overview.mdx b/compressed-tokens/overview.mdx new file mode 100644 index 00000000..0d69269a --- /dev/null +++ b/compressed-tokens/overview.mdx @@ -0,0 +1,86 @@ +--- +title: Overview +description: "Overview to compressed tokens and guides with full code examples. Use for distributing tokens (eg rewards, airdrops) or creating associated token accounts for users." +keywords: ["compressed tokens on solana", "scalable token distribution on solana", "infrastructure for token distribution", "airdrop infrastructure on solana", "launchpad infrastructure on solana"] +--- + +import GuidesTable from "/snippets/overview-tables/compressed-tokens-guides-table.mdx"; +import AdvancedGuidesTable from "/snippets/overview-tables/compressed-tokens-advanced-guides-table.mdx"; +import SetupEnvironment from "/snippets/setup/setup-environment-tabs.mdx"; +import InstallDependencies from "/snippets/setup/install-dependencies-codegroup.mdx"; +import { TokenAccountCompressedVsSpl } from "/snippets/jsx/token-account-compressed-vs-spl.jsx"; + + + **Compressed Tokens are supported by leading Solana wallets such as Phantom and Backpack.** + + +| Creation | Solana | Compressed | +| :---------------- | :------------------ | :----------------- | +| **Token Account** | ~2,000,000 lamports | **5,000** lamports | + +1. Compressed token accounts store token balance, owner, and other information for SPL and Token 2022 mints. +2. Compressed token accounts are rent-free. +3. Any SPL or Token 2022 token can be compressed and decompressed at will. + +## Recommended Usage of Compressed Tokens + + + Distribute tokens without paying upfront rent per recipient. + + + + + + Compress existing SPL-token accounts to save rent costs for your users. + + + + +# Get Started + + + + + +### Install dependencies + + + + + + +### Set up your developer environment + + + + + + + + + + + + + ### Basic Guides + + + + + ### Advanced Guides + + + + diff --git a/compressed-tokens/privy.mdx b/compressed-tokens/privy.mdx new file mode 100644 index 00000000..0c1ef842 --- /dev/null +++ b/compressed-tokens/privy.mdx @@ -0,0 +1,170 @@ +--- +title: "Rent-Free SPL Accounts with Privy" +sidebarTitle: "Sign with Privy" +description: "Integrate compressed tokens with Privy embedded wallets for rent-free SPL token accounts and transfers." +keywords: ["privy solana", "privy compressed tokens", "embedded wallet compression", "rent-free tokens privy"] +--- +import ToolkitsSetup from "/snippets/setup/toolkits-setup.mdx"; +import TransferNodejs from "/snippets/code-snippets/privy/transfer/nodejs.mdx"; +import CompressNodejs from "/snippets/code-snippets/privy/compress/nodejs.mdx"; +import DecompressNodejs from "/snippets/code-snippets/privy/decompress/nodejs.mdx"; +import BalancesNodejs from "/snippets/code-snippets/privy/balances/nodejs.mdx"; +import TransactionHistoryNodejs from "/snippets/code-snippets/privy/transaction-history/nodejs.mdx"; +import ActionCode from '/snippets/code-snippets/compressed-token/create-mint/action.mdx'; + +| Creation Cost | SPL Token Account | Compressed Token | +| :------------ | :---------------- | :--------------- | +| **Per account** | ~2,000,000 lamports | ~**5,000** lamports | + +Privy handles user authentication and wallet management. You build transactions with tokens (SOL, SPL or compressed) and Privy signs them client-side: + +1. Authenticate with Privy +2. Build unsigned transaction +4. Sign transaction using Privy's wallet provider +5. Send signed transaction to RPC + +## What you will implement + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SPLCompressed
**Get Balance**getAccount()getCompressedTokenAccountsByOwner()
**Transfer**transferChecked()transfer()
**Compress**N/Acompress()
**Decompress**N/Adecompress()
**Transaction History**getSignaturesForAddress()getCompressionSignaturesForOwner()
+ + + +### Prerequisites + + + +Connect to an RPC endpoint that supports ZK Compression (Helius, Triton) +```typescript +import { createRpc } from "@lightprotocol/stateless.js"; + +import { + transfer, + compress, + decompress, + selectMinCompressedTokenAccountsForTransfer, +} from "@lightprotocol/compressed-token"; + +const rpc = createRpc(RPC_ENDPOINT); +``` + + + + + +Before we can compress or decompresss, we need: + +* An SPL mint with an interface PDA for compression. This interface PDA can be created for new SPL mints via [`createMint()`](/compressed-tokens/guides/create-mint-with-token-pool) or added to existing SPL mints via [`createTokenPool()`](/compressed-tokens/guides/add-token-pools-to-mint-accounts). +* For `compress()` SPL tokens in an Associated Token Account, or +* For `decompress()` compressed token accounts with sufficient balance. + + + + + + + +## Full Code Examples + + +Find a complete example on Github: [privy/nodejs-privy-compressed](https://github.com/Lightprotocol/examples-zk-compression/tree/main/privy). + + + + + +Send compressed tokens to another recipient, similar to SPL token transfers: + +1. Fetch compressed token accounts with `getCompressedTokenAccountsByOwner` +2. Select sender accounts with `selectMinCompressedTokenAccountsForTransfer` +3. Fetch a validity proof from your RPC provider to prove the account's state correctness +4. Build the transfer instruction and transaction +5. Sign with Privy and send transaction + + + + + + + + + + + +Convert SPL to compressed tokens and send to a recipient in one instruction. + + + + + + + + + + + +Convert compressed tokens back to SPL tokens. + + + + + + + + + + + + +## Get balances + +Fetch SPL and compressed token balances. + + + + + + + +## Get transaction history + +Fetch compressed token transaction history for an owner, with optional detailed compression information. + + + + + + diff --git a/compressed-tokens/token-2022.mdx b/compressed-tokens/token-2022.mdx new file mode 100644 index 00000000..fbfc28f7 --- /dev/null +++ b/compressed-tokens/token-2022.mdx @@ -0,0 +1,277 @@ +--- +title: Use Token-2022 with Compression +description: Complete guide to mint, compress and transfer tokens with Token-2022 Metadata with ZK Compression. +keywords: ["token 2022 on solana", "token extensions on solana", "token 2022 compression"] +--- + +import InstallDependencies from '/snippets/setup/install-dependencies-codegroup.mdx'; +import SetupEnvironment from '/snippets/setup/setup-environment-tabs.mdx'; + +# What you will do + +With this guide you will mint, compress, and transfer tokens with Token-2022 Metadata. + +# Overview Token 2022 Extensions + +Token 2022 Extensions are optional features that can be added to Token 2022 mints on Solana to enable additional functionality. + +ZK Compression supports compressing the following mint-extensions: + +* MetadataPointer +* TokenMetadata +* InterestBearingConfig +* GroupPointer +* GroupMemberPointer +* TokenGroup +* TokenGroupMember + +All other extensions are not yet supported. + + +If you require support for other mint-extensions, [let us know](https://t.me/swen_light)! + + +# Get started + + + + + +You need the following SDK versions: + +* `@lightprotocol/stateless.js` ≥ 0.21.0 +* `@lightprotocol/compressed-token` ≥ 0.21.0 +* `@solana/web3.js` ≥ 1.95.3 + + +Make sure you have dependencies and developer environment set up! + + + +**Dependencies** + + + +**Developer Environment** + + + + + + +Run `compress-t22.ts`. + +```typescript compress-t22.ts expandable +// Token-2022 with ZK Compression - Local +// 1. Load wallet and connect to local validator +// 2. Create Token-2022 mint with metadata extension and register for compression via createTokenPool() +// 3. Mint SPL tokens to ATA, compress via compress(), and transfer compressed tokens via transfer() +// 4. Verify balances via getTokenAccountBalance and getCompressedTokenAccountsByOwner + +import { confirmTx, createRpc } from "@lightprotocol/stateless.js"; +import { + compress, + createTokenPool, + transfer, +} from "@lightprotocol/compressed-token"; +import { + getOrCreateAssociatedTokenAccount, + mintTo as mintToSpl, + TOKEN_2022_PROGRAM_ID, + createInitializeMetadataPointerInstruction, + createInitializeMintInstruction, + ExtensionType, + getMintLen, + LENGTH_SIZE, + TYPE_SIZE, +} from "@solana/spl-token"; +import { + Keypair, + sendAndConfirmTransaction, + SystemProgram, + Transaction, +} from "@solana/web3.js"; +import { + createInitializeInstruction, + pack, + TokenMetadata, +} from "@solana/spl-token-metadata"; + +// Step 1: Setup local connection and load wallet +import * as fs from 'fs'; +import * as os from 'os'; + +const walletPath = `${os.homedir()}/.config/solana/id.json`; +const secretKey = JSON.parse(fs.readFileSync(walletPath, 'utf8')); +const payer = Keypair.fromSecretKey(Buffer.from(secretKey)); +const connection = createRpc(); // defaults to localhost:8899 + +(async () => { + + // Generate mint keypair and define Token-2022 metadata + const mint = Keypair.generate(); + const decimals = 9; + + const metadata: TokenMetadata = { + mint: mint.publicKey, + name: "Local Test Token", + symbol: "LTT", + uri: "https://example.com/token-metadata.json", + additionalMetadata: [["environment", "localnet"], ["test", "true"]], + }; + + // Calculate space requirements for Token-2022 mint with MetadataPointer extension + const mintLen = getMintLen([ExtensionType.MetadataPointer]); + const metadataLen = TYPE_SIZE + LENGTH_SIZE + pack(metadata).length; + + // Check wallet balance + const balance = await connection.getBalance(payer.publicKey); + + // Step 2: Create Token-2022 mint with metadata extension + const mintLamports = await connection.getMinimumBalanceForRentExemption( + mintLen + metadataLen + ); + + const mintTransaction = new Transaction().add( + // Create account for Token-2022 mint + SystemProgram.createAccount({ + fromPubkey: payer.publicKey, + newAccountPubkey: mint.publicKey, + space: mintLen, + lamports: mintLamports, + programId: TOKEN_2022_PROGRAM_ID, + }), + // Initialize MetadataPointer extension + createInitializeMetadataPointerInstruction( + mint.publicKey, + payer.publicKey, + mint.publicKey, + TOKEN_2022_PROGRAM_ID + ), + // Initialize Token-2022 mint account + createInitializeMintInstruction( + mint.publicKey, + decimals, + payer.publicKey, + null, + TOKEN_2022_PROGRAM_ID + ), + // Initialize token metadata + createInitializeInstruction({ + programId: TOKEN_2022_PROGRAM_ID, + mint: mint.publicKey, + metadata: mint.publicKey, + name: metadata.name, + symbol: metadata.symbol, + uri: metadata.uri, + mintAuthority: payer.publicKey, + updateAuthority: payer.publicKey, + }) + ); + + // Send Token-2022 mint creation transaction + const mintCreationTxId = await sendAndConfirmTransaction( + connection, + mintTransaction, + [payer, mint] + ); + console.log(`Token-2022 mint created with address: ${mint.publicKey.toString()}`); + + // Step 3: Call createTokenPool() to initialize omnibus account + // and register Token-2022 mint with Compressed Token Program + // Create PDA that holds SPL tokens for compressed tokens + const registerTxId = await createTokenPool( + connection, + payer, + mint.publicKey, // Token-2022 mint to register with compressed token program + undefined, + TOKEN_2022_PROGRAM_ID + ); + + // Step 4: Create associated token account and mint tokens + const ata = await getOrCreateAssociatedTokenAccount( + connection, + payer, + mint.publicKey, // Token-2022 mint with interface PDA for compression + payer.publicKey, + undefined, + undefined, + undefined, + TOKEN_2022_PROGRAM_ID + ); + + // Mint Token-2022 tokens to ATA + const mintAmount = 400_000_000; // 0.4 tokens + const mintToTxId = await mintToSpl( + connection, + payer, + mint.publicKey, // Token-2022 mint with interface PDA for compression + ata.address, // destination token account + payer.publicKey, // mint authority + mintAmount, // amount to mint + undefined, // multiSigners (not used for single authority) + undefined, + TOKEN_2022_PROGRAM_ID + ); + console.log(`Minted ${mintAmount / 1e9} Token-2022 tokens with metadata extension`); + console.log(`Transaction: ${mintToTxId}`); + + // Step 5: Call compress() to convert Token-2022 tokens to compressed format + // Transfer Token-2022 tokens to omnibus pool and mint compressed tokens + const compressAmount = 300_000_000; // 0.3 tokens + const compressTxId = await compress( + connection, + payer, + mint.publicKey, // Token-2022 mint with interface PDA for compression + compressAmount, // amount to compress + payer, // owner of SPL tokens + ata.address, // Source ATA for compression + payer.publicKey // recipient for compressed tokens + ); + console.log(`\nCompressed ${compressAmount / 1e9} Token-2022 tokens`); + console.log(`Transaction: ${compressTxId}`); + + // Step 6: Transfer compressed Token-2022 tokens + const transferRecipient = Keypair.generate(); // Keypair recipient + const transferAmount = 100_000_000; // 0.1 tokens + const transferTxId = await transfer( + connection, + payer, + mint.publicKey, // Token-2022 mint with interface PDA for compression + transferAmount, + payer, + transferRecipient.publicKey + ); + console.log(`\nTransferred ${transferAmount / 1e9} Compressed Token-2022 tokens`); + console.log(`Transaction: ${transferTxId}`); + console.log(`Recipient: ${transferRecipient.publicKey.toString()}`); + + // Step 7: Verify balances via getTokenAccountBalance and getCompressedTokenAccountsByOwner + const senderCompressedAccounts = await connection.getCompressedTokenAccountsByOwner(payer.publicKey, { mint: mint.publicKey }); + const senderBalance = senderCompressedAccounts.items.reduce((sum, account) => sum + Number(account.parsed.amount), 0); + + const recipientCompressedAccounts = await connection.getCompressedTokenAccountsByOwner(transferRecipient.publicKey, { mint: mint.publicKey }); + const recipientBalance = recipientCompressedAccounts.items.reduce((sum, account) => sum + Number(account.parsed.amount), 0); + + const splBalance = await connection.getTokenAccountBalance(ata.address); + + console.log(`\nSummary Token-2022 balances:`); + console.log(`Sender balance: ${senderBalance / 1e9} compressed tokens / ${splBalance.value.uiAmount} SPL tokens`); + console.log(`Recipient balance: ${recipientBalance / 1e9} compressed tokens`); + +})().catch(console.error); +``` + + + +# Next Steps + + + + diff --git a/token-distribution.mdx b/compressed-tokens/token-distribution.mdx similarity index 99% rename from token-distribution.mdx rename to compressed-tokens/token-distribution.mdx index 67b03e16..c86c9eb3 100644 --- a/token-distribution.mdx +++ b/compressed-tokens/token-distribution.mdx @@ -1,6 +1,6 @@ --- -title: Token Distribution -sidebarTitle: Token Distribution +title: Token Distribution Guide +sidebarTitle: Distribute Tokens description: Complete client and program guides to create an airdrop – with or without code. ZK compression is the most efficient way to distribute SPL tokens. keywords: ["solana airdrop", "merkle distributor", "merkle airdrop", "airdrop infrastructure on solana", "scalable token distribution on solana", "token airdrop for protocols"] --- diff --git a/compressed-tokens/wallet-integration.mdx b/compressed-tokens/wallet-integration.mdx new file mode 100644 index 00000000..ab828b43 --- /dev/null +++ b/compressed-tokens/wallet-integration.mdx @@ -0,0 +1,640 @@ +--- +title: Add Wallet Support for Compressed Tokens +description: Guide to add Compressed Token Support to Your Wallet Application +keywords: ["wallet integration compressed tokens", "wallet infrastructure on solana"] +--- + +import InstallDependencies from '/snippets/setup/install-dependencies-codegroup.mdx'; +import SetupEnvironment from '/snippets/setup/setup-environment-tabs.mdx'; + + +Leading Solana Wallets like Phantom and Backpack already support compressed tokens. + + +# Integration Steps + + + + +### Display Compressed Token Balances + +```javascript +import { Rpc, createRpc } from '@lightprotocol/stateless.js'; +import { PublicKey } from '@solana/web3.js'; + +const connection: Rpc = createRpc(); +const publicKey = new PublicKey('FWwR2s4TwpWN3nkCzVfhuPrpePG8kNzBXAxEbNsaDFNu'); + +(async () => { + const balances = await connection.getCompressedTokenBalancesByOwnerV2(publicKey); + + if (balances.value.items.length === 0) { + console.log("No compressed token balances found"); + return; + } + + for (const item of balances.value.items) { + const balanceValue = typeof item.balance === 'string' + ? parseInt(item.balance, 16) + : item.balance; + + const mintInfo = await connection.getAccountInfo(new PublicKey(item.mint)); + const decimals = mintInfo.data[44]; + const formattedBalance = balanceValue / Math.pow(10, decimals); + + console.log(`Mint: ${item.mint}`); + console.log(`Balance: ${formattedBalance} tokens\n`); + } +})(); +``` + +### Get Transaction History + +```typescript +import { Rpc, createRpc } from '@lightprotocol/stateless.js'; +import { PublicKey } from '@solana/web3.js'; + +const connection: Rpc = createRpc(); +const publicKey = new PublicKey('FWwR2s4TwpWN3nkCzVfhuPrpePG8kNzBXAxEbNsaDFNu'); + +(async () => { + const signatures = await connection.getCompressionSignaturesForTokenOwner(publicKey); + + if (signatures.items.length > 0) { + console.log(`Signatures:`); + signatures.items.forEach((sig, index) => { + console.log(`${index + 1}. ${sig.signature}`); + console.log(` Slot: ${sig.slot}`); + console.log(` Time: ${new Date(sig.blockTime * 1000).toISOString()}`); + }); + } else { + console.log("No transactions found"); + } +})(); +``` + + + +```typescript +import { Rpc, createRpc } from '@lightprotocol/stateless.js'; +import { PublicKey } from '@solana/web3.js'; + +const RPC_ENDPOINT = process.env.RPC_ENDPOINT || 'https://devnet.helius-rpc.com?api-key='; + +const connection: Rpc = createRpc(RPC_ENDPOINT, RPC_ENDPOINT); +const publicKey = new PublicKey('FWwR2s4TwpWN3nkCzVfhuPrpePG8kNzBXAxEbNsaDFNu'); + +(async () => { + try { + const signatures = await connection.getCompressionSignaturesForTokenOwner(publicKey); + + if (signatures.items.length === 0) { + console.log("No transactions found"); + return; + } + + console.log(`Latest Transaction:`); + console.log(`Signature: ${signatures.items[0].signature}`); + console.log(`Slot: ${signatures.items[0].slot}`); + + const txInfo = await connection.getTransactionWithCompressionInfo(signatures.items[0].signature); + + if (!txInfo) { + console.log('Transaction not found or has no compression info'); + return; + } + + if (txInfo.compressionInfo) { + console.log(`\nClosed Accounts: ${txInfo.compressionInfo.closedAccounts.length}`); + console.log(`Opened Accounts: ${txInfo.compressionInfo.openedAccounts.length}`); + } + } catch (error) { + console.error('Error fetching transaction history:', error); + } +})(); +``` + + + +### Send Compressed Tokens + +```typescript expandable +import { + Rpc, + createRpc, + bn, + dedupeSigner, + sendAndConfirmTx, + buildAndSignTx, +} from "@lightprotocol/stateless.js"; +import { + CompressedTokenProgram, + selectMinCompressedTokenAccountsForTransfer, +} from "@lightprotocol/compressed-token"; +import { ComputeBudgetProgram, Keypair, PublicKey } from "@solana/web3.js"; + +const connection: Rpc = createRpc(); +const mint = new PublicKey("MINT_ADDRESS"); +const payer = PAYER_KEYPAIR; +const owner = payer; +const recipient = Keypair.generate(); +const amount = bn(1e8); + +(async () => { + const compressedTokenAccounts = + await connection.getCompressedTokenAccountsByOwner(owner.publicKey, { mint }); + + if (compressedTokenAccounts.items.length === 0) { + console.log("No compressed token accounts found"); + return; + } + + const [inputAccounts] = selectMinCompressedTokenAccountsForTransfer( + compressedTokenAccounts.items, + amount + ); + + const proof = await connection.getValidityProof( + inputAccounts.map((account) => account.compressedAccount.hash) + ); + + const ix = await CompressedTokenProgram.transfer({ + payer: payer.publicKey, + inputCompressedTokenAccounts: inputAccounts, + toAddress: recipient.publicKey, + amount, + recentInputStateRootIndices: proof.rootIndices, + recentValidityProof: proof.compressedProof, + }); + + const { blockhash } = await connection.getLatestBlockhash(); + const additionalSigners = dedupeSigner(payer, [owner]); + const signedTx = buildAndSignTx( + [ComputeBudgetProgram.setComputeUnitLimit({ units: 300_000 }), ix], + payer, + blockhash, + additionalSigners + ); + + const transferTxId = await sendAndConfirmTx(connection, signedTx); + console.log(`Transaction: ${transferTxId}`); +})(); +``` + + + + + +### Prerequisites + +Make sure you have dependencies and developer environment set up! + + + +**Dependencies** + + + +**Developer Environment** + + + + + + +### Display Compressed Token Balances + +This example fetches and displays all compressed token balances for a wallet address. + +```javascript +import { Rpc, createRpc } from '@lightprotocol/stateless.js'; +import { Keypair, PublicKey } from '@solana/web3.js'; +import * as fs from 'fs'; +import * as os from 'os'; + +const connection: Rpc = createRpc(); + +const walletPath = `${os.homedir()}/.config/solana/id.json`; +const secretKey = JSON.parse(fs.readFileSync(walletPath, 'utf8')); +const payer = Keypair.fromSecretKey(Buffer.from(secretKey)); + +(async () => { + const balances = await connection.getCompressedTokenBalancesByOwnerV2(payer.publicKey); + + if (balances.value.items.length === 0) { + console.log("No compressed token balances found"); + return; + } + + for (const item of balances.value.items) { + const balanceValue = typeof item.balance === 'string' + ? parseInt(item.balance, 16) + : item.balance; + + const mintInfo = await connection.getAccountInfo(new PublicKey(item.mint)); + const decimals = mintInfo.data[44]; + const formattedBalance = balanceValue / Math.pow(10, decimals); + + console.log(`Mint: ${item.mint}`); + console.log(`Balance: ${formattedBalance} tokens\n`); + } +})(); +``` + + + +### Get Transaction History + +This example retrieves compression transaction signatures to display transaction history of the wallet. + +```javascript +import { Rpc, createRpc } from '@lightprotocol/stateless.js'; +import { Keypair } from '@solana/web3.js'; +import * as fs from 'fs'; +import * as os from 'os'; + +const connection: Rpc = createRpc(); + +const walletPath = `${os.homedir()}/.config/solana/id.json`; +const secretKey = JSON.parse(fs.readFileSync(walletPath, 'utf8')); +const payer = Keypair.fromSecretKey(Buffer.from(secretKey)); + +(async () => { + const signatures = await connection.getCompressionSignaturesForTokenOwner(payer.publicKey); + + if (signatures.items.length > 0) { + console.log(`Signatures:`); + signatures.items.forEach((sig, index) => { + console.log(`${index + 1}. ${sig.signature}`); + console.log(` Slot: ${sig.slot}`); + console.log(` Time: ${new Date(sig.blockTime * 1000).toISOString()}`); + }); + } else { + console.log("No transactions found"); + } +})(); +``` + + + +### Send Compressed Tokens + +First, set up a test mint to and mint 10 compressed tokens to your filesystem wallet. + + + +```typescript +import { Keypair } from "@solana/web3.js"; +import { Rpc, confirmTx, createRpc } from '@lightprotocol/stateless.js'; +import { createMint, mintTo } from '@lightprotocol/compressed-token'; +import * as fs from 'fs'; +import * as os from 'os'; + +// 1. Setup RPC connection and load filesystem wallet for mint operations +// 2. Call createMint() to create SPL mint with interface PDA for compression +// 3. Call mintTo() to mint compressed tokens to filesystem wallet + +const connection: Rpc = createRpc(); // defaults to localhost:8899 + +// Load wallet from filesystem +const walletPath = `${os.homedir()}/.config/solana/id.json`; +const secretKey = JSON.parse(fs.readFileSync(walletPath, 'utf8')); +const payer = Keypair.fromSecretKey(Buffer.from(secretKey)); +const mintKeypair = Keypair.generate(); + +(async() => { + // Fund payer with SOL + await connection.requestAirdrop(payer.publicKey, 1e9); + await new Promise(resolve => setTimeout(resolve, 1000)); + + // Create SPL mint with interface PDA for compression + const { mint, transactionSignature } = await createMint( + connection, + payer, + payer.publicKey, // mint authority + 9, + mintKeypair, + ); + console.log(`Mint address: ${mint.toString()}`); + console.log(`Transaction: ${transactionSignature}`); + + // Mint compressed tokens to payer + const mintToTxId = await mintTo( + connection, + payer, + mint, // SPL mint with interface PDA for compression + payer.publicKey, // recipient address + payer, + 10e9, + ); + + console.log(`\nMinted ${10e9 / 1e9} compressed token`); + console.log(`Transaction: ${mintToTxId}`); +})(); +``` + + + + +Make sure you add your Mint address to `send-tokens.ts`. + + +```typescript send-tokens.ts expandable +// Compressed Token Transfer - Local +// 1. Load wallet and fetch compressed token accounts with getCompressedTokenAccountsByOwner() +// 2. Select accounts for transfer using selectMinCompressedTokenAccountsForTransfer() +// and get validity proof with getValidityProof() +// 3. Create transfer instruction with CompressedTokenProgram.transfer() +// and submit transaction with sendAndConfirmTx() +// 4. Verify balances via getCompressedTokenAccountsByOwner() + +import { + Rpc, + createRpc, + bn, + dedupeSigner, + sendAndConfirmTx, + buildAndSignTx, +} from "@lightprotocol/stateless.js"; +import { + CompressedTokenProgram, + selectMinCompressedTokenAccountsForTransfer, +} from "@lightprotocol/compressed-token"; +import { ComputeBudgetProgram, Keypair, PublicKey } from "@solana/web3.js"; +import * as fs from 'fs'; +import * as os from 'os'; + +// Step 1: Setup RPC connection and define transfer parameters +const connection: Rpc = createRpc(); // defaults to localhost:8899 +const mint = new PublicKey("MINT ADDRESS"); // Replace with mint address + +// Load wallet from filesystem +const walletPath = `${os.homedir()}/.config/solana/id.json`; +const secretKey = JSON.parse(fs.readFileSync(walletPath, 'utf8')); +const payer = Keypair.fromSecretKey(Buffer.from(secretKey)); +const owner = payer; + +const recipient = Keypair.generate(); +const amount = bn(1e8); + +(async () => { + // Step 2: Fetch compressed account hashes from state trees + const compressedTokenAccounts = + await connection.getCompressedTokenAccountsByOwner(owner.publicKey, { + mint, // SPL mint with interface PDA for compression + }); + + if (compressedTokenAccounts.items.length === 0) { + console.log("No compressed token accounts found for this mint"); + return; + } + + // Show initial sender balance + const initialBalance = compressedTokenAccounts.items.reduce((sum, account) => sum + Number(account.parsed.amount), 0); + console.log(`Sender balance: ${initialBalance / 1e8} compressed tokens`); + + // Step 3: Select minimum compressed accounts for transfer amount + const [inputAccounts] = selectMinCompressedTokenAccountsForTransfer( + compressedTokenAccounts.items, + amount + ); + + // Get validity proof for Merkle tree verification + const proof = await connection.getValidityProof( + inputAccounts.map((account) => account.compressedAccount.hash) + ); + + // Step 4: Create transfer instruction that consumes input accounts and creates new output accounts + const ix = await CompressedTokenProgram.transfer({ + payer: payer.publicKey, + inputCompressedTokenAccounts: inputAccounts, // accounts to consume + toAddress: recipient.publicKey, + amount, + recentInputStateRootIndices: proof.rootIndices, + recentValidityProof: proof.compressedProof, + }); + + // Step 5: Build, sign, and submit transaction + const { blockhash } = await connection.getLatestBlockhash(); + const additionalSigners = dedupeSigner(payer, [owner]); + const signedTx = buildAndSignTx( + [ComputeBudgetProgram.setComputeUnitLimit({ units: 300_000 }), ix], + payer, + blockhash, + additionalSigners + ); + const transferTxId = await sendAndConfirmTx(connection, signedTx); + + console.log(`\nTransferred ${amount.toNumber() / 1e8} compressed tokens`); + console.log(`Transaction: ${transferTxId}`); + console.log(`Recipient: ${recipient.publicKey.toString()}`); + + // Step 6: Verify via getCompressedTokenAccountsByOwner + const senderCompressedAccounts = await connection.getCompressedTokenAccountsByOwner(payer.publicKey, { mint }); + const senderBalance = senderCompressedAccounts.items.reduce((sum, account) => sum + Number(account.parsed.amount), 0); + + const recipientCompressedAccounts = await connection.getCompressedTokenAccountsByOwner(recipient.publicKey, { mint }); + const recipientBalance = recipientCompressedAccounts.items.reduce((sum, account) => sum + Number(account.parsed.amount), 0); + + console.log(`\nSummary compressed token balances:`); + console.log(`Sender balance: ${senderBalance / 1e8} compressed tokens`); + console.log(`Recipient balance: ${recipientBalance / 1e8} compressed token`); + + return transferTxId; +})(); +``` + + + + + +# Advanced Integrations + +Use these integrations to let users convert between regular and compressed format as needed. + + + +This example converts compressed tokens to regular SPL format using `CompressedTokenProgram.decompress().` + +```javascript +import { + bn, + buildAndSignTx, + sendAndConfirmTx, + dedupeSigner, + Rpc, + createRpc, +} from "@lightprotocol/stateless.js"; +import { ComputeBudgetProgram } from "@solana/web3.js"; +import { + CompressedTokenProgram, + getTokenPoolInfos, + selectMinCompressedTokenAccountsForTransfer, + selectTokenPoolInfosForDecompression, +} from "@lightprotocol/compressed-token"; + +// 1. Setup RPC connection and fetch compressed token accounts with getCompressedTokenAccountsByOwner() +// 2. Select accounts and token pool infos using selectMinCompressedTokenAccountsForTransfer() and selectTokenPoolInfosForDecompression() +// 3. Create decompress instruction with CompressedTokenProgram.decompress() and submit transaction + +// Step 1: Setup RPC connection and define decompression parameters +const connection: Rpc = createRpc("https://mainnet.helius-rpc.com?api-key=";); +const payer = PAYER_KEYPAIR; +const owner = PAYER_KEYPAIR; +const mint = MINT_ADDRESS; +const amount = 1e5; // 100K tokens to decompress + +(async () => { + // 1. Fetch compressed token accounts + const compressedTokenAccounts = + await connection.getCompressedTokenAccountsByOwner(owner.publicKey, { + mint, + }); + + // 2. Select + const [inputAccounts] = selectMinCompressedTokenAccountsForTransfer( + compressedTokenAccounts.items, + bn(amount) + ); + + // 3. Fetch validity proof + const proof = await connection.getValidityProof( + inputAccounts.map((account) => account.compressedAccount.hash) + ); + + // 4. Fetch & Select tokenPoolInfos + const tokenPoolInfos = await getTokenPoolInfos(connection, mint); + const selectedTokenPoolInfos = selectTokenPoolInfosForDecompression( + tokenPoolInfos, + amount + ); + + // 5. Build instruction + const ix = await CompressedTokenProgram.decompress({ + payer: payer.publicKey, + inputCompressedTokenAccounts: inputAccounts, + toAddress: owner.publicKey, + amount, + tokenPoolInfos: selectedTokenPoolInfos, + recentInputStateRootIndices: proof.rootIndices, + recentValidityProof: proof.compressedProof, + }); + + + // 6. Sign, send, and confirm. + // Example with keypair: + const { blockhash } = await connection.getLatestBlockhash(); + const additionalSigners = dedupeSigner(payer, [owner]); + const signedTx = buildAndSignTx( + [ComputeBudgetProgram.setComputeUnitLimit({ units: 300_000 }), ix], + payer, + blockhash, + additionalSigners + ); + + return await sendAndConfirmTx(connection, signedTx); +})(); +``` + + + + + +This example converts regular SPL tokens to compressed format using `CompressedTokenProgram.compress().` + +```typescript +// 1. Setup RPC connection and get user ATA with getOrCreateAssociatedTokenAccount() +// 2. Fetch state tree and token pool infos using getStateTreeInfos() and getTokenPoolInfos() +// 3. Create compress instruction with CompressedTokenProgram.compress() and submit transaction + + +import { + buildAndSignTx, + sendAndConfirmTx, + Rpc, + createRpc, + selectStateTreeInfo, +} from "@lightprotocol/stateless.js"; +import { ComputeBudgetProgram } from "@solana/web3.js"; +import { + CompressedTokenProgram, + getTokenPoolInfos, + selectTokenPoolInfo, +} from "@lightprotocol/compressed-token"; +import { getOrCreateAssociatedTokenAccount } from "@solana/spl-token"; + +// Step 1: Setup RPC connection and define compression parameters +const connection: Rpc = createRpc( + "https://mainnet.helius-rpc.com?api-key=" +); + const payer = ; + const mint = ; +const amount = 1e5; // 100K tokens to compress + +(async () => { + // Step 2: Get or create associated token account for SPL tokens + const sourceTokenAccount = await getOrCreateAssociatedTokenAccount( + connection, + payer, // fee payer + mint, // token mint address + payer.publicKey // token account owner + ); + + // Step 3: Fetch and select state tree info for compression + const treeInfos = await connection.getStateTreeInfos(); + const treeInfo = selectStateTreeInfo(treeInfos); + + // Step 4: Fetch and select interface PDA info for compression + const tokenPoolInfos = await getTokenPoolInfos(connection, mint); + const tokenPoolInfo = selectTokenPoolInfo(tokenPoolInfos); + + // Step 5: Create compress instruction - transfer SPL tokens to pool and create compressed accounts + const compressInstruction = await CompressedTokenProgram.compress({ + payer: payer.publicKey, // fee payer + owner: payer.publicKey, // owner of source SPL tokens + source: sourceTokenAccount.address, // source ATA address + toAddress: payer.publicKey, // recipient of compressed tokens (self) + amount, // amount to compress + mint, // token mint address + outputStateTreeInfo: treeInfo, // state tree for compressed accounts + tokenPoolInfo, // token pool for compression + }); + + // Step 6: Build, sign, and submit compression transaction + const { blockhash } = await connection.getLatestBlockhash(); + const tx = buildAndSignTx( + [ + ComputeBudgetProgram.setComputeUnitLimit({ units: 300_000 }), + compressInstruction, + ], + payer, // transaction signer + blockhash, + [payer] // additional signers + ); + await sendAndConfirmTx(connection, tx); +})(); +``` + + + +# Common Errors + + + +If `getCompressedTokenBalancesByOwnerV2` returns empty: + +* Ensure the wallet has compressed tokens (not regular SPL tokens) +* Verify you're on the correct network (devnet/mainnet) + + + +# Next Steps + + + diff --git a/docs.json b/docs.json index 4d07401f..c45ffa21 100644 --- a/docs.json +++ b/docs.json @@ -28,157 +28,78 @@ { "group": "Introduction", "pages": [ - "home", - "faq" + "home" ] }, { - "group": "Light Token APIs", + "group": "Compressed Tokens", "pages": [ - "light-token/welcome", + "compressed-tokens/overview", { "group": "Cookbook", "pages": [ - { - "group": "Mint Accounts", - "pages": [ - "light-token/cookbook/create-mint", - "light-token/cookbook/add-interface-pda" - ] - }, - "light-token/cookbook/create-ata", - "light-token/cookbook/create-token-account", - "light-token/cookbook/mint-to", - "light-token/cookbook/transfer-interface", - "light-token/cookbook/transfer-checked", - { - "group": "Delegates", - "pages": [ - "light-token/cookbook/approve-revoke", - "light-token/cookbook/transfer-delegated" - ] - }, - "light-token/cookbook/freeze-thaw", - "light-token/cookbook/wrap-unwrap", - "light-token/cookbook/load-ata", - "light-token/cookbook/close-token-account", - "light-token/cookbook/burn" + "compressed-tokens/guides/create-compressed-token-accounts", + "compressed-tokens/guides/mint-compressed-tokens", + "compressed-tokens/guides/transfer-compressed-tokens", + "compressed-tokens/guides/compress-decompress", + "compressed-tokens/guides/compress-spl-token-account", + "compressed-tokens/guides/create-mint-with-token-pool", + "compressed-tokens/guides/add-token-pools-to-mint-accounts", + "compressed-tokens/guides/merge-compressed-token-accounts", + "compressed-tokens/guides/delegate", + "compressed-tokens/combine-instructions" ] }, - "light-token/extensions/overview", { - "group": "For Stablecoin Payments", + "group": "Integration Guides", "pages": [ - "light-token/payments/overview", - { - "group": "Send Payments", - "pages": [ - "light-token/payments/basic-payment", - "light-token/payments/batch-payments", - "light-token/payments/payment-with-memo" - ] - }, - "light-token/payments/receive-payments", - { - "group": "Verify Payments", - "pages": [ - "light-token/payments/verify-payments", - "light-token/payments/verify-recipient-address" - ] - }, - "light-token/payments/spend-permissions", - "light-token/payments/wrap-unwrap", - "pda/compressed-pdas/nullifier-pda", - "light-token/payments/production-readiness" - ] - }, - { - "group": "For Wallets", - "pages": [ - "light-token/wallets/overview", - "light-token/wallets/privy", - "light-token/wallets/wallet-adapter", - "light-token/wallets/gasless-transactions" - ] - }, - { - "group": "For DeFi", - "pages": [ - "light-token/defi/routers", - "light-token/defi/programs", - "light-token/defi/programs-pinocchio" - ] - }, - { - "group": "For Data Streaming", - "pages": [ - "light-token/streaming/mints", - "light-token/streaming/tokens" - ] - }, - { - "group": "Examples", - "pages": [ - "light-token/examples/client", - "light-token/examples/program" + "compressed-tokens/privy", + "compressed-tokens/token-distribution", + "compressed-tokens/wallet-integration", + "compressed-tokens/token-2022" ] } ] }, { - "group": "PDA Accounts", + "group": "Compressed PDA", "pages": [ - "pda/overview", - "pda/light-pda/overview", + "compressed-pdas/overview", + "compressed-pdas/guides/client-guide", { - "group": "Compressed PDA", + "group": "Program Guides", "pages": [ - "pda/compressed-pdas/overview", - "pda/compressed-pdas/guides/client-guide", - { - "group": "Program Guides", - "expanded": true, - "pages": [ - "pda/compressed-pdas/guides", - "pda/compressed-pdas/guides/how-to-create-compressed-accounts", - "pda/compressed-pdas/guides/how-to-update-compressed-accounts", - "pda/compressed-pdas/guides/how-to-close-compressed-accounts", - "pda/compressed-pdas/guides/how-to-reinitialize-compressed-accounts", - "pda/compressed-pdas/guides/how-to-burn-compressed-accounts" - ] - }, - "pda/compressed-pdas/program-examples" + "compressed-pdas/guides", + "compressed-pdas/guides/how-to-create-compressed-accounts", + "compressed-pdas/guides/how-to-update-compressed-accounts", + "compressed-pdas/guides/how-to-close-compressed-accounts", + "compressed-pdas/guides/how-to-reinitialize-compressed-accounts", + "compressed-pdas/guides/how-to-burn-compressed-accounts" ] - } + }, + "compressed-pdas/program-examples", + "compressed-pdas/nullifier-pda", + "compressed-pdas/solana-attestation-service" ] }, { - "group": "For Other Use Cases", + "group": "Custom ZK Applications", "pages": [ - "token-distribution", - "pda/compressed-pdas/solana-attestation-service", - { - "group": "Custom ZK Applications", - "pages": [ - "zk/overview", - "zk/examples" - ] - } + "zk/overview", + "zk/examples" ] }, { "group": "Learn", "pages": [ - "learn/overview", - "learn/light-token-standard", { - "group": "Core Concepts (ZK Compression)", + "group": "Core Concepts", "pages": [ - "learn/core-concepts", - "learn/core-concepts/compressed-account-model", - "learn/core-concepts/merkle-trees-validity-proofs", - "learn/core-concepts/transaction-lifecycle", - "learn/core-concepts/considerations" + "learn/overview", + "learn/compressed-account-model", + "learn/merkle-trees-validity-proofs", + "learn/transaction-lifecycle", + "learn/considerations" ] } ] @@ -195,14 +116,13 @@ "resources/error-cheatsheet/debug-0x179b-6043-proofverificationfailed" ] }, - "resources/legacy-compressed-tokens", "resources/security" ] } ] }, { - "anchor": "API Reference", + "anchor": "API & SDK Reference", "icon": "code", "groups": [ { @@ -211,18 +131,6 @@ "api-reference/sdk" ] }, - { - "group": "Solana to Light", - "pages": [ - "api-reference/solana-to-light-comparison" - ] - }, - { - "group": "Anchor", - "pages": [ - "api-reference/anchor" - ] - }, { "group": "JSON RPC Methods", "pages": [ @@ -347,29 +255,21 @@ } }, "redirects": [ - { - "source": "/light-token/payments/integration-guide", - "destination": "https://zkcompression.com/light-token/payments/overview" - }, { "source": "/light-token/payments/nullifier-pda", - "destination": "https://zkcompression.com/pda/compressed-pdas/nullifier-pda" + "destination": "https://zkcompression.com/compressed-pdas/nullifier-pda" }, { "source": "/light-token/nullifier-pda", - "destination": "https://zkcompression.com/pda/compressed-pdas/nullifier-pda" + "destination": "https://zkcompression.com/compressed-pdas/nullifier-pda" }, { "source": "/airdrop", - "destination": "https://zkcompression.com/token-distribution" + "destination": "https://zkcompression.com/compressed-tokens/token-distribution" }, { "source": "/compressed-tokens/airdrop", - "destination": "https://zkcompression.com/token-distribution" - }, - { - "source": "/compressed-tokens/overview", - "destination": "https://zkcompression.com/resources/legacy-compressed-tokens" + "destination": "https://zkcompression.com/compressed-tokens/token-distribution" }, { "source": "/landing", @@ -391,17 +291,13 @@ "source": "/resources/sdks/program-development", "destination": "https://zkcompression.com/api-reference/sdk" }, - { - "source": "/compressed-tokens/for-privy", - "destination": "https://zkcompression.com/light-token/wallets/privy" - }, { "source": "/client-library/client-guide", - "destination": "https://zkcompression.com/pda/compressed-pdas/guides/client-guide" + "destination": "https://zkcompression.com/compressed-pdas/guides/client-guide" }, { "source": "/light-token/faq", - "destination": "/faq" + "destination": "https://zkcompression.com/home" }, { "source": "/references/migration-v1-to-v2", @@ -421,211 +317,31 @@ }, { "source": "/references/anchor-constraints", - "destination": "https://zkcompression.com/api-reference/anchor" - }, - { - "source": "/resources/spl-to-light-reference", - "destination": "https://zkcompression.com/api-reference/solana-to-light-comparison" + "destination": "https://zkcompression.com/api-reference/overview" }, { "source": "/resources/cli-installation", - "destination": "https://zkcompression.com/resources/cli" - }, - { - "source": "/references/whitepaper", - "destination": "https://zkcompression.com/resources/whitepaper" + "destination": "https://zkcompression.com/home" }, { "source": "/references/terminology", "destination": "https://zkcompression.com/resources/terminology" }, - { - "source": "/compressed-pdas/overview", - "destination": "https://zkcompression.com/pda/compressed-pdas/overview" - }, - { - "source": "/compressed-pdas/guides", - "destination": "https://zkcompression.com/pda/compressed-pdas/guides" - }, - { - "source": "/compressed-pdas/guides/how-to-burn-compressed-accounts", - "destination": "https://zkcompression.com/pda/compressed-pdas/guides/how-to-burn-compressed-accounts" - }, - { - "source": "/compressed-pdas/guides/how-to-close-compressed-accounts", - "destination": "https://zkcompression.com/pda/compressed-pdas/guides/how-to-close-compressed-accounts" - }, - { - "source": "/compressed-pdas/guides/how-to-create-compressed-accounts", - "destination": "https://zkcompression.com/pda/compressed-pdas/guides/how-to-create-compressed-accounts" - }, { "source": "/compressed-pdas/guides/how-to-create-nullifier-pdas", - "destination": "https://zkcompression.com/pda/compressed-pdas/nullifier-pda" - }, - { - "source": "/compressed-pdas/guides/how-to-reinitialize-compressed-accounts", - "destination": "https://zkcompression.com/pda/compressed-pdas/guides/how-to-reinitialize-compressed-accounts" - }, - { - "source": "/compressed-pdas/guides/how-to-update-compressed-accounts", - "destination": "https://zkcompression.com/pda/compressed-pdas/guides/how-to-update-compressed-accounts" - }, - { - "source": "/compressed-pdas/program-examples", - "destination": "https://zkcompression.com/pda/compressed-pdas/program-examples" - }, - { - "source": "/compressed-pdas/solana-attestation-service", - "destination": "https://zkcompression.com/pda/compressed-pdas/solana-attestation-service" - }, - { - "source": "/compressed-tokens/advanced-guides/airdrop", - "destination": "https://zkcompression.com/token-distribution" - }, - { - "source": "/quickstart", - "destination": "https://zkcompression.com/light-token/quickstart" - }, - { - "source": "/light-token/cookbook/extensions", - "destination": "https://zkcompression.com/light-token/extensions" + "destination": "https://zkcompression.com/compressed-pdas/nullifier-pda" }, { "source": "/api-reference/json-rpc-methods/methods", "destination": "https://zkcompression.com/api-reference/json-rpc-methods/overview" }, - { - "source": "/compressed-tokens/advanced-guides", - "destination": "https://zkcompression.com/resources/legacy-compressed-tokens" - }, - { - "source": "/compressed-tokens/advanced-guides/add-wallet-support-for-compressed-tokens", - "destination": "https://zkcompression.com/light-token/wallets/overview" - }, - { - "source": "/compressed-tokens/advanced-guides/example-token-distribution", - "destination": "https://zkcompression.com/token-distribution" - }, - { - "source": "/compressed-tokens/advanced-guides/use-token-2022-with-compression", - "destination": "https://zkcompression.com/resources/legacy-compressed-tokens" - }, - { - "source": "/compressed-tokens/guides", - "destination": "https://zkcompression.com/resources/legacy-compressed-tokens" - }, - { - "source": "/compressed-tokens/guides/add-token-pools-to-mint-accounts", - "destination": "https://zkcompression.com/resources/legacy-compressed-tokens" - }, - { - "source": "/compressed-tokens/guides/compress-decompress", - "destination": "https://zkcompression.com/resources/legacy-compressed-tokens" - }, - { - "source": "/compressed-tokens/guides/compress-spl-token-account", - "destination": "https://zkcompression.com/resources/legacy-compressed-tokens" - }, - { - "source": "/compressed-tokens/guides/create-compressed-token-accounts", - "destination": "https://zkcompression.com/resources/legacy-compressed-tokens" - }, - { - "source": "/compressed-tokens/guides/create-mint-with-token-pool", - "destination": "https://zkcompression.com/light-token/cookbook/create-mint" - }, - { - "source": "/compressed-tokens/guides/delegate", - "destination": "https://zkcompression.com/resources/legacy-compressed-tokens" - }, - { - "source": "/compressed-tokens/guides/merge-compressed-token-accounts", - "destination": "https://zkcompression.com/resources/legacy-compressed-tokens" - }, - { - "source": "/compressed-tokens/guides/mint-compressed-tokens", - "destination": "https://zkcompression.com/resources/legacy-compressed-tokens" - }, - { - "source": "/compressed-tokens/guides/transfer-compressed-tokens", - "destination": "https://zkcompression.com/resources/legacy-compressed-tokens" - }, { "source": "/references/light-token-terminology", "destination": "https://zkcompression.com/resources/terminology" }, - { - "source": "/light-token/cookbook/update-metadata", - "destination": "https://zkcompression.com/light-token/extensions" - }, - { - "source": "/learn/c-token-program", - "destination": "https://zkcompression.com/learn/light-token-standard" - }, - { - "source": "/c-token-program/README", - "destination": "https://zkcompression.com/light-token/welcome" - }, - { - "source": "/c-token-program/ctoken/close-ctoken-account", - "destination": "https://zkcompression.com/light-token/cookbook/close-token-account" - }, - { - "source": "/c-token-program/ctoken/create-cata", - "destination": "https://zkcompression.com/light-token/cookbook/create-ata" - }, - { - "source": "/c-token-program/cmint/create-cmint", - "destination": "https://zkcompression.com/light-token/cookbook/create-mint" - }, - { - "source": "/c-token-program/ctoken/create-ctoken", - "destination": "https://zkcompression.com/light-token/cookbook/create-token-account" - }, - { - "source": "/c-token-program/ctoken/extensions", - "destination": "https://zkcompression.com/light-token/extensions" - }, - { - "source": "/c-token-program/cmint/mint-ctokens", - "destination": "https://zkcompression.com/light-token/cookbook/mint-to" - }, - { - "source": "/c-token-program/cmint/update-metadata", - "destination": "https://zkcompression.com/light-token/cookbook/create-mint" - }, { "source": "/c-token-program/ctoken-faq", - "destination": "https://zkcompression.com/faq" - }, - { - "source": "/c-token-program/c-token-toolkits/for-payments", - "destination": "https://zkcompression.com/light-token/payments/overview" - }, - { - "source": "/c-token-program/c-token-toolkits/for-streaming-mints", - "destination": "https://zkcompression.com/light-token/streaming/mints" - }, - { - "source": "/c-token-program/c-token-toolkits/for-streaming-tokens", - "destination": "https://zkcompression.com/light-token/streaming/tokens" - }, - { - "source": "/c-token-program/c-token-toolkits/for-wallets", - "destination": "https://zkcompression.com/light-token/wallets/overview" - }, - { - "source": "/c-token-program/c-token-toolkits/for-dexs", - "destination": "https://zkcompression.com/light-token/defi/routers" - }, - { - "source": "/c-token-program/c-token-toolkits/for-launchpads", - "destination": "https://zkcompression.com/light-token/welcome" - }, - { - "source": "/c-token-program/c-token-toolkits/for-trading-apps", - "destination": "https://zkcompression.com/light-token/welcome" + "destination": "https://zkcompression.com/home" }, { "source": "/resources/json-rpc-methods", @@ -715,26 +431,10 @@ "source": "/resources/json-rpc-methods/getvalidityproof", "destination": "https://zkcompression.com/api-reference/json-rpc-methods/getvalidityproof" }, - { - "source": "/blog/c-token", - "destination": "https://zkcompression.com/light-token/welcome" - }, { "source": "/learn/migration-v1-to-v2", "destination": "https://zkcompression.com/resources/migration-v1-to-v2" }, - { - "source": "/light-token/README", - "destination": "https://zkcompression.com/light-token/welcome" - }, - { - "source": "/compressed-token-program/README", - "destination": "https://zkcompression.com/light-token/welcome" - }, - { - "source": "/compressed-token-program/overview", - "destination": "https://zkcompression.com/light-token/welcome" - }, { "source": "/api-reference/api-reference-overview", "destination": "https://zkcompression.com/api-reference/overview" @@ -743,33 +443,21 @@ "source": "/api-reference/links", "destination": "https://zkcompression.com/api-reference/overview" }, - { - "source": "/c-token-program/c-token-toolkits/for-aggregators", - "destination": "https://zkcompression.com/light-token/welcome" - }, - { - "source": "/c-token-program/c-token-toolkits/for-defi-markets", - "destination": "https://zkcompression.com/light-token/defi/routers" - }, - { - "source": "/c-token-program/cmint/README", - "destination": "https://zkcompression.com/light-token/cookbook/create-mint" - }, { "source": "/c-token-program/faq", - "destination": "https://zkcompression.com/faq" + "destination": "https://zkcompression.com/home" }, { "source": "/client-library", - "destination": "https://zkcompression.com/pda/compressed-pdas/guides/client-guide" + "destination": "https://zkcompression.com/compressed-pdas/guides/client-guide" }, { "source": "/client-library/README", - "destination": "https://zkcompression.com/pda/compressed-pdas/guides/client-guide" + "destination": "https://zkcompression.com/compressed-pdas/guides/client-guide" }, { "source": "/compressed-pdas/client-library", - "destination": "https://zkcompression.com/pda/compressed-pdas/guides/client-guide" + "destination": "https://zkcompression.com/compressed-pdas/guides/client-guide" }, { "source": "/resources/sdks", @@ -777,128 +465,44 @@ }, { "source": "/compressed-tokens/advanced-guides/create-an-airdrop-with-claim", - "destination": "https://zkcompression.com/token-distribution" + "destination": "https://zkcompression.com/compressed-tokens/token-distribution" }, { "source": "/compressed-tokens/advanced-guides/example-node-js", - "destination": "https://zkcompression.com/resources/legacy-compressed-tokens" + "destination": "https://zkcompression.com/compressed-tokens/token-distribution" }, { "source": "/compressed-tokens/advanced-guides/example-web-client", - "destination": "https://zkcompression.com/resources/legacy-compressed-tokens" - }, - { - "source": "/compressed-tokens/guides/how-to-approve-and-revoke-delegate-authority", - "destination": "https://zkcompression.com/light-token/cookbook/approve-revoke" + "destination": "https://zkcompression.com/compressed-tokens/token-distribution" }, { "source": "/compressed-tokens/guides/how-to-compress-and-decompress-spl-tokens", - "destination": "https://zkcompression.com/resources/legacy-compressed-tokens" + "destination": "https://zkcompression.com/compressed-tokens/guides/compress-decompress" }, { "source": "/compressed-tokens/guides/how-to-compress-complete-spl-token-accounts", - "destination": "https://zkcompression.com/resources/legacy-compressed-tokens" + "destination": "https://zkcompression.com/compressed-tokens/guides/compress-spl-token-account" }, { "source": "/compressed-tokens/guides/how-to-create-and-register-a-mint-account-for-compression", - "destination": "https://zkcompression.com/light-token/cookbook/create-mint" + "destination": "https://zkcompression.com/compressed-tokens/guides/create-mint-with-token-pool" }, { "source": "/compressed-tokens/guides/how-to-create-compressed-token-pools-for-mint-accounts", - "destination": "https://zkcompression.com/light-token/cookbook/create-mint" + "destination": "https://zkcompression.com/compressed-tokens/guides/create-mint-with-token-pool" }, { "source": "/compressed-tokens/guides/how-to-merge-compressed-token-accounts", - "destination": "https://zkcompression.com/resources/legacy-compressed-tokens" + "destination": "https://zkcompression.com/compressed-tokens/guides/merge-compressed-token-accounts" }, { "source": "/compressed-tokens/guides/how-to-mint-compressed-tokens", - "destination": "https://zkcompression.com/resources/legacy-compressed-tokens" - }, - { - "source": "/integration-guides/privy", - "destination": "https://zkcompression.com/light-token/wallets/privy" - }, - { - "source": "/light-token/cookbook/compress", - "destination": "https://zkcompression.com/light-token/cookbook/wrap-unwrap" - }, - { - "source": "/light-token/cookbook/compress-decompress", - "destination": "https://zkcompression.com/light-token/cookbook/wrap-unwrap" - }, - { - "source": "/light-token/cookbook/decompress", - "destination": "https://zkcompression.com/light-token/cookbook/wrap-unwrap" - }, - { - "source": "/light-token/cookbook/delegate", - "destination": "https://zkcompression.com/light-token/cookbook/approve-revoke" + "destination": "https://zkcompression.com/compressed-tokens/guides/mint-compressed-tokens" }, { "source": "/light-token/cookbook/merge-token-accounts", "destination": "https://zkcompression.com/resources/legacy-compressed-tokens" }, - { - "source": "/light-token/cookbook/unwrap", - "destination": "https://zkcompression.com/light-token/cookbook/wrap-unwrap" - }, - { - "source": "/light-token/cookbook/wrap", - "destination": "https://zkcompression.com/light-token/cookbook/wrap-unwrap" - }, - { - "source": "/light-token/interface-methods", - "destination": "https://zkcompression.com/light-token/cookbook/transfer-interface" - }, - { - "source": "/light-token/toolkits/for-dexs", - "destination": "https://zkcompression.com/light-token/defi/routers" - }, - { - "source": "/light-token/toolkits/for-launchpads", - "destination": "https://zkcompression.com/light-token/welcome" - }, - { - "source": "/light-token/toolkits/for-trading-apps", - "destination": "https://zkcompression.com/light-token/welcome" - }, - { - "source": "/compressed-token-program/c-token-program", - "destination": "https://zkcompression.com/light-token/welcome" - }, - { - "source": "/compressed-token-program/integrate/for-payment-companies", - "destination": "https://zkcompression.com/light-token/payments/overview" - }, - { - "source": "/compressed-token-program/integrate/for-wallet-applications", - "destination": "https://zkcompression.com/light-token/wallets/overview" - }, - { - "source": "/compressed-token-program/ctoken/README", - "destination": "https://zkcompression.com/light-token/welcome" - }, - { - "source": "/compressed-token-program/ctoken/close-ctoken", - "destination": "https://zkcompression.com/light-token/cookbook/close-token-account" - }, - { - "source": "/compressed-token-program/ctoken/create-ata", - "destination": "https://zkcompression.com/light-token/cookbook/create-ata" - }, - { - "source": "/compressed-token-program/ctoken/create-ctoken", - "destination": "https://zkcompression.com/light-token/cookbook/create-token-account" - }, - { - "source": "/compressed-token-program/ctoken/mint-ctokens", - "destination": "https://zkcompression.com/light-token/cookbook/mint-to" - }, - { - "source": "/compressed-token-program/ctoken/transfer-interface", - "destination": "https://zkcompression.com/light-token/cookbook/transfer-interface" - }, { "source": "/api-reference/index", "destination": "https://zkcompression.com/api-reference/sdk" @@ -931,18 +535,10 @@ "source": "/blog/overview", "destination": "https://zkcompression.com/home" }, - { - "source": "/blog/light-token", - "destination": "https://zkcompression.com/light-token/welcome" - }, { "source": "/changelog", "destination": "https://github.com/Lightprotocol/light-protocol/releases" }, - { - "source": "/compressed-tokens/advanced-guides/how-to-combine-operations-in-one-transaction", - "destination": "https://zkcompression.com/resources/legacy-compressed-tokens" - }, { "source": "/learn/ask-deepwiki-public", "destination": "https://zkcompression.com/ai-tools/mcp" @@ -951,57 +547,13 @@ "source": "/ai-tools/guide", "destination": "https://zkcompression.com/ai-tools/overview" }, - { - "source": "/light-token/cookbook/overview", - "destination": "https://zkcompression.com/light-token/cookbook/create-mint" - }, { "source": "/rent", - "destination": "https://zkcompression.com/faq" - }, - { - "source": "/light-token/toolkits/for-payments", - "destination": "https://zkcompression.com/light-token/payments/overview" - }, - { - "source": "/light-token/toolkits/for-wallets", - "destination": "https://zkcompression.com/light-token/wallets/overview" - }, - { - "source": "/light-token/toolkits/for-privy", - "destination": "https://zkcompression.com/light-token/wallets/privy" - }, - { - "source": "/light-token/toolkits/for-wallet-adapter", - "destination": "https://zkcompression.com/light-token/wallets/wallet-adapter" - }, - { - "source": "/light-token/toolkits/sponsor-top-ups", - "destination": "https://zkcompression.com/light-token/wallets/gasless-transactions" - }, - { - "source": "/light-token/wallets/sponsor-top-ups", - "destination": "https://zkcompression.com/light-token/wallets/gasless-transactions" - }, - { - "source": "/light-token/payments/fee-abstraction", - "destination": "https://zkcompression.com/light-token/wallets/gasless-transactions" - }, - { - "source": "/light-token/toolkits/for-streaming-mints", - "destination": "https://zkcompression.com/light-token/streaming/mints" - }, - { - "source": "/light-token/toolkits/for-streaming-tokens", - "destination": "https://zkcompression.com/light-token/streaming/tokens" - }, - { - "source": "/light-token/toolkits/for-streaming-pdas", - "destination": "https://zkcompression.com/light-token/streaming/pdas" + "destination": "https://zkcompression.com/home" }, { "source": "/pda/compressed-pdas/guides/how-to-create-nullifier-pdas", - "destination": "https://zkcompression.com/pda/compressed-pdas/nullifier-pda" + "destination": "https://zkcompression.com/compressed-pdas/nullifier-pda" } ] } diff --git a/faq.mdx b/faq.mdx deleted file mode 100644 index 0e2bc81e..00000000 --- a/faq.mdx +++ /dev/null @@ -1,286 +0,0 @@ ---- -title: FAQ -description: Frequently asked questions about light token, PDA accounts, and use cases. -keywords: ["spl token vs light token comparison", "token 2022 vs light token differences", "rent exemption on solana explained", "token account cost on solana", "light pda vs compressed pda", "rent free pda solana", "solana pda cost", "compressed accounts solana"] ---- - -import { CodeCompare } from "/snippets/jsx/code-compare.jsx"; -import ExtensionsTable from "/snippets/extensions-table.mdx"; -import CompressibleRentExplained from "/snippets/compressible-rent-explained.mdx"; -import RentSponsorshipExplained from "/snippets/rent-sponsorship-explained.mdx"; -import { RentLifecycleVisualizer } from "/snippets/jsx/rent-lifecycle-visualizer.jsx"; -import { - splCreateAtaCode, - lightCreateAtaCode, -} from "/snippets/code-samples/code-compare-snippets.jsx"; -import RentSponsorshipCost from "/snippets/cost-tables/rent-sponsorship-cost.mdx"; -import TokenCreationCost from "/snippets/cost-tables/token-creation-cost.mdx"; -import CuPerformance from "/snippets/cost-tables/cu-performance.mdx"; -import LightPdaCost from "/snippets/cost-tables/light-pda-cost.mdx"; -import CompressedPdaCost from "/snippets/cost-tables/compressed-pda-cost.mdx"; - -## Rent Sponsorship - - - -Rent sponsorship is a built-in feature of the Light SDK’s that sponsors rent-exemption for all account types to reduce creation cost: mints, token accounts, and PDAs. -This is dealt with under the hood in a way that doesn’t disrupt the UX of what your users are used to with SPL-token. - - - - - - - - - -Set the `payer` parameter to the sponsor's public key on any Light Token instruction. The sponsor pays SOL for rent top-ups and transaction fees while the user only signs to authorize the transfer. - -```typescript -const ix = createLightTokenTransferInstruction( - senderAta, - recipientAta, - sender.publicKey, - amount, - sponsor.publicKey, // sponsor pays rent top-ups and transaction fees -); - -await sendAndConfirmTransaction(rpc, tx, [sponsor, sender]); -``` - - - - - -## Light Token Program - - - -Light token is a high-performance token standard that is functionally equivalent to SPL, but stores mint and token accounts more efficiently. This reduces account creation cost while being more CU efficient than SPL on hot paths. - -**Creation Cost** - - - -**CU Performance** - - - - - - - -Yes! Light Token is live on Solana mainnet. Start integrating with the [Quickstart](/light-token/quickstart) and [Toolkits](/light-token/welcome). - -For token distribution use cases (airdrops, claims), see [Compressed Tokens](/resources/legacy-compressed-tokens), supported by leading wallets such as Phantom and Backpack. - - - - - -No. The `light-token-sdk` methods are a superset of the SPL-token API — every SPL operation (transfer, approve, revoke, freeze, thaw, burn, close) plus unified balance aggregation, automatic load/decompress, wrap/unwrap, and cross-program dispatch. See "What does 'superset of the SPL-token API' mean?" below for details. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
LightSPL
**Get/Create ATA**getOrCreateAtaInterface()getOrCreateAssociatedTokenAccount()
**Derive ATA**getAssociatedTokenAddressInterface()getAssociatedTokenAddress()
**Transfer**transferInterface()transferChecked()
**Get Balance**getAtaInterface()getAccount()
- - - Side-by-side mapping of every Light Token instruction against its SPL/Solana equivalent. - - -
- - - -The Light Token SDK covers every SPL Token operation and adds extra capabilities: - - - - - - - - - - - - - - - - - - - - - - -
CategoryWhat it does
**Cross-program dispatch**`Interface` methods (e.g., `transferInterface`) auto-detect the token program and dispatch to SPL, Token 2022, or Light Token.
**Unified balance**`getAtaInterface` returns a unified balance for a given mint, aggregating Light Token (hot + cold), SPL, and Token 2022 sources.
**Wrap / Unwrap**For interoperability with applications that don't support Light Token yet, you can wrap / unwrap SPL or Token 2022 tokens into Light Token associated token accounts and back.
- - - Side-by-side mapping of every Light Token instruction against its SPL/Solana equivalent. - - -
- - - -Yes, light-token accounts can hold tokens from light, SPL, or Token 2022 mints. - -SPL tokens can be deposited into light-token accounts and withdrawn back to SPL token accounts via the `transferInterface` method. - - - - - -The token standard pays rent-exemption cost for you. To prevent griefing, "rent" is paid over time to keep an account in memory. This is dealt with under the hood in a way that doesn't disrupt the UX of what your users are used to with SPL-token. - - - - - - - - - -The account is automatically compressed. -Your tokens are cryptographically preserved as a compressed token account (rent-free). -The account is loaded into hot account state in-flight when someone interacts with it again. - - - - - -Light Token supports 16 Token-2022 extensions. Some have restrictions. - - - - - -Additional extensions can be requested. - - - - - -- **light-token**: Solana account that holds token balances of light-mints, SPL or Token 22 mints. -- **Compressed token**: Compressed account storing token data. Rent-free, for storage and distribution. - - - ---- - -## PDA Accounts - - - -A standard Solana PDA with sponsored rent-exemption. Seeds, bump derivation, and `invoke_signed` work the same way. Your instruction handlers for reads, updates, and closes don't change. - - - - - - - -A compressed account with a derived address. Programs invoke the Light System program instead of the System program to create and update compressed accounts. Compressed PDAs are always compressed and require a validity proof for every read and write. - - - - - - - -| | Light-PDA | Compressed PDA | -| :----------------- | :--------------------------------------------------------------- | :-------------------------------------------------------------------- | -| **Storage** | On-chain; auto-compresses when inactive | Always compressed | -| **Validity proof** | Not required | Required for every read and write | -| **Program changes**| Minimal changes. Leaves program logic mostly untouched. | Custom Logic | -| **Best for** | Shared state: DeFi pools, vaults, config, program-owned accounts | Per-user state: profiles, credentials, DePIN nodes, nullifiers | - - - - - - - - -No. Add `compression_info: CompressionInfo` to your state struct, derive `LightAccount` and `LightAccounts`, and add `#[light_program]` above `#[program]`. Your instruction logic for reads, updates, and closes stays the same. The client prepends a load instruction if the account is cold. - - - - - - - - -The SDK sponsors rent-exemption for your Light-PDAs. After extended inactivity, the account compresses to cold state and the rent-exempt lamports return to the rent sponsor. The common path (hot accounts) has no extra overhead. - - - - - - - -The account data is cryptographically preserved in compressed state. The client prepends a load instruction when someone interacts with it again — your program code doesn't change. Reads, updates, and closes work the same way regardless of whether the account is hot or cold. - - - ---- - -## I don't see the question I want answered - -DM us [@lightprotocol on X (Twitter)](http://x.com/lightprotocol) or [Discord](https://discord.com/invite/rpddh53TeG). - - - \ No newline at end of file diff --git a/home.mdx b/home.mdx index 9979c3b8..f3198f65 100644 --- a/home.mdx +++ b/home.mdx @@ -27,66 +27,70 @@ import PdaCostCombined from "/snippets/cost-tables/pda-cost-combined.mdx"; ZK Compression is a Solana framework that reduces the cost of token accounts and PDAs by 99%. -Whether you're building the next DeFi protocol or integrating enterprise-grade -stablecoin payments, our APIs help you scale. - -## Token APIs +## Compressed Token - High-performance token program and APIs that reduce account creation cost by 99%, while being more CU efficient on hot paths. - The Light Token APIs are a superset of - and fully compatible with - SPL-Tokens. + Rent-free token accounts that reduce account creation cost by 99%. Compressed tokens are supported by leading wallets like Phantom and Backpack, and work with any SPL or Token 2022 mint. ### Integration Guides - - Learn how to integrate Light Token in your stablecoin payment infrastructure. - - - Let users display and swap light-tokens in your wallet application. + + Integrate compressed tokens with Privy embedded wallets for rent-free token accounts. + + + Distribute SPL tokens to many recipients without paying upfront rent per account. - - Build rent-free AMMs and DeFi programs with light-tokens. + + Display balances, fetch history, and send compressed tokens from your wallet application. - - Stream token and mint events from the network in real-time. + + Use Token 2022 mints and extensions with compression. ### Cookbook & Reference - - Step-by-step recipes for every token operation. + + Step-by-step recipes for every compressed token operation. TypeScript and Rust SDKs, Anchor constraints and JSON RPC methods. - - Side-by-side mapping of every Light Token instruction against its SPL/Solana equivalent. - -## PDA Accounts +## Compressed PDAs + + Compressed PDAs are the core primitive. They let you store user, app, or other infrequently accessed state without paying rent-exemption fees. + + +### Guides + - - Solana PDAs with sponsored rent-exemption that you can use with minimal coding overhead. - Works just like any other PDA, e.g. in your DeFi program. + + Build and send transactions that read and write compressed PDA state from a client. + + + Create, update, close, reinitialize, and burn compressed accounts in your program. + + + Issue attestations backed by compressed accounts on devnet. - - Compressed PDAs are the core primitive. They let you store user, app, or other infrequently accessed state without paying rent-exemption fees at all. + + Prevent an instruction from running twice, rent-free. Useful for payments and ZK apps. @@ -154,7 +158,7 @@ codex mcp add deepwiki -- npx -y mcp-remote@latest https://mcp.deepwiki.com/mcp - Learn about the Light Token program and ZK Compression Core. + Learn about compressed tokens and ZK Compression Core. View security audits and formal verification. diff --git a/learn/core-concepts/compressed-account-model.mdx b/learn/compressed-account-model.mdx similarity index 98% rename from learn/core-concepts/compressed-account-model.mdx rename to learn/compressed-account-model.mdx index 51b5554f..814a2246 100644 --- a/learn/core-concepts/compressed-account-model.mdx +++ b/learn/compressed-account-model.mdx @@ -40,7 +40,7 @@ Transactions can use compressed account data inside Solana's virtual machine as - Merkle trees are provided by the protocol and Indexers generate validity proofs. - Developers don't configure state Merkle trees or generate validity proofs. -[You will learn more about Merkle trees and validity proofs in the next section](/learn/core-concepts/merkle-trees-validity-proofs). +[You will learn more about Merkle trees and validity proofs in the next section](/learn/merkle-trees-validity-proofs).
@@ -194,6 +194,6 @@ pub struct CompressedAccountData { title="Learn about the role of validity proofs and Merkle trees in the protocol." icon="chevron-right" color="#0066ff" - href="/learn/core-concepts/merkle-trees-validity-proofs" + href="/learn/merkle-trees-validity-proofs" horizontal > diff --git a/learn/core-concepts/considerations.mdx b/learn/considerations.mdx similarity index 73% rename from learn/core-concepts/considerations.mdx rename to learn/considerations.mdx index 9f50bafc..63425be3 100644 --- a/learn/core-concepts/considerations.mdx +++ b/learn/considerations.mdx @@ -6,15 +6,11 @@ keywords: ["zk compression tradeoffs", "compressed accounts limitations"] # Overview -The sections below describe **compressed account** tradeoffs: larger tx size, higher CU when reading/writing state trees, and per-transaction state cost. These apply when your transaction reads or writes compressed state (e.g. Compressed Tokens, Compressed PDAs, or loading cold Light Token / Light PDA accounts). - -**Light Token** and **Light PDA** have different tradeoffs on the hot path: Light Token is more CU efficient than SPL (e.g. ~312 CU transfer vs ~4,645 SPL); Light PDA hot path adds no extra CU versus a regular PDA. Cold path (loading from compressed) uses the same mechanics as below. +The sections below describe **compressed account** tradeoffs: larger tx size, higher CU when reading/writing state trees, and per-transaction state cost. These apply when your transaction reads or writes compressed state (e.g. Compressed Tokens or Compressed PDAs). | Primitive | Tx size / CU / State cost | More | |:-|:-|:-| -| **Compressed Token / Compressed PDA** | The limits below apply to every operation. | [Legacy Compressed Tokens](/resources/legacy-compressed-tokens), [Compressed PDAs](/pda/compressed-pdas/overview) | -| **Light Token** | Hot path: smaller tx, fewer CU than SPL. Cold path: same as compressed. Rent calculator for creation cost. | [Light Token Standard](/learn/light-token-standard) | -| **Light PDA** | Hot path: same tx size and CU as regular PDA. Cold path: same as compressed. | [Light PDA](/pda/light-pda/overview) | +| **Compressed Token / Compressed PDA** | The limits below apply to every operation. | [Compressed Tokens](/compressed-tokens/overview), [Compressed PDAs](/compressed-pdas/overview) | # Limitations of compressed account operations @@ -56,8 +52,6 @@ System CU usage when reading/writing **compressed state**: - \~6,000 CU per compressed account read/write **Example**: a typical compressed token transfer uses around 292,000 CU. - -This does not apply to **Light Token** or **Light PDA** hot path: Light Token transfers use far fewer CU than SPL; Light PDA hot path adds no extra CU. See [Light Token Standard](/learn/light-token-standard) and [Light PDA](/pda/light-pda/overview). Higher CU usage can: @@ -84,34 +78,18 @@ Writing compressed account state costs a **network fee per state tree** plus **r You're ready to take the next step and start building! - - Rent calculator and CU comparison vs SPL. - - \ No newline at end of file diff --git a/learn/core-concepts.mdx b/learn/core-concepts.mdx deleted file mode 100644 index 1e6290b7..00000000 --- a/learn/core-concepts.mdx +++ /dev/null @@ -1,75 +0,0 @@ ---- -title: "High-level System Overview" -sidebarTitle: "Overview" -description: "Overview to ZK Compression's Core Concepts. Get a high-level system overview and learn about the compressed account model, lifecycle of a transaction, and considerations." -keywords: ["zk compression concepts", "compressed accounts explained", "zk on solana"] ---- - - - - -### Storage of Compressed State - -Compressed accounts store state as call data on Solana's ledger. -This maintains Solana's security and removes the need for rent-exemption per account. - - - -### Accessing Compressed State - -Transactions specify state they access (read/write) and include it in the transaction payload. - - - -### State Validation - -Solana Programs invoke the Light System Program to update compressed state - -1. **The protocol validates the state** (validity of existing state, sum checks, ownership checks) -2. **The protocol enforces a schema:** Classic Accounts → Compressed Accounts.\ - Compressed accounts have a layout similar to classic accounts. - - - -### State Updates - -The new state is recorded as a log on the Solana ledger with each transaction. - - - -### RPC Nodes - -Photon RPC nodes -index the state changes and make the compressed account state available to clients via the ZK Compression RPC API. - - - - -### Forester Nodes - -Keeper nodes that interact with the Account Compression Program to empty queues and rollover state trees. - - -Clients and custom programs do not interact with Forester nodes or the Account Compression Program. This is all done under the hood. - - - - -# Next Steps - -In the following sections, we'll dive into the core concepts that make ZK Compression possible: - -- **Compressed Account Model**: Understand how compressed accounts differ from regular Solana accounts (not much!) and how they enhance efficiency. -- **State Trees**: Learn about the Merkle tree structure used to store compressed accounts and how it minimizes on-chain storage. -- **Validity Proofs**: Learn how zero-knowledge proofs verify data efficiently while keeping proof sizes small. -- **Lifecycle of a Transaction**: Follow the journey of a transaction from creation to execution with ZK Compression. -- **Considerations**: Discover the trade-offs and scenarios where ZK Compression may or may not be the best solution. - - - \ No newline at end of file diff --git a/learn/light-token-standard.mdx b/learn/light-token-standard.mdx deleted file mode 100644 index 3009b099..00000000 --- a/learn/light-token-standard.mdx +++ /dev/null @@ -1,353 +0,0 @@ ---- -title: Core concepts of the Light Token program -sidebarTitle: Core Concepts (Light Token Program) -description: The Light Token Program is a high performance token program that reduces the cost of account creations by 200x, while being more CU efficient than SPL on hot paths. -keywords: ["light token standard on solana", "token 2022 on solana", "token extensions on solana", "spl token on solana", "rent free tokens on solana"] ---- - -import CompressibleVsSolanaRent from "/snippets/compressible-vs-solana-rent.mdx"; -import MintAccountCost from "/snippets/cost-tables/mint-account-cost.mdx"; -import TokenAccountCost from "/snippets/cost-tables/token-account-cost.mdx"; -import CuPerformance from "/snippets/cost-tables/cu-performance.mdx"; -import { CompressibleRentCalculator } from "/snippets/jsx/compressible-rent-calculator.jsx"; -import { RentLifecycleVisualizer } from "/snippets/jsx/rent-lifecycle-visualizer.jsx"; -import CompressibleRentExplained from "/snippets/compressible-rent-explained.mdx"; - - - - - - - - - - - - - - - - - - - - - -
Account TypeKey Features
**[Mint Accounts](#mint-accounts)**Solana Account -
    -
  • Represents a unique mint and optionally can store token-metadata.
  • -
  • Functionally equivalent to SPL mints.
  • -
  • Rent-exemption cost covered by the Light Token Program
  • -
-
**[Token Accounts](#token-account)**Solana account -
    -
  • Stores token balances of mints (SPL, Token-2022, or Light)
  • -
  • Rent-exemption cost covered by the Light Token Program
  • -
-
- - -## Rent Config by Light Token Program - - - - -# Mint Accounts - - - Light mints are on-chain accounts like SPL mints, but with rent-exemption paid for by the Token - program, instead of the user. - - -Light-mints **uniquely represent a token on Solana and store its global metadata**, similar to SPL mint accounts with few core differences: - -1. Tokens created from light-mints are light-tokens. -2. Token metadata (name, symbol, URI) is stored as an extension in the struct. - - - - - - - Diagram showing light-mint account structure with three components: Address (identifier for light-mint in purple box), Account (struct containing BaseMint with SPL-compatible fields, MintMetadata for program state, and optional Extensions for Token Metadata), and BaseMint (containing Supply, Decimals, Mint Authority, and Freeze Authority fields) with Token Metadata extension - - - - ```rust - pub struct Mint { - pub base: BaseMint, - pub metadata: MintMetadata, - /// Reserved bytes (16 bytes) for T22 layout compatibility. - /// Positions account_type at offset 165: 82 (BaseMint) + 67 (metadata) + 16 (reserved) = 165. - pub reserved: [u8; 16], - /// Account type discriminator at byte 165 (1 = Mint, 2 = Account) - pub account_type: u8, - /// Compression info embedded directly in the mint - pub compression: CompressionInfo, - pub extensions: Option>, - } - ``` - - - - - Find the [source code of light-mints - here](https://github.com/Lightprotocol/light-protocol/blob/main/program-libs/token-interface/src/state/mint/compressed_mint.rs#L20). - - -The `metadata` field is used by the Light Token Program to store the internal state of a light-mint. - -The `BaseMint` field replicates the field layout and serialization format of [SPL Mint accounts](https://solana.com/docs/tokens#mint-account). The struct is serialized with Borsh to match the on-chain format of SPL tokens and mints. - -Here is how light-mints and SPL mints compare: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FieldLight-MintSPL Mint
mint_authority
supply
decimals
is_initialized
freeze_authority
Light-Mint Data-
Extensionsvia Token-2022
-
- - ```rust - pub struct BaseMint { - /// Optional authority used to mint new tokens. The mint authority may only - /// be provided during mint creation. If no mint authority is present - /// then the mint has a fixed supply and no further tokens may be - /// minted. - pub mint_authority: Option, - /// Total supply of tokens. - pub supply: u64, - /// Number of base 10 digits to the right of the decimal place. - pub decimals: u8, - /// Is initialized - for SPL compatibility - pub is_initialized: bool, - /// Optional authority to freeze token accounts. - pub freeze_authority: Option, - } - ``` - -
- -# Token Account - - - Light token accounts are on-chain accounts like SPL token accounts, but with rent-exemption paid - for by the Token program, instead of the user. - - -A light-token account holds token balances like SPL Token accounts: - -- A wallet needs a light-token account for each light-mint, SPL mint, or Token 2022 mint it wants to hold, with the wallet address set as the light-token account owner. -- Each wallet can own multiple light-token accounts for the same light-mint. -- A light-token account can only have one owner and hold units of one light-mint. - - - -Additionally Light Token is more compute-efficient than SPL on hot paths: - - - - - - - Diagram showing light-token Solana account structure with three components: Address (identifier for light-token account in purple box), Account (struct containing Data bytes, Executable flag, Lamports balance, and Owner set to Light Token Program), and AccountData (containing Mint, Owner, Amount, and Extensions fields) - - - - ```rust - /// Ctoken account structure (same as SPL Token Account but with extensions). - pub struct Token { - pub mint: Pubkey, - pub owner: Pubkey, - pub amount: u64, - pub delegate: Option, - pub state: AccountState, - pub is_native: Option, - pub delegated_amount: u64, - pub close_authority: Option, - pub account_type: u8, - pub extensions: Option>, - } - ``` - - - - - Find the [source code of light-tokens - here](https://github.com/Lightprotocol/light-protocol/blob/main/program-libs/token-interface/src/state/token/token_struct.rs#L34). - - -Light token accounts replicate the field layout and serialization format of [SPL Token accounts](https://solana.com/docs/tokens#token-account). The struct is serialized with Borsh to match the on-chain format of SPL tokens. - -Here is how light-tokens and SPL tokens compare: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FieldLight TokenSPL Token Account
mint
owner
amount
delegate
state
is_native
delegated_amount
close_authority
extensionsvia Token-2022
- - -# Associated Light Token Account - -**Associated light-token** accounts (light-ATAs) follow the same pattern as [associated token accounts](https://solana.com/docs/tokens#associated-token-account) (ATA): - -- Each wallet needs its own light-token account to hold tokens from the same light-mint. -- The address for light-ATAs is deterministically derived with the owner's address, light token program ID, and mint address. - -```rust -let seeds = [ - owner.as_ref(), // Wallet address (32 bytes) - program_id.as_ref(), // Light Token Program ID (32 bytes) - mint.as_ref(), // light-mint address (32 bytes) - bump.as_ref(), // Bump seed (1 byte) -]; -``` - - - Find the [source code to associated light-token accounts - here](https://github.com/Lightprotocol/light-protocol/blob/main/programs/compressed-token/program/src/ctoken/create_ata.rs). - - -# Compressed Token Account - -Under the hood, compressed token accounts store token balance, owner, and other information of inactive light-tokens. - -1. Light token accounts are automatically compressed/decompressed when active/inactive. -2. Any light-token or SPL token can be compressed/decompressed at will. - -You can still use compressed tokens for [token distribution](/token-distribution). - - - - - Diagram showing compressed token account structure with three components: Hash (identifier for compressed token account in purple box), Account (struct containing Data bytes, Executable flag, Lamports balance, and Address set to None), and AccountData (containing Mint, Owner, Amount, and Extensions fields) - - - - ```rust - pub struct TokenData { - pub mint: Pubkey, - pub owner: Pubkey, - pub amount: u64, - pub delegate: Option, - pub state: u8, - /// Extensions for the compressed token account - pub tlv: Option>, - } - ``` - - - -# Next Steps - - diff --git a/learn/core-concepts/merkle-trees-validity-proofs.mdx b/learn/merkle-trees-validity-proofs.mdx similarity index 98% rename from learn/core-concepts/merkle-trees-validity-proofs.mdx rename to learn/merkle-trees-validity-proofs.mdx index 5d0c4b4d..bd015c87 100644 --- a/learn/core-concepts/merkle-trees-validity-proofs.mdx +++ b/learn/merkle-trees-validity-proofs.mdx @@ -58,7 +58,7 @@ The `state_hash` ensures that each account hash is globally unique. It includes Lastly, `owner_hashed` determines which program owns this account and `lamports` show the account balance. -For [details on the compressed account structure see this section](/learn/core-concepts/compressed-account-model#compressed-account-structure). +For [details on the compressed account structure see this section](/learn/compressed-account-model#compressed-account-structure). @@ -181,7 +181,7 @@ For those interested in learning more about the fundamentals of ZK and its appli title="Learn about the lifecycle of a transaction with compressed accounts." icon="chevron-right" color="#0066ff" - href="/learn/core-concepts/transaction-lifecycle" + href="/learn/transaction-lifecycle" horizontal > \ No newline at end of file diff --git a/learn/overview.mdx b/learn/overview.mdx index 9c513952..e5169c67 100644 --- a/learn/overview.mdx +++ b/learn/overview.mdx @@ -1,36 +1,14 @@ --- -title: Overview of core concepts -sidebarTitle: Overview -description: Learn about Light Token and ZK Compression Core. -keywords: ["zk compression on solana", "scalable solana infrastructure", "compressed accounts on solana", "privacy on solana", "zk on solana", "shielded transactions on solana"] +title: "High-level System Overview" +sidebarTitle: "Overview" +description: "Overview to ZK Compression's Core Concepts. Get a high-level system overview and learn about the compressed account model, lifecycle of a transaction, and considerations." +keywords: ["zk compression concepts", "compressed accounts explained", "zk on solana"] --- - -## What is Light Token? - -Light token is a high-performance token standard that is functionally equivalent to SPL, but stores mint and token accounts more efficiently. This reduces account creation cost while being more CU efficient than SPL on hot paths. - - - - - - - - ## What is ZK Compression? ZK Compression is a Solana account primitive that lets you create tokens and PDAs without rent-exemption cost with L1 performance and security. -The Light Token Program uses ZK Compression under the hood. +Compressed tokens use ZK Compression under the hood. Storage cost of Solana accounts are reduced by combining generalized state compression and zero-knowledge proofs. @@ -46,10 +24,71 @@ Storage cost of Solana accounts are reduced by combining generalized state compr + + + +### Storage of Compressed State + +Compressed accounts store state as call data on Solana's ledger. +This maintains Solana's security and removes the need for rent-exemption per account. + + + +### Accessing Compressed State + +Transactions specify state they access (read/write) and include it in the transaction payload. + + + +### State Validation + +Solana Programs invoke the Light System Program to update compressed state + +1. **The protocol validates the state** (validity of existing state, sum checks, ownership checks) +2. **The protocol enforces a schema:** Classic Accounts → Compressed Accounts.\ + Compressed accounts have a layout similar to classic accounts. + + + +### State Updates + +The new state is recorded as a log on the Solana ledger with each transaction. + + + +### RPC Nodes + +Photon RPC nodes +index the state changes and make the compressed account state available to clients via the ZK Compression RPC API. + + + + +### Forester Nodes + +Keeper nodes that interact with the Account Compression Program to empty queues and rollover state trees. + + +Clients and custom programs do not interact with Forester nodes or the Account Compression Program. This is all done under the hood. + + + + +# Next Steps + +In the following sections, we'll dive into the core concepts that make ZK Compression possible: + +- **Compressed Account Model**: Understand how compressed accounts differ from regular Solana accounts (not much!) and how they enhance efficiency. +- **State Trees**: Learn about the Merkle tree structure used to store compressed accounts and how it minimizes on-chain storage. +- **Validity Proofs**: Learn how zero-knowledge proofs verify data efficiently while keeping proof sizes small. +- **Lifecycle of a Transaction**: Follow the journey of a transaction from creation to execution with ZK Compression. +- **Considerations**: Discover the trade-offs and scenarios where ZK Compression may or may not be the best solution. + \ No newline at end of file +> + \ No newline at end of file diff --git a/learn/core-concepts/transaction-lifecycle.mdx b/learn/transaction-lifecycle.mdx similarity index 97% rename from learn/core-concepts/transaction-lifecycle.mdx rename to learn/transaction-lifecycle.mdx index f234959d..cf23e167 100644 --- a/learn/core-concepts/transaction-lifecycle.mdx +++ b/learn/transaction-lifecycle.mdx @@ -138,7 +138,7 @@ The Solana program executing the state transition _**Data**_** -> **_**Data'**_ - `validity proof`: 128-byte ZK proof that verifies the current account hash exists in the state tree -See this [guide to update a compressed account](/pda/compressed-pdas/guides/how-to-update-compressed-accounts). +See this [guide to update a compressed account](/compressed-pdas/guides/how-to-update-compressed-accounts). @@ -178,7 +178,7 @@ An RPC node then parses the transaction and compressed state and provides the re title="Understand the trade-offs for compressed accounts." icon="chevron-right" color="#0066ff" - href="/learn/core-concepts/considerations" + href="/learn/considerations" horizontal > \ No newline at end of file diff --git a/light-token/cookbook/add-interface-pda.mdx b/light-token/cookbook/add-interface-pda.mdx deleted file mode 100644 index 9e802bf7..00000000 --- a/light-token/cookbook/add-interface-pda.mdx +++ /dev/null @@ -1,55 +0,0 @@ ---- -title: Add Interface PDA to Existing SPL / Token 2022 Mints -sidebarTitle: Add Interface PDA to Existing Mints -description: Create an interface PDA for an existing SPL or Token 2022 mint for interoperability with Light Token. Does not require mint authority. The interface PDA holds SPL or Token 2022 tokens when wrapped to Light Token. ---- - -import TokenPoolActionCode from "/snippets/code-snippets/light-token/create-token-pool/action.mdx"; -import TokenPoolInstructionCode from "/snippets/code-snippets/light-token/create-token-pool/instruction.mdx"; -import TokenPoolTokenInterfaceInstructionCode from "/snippets/code-snippets/light-token/create-token-pool/token-interface-instruction.mdx"; -import SupportFooter from "/snippets/support-footer.mdx"; -import TokenClientPrerequisites from "/snippets/light-token-guides/light-token-client-prerequisites.mdx"; -import AgentSkillGeneric from "/snippets/setup/agent-skill-generic.mdx"; -import AddInterfacePdaAiPrompt from "/snippets/ai-prompts/ts-cookbook/add-interface-pda.mdx"; - - - - - Find the [source code](https://github.com/Lightprotocol/light-protocol/blob/main/js/compressed-token/src/actions/create-token-pool.ts) and examples: [Action](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/actions/create-spl-interface.ts) · [Instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/instructions/create-spl-interface.ts). - - - - - - -### Prerequisites - - - - - - - - - - - - - - - - - - - - - - -## Related Guides - - - - - - - diff --git a/light-token/cookbook/approve-revoke.mdx b/light-token/cookbook/approve-revoke.mdx deleted file mode 100644 index 7ff982eb..00000000 --- a/light-token/cookbook/approve-revoke.mdx +++ /dev/null @@ -1,355 +0,0 @@ ---- -title: Approve and Revoke Delegates -sidebarTitle: Approve / Revoke -description: Guide to approve and revoke delegates for Light Token accounts. Includes step-by-step implementation and full code examples. -keywords: ["approve delegate solana", "revoke delegate solana", "token delegation"] ---- - ---- - -import TokenClientPrerequisites from "/snippets/light-token-guides/light-token-client-prerequisites.mdx"; -import FullSetup from "/snippets/setup/full-setup.mdx"; -import { CodeCompare } from "/snippets/jsx/code-compare.jsx"; -import { - splApproveCode, - lightApproveCode, - splRevokeCode, - lightRevokeCode, - splApproveRustCode, - lightApproveRustCode, - splRevokeRustCode, - lightRevokeRustCode, -} from "/snippets/code-samples/code-compare-snippets.jsx"; -import TsApproveActionCode from "/snippets/code-snippets/light-token/approve-revoke/approve-action.mdx"; -import TsRevokeActionCode from "/snippets/code-snippets/light-token/approve-revoke/revoke-action.mdx"; -import TsApproveTokenInterfaceInstructionCode from "/snippets/code-snippets/light-token/approve-revoke/token-interface-approve-instruction.mdx"; -import TsRevokeTokenInterfaceInstructionCode from "/snippets/code-snippets/light-token/approve-revoke/token-interface-revoke-instruction.mdx"; -import ApproveActionCode from "/snippets/code-snippets/light-token/approve-revoke/rust-client/approve-action.mdx"; -import ApproveInstructionCode from "/snippets/code-snippets/light-token/approve-revoke/rust-client/approve-instruction.mdx"; -import RevokeActionCode from "/snippets/code-snippets/light-token/approve-revoke/rust-client/revoke-action.mdx"; -import RevokeInstructionCode from "/snippets/code-snippets/light-token/approve-revoke/rust-client/revoke-instruction.mdx"; -import ApproveAnchorProgramCode from "/snippets/code-snippets/light-token/approve/anchor-program/full-example.mdx"; -import RevokeAnchorProgramCode from "/snippets/code-snippets/light-token/revoke/anchor-program/full-example.mdx"; -import AgentSkillGeneric from "/snippets/setup/agent-skill-generic.mdx"; -import ApproveRevokeAiPrompt from "/snippets/ai-prompts/ts-cookbook/approve-revoke.mdx"; -import RustApproveRevokeAiPrompt from "/snippets/ai-prompts/rust-cookbook/approve-revoke.mdx"; -import ProgramApproveRevokeAiPrompt from "/snippets/ai-prompts/program-cookbook/approve-revoke.mdx"; -import SupportFooter from "/snippets/support-footer.mdx"; - -1. Approve grants a delegate permission to transfer up to a specified amount of tokens from your account. - * Each token account can have only one delegate at a time. - * Any new approval overwrites the previous one. -2. Revoke removes all delegate permissions from a Light Token account. -3. Only the token account owner can approve or revoke delegates. - - - - - - - - - - -`approveInterface` grants a delegate permission to transfer up to a specified amount of tokens. - - - - - - -`revokeInterface` removes all delegate permissions from a Light Token account. - - - - - - - - - - -### Prerequisites - - - - - - -### Approve or revoke delegates - - - Find the source code: - [delegate-approve.ts](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/actions/delegate-approve.ts) - | - [delegate-revoke.ts](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/actions/delegate-revoke.ts) - | - [delegate-approve (instruction)](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/instructions/delegate-approve.ts) - | - [delegate-revoke (instruction)](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/instructions/delegate-revoke.ts) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -### Prerequisites - - - - - - -### Approve or revoke delegates - - - Find the source code [here](https://github.com/Lightprotocol/light-protocol/blob/main/sdk-libs/token-sdk/src/instruction/approve.rs). - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Find [a full code example at the end](#full-code-example). - - - - - - - -### Build Account Infos and CPI the Light Token Program - -Use `invoke` for external signers or `invoke_signed` when the authority is a PDA. - - - - -```rust -use light_token::instruction::ApproveCpi; - -ApproveCpi { - token_account: token_account.clone(), - delegate: delegate.clone(), - owner: owner.clone(), - system_program: system_program.clone(), - amount, -} -.invoke()?; -``` - - - - -```rust -use light_token::instruction::ApproveCpi; - -let approve_cpi = ApproveCpi { - token_account: token_account.clone(), - delegate: delegate.clone(), - owner: owner.clone(), - system_program: system_program.clone(), - amount, -}; - -let signer_seeds: &[&[u8]] = &[TOKEN_ACCOUNT_SEED, &[bump]]; -approve_cpi.invoke_signed(&[signer_seeds])?; -``` - - - - - - - - - - - - -### Build Account Infos and CPI the Light Token Program - -Use `invoke` for external signers or `invoke_signed` when the authority is a PDA. - - - - -```rust -use light_token::instruction::RevokeCpi; - -RevokeCpi { - token_account: token_account.clone(), - owner: owner.clone(), - system_program: system_program.clone(), -} -.invoke()?; -``` - - - - -```rust -use light_token::instruction::RevokeCpi; - -let revoke_cpi = RevokeCpi { - token_account: token_account.clone(), - owner: owner.clone(), - system_program: system_program.clone(), -}; - -let signer_seeds: &[&[u8]] = &[TOKEN_ACCOUNT_SEED, &[bump]]; -revoke_cpi.invoke_signed(&[signer_seeds])?; -``` - - - - - - - - - -# Full Code Example - - - - - - View the [source code](https://github.com/Lightprotocol/light-protocol/blob/main/sdk-libs/token-sdk/src/instruction/approve.rs) and [full example](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-instructions/approve) with shared test utilities. - - - - - - - - - - View the [source code](https://github.com/Lightprotocol/light-protocol/blob/main/sdk-libs/token-sdk/src/instruction/revoke.rs) and [full example](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-instructions/revoke) with shared test utilities. - - - - - - - - - - - - - - - - -## Related Guides - - - - - - - diff --git a/light-token/cookbook/burn.mdx b/light-token/cookbook/burn.mdx deleted file mode 100644 index 39a5b7b2..00000000 --- a/light-token/cookbook/burn.mdx +++ /dev/null @@ -1,156 +0,0 @@ ---- -title: Burn Light Tokens -sidebarTitle: Burn -description: Rust client guide to burn Light Tokens. Includes step-by-step implementation and full code examples. -keywords: ["burn tokens on solana", "destroy tokens solana", "reduce token supply"] ---- - ---- - -import TokenClientPrerequisites from "/snippets/light-token-guides/light-token-client-prerequisites.mdx"; -import { CodeCompare } from "/snippets/jsx/code-compare.jsx"; -import { - splBurnRustCode, - lightBurnRustCode, -} from "/snippets/code-samples/code-compare-snippets.jsx"; -import RustInstructionCode from "/snippets/code-snippets/light-token/burn/rust-client/instruction.mdx"; -import BurnCheckedRustInstructionCode from "/snippets/code-snippets/light-token/burn-checked/rust-client/instruction.mdx"; -import AnchorProgramCode from "/snippets/code-snippets/light-token/burn/anchor-program/full-example.mdx"; -import AgentSkillGeneric from "/snippets/setup/agent-skill-generic.mdx"; -import RustBurnAiPrompt from "/snippets/ai-prompts/rust-cookbook/burn.mdx"; -import ProgramBurnAiPrompt from "/snippets/ai-prompts/program-cookbook/burn.mdx"; -import SupportFooter from "/snippets/support-footer.mdx"; - - -1. Burn permanently destroys tokens by reducing the balance in a token account. -2. Burned tokens are removed from circulation and decreases the supply tracked on the mint account. -3. Only the token account owner (or approved delegate) can burn tokens. - - - - - - -Compare to SPL: - - - - - - - -### Prerequisites - - - - - - -### Burn Light Tokens - - - Find the source code [here](https://github.com/Lightprotocol/light-protocol/blob/main/sdk-libs/token-sdk/src/instruction/burn.rs). - - - - - - - - - - - - - - - - - - - - - -Find [a full code example at the end](#full-code-example). - - - - - -### Build Account Infos and CPI the Light Token Program - -Use `invoke` for external signers or `invoke_signed` when the authority is a PDA. - - - - -```rust -use light_token::instruction::BurnCpi; - -BurnCpi { - source: source.clone(), - mint: mint.clone(), - amount, - authority: authority.clone(), - system_program: system_program.clone(), - fee_payer: None, - max_top_up: None, -} -.invoke() -``` - - - - -```rust -use light_token::instruction::BurnCpi; - -BurnCpi { - source: source.clone(), - mint: mint.clone(), - amount, - authority: authority.clone(), - system_program: system_program.clone(), - fee_payer: None, - max_top_up: None, -} -.invoke_signed(&[signer_seeds]) -``` - - - - - - - -# Full Code Example - - - View the [source code](https://github.com/Lightprotocol/light-protocol/blob/main/sdk-libs/token-sdk/src/instruction/burn.rs) and [full example](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-instructions/burn) with shared test utilities. - - - - - - - - - - - - - -## Related Guides - - - - - - - diff --git a/light-token/cookbook/close-token-account.mdx b/light-token/cookbook/close-token-account.mdx deleted file mode 100644 index ab7f6729..00000000 --- a/light-token/cookbook/close-token-account.mdx +++ /dev/null @@ -1,163 +0,0 @@ ---- -title: Close Light Token Account -sidebarTitle: Close Token Account -description: Program guide to close Light Token accounts via CPI. Includes step-by-step implementation and full code examples. -keywords: ["close token account on solana", "reclaim rent on solana"] ---- - ---- - -import CloseAccountInfosAccountsList from "/snippets/accounts-list/close-account-infos-accounts-list.mdx"; -import TokenClientPrerequisites from "/snippets/light-token-guides/light-token-client-prerequisites.mdx"; -import ClientCustomRentConfig from "/snippets/light-token-guides/client-custom-rent-config.mdx"; -import { CodeCompare } from "/snippets/jsx/code-compare.jsx"; -import { - splCloseAccountRustCode, - lightCloseAccountRustCode, -} from "/snippets/code-samples/code-compare-snippets.jsx"; -import RustInstructionCode from "/snippets/code-snippets/light-token/close-token-account/rust-client/instruction.mdx"; -import AnchorProgramCode from "/snippets/code-snippets/light-token/close-token-account/anchor-program/full-example.mdx"; -import AgentSkillGeneric from "/snippets/setup/agent-skill-generic.mdx"; -import RustCloseTokenAccountAiPrompt from "/snippets/ai-prompts/rust-cookbook/close-token-account.mdx"; -import ProgramCloseTokenAccountAiPrompt from "/snippets/ai-prompts/program-cookbook/close-token-account.mdx"; -import SupportFooter from "/snippets/support-footer.mdx"; - -1. Closing a Light Token account transfers remaining lamports to a destination account and the rent sponsor can reclaim sponsored rent. -2. Light token accounts can be closed by the owner. - - -The `compression_authority` -closes the account and preserves the balance as compressed token account when the account becomes compressible. -The account is loaded in flight with the same state the next time it is accessed. - - - - - - - -Use `CloseTokenAccount` to close an empty Light Token account. - -Compare to SPL: - - - - - - - -### Prerequisites - - - - - - -### Close Light Token Account - - - Find the source code [here](https://github.com/Lightprotocol/light-protocol/blob/main/sdk-libs/token-sdk/src/instruction/close.rs). - - - - - - - - - - - - - - - - - - - - - - -Find [a full code example at the end](#full-code-example). - - - - -### Build Account Infos and CPI the Light Token Program - -Use `invoke` for external signers or `invoke_signed` when the authority is a PDA. - - - - -```rust -use light_token::instruction::CloseAccountCpi; - -CloseAccountCpi { - token_program: token_program.clone(), - account: account.clone(), - destination: destination.clone(), - owner: owner.clone(), - rent_sponsor: rent_sponsor.clone(), -} -.invoke()?; -``` - - - - -```rust -use light_token::instruction::CloseAccountCpi; - -CloseAccountCpi { - token_program: token_program.clone(), - account: account.clone(), - destination: destination.clone(), - owner: owner.clone(), - rent_sponsor: rent_sponsor.clone(), -} -.invoke_signed(&[signer_seeds])?; -``` - - - - - - - - - - - -# Full Code Example - - - View the [source code](https://github.com/Lightprotocol/light-protocol/blob/main/sdk-libs/token-sdk/src/instruction/close.rs) and [full example](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-instructions/close) with shared test utilities. - - - - - - - - - - - - - -## Related Guides - - - - - - - diff --git a/light-token/cookbook/create-ata.mdx b/light-token/cookbook/create-ata.mdx deleted file mode 100644 index 2787a43f..00000000 --- a/light-token/cookbook/create-ata.mdx +++ /dev/null @@ -1,352 +0,0 @@ ---- -title: Create Associated Light Token Accounts -sidebarTitle: Create Associated Token Account -description: Client and program guide to create associated Light Token accounts. Includes step-by-step implementation and full code examples. -keywords: ["associated token account on solana", "create ata for solana tokens", "rent free ata on solana", "rent free accounts on solana"] ---- - -import TokenCreateATAAccountsList from "/snippets/accounts-list/light-token-create-ata-accounts-list.mdx"; -import TokenConfigureRent from "/snippets/light-token-configure-rent.mdx"; -import CompressibleRentExplained from "/snippets/compressible-rent-explained.mdx"; -import TokenClientPrerequisites from "/snippets/light-token-guides/light-token-client-prerequisites.mdx"; -import { CodeCompare } from "/snippets/jsx/code-compare.jsx"; -import FullSetup from "/snippets/setup/full-setup.mdx"; -import { - splCreateAtaCode, - lightCreateAtaCode, - splCreateAtaRustCode, - lightCreateAtaRustCode, - splCreateAtaMacroCode, - lightCreateAtaMacroCode, - splCreateAtaCpiCode, - lightCreateAtaCpiCode, -} from "/snippets/code-samples/code-compare-snippets.jsx"; -import ActionCode from "/snippets/code-snippets/light-token/create-ata/action.mdx"; -import InstructionCode from "/snippets/code-snippets/light-token/create-ata/instruction.mdx"; -import TokenInterfaceInstructionCode from "/snippets/code-snippets/light-token/create-ata/token-interface-instruction.mdx"; -import RustActionCode from "/snippets/code-snippets/light-token/create-ata/rust-client/action.mdx"; -import RustInstructionCode from "/snippets/code-snippets/light-token/create-ata/rust-client/instruction.mdx"; -import AnchorProgramCode from "/snippets/code-snippets/light-token/create-ata/anchor-program/full-example.mdx"; -import AnchorMacroCode from "/snippets/code-snippets/light-token/create-ata/anchor-macro/full-example.mdx"; -import AgentSkillGeneric from "/snippets/setup/agent-skill-generic.mdx"; -import CreateAtaAiPrompt from "/snippets/ai-prompts/ts-cookbook/create-ata.mdx"; -import RustCreateAtaAiPrompt from "/snippets/ai-prompts/rust-cookbook/create-ata.mdx"; -import ProgramCreateAtaCpiAiPrompt from "/snippets/ai-prompts/program-cookbook/create-ata-cpi.mdx"; -import ProgramCreateAtaMacrosAiPrompt from "/snippets/ai-prompts/program-cookbook/create-ata-macros.mdx"; -import SupportFooter from "/snippets/support-footer.mdx"; - -1. Associated Light Token accounts can hold token balances of light, SPL, or Token 2022 mints. -2. Light-ATAs are on-chain accounts like SPL ATA's, but the light token program sponsors the rent-exemption cost for you. - - - - - - - - - - - -The `createAtaInterface` function creates an associated Light Token account in a single call. - -Compare to SPL: - - - - - Find the source code - [here](https://github.com/Lightprotocol/light-protocol/blob/main/js/compressed-token/src/v3/actions/create-ata-interface.ts). - - - - - - - -### Create Associated Token Account - - - - - - - - - - - - - - - - - - - - - - - - - - - -`CreateAssociatedTokenAccount` creates an on-chain ATA to store token balances of light, SPL, or Token 2022 mints. - -Compare to SPL: - - - - - - - - -### Prerequisites - - - - - - - -### Create ATA - - - Find the source code [here](https://github.com/Lightprotocol/light-protocol/blob/main/sdk-libs/token-sdk/src/instruction/create_ata.rs). - - - - - - - - - - - - - - - - - - - - - - - - - - -Compare to SPL: - - - - -Find [a full code example at the end](#full-code-example). - - - - - -### Build Account Infos and CPI the Light Token Program - -1. Pass ATA accounts and call `.rent_free()` with rent config accounts. -2. Use `invoke` or `invoke_signed`: - - When the `payer` is an external wallet, use `invoke`. - - When the `payer` is a PDA, use `invoke_signed` with its seeds. - - - The light-ATA address is derived from `[owner, light_token_program_id, mint]`. - Unlike Light Token accounts, owner and mint are passed as accounts, not in - instruction data. - - - - - -```rust -use light_token::instruction::CreateAssociatedAccountCpi; - -CreateAssociatedAccountCpi { - payer: payer.clone(), - owner: owner.clone(), - mint: mint.clone(), - ata: associated_token_account.clone(), - bump, -} -.rent_free( - compressible_config.clone(), - rent_sponsor.clone(), - system_program.clone(), -) -.invoke() -``` - - - - -```rust -use light_token::instruction::CreateAssociatedAccountCpi; - -let signer_seeds: &[&[u8]] = &[ATA_SEED, &[authority_bump]]; - -CreateAssociatedAccountCpi { - payer: payer.clone(), - owner: owner.clone(), - mint: mint.clone(), - ata: associated_token_account.clone(), - bump, -} -.rent_free( - compressible_config.clone(), - rent_sponsor.clone(), - system_program.clone(), -) -.invoke_signed(&[signer_seeds]) -``` - - - - - - - -# Full Code Example - - - View the [source code](https://github.com/Lightprotocol/light-protocol/blob/main/sdk-libs/token-sdk/src/instruction/create_ata.rs) and [full example](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-instructions/create-associated-token-account) with shared test utilities. - - - - - - - - - - - - - - -Compare to SPL: - - - - -Find [a full code example at the end](#full-code-example-1). - - - - - -### Dependencies - -```toml -[dependencies] -light-sdk = { version = "0.23.0", features = ["anchor", "v2", "cpi-context"] } -light-sdk-macros = "0.23.0" -light-compressible = "0.6.0" -anchor-lang = "0.31" -``` - - - - -### Program - -Add `#[light_program]` above `#[program]`: - -```rust -use light_sdk_macros::light_program; - -#[light_program] -#[program] -pub mod light_token_macro_create_ata { - use super::*; - - pub fn create_ata<'info>( - ctx: Context<'_, '_, '_, 'info, CreateAta<'info>>, - params: CreateAtaParams, - ) -> Result<()> { - Ok(()) - } -} -``` - - - - -### Accounts struct - -Derive `LightAccounts` on your `Accounts` struct and add `#[light_account(...)]` next to `#[account(...)]`. - -```rust -/// CHECK: Validated by light-token CPI -#[account(mut)] -#[light_account( - init, - associated_token::authority = ata_owner, - associated_token::mint = ata_mint, - associated_token::bump = params.ata_bump -)] -pub ata: UncheckedAccount<'info>, -``` - - - - - -# Full code example - - - View the [source code](https://github.com/Lightprotocol/light-protocol/blob/main/sdk-libs/token-sdk/src/instruction/create_ata.rs) and [full example](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-macros/create-associated-token-account) with shared test utilities. - - - - - - - - - - - - - - -## Related Guides - - - - - - - diff --git a/light-token/cookbook/create-mint.mdx b/light-token/cookbook/create-mint.mdx deleted file mode 100644 index 2e4b51af..00000000 --- a/light-token/cookbook/create-mint.mdx +++ /dev/null @@ -1,579 +0,0 @@ ---- -title: Create Mint Account with Token Metadata -sidebarTitle: Create Light / SPL / Token 2022 Mint Account -description: Create a Light mint with token metadata, or create SPL and Token 2022 mints with interface PDA for interoperability. -keywords: ["create mint account on solana", "rent free mint on solana", "rent free token mints on solana", "spl create mint alternative"] ---- - ---- - -import CMintSystemAccountsList from "/snippets/accounts-list/light-mint-system-accounts-list.mdx"; -import TokenClientPrerequisites from "/snippets/light-token-guides/light-token-client-prerequisites.mdx"; -import TokenTsClientPrerequisites from "/snippets/light-token-guides/light-token-ts-client-prerequisites.mdx"; -import ClientCustomRentConfig from "/snippets/light-token-guides/client-custom-rent-config.mdx"; -import FullSetup from "/snippets/setup/full-setup.mdx"; -import { CodeCompare } from "/snippets/jsx/code-compare.jsx"; -import { - splCreateMintCode, - lightCreateMintCode, - splCreateMintRustCode, - lightCreateMintRustCode, - splCreateMintMacroCode, - lightCreateMintMacroCode, - splCreateMintMetadataMacroCode, - lightCreateMintMetadataMacroCode, - splCreateMintCpiCode, - lightCreateMintCpiCode, - splCreateMintMetadataCpiCode, - lightCreateMintMetadataCpiCode, -} from "/snippets/code-samples/code-compare-snippets.jsx"; -import ActionCode from "/snippets/code-snippets/light-token/create-mint/action.mdx"; -import InstructionCode from "/snippets/code-snippets/light-token/create-mint/instruction.mdx"; -import TokenInterfaceInstructionCode from "/snippets/code-snippets/light-token/create-mint/token-interface-instruction.mdx"; -import SplActionCode from "/snippets/code-snippets/light-token/create-spl-mint/action.mdx"; -import SplInstructionCode from "/snippets/code-snippets/light-token/create-spl-mint/instruction.mdx"; -import SplTokenInterfaceInstructionCode from "/snippets/code-snippets/light-token/create-spl-mint/token-interface-instruction.mdx"; -import T22ActionCode from "/snippets/code-snippets/light-token/create-t22-mint/action.mdx"; -import T22InstructionCode from "/snippets/code-snippets/light-token/create-t22-mint/instruction.mdx"; -import T22TokenInterfaceInstructionCode from "/snippets/code-snippets/light-token/create-t22-mint/token-interface-instruction.mdx"; - -import RustActionCode from "/snippets/code-snippets/light-token/create-mint/rust-client/action.mdx"; -import RustInstructionCode from "/snippets/code-snippets/light-token/create-mint/rust-client/instruction.mdx"; -import AnchorProgramCode from "/snippets/code-snippets/light-token/create-mint/anchor-program/full-example.mdx"; -import AnchorMacroCode from "/snippets/code-snippets/light-token/create-mint/anchor-macro/full-example.mdx"; -import CompressibleRentExplained from "/snippets/compressible-rent-explained.mdx"; -import AgentSkillGeneric from "/snippets/setup/agent-skill-generic.mdx"; -import CreateMintAiPrompt from "/snippets/ai-prompts/ts-cookbook/create-mint.mdx"; -import RustCreateMintAiPrompt from "/snippets/ai-prompts/rust-cookbook/create-mint.mdx"; -import ProgramCreateMintCpiAiPrompt from "/snippets/ai-prompts/program-cookbook/create-mint-cpi.mdx"; -import ProgramCreateMintMacrosAiPrompt from "/snippets/ai-prompts/program-cookbook/create-mint-macros.mdx"; -import SupportFooter from "/snippets/support-footer.mdx"; - -1. Mint accounts uniquely represent a token on Solana and store its global metadata. -2. Light mints are on-chain accounts like SPL mints, but the light token program sponsors the rent-exemption cost for you. -3. [Add an interface PDA](/light-token/cookbook/add-interface-pda) to existing SPL or Token 2022 mints for interoperability with Light Token. The interface PDA holds SPL or Token 2022 tokens when wrapped to Light Token. - - - - - - - - - - - - -`createMintInterface` is a unified interface that dispatches to different mint creation paths based on programId: - -- `TOKEN_PROGRAM_ID` or `TOKEN_2022_PROGRAM_ID` → delegates to SPL or Token 2022 `createMint` -- Otherwise it defaults to `LIGHT_TOKEN_PROGRAM_ID` → creates a Light Token mint - -You can use the same interface regardless of mint type. - -Compare to SPL: - - - - - Find the source code - [here](https://github.com/Lightprotocol/light-protocol/blob/main/js/compressed-token/src/v3/actions/create-mint-interface.ts). - - - - - - - -### Create Mint with Token Metadata - - - - - The `mintAuthority` must be a `Signer` for light-mints but can be just a - `PublicKey` for SPL/Token 2022. - - - - - - - - - - - - - - - - - - - - - - -## Create SPL mint with interface PDA - -Pass `TOKEN_PROGRAM_ID` to create a standard SPL mint with an interface PDA in one transaction for interoperability with Light Token. - - - - - - - - - - - - - -## Create Token 2022 mint with interface PDA - -Pass `TOKEN_2022_PROGRAM_ID` to create a Token-2022 mint with an interface PDA in one transaction for interoperability with Light Token. - - - - - - - - - - - - - - - - - -`CreateMint` creates an on-chain mint account that can optionally include token metadata. -The instruction also writes a compressed mint address to the address Merkle tree, which preserves the mint state when the on-chain account is compressed. - -Compare to SPL: - - - - - - - -### Prerequisites - - - - - - -### Create Light Token Mint with Token Metadata - - - Find the source code [here](https://github.com/Lightprotocol/light-protocol/blob/main/sdk-libs/token-sdk/src/instruction/create_mint.rs). - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Compare to SPL: - - - - - - - - - - - -Find [a full code example at the end](#full-code-example). - - - - -### Configure Token Metadata - -```rust -use light_token_interface::instructions::extensions::{ - token_metadata::TokenMetadataInstructionData, ExtensionInstructionData, -}; - -let extensions = Some(vec![ExtensionInstructionData::TokenMetadata( - TokenMetadataInstructionData { - update_authority: Some(authority.key.to_bytes().into()), - name: b"Example Token".to_vec(), - symbol: b"EXT".to_vec(), - uri: b"https://example.com/metadata.json".to_vec(), - additional_metadata: None, - }, -)]); -``` - - - **Fields must be set at light-mint creation.** Standard fields (`name`, - `symbol`, `uri`) can be updated by `update_authority`. For - `additional_metadata`, only existing keys can be modified or removed. New keys - cannot be added after creation. - - - - - -### Configure Mint - -Configure mint parameters including `decimals`, authorities, rent settings, and pass `extensions` from the previous step. - -```rust -use light_token::instruction::CreateMintParams; - -let params = CreateMintParams { - decimals, - address_merkle_tree_root_index, - mint_authority: *ctx.accounts.authority.key, - proof, - compression_address, - mint, - bump, - freeze_authority, - extensions, - rent_payment: rent_payment.unwrap_or(16), // ~24 hours rent - write_top_up: write_top_up.unwrap_or(766), // ~3 hours rent -}; -``` - - - The address of the mint account is stored in an address Merkle tree - , which is maintained by the protocol. - The client passes a validity proof that proves the mint address does not - exist yet. - - - - - -### System Accounts - -Include system accounts such as the Light System Program - to verify the proof and write the mint address to the address tree. - - - - - -```rust -use light_token::instruction::SystemAccountInfos; - -let system_accounts = SystemAccountInfos { - light_system_program: ctx.accounts.light_system_program.to_account_info(), - cpi_authority_pda: ctx.accounts.cpi_authority_pda.to_account_info(), - registered_program_pda: ctx.accounts.registered_program_pda.to_account_info(), - account_compression_authority: ctx.accounts.account_compression_authority.to_account_info(), - account_compression_program: ctx.accounts.account_compression_program.to_account_info(), - system_program: ctx.accounts.system_program.to_account_info(), -}; -``` - - - - -### Build Account Infos and CPI the Light Token Program - -Use `invoke` or `invoke_signed`: - - When `mint_seed` is an external keypair, use `invoke`. - - When `mint_seed` is a PDA, use `invoke_signed` with its seeds. - - When both `mint_seed` and `authority` are PDAs, use `invoke_signed` with both seeds. - - - - -```rust -use light_token::instruction::CreateMintCpi; - -CreateMintCpi::new( - mint_seed.clone(), - authority.clone(), - payer.clone(), - address_tree.clone(), // stores address - output_queue.clone(), // stores account when inactive - compressible_config.clone(), // rent settings - mint.clone(), - rent_sponsor.clone(), - system_accounts, - params, -) -.invoke() -``` - - - - - -```rust -use light_token::instruction::CreateMintCpi; - -let signer_seeds: &[&[u8]] = &[MINT_SIGNER_SEED, &[bump]]; - -CreateMintCpi::new( - mint_seed.clone(), - authority.clone(), - payer.clone(), - address_tree.clone(), - output_queue.clone(), - compressible_config.clone(), - mint.clone(), - rent_sponsor.clone(), - system_accounts, - params, -) -.invoke_signed(&[signer_seeds]) -``` - - - - - -```rust -use light_token::instruction::CreateMintCpi; - -let mint_seed_seeds: &[&[u8]] = &[MINT_SIGNER_SEED, &[mint_seed_bump]]; -let authority_seeds: &[&[u8]] = &[MINT_AUTHORITY_SEED, &[authority_bump]]; - -CreateMintCpi::new( - mint_seed.clone(), - authority.clone(), - payer.clone(), - address_tree.clone(), - output_queue.clone(), - compressible_config.clone(), - mint.clone(), - rent_sponsor.clone(), - system_accounts, - params, -) -.invoke_signed(&[mint_seed_seeds, authority_seeds]) -``` - - - - - - - - - -# Full Code Example - - - - - - View the [source code](https://github.com/Lightprotocol/light-protocol/blob/main/sdk-libs/token-sdk/src/instruction/create_mint.rs) and [full example](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-instructions/create-mint) with shared test utilities. - - - - - - - - - - - - - - - - - - -Compare to SPL: - - - - - - - - - - - -Find [a full code example at the end](#full-code-example). - - - - - -### Dependencies - -```toml -[dependencies] -light-sdk = { version = "0.23.0", features = ["anchor", "v2", "cpi-context"] } -light-sdk-macros = "0.23.0" -light-compressible = "0.6.0" -anchor-lang = "0.31" -``` - - - - -### Program - -Add `#[light_program]` above `#[program]`: - -```rust -use light_sdk_macros::light_program; - -#[light_program] -#[program] -pub mod my_program { - use super::*; - - pub fn create_mint<'info>( - ctx: Context<'_, '_, '_, 'info, CreateMint<'info>>, - params: CreateMintParams, - ) -> Result<()> { - Ok(()) - } -} -``` - - - - -### Accounts struct - -Derive `LightAccounts` on your `Accounts` struct and add `#[light_account(...)]` next to `#[account(...)]`. - - - - -```rust -/// CHECK: Validated by light-token CPI -#[account(mut)] -#[light_account(init, - mint::signer = mint_signer, - mint::authority = fee_payer, - mint::decimals = 9, - mint::seeds = &[MINT_SIGNER_SEED, self.authority.to_account_info().key.as_ref()], - mint::bump = params.mint_signer_bump -)] -pub mint: UncheckedAccount<'info>, -``` - - - - -```rust -/// CHECK: Validated by light-token CPI -#[account(mut)] -#[light_account(init, - mint::signer = mint_signer, - mint::authority = fee_payer, - mint::decimals = 9, - mint::seeds = &[MINT_SIGNER_SEED, self.authority.to_account_info().key.as_ref()], - mint::bump = params.mint_signer_bump, - mint::name = params.name.clone(), - mint::symbol = params.symbol.clone(), - mint::uri = params.uri.clone(), - mint::update_authority = authority, - mint::additional_metadata = params.additional_metadata.clone() -)] -pub mint: UncheckedAccount<'info>, -``` - - - - - - - - -# Full code example - - - View the [source code](https://github.com/Lightprotocol/light-protocol/blob/main/sdk-libs/token-sdk/src/instruction/create_mint.rs) and [full example](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-macros/create-mint) with shared test utilities. - - - - - - - - - - - - - - - -## Related Guides - - - - - - - diff --git a/light-token/cookbook/create-token-account.mdx b/light-token/cookbook/create-token-account.mdx deleted file mode 100644 index 0deab881..00000000 --- a/light-token/cookbook/create-token-account.mdx +++ /dev/null @@ -1,287 +0,0 @@ ---- -title: Create Light Token Account -sidebarTitle: Create Token Account -description: Client and program guide to create Light Token accounts. Includes step-by-step implementation and full code examples. -keywords: ["token account on solana", "rent free token account for apps", "rent free solana accounts"] ---- - ---- - -import TokenCreateAccountsList from "/snippets/accounts-list/light-token-create-accounts-list.mdx"; -import TokenClientPrerequisites from "/snippets/light-token-guides/light-token-client-prerequisites.mdx"; -import CompressibleRentExplained from "/snippets/compressible-rent-explained.mdx"; -import { CodeCompare } from "/snippets/jsx/code-compare.jsx"; -import { - splCreateTokenAccountRustCode, - lightCreateTokenAccountRustCode, - splCreateTokenAccountMacroCode, - lightCreateTokenAccountMacroCode, - splCreateTokenAccountCpiCode, - lightCreateTokenAccountCpiCode, -} from "/snippets/code-samples/code-compare-snippets.jsx"; -import RustInstructionCode from "/snippets/code-snippets/light-token/create-token-account/rust-client/instruction.mdx"; -import AnchorProgramCode from "/snippets/code-snippets/light-token/create-token-account/anchor-program/full-example.mdx"; -import AnchorMacroCode from "/snippets/code-snippets/light-token/create-token-account/anchor-macro/full-example.mdx"; -import AgentSkillGeneric from "/snippets/setup/agent-skill-generic.mdx"; -import RustCreateTokenAccountAiPrompt from "/snippets/ai-prompts/rust-cookbook/create-token-account.mdx"; -import ProgramCreateTokenAccountCpiAiPrompt from "/snippets/ai-prompts/program-cookbook/create-token-account-cpi.mdx"; -import ProgramCreateTokenAccountMacrosAiPrompt from "/snippets/ai-prompts/program-cookbook/create-token-account-macros.mdx"; -import SupportFooter from "/snippets/support-footer.mdx"; - -1. Light token accounts are Solana accounts that hold token balances of light, SPL, or Token 2022 mints. -2. Light token accounts are on-chain accounts like SPL ATA's, but the light token program sponsors the rent-exemption cost for you. - - - - - - - - - - - -`CreateTokenAccount` creates an on-chain token account to store token balances of light, SPL, or Token 2022 mints. - -Compare to SPL: - - - - - - -### Prerequisites - - - - - - -### Create Token Account - - - Find the source code [here](https://github.com/Lightprotocol/light-protocol/blob/main/sdk-libs/token-sdk/src/instruction/create_associated_token_account.rs). - - - - - - - - - - - - - - - - - - - - - - - - -Compare to SPL: - - - - -Find [a full code example at the end](#full-code-example). - - - - -### Build Account Infos and CPI the Light Token Program - -Use `invoke` for external signers or `invoke_signed` when the authority is a PDA. - - - - -```rust -use light_token::instruction::CreateTokenAccountCpi; - -CreateTokenAccountCpi { - payer: payer.clone(), - account: account.clone(), - mint: mint.clone(), - owner, -} -.rent_free( - compressible_config.clone(), - rent_sponsor.clone(), - system_program.clone(), - token_program.key, // light token program -) -.invoke() -``` - - - - - - -```rust -use light_token::instruction::CreateTokenAccountCpi; - -let signer_seeds = authority_seeds!(authority_bump); - -CreateTokenAccountCpi { - payer: payer.clone(), - account: account.clone(), - mint: mint.clone(), - owner, -} -.rent_free( - compressible_config.clone(), - rent_sponsor.clone(), - system_program.clone(), - program_id, -) -.invoke_signed(signer_seeds) -``` - - - - - - - -# Full Code Example - - - View the [source code](https://github.com/Lightprotocol/light-protocol/blob/main/sdk-libs/token-sdk/src/instruction/create_associated_token_account.rs) and [full example](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-instructions/create-token-account) with shared test utilities. - - - - - - - - - - - - - - -Compare to SPL: - - - - -Find [a full code example at the end](#full-code-example-1). - - - - - -### Dependencies - -```toml -[dependencies] -light-sdk = { version = "0.23.0", features = ["anchor", "v2", "cpi-context"] } -light-sdk-macros = "0.23.0" -light-compressible = "0.6.0" -anchor-lang = "0.31" -``` - - - - -### Program - -Add `#[light_program]` above `#[program]`: - -```rust -use light_sdk_macros::light_program; - -#[light_program] -#[program] -pub mod light_token_macro_create_token_account { - use super::*; - - pub fn create_token_account<'info>( - ctx: Context<'_, '_, '_, 'info, CreateTokenAccount<'info>>, - params: CreateTokenAccountParams, - ) -> Result<()> { - Ok(()) - } -} -``` - - - - -### Accounts struct - -Derive `LightAccounts` on your `Accounts` struct and add `#[light_account(...)]` next to `#[account(...)]`. - -```rust -/// CHECK: Validated by light-token CPI -#[account( - mut, - seeds = [VAULT_SEED, mint.key().as_ref()], - bump, -)] -#[light_account(init, - token::authority = [VAULT_SEED, self.mint.key()], - token::mint = mint, - token::owner = vault_authority, - token::bump = params.vault_bump -)] -pub vault: UncheckedAccount<'info>, -``` - - - - - -# Full code example - - - View the [source code](https://github.com/Lightprotocol/light-protocol/blob/main/sdk-libs/token-sdk/src/instruction/create_associated_token_account.rs) and [full example](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-macros/create-token-account) with shared test utilities. - - - - - - - - - - - - - - -## Related Guides - - - - - - - diff --git a/light-token/cookbook/freeze-thaw.mdx b/light-token/cookbook/freeze-thaw.mdx deleted file mode 100644 index d5121e63..00000000 --- a/light-token/cookbook/freeze-thaw.mdx +++ /dev/null @@ -1,246 +0,0 @@ ---- -title: Freeze and Thaw Light Token Accounts -sidebarTitle: Freeze / Thaw -description: Rust client guide to freeze and thaw Light Token accounts. Includes step-by-step implementation and full code examples. -keywords: ["freeze token account solana", "thaw token account solana", "token account management"] ---- - ---- - -import TokenClientPrerequisites from "/snippets/light-token-guides/light-token-client-prerequisites.mdx"; -import { CodeCompare } from "/snippets/jsx/code-compare.jsx"; -import { - splFreezeRustCode, - lightFreezeRustCode, - splThawRustCode, - lightThawRustCode, -} from "/snippets/code-samples/code-compare-snippets.jsx"; -import FreezeInstructionCode from "/snippets/code-snippets/light-token/freeze-thaw/rust-client/freeze-instruction.mdx"; -import ThawInstructionCode from "/snippets/code-snippets/light-token/freeze-thaw/rust-client/thaw-instruction.mdx"; -import FreezeAnchorProgramCode from "/snippets/code-snippets/light-token/freeze/anchor-program/full-example.mdx"; -import ThawAnchorProgramCode from "/snippets/code-snippets/light-token/thaw/anchor-program/full-example.mdx"; -import AgentSkillGeneric from "/snippets/setup/agent-skill-generic.mdx"; -import RustFreezeThawAiPrompt from "/snippets/ai-prompts/rust-cookbook/freeze-thaw.mdx"; -import ProgramFreezeThawAiPrompt from "/snippets/ai-prompts/program-cookbook/freeze-thaw.mdx"; -import SupportFooter from "/snippets/support-footer.mdx"; - -1. Freeze prevents all transfers or token burns from a specific Light Token account. -2. Once frozen, the account cannot send tokens, receive tokens, or be closed until it is thawed. -3. Thaw re-enables transfers on a frozen Light Token account. -4. Only the freeze authority (set at mint creation) can freeze or thaw accounts. -5. If the freeze authority is revoked (set to null) on the mint account, tokens can never be frozen. - - - - - - - - - - - - - - - - - - - - - - - -### Prerequisites - - - - - - -### Freeze or thaw Light Token accounts - - - Find the source code [here](https://github.com/Lightprotocol/light-protocol/blob/main/sdk-libs/token-sdk/src/instruction/freeze.rs). - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Find [a full code example at the end](#full-code-example). - - - - - - - -### Build Account Infos and CPI the Light Token Program - -Use `invoke` for external signers or `invoke_signed` when the authority is a PDA. - - - - -```rust -use light_token::instruction::FreezeCpi; - -FreezeCpi { - token_account: ctx.accounts.token_account.to_account_info(), - mint: ctx.accounts.mint.to_account_info(), - freeze_authority: ctx.accounts.freeze_authority.to_account_info(), -} -.invoke()?; -``` - - - - -```rust -use light_token::instruction::FreezeCpi; - -let signer_seeds = authority_seeds!(bump); - -FreezeCpi { - token_account: token_account.clone(), - mint: mint.clone(), - freeze_authority: freeze_authority.clone(), -} -.invoke_signed(&[signer_seeds]) -``` - - - - - - - - - - - - -### Build Account Infos and CPI the Light Token Program - -Use `invoke` for external signers or `invoke_signed` when the authority is a PDA. - - - - -```rust -use light_token::instruction::ThawCpi; - -ThawCpi { - token_account: ctx.accounts.token_account.to_account_info(), - mint: ctx.accounts.mint.to_account_info(), - freeze_authority: ctx.accounts.freeze_authority.to_account_info(), -} -.invoke()?; -``` - - - - -```rust -use light_token::instruction::ThawCpi; - -let signer_seeds = authority_seeds!(bump); - -ThawCpi { - token_account: token_account.clone(), - mint: mint.clone(), - freeze_authority: freeze_authority.clone(), -} -.invoke_signed(&[signer_seeds]) -``` - - - - - - - - - -# Full Code Example - - - - - - View the [source code](https://github.com/Lightprotocol/light-protocol/blob/main/sdk-libs/token-sdk/src/instruction/freeze.rs) and [full example](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-instructions/freeze) with shared test utilities. - - - - - - - - - - View the [source code](https://github.com/Lightprotocol/light-protocol/blob/main/sdk-libs/token-sdk/src/instruction/thaw.rs) and [full example](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-instructions/thaw) with shared test utilities. - - - - - - - - - - - - - - - - -## Related Guides - - - - - - - diff --git a/light-token/cookbook/load-ata.mdx b/light-token/cookbook/load-ata.mdx deleted file mode 100644 index e45da727..00000000 --- a/light-token/cookbook/load-ata.mdx +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: Load Token Balances to Light Associated Token Account -sidebarTitle: Load Associated Token Account -description: Unify token balances from compressed tokens (cold Light Tokens), SPL, and Token 2022 to one light ATA. -keywords: ["load ata on solana", "get token balance for wallets"] ---- - -import FullSetup from "/snippets/setup/full-setup.mdx"; -import ActionCode from "/snippets/code-snippets/light-token/load-ata/action.mdx"; -import InstructionCode from "/snippets/code-snippets/light-token/load-ata/instruction.mdx"; -import TokenInterfaceInstructionCode from "/snippets/code-snippets/light-token/load-ata/token-interface-instruction.mdx"; -import AgentSkillGeneric from "/snippets/setup/agent-skill-generic.mdx"; -import SupportFooter from "/snippets/support-footer.mdx"; - -1. `loadAta` unifies tokens from multiple sources to a single ATA: - * Compressed tokens (cold Light Tokens) -> Decompresses -> light ATA - * SPL balance (if wrap=true) -> Wraps -> light ATA - * Token 2022 balance (if wrap=true) -> Wraps -> light ATA - -2. Returns `null` if there's nothing to load (idempotent) - -3. Creates the ATA if it doesn't exist - - -Find the source code [here](https://github.com/Lightprotocol/light-protocol/blob/main/js/compressed-token/src/v3/actions/load-ata.ts). - - - - - - -### Unify Tokens to Light-ATA Balance - - - - - - - - - - - - - - - - - - -## Related Guides - - - - - - - diff --git a/light-token/cookbook/mint-to.mdx b/light-token/cookbook/mint-to.mdx deleted file mode 100644 index bff1d1fb..00000000 --- a/light-token/cookbook/mint-to.mdx +++ /dev/null @@ -1,227 +0,0 @@ ---- -title: Mint to Light Token Accounts -sidebarTitle: Mint To -description: Client and program guide to mint tokens to a account. Includes step-by-step implementation and full code examples. -keywords: ["mint tokens on solana", "spl mint to for developers", "token minting for protocols"] ---- - ---- - -import CMintSystemAccountsList from "/snippets/accounts-list/light-mint-system-accounts-list.mdx"; -import MintToTokenAccountsList from "/snippets/accounts-list/light-mint-to-light-token-accounts-list.mdx"; -import TokenClientPrerequisites from "/snippets/light-token-guides/light-token-client-prerequisites.mdx"; -import ClientCustomRentConfig from "/snippets/light-token-guides/client-custom-rent-config.mdx"; -import { CodeCompare } from "/snippets/jsx/code-compare.jsx"; -import FullSetup from "/snippets/setup/full-setup.mdx"; -import { - splMintToCode, - lightMintToCode, - splMintToRustCode, - lightMintToRustCode, -} from "/snippets/code-samples/code-compare-snippets.jsx"; -import ActionCode from "/snippets/code-snippets/light-token/mint-to/action.mdx"; -import InstructionCode from "/snippets/code-snippets/light-token/mint-to/instruction.mdx"; -import TokenInterfaceInstructionCode from "/snippets/code-snippets/light-token/mint-to/token-interface-instruction.mdx"; -import RustActionCode from "/snippets/code-snippets/light-token/mint-to/rust-client/action.mdx"; -import RustInstructionCode from "/snippets/code-snippets/light-token/mint-to/rust-client/instruction.mdx"; -import AnchorProgramCode from "/snippets/code-snippets/light-token/mint-to/anchor-program/full-example.mdx"; -import AgentSkillGeneric from "/snippets/setup/agent-skill-generic.mdx"; -import MintToAiPrompt from "/snippets/ai-prompts/ts-cookbook/mint-to.mdx"; -import RustMintToAiPrompt from "/snippets/ai-prompts/rust-cookbook/mint-to.mdx"; -import ProgramMintToAiPrompt from "/snippets/ai-prompts/program-cookbook/mint-to.mdx"; -import SupportFooter from "/snippets/support-footer.mdx"; - - -1. Mint To creates new tokens of a mint and deposits them to a specified token account. -2. Before we can mint any tokens, we need an initialized mint account (SPL, Token 2022 or Light) for which we hold the mint authority. - - - - - - - -`mintToInterface` mints tokens to token accounts in a single call. - -The function auto-detects the token program (SPL, Token 2022, or Light) from the mint address. - -Compare to SPL: - - - - - Find the source code - [here](https://github.com/Lightprotocol/light-protocol/blob/main/js/compressed-token/src/v3/actions/mint-to-interface.ts). - - - - - - -### Mint Tokens to Light Token Account - - - - - - - - - - - - - - - - - - - - - - - - - - - -Use `MintTo` to mint tokens to a Light Token account. - -Compare to SPL: - - - - - - - -### Prerequisites - - - - - - -### Mint to Light Token Accounts - - - Find the source code [here](https://github.com/Lightprotocol/light-protocol/blob/main/sdk-libs/token-sdk/src/instruction/mint_to.rs). - - - - - - - - - - - - - - - - - - - - - - - - -Find [a full code example at the end](#full-code-example). - - - - - -### Build Account Infos and CPI the Light Token Program - -Use `invoke` for external signers or `invoke_signed` when the authority is a PDA. - - - - -```rust -use light_token::instruction::MintToCpi; - -MintToCpi { - mint: mint.clone(), - destination: destination.clone(), - amount, - authority: authority.clone(), - system_program: system_program.clone(), - fee_payer: None, - max_top_up: None, -} -.invoke() -``` - - - - -```rust -use light_token::instruction::MintToCpi; - -let signer_seeds: &[&[u8]] = &[MINT_AUTHORITY_SEED, &[bump]]; - -MintToCpi { - mint: mint.clone(), - destination: destination.clone(), - amount, - authority: authority.clone(), - system_program: system_program.clone(), - fee_payer: None, - max_top_up: None, -} -.invoke_signed(&[signer_seeds]) -``` - - - - - - `fee_payer` and `max_top_up` are optional fields to customize rent top-ups. - Set to `None` to use defaults. - - - - - -# Full Code Example - - - View the [source code](https://github.com/Lightprotocol/light-protocol/blob/main/sdk-libs/token-sdk/src/instruction/mint_to.rs) and [full example](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-instructions/mint-to) with shared test utilities. - - - - - - - - - - - - -## Related Guides - - - - - - - diff --git a/light-token/cookbook/transfer-checked.mdx b/light-token/cookbook/transfer-checked.mdx deleted file mode 100644 index 254ed4b7..00000000 --- a/light-token/cookbook/transfer-checked.mdx +++ /dev/null @@ -1,117 +0,0 @@ ---- -title: Transfer Checked -sidebarTitle: Transfer Checked -description: Program CPI guide for Light Token transfer with decimal validation. Includes step-by-step implementation and full code examples. -keywords: ["transfer tokens solana", "checked transfer", "decimal validation"] ---- - -import AnchorProgramCode from "/snippets/code-snippets/light-token/transfer-checked/anchor-program/full-example.mdx"; -import AgentSkillGeneric from "/snippets/setup/agent-skill-generic.mdx"; -import ProgramTransferCheckedAiPrompt from "/snippets/ai-prompts/program-cookbook/transfer-checked.mdx"; -import SupportFooter from "/snippets/support-footer.mdx"; - -1. TransferChecked validates that the decimals parameter matches the mint's decimals. -2. Use `TransferCheckedCpi` for Light-to-Light transfers in on-chain programs when you need decimal verification without interface routing. -3. For transfers involving SPL or Token 2022 accounts, use [Transfer Interface](/light-token/cookbook/transfer-interface) instead. It uses `transferChecked` under the hood. - - - - - - - -`transferChecked` is called automatically under the hood by [`transferInterface`](/light-token/cookbook/transfer-interface) and `createTransferInterfaceInstructions`. You do not need to call it directly. - - - - - -`TransferChecked` is called automatically under the hood by [`TransferInterface`](/light-token/cookbook/transfer-interface). You do not need to call it directly. - - - - - - - - -Find [a full code example at the end](#full-code-example). - - - - -### Transfer Checked with CPI - - - - -```rust -use light_token::instruction::TransferCheckedCpi; - -TransferCheckedCpi { - source: source.clone(), - mint: mint.clone(), - destination: destination.clone(), - amount, - decimals, - authority: authority.clone(), - system_program: system_program.clone(), - max_top_up: None, - fee_payer: None, -} -.invoke()?; -``` - - - - -```rust -use light_token::instruction::TransferCheckedCpi; - -let signer_seeds = authority_seeds!(bump); - -TransferCheckedCpi { - source: source.clone(), - mint: mint.clone(), - destination: destination.clone(), - amount, - decimals, - authority: authority.clone(), - system_program: system_program.clone(), - max_top_up: None, - fee_payer: None, -} -.invoke_signed(&[signer_seeds])?; -``` - - - - - - - -# Full Code Example - - - View the [source code](https://github.com/Lightprotocol/light-protocol/blob/main/sdk-libs/token-sdk/src/instruction/transfer_checked.rs) and [full example](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-instructions/transfer-checked) with shared test utilities. - - - - - - - - - - - - - -## Related Guides - - - - - - - diff --git a/light-token/cookbook/transfer-delegated.mdx b/light-token/cookbook/transfer-delegated.mdx deleted file mode 100644 index 1a37ef76..00000000 --- a/light-token/cookbook/transfer-delegated.mdx +++ /dev/null @@ -1,56 +0,0 @@ ---- -title: Delegated Transfer -sidebarTitle: Delegated Transfer -description: Transfer tokens as an approved delegate. The delegate signs instead of the owner, spending within the approved allowance. -keywords: ["delegated transfer solana", "delegate transfer light token", "token delegation transfer"] ---- - -import FullSetup from "/snippets/setup/full-setup.mdx"; -import AgentSkillGeneric from "/snippets/setup/agent-skill-generic.mdx"; -import DelegateTransferAction from "/snippets/code-snippets/payments/spend-permissions/delegate-transfer.mdx"; -import DelegateTransferInstruction from "/snippets/code-snippets/payments/spend-permissions/delegate-transfer-instruction.mdx"; -import DelegateTransferTokenInterfaceInstruction from "/snippets/code-snippets/payments/spend-permissions/delegate-transfer-token-interface-instruction.mdx"; -import SupportFooter from "/snippets/support-footer.mdx"; - -`transferInterface` with `{ owner }` transfers tokens from an associated token account as an approved delegate. The delegate is the transaction authority. Only the delegate and fee payer sign; the owner's signature is not required. - -- The recipient is a wallet address (associated token account derived and created internally) -- The amount must be within the approved allowance -- Each transfer reduces the remaining allowance - - - - - - - - -### Delegated Transfer - - - - - - - - - - - - - - - - - - - - -## Related Guides - - - - - - - diff --git a/light-token/cookbook/transfer-interface.mdx b/light-token/cookbook/transfer-interface.mdx deleted file mode 100644 index 09983982..00000000 --- a/light-token/cookbook/transfer-interface.mdx +++ /dev/null @@ -1,365 +0,0 @@ ---- -title: Transfer Interface -description: Transfer tokens between Light Token, SPL and Token 2022 accounts. The interface checks decimals under the hood and detects account types to invoke the right programs. -keywords: ["transfer tokens on solana", "token transfer on solana", "interface methods on solana", "spl transfer for developers"] ---- - -import TransferInterfaceIntro from "/snippets/light-token-guides/transfer-interface-intro.mdx"; -import TokenClientPrerequisites from "/snippets/light-token-guides/light-token-client-prerequisites.mdx"; -import TokenTsClientPrerequisites from "/snippets/light-token-guides/light-token-ts-client-prerequisites.mdx"; -import ClientCustomRentConfig from "/snippets/light-token-guides/client-custom-rent-config.mdx"; -import { CodeCompare } from "/snippets/jsx/code-compare.jsx"; -import FullSetup from "/snippets/setup/full-setup.mdx"; -import { - splTransferCode, - lightTransferCode, - splTransferRustCode, - lightTransferRustCode, -} from "/snippets/code-samples/code-compare-snippets.jsx"; -import ActionCode from "/snippets/code-snippets/light-token/transfer-interface/action.mdx"; -import InstructionCode from "/snippets/code-snippets/light-token/transfer-interface/instruction.mdx"; -import TokenInterfaceInstructionCode from "/snippets/code-snippets/light-token/transfer-interface/token-interface-instruction.mdx"; -import RustActionCode from "/snippets/code-snippets/light-token/transfer-interface/rust-client/action.mdx"; -import RustInstructionCode from "/snippets/code-snippets/light-token/transfer-interface/rust-client/instruction.mdx"; -import AnchorProgramCode from "/snippets/code-snippets/light-token/transfer-interface/anchor-program/full-example.mdx"; -import CreateAndTransferCode from "/snippets/code-snippets/light-token/transfer-interface/anchor-program/create-and-transfer-example.mdx"; -import AgentSkillGeneric from "/snippets/setup/agent-skill-generic.mdx"; -import TransferInterfaceAiPrompt from "/snippets/ai-prompts/ts-cookbook/transfer-interface.mdx"; -import RustTransferInterfaceAiPrompt from "/snippets/ai-prompts/rust-cookbook/transfer-interface.mdx"; -import ProgramTransferInterfaceAiPrompt from "/snippets/ai-prompts/program-cookbook/transfer-interface.mdx"; -import SupportFooter from "/snippets/support-footer.mdx"; - - - - - - - - - - - - - - - - - -
**Light Token -> Light Token Account** -
    -
  • Transfers tokens between Light Token accounts
  • -
-
**Token 2022 / SPL token -> Light Token Account** -
    -
  • Transfers SPL tokens to Light Token accounts
  • -
  • SPL / Token 2022 tokens are locked in interface PDA
  • -
  • Tokens are minted to Light Token account
  • -
-
**Light Token -> SPL / Token 2022 Account** -
    -
  • Releases SPL / Token 2022 tokens from interface PDA to SPL account
  • -
  • Burns tokens in source Light Token account
  • -
-
- - - - - - - -The `transferInterface` function transfers tokens between token accounts (SPL, Token 2022, or Light) in a single call and checks decimals. - -Compare to SPL: - - - - - Find the source code - [here](https://github.com/Lightprotocol/light-protocol/blob/main/js/compressed-token/src/v3/actions/transfer-interface.ts). - - - - - - - -### Transfer Interface - - - - - - - - - - - - - - - - - - - - - - - -### Advanced: Explicit Destination Account - -For PDA destinations or program-owned accounts where you need to specify the exact destination token account, use `transferToAccountInterface`. This is an edge case; most transfers should use `transferInterface` with a wallet address. - - - - -```typescript -import { - transferToAccountInterface, - getAssociatedTokenAddressInterface, -} from "@lightprotocol/compressed-token"; - -// The destination must be an existing token account (not a wallet address). -await transferToAccountInterface( - rpc, - payer, - sourceAta, - mint, - destinationTokenAccount, - owner, - amount, -); -``` - - - - -```typescript -import { - createTransferToAccountInterfaceInstructions, - getMintInterface, - sliceLast, -} from "@lightprotocol/compressed-token"; - -const decimals = (await getMintInterface(rpc, mint)).mint.decimals; - -// Returns TransactionInstruction[][]. The destination must be an existing token account. -const batches = await createTransferToAccountInterfaceInstructions( - rpc, - payer.publicKey, - mint, - amount, - owner.publicKey, - destinationTokenAccount, - decimals, -); - -const { rest: loads, last: transfer } = sliceLast(batches); -``` - - - - -```typescript -import { Transaction, sendAndConfirmTransaction } from "@solana/web3.js"; -import { - createTransferCheckedInstruction, - createLoadInstructions, -} from "@lightprotocol/token-interface"; - -// The destination must be an existing token account. -const destinationTokenAccount = /* existing ATA or program-owned token account */; -const sourceAta = /* owner's Light ATA */; -const decimals = 9; - -const loadIxs = await createLoadInstructions({ - rpc, - payer: payer.publicKey, - owner: owner.publicKey, - mint, - authority: owner.publicKey, -}); - -const transferIx = createTransferCheckedInstruction({ - source: sourceAta, - destination: destinationTokenAccount, - mint, - authority: owner.publicKey, - payer: payer.publicKey, - amount: 500_000_000n, - decimals, -}); - -const tx = new Transaction().add(...loadIxs, transferIx); -await sendAndConfirmTransaction(rpc, tx, [payer, owner]); -``` - - - - - - - - - -Use the unified `TransferInterface` to transfer tokens between token accounts (SPL, Token 2022, or Light) in a single call and checks decimals. - - - - - - - -### Prerequisites - - - - - - -### Transfer Interface - -The example transfers -1. SPL token -> Light Token, -2. Light Token -> Light Token, and -3. Light Token -> SPL token. - - - Find the source code [here](https://github.com/Lightprotocol/light-protocol/blob/main/sdk-libs/token-sdk/src/instruction/transfer_interface.rs). - - - - - - - - - - - - - - - - - - - - - - - - - - -Find [a full code example at the end](#full-code-example). - - - - -### Transfer Interface CPI - -The `TransferInterfaceCpi` transfers tokens between token accounts (SPL, Token 2022, or Light Token). - - - - -```rust -use light_token::instruction::TransferInterfaceCpi; - -TransferInterfaceCpi::new( - amount, - decimals, - source.clone(), - destination.clone(), - authority.clone(), - payer.clone(), - light_token_authority.clone(), - system_program.clone(), -) -.invoke()?; -``` - - - - -```rust -use light_token::instruction::TransferInterfaceCpi; - -let signer_seeds = authority_seeds!(bump); - -TransferInterfaceCpi::new( - amount, - decimals, - source.clone(), - destination.clone(), - authority.clone(), - payer.clone(), - light_token_authority.clone(), - system_program.clone(), -) -.invoke_signed(&[signer_seeds])?; -``` - - - - - - - -# Full code example - - - - - - View the [source code](https://github.com/Lightprotocol/light-protocol/blob/main/sdk-libs/token-sdk/src/instruction/transfer_interface.rs) and [full example](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-instructions/transfer-interface) with shared test utilities. - - - - - - - - -Uses the `#[light_account(init, associated_token::...)]` macro to create the destination ATA during the transfer. - - - View the [full example](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/create-and-transfer) with test utilities. - - - - - - - - - - - - - - - - -## Related Guides - - - - - - - diff --git a/light-token/cookbook/wrap-unwrap.mdx b/light-token/cookbook/wrap-unwrap.mdx deleted file mode 100644 index 574a8d1c..00000000 --- a/light-token/cookbook/wrap-unwrap.mdx +++ /dev/null @@ -1,172 +0,0 @@ ---- -title: Wrap & Unwrap SPL/Token 2022 <> Light Token -sidebarTitle: Wrap & Unwrap SPL -description: Move tokens between SPL/Token 2022 token and Light Token accounts. Use to interact with applications that only support SPL/Token 2022. -keywords: ["wrap tokens on solana", "unwrap tokens for developers", "spl to light token conversion"] ---- - ---- - -import FullSetup from "/snippets/setup/full-setup.mdx"; -import WrapActionCode from "/snippets/code-snippets/light-token/wrap/action.mdx"; -import WrapInstructionCode from "/snippets/code-snippets/light-token/wrap/instruction.mdx"; -import WrapTokenInterfaceInstructionCode from "/snippets/code-snippets/light-token/wrap/token-interface-instruction.mdx"; -import UnwrapActionCode from "/snippets/code-snippets/light-token/unwrap/action.mdx"; -import UnwrapInstructionCode from "/snippets/code-snippets/light-token/unwrap/instruction.mdx"; -import UnwrapTokenInterfaceInstructionCode from "/snippets/code-snippets/light-token/unwrap/token-interface-instruction.mdx"; -import WrapRustActionCode from "/snippets/code-snippets/light-token/wrap/rust-client/action.mdx"; -import UnwrapRustActionCode from "/snippets/code-snippets/light-token/unwrap/rust-client/action.mdx"; -import TokenClientPrerequisites from "/snippets/light-token-guides/light-token-client-prerequisites.mdx"; -import AgentSkillGeneric from "/snippets/setup/agent-skill-generic.mdx"; -import WrapUnwrapAiPrompt from "/snippets/ai-prompts/ts-cookbook/wrap-unwrap.mdx"; -import RustWrapUnwrapAiPrompt from "/snippets/ai-prompts/rust-cookbook/wrap-unwrap.mdx"; -import SupportFooter from "/snippets/support-footer.mdx"; - -- **Wrap**: Move tokens from SPL/Token 2022 account → Light Token ATA (hot balance) -- **Unwrap**: Move tokens from Light Token ATA (hot balance) → SPL/Token 2022 account - - - Find the source code: - [wrap.ts](https://github.com/Lightprotocol/light-protocol/blob/main/js/compressed-token/src/v3/actions/wrap.ts) - | - [unwrap.ts](https://github.com/Lightprotocol/light-protocol/blob/main/js/compressed-token/src/v3/actions/unwrap.ts) - - - - - - - - - - - - - - -### Wrap SPL Tokens to Light Token ATA - - - - - - - - - - - - - - - - - - - - - - - - -### Unwrap Light Tokens to SPL Account - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -### Prerequisites - - - - - - -### Wrap SPL tokens to Light Token ATA - - - Find the full example [here](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/actions/wrap.rs). - - - - - - - - - - - - - - - -### Prerequisites - - - - - - -### Unwrap Light Tokens to SPL account - - - Find the full example [here](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/actions/unwrap.rs). - - - - - - - - - - - - - - - - - - - - - -## Related Guides - - - - - - - diff --git a/light-token/defi/programs-pinocchio.mdx b/light-token/defi/programs-pinocchio.mdx deleted file mode 100644 index f22b88f1..00000000 --- a/light-token/defi/programs-pinocchio.mdx +++ /dev/null @@ -1,525 +0,0 @@ ---- -title: "Pinocchio Programs" -description: "Build high-performance DeFi programs with rent-free accounts using Pinocchio" ---- - -import AgentSkillDefi from "/snippets/setup/agent-skill-defi.mdx"; -import DefiPinocchioAiPrompt from "/snippets/ai-prompts/defi/defi-pinocchio.mdx"; - -The Light-SDK sponsors rent-exemption for your PDAs, token accounts, and mints. Your program logic stays the same. - -| | Before | After | -|------------------------|--------|-------| -| Rent (avg. DeFi pool) | ~$2 | ~$0.02 | - -## What Changes - -| Area | Change | -|------|--------| -| State struct | Add `compression_info: CompressionInfo` field, derive `LightPinocchioAccount` | -| Program enum | Derive `LightProgramPinocchio` to generate compress/decompress handlers | -| Entrypoint | Route generated discriminators alongside your custom ones | -| Init handler | Replace `spl_token` CPIs with `light_token_pinocchio` CPIs to create rent-free accounts | -| Other instructions | No changes | - -If you use Anchor instead of Pinocchio, see [Program Integration](./programs). - ---- - - - - -Complete pinocchio Swap reference implementation: [pinocchio-swap](https://github.com/Lightprotocol/examples-light-token/tree/simplify-trait/pinocchio/swap) - - - - - -## Step 1: Dependencies - -```toml -[dependencies] -light-account-pinocchio = { version = "0.23.0", features = ["token", "std"] } -light-token-pinocchio = "0.23.0" - -pinocchio = "0.9" -pinocchio-pubkey = { version = "0.3", features = ["const"] } -pinocchio-system = "0.3" -borsh = { version = "0.10.4", default-features = false } -bytemuck = { version = "1.21", features = ["derive"] } -``` - -## Step 2: State Struct - -Add `compression_info` field and derive `LightPinocchioAccount`: - -```rust -use borsh::{BorshDeserialize, BorshSerialize}; -use light_account_pinocchio::{CompressionInfo, LightPinocchioAccount}; - -#[derive( - Default, Debug, Copy, Clone, PartialEq, - BorshSerialize, BorshDeserialize, - LightPinocchioAccount, - bytemuck::Pod, bytemuck::Zeroable, -)] -#[repr(C)] -pub struct PoolState { - pub compression_info: CompressionInfo, - - // Your regular state... - pub fee_bps: u16, -} -``` - -## Step 3: Program Enum - -Declare your account types with their seed schemas: - -```rust -use light_account_pinocchio::{ - derive_light_cpi_signer, pubkey_array, CpiSigner, LightProgramPinocchio, -}; -use pinocchio::pubkey::Pubkey; - -pub const ID: Pubkey = pubkey_array!("YourProgram11111111111111111111111111111111"); -pub const LIGHT_CPI_SIGNER: CpiSigner = - derive_light_cpi_signer!("YourProgram11111111111111111111111111111111"); - -#[derive(LightProgramPinocchio)] -pub enum ProgramAccounts { - #[light_account(pda::seeds = [POOL_SEED, ctx.mint_a, ctx.mint_b], pda::zero_copy)] - PoolState(PoolState), - - #[light_account(token::seeds = [POOL_VAULT_SEED, ctx.pool, ctx.mint], token::owner_seeds = [POOL_AUTHORITY_SEED])] - Vault, - - #[light_account(associated_token)] - UserToken, -} -``` - -This auto-generates 4 instructions, discriminators, and the `LightAccountVariant` enum used by the client SDK. - -## Step 4: Entrypoint - -Dispatch the generated handlers in your entrypoint - -```rust -pinocchio::entrypoint!(process_instruction); - -pub fn process_instruction( - _program_id: &Pubkey, - accounts: &[AccountInfo], - instruction_data: &[u8], -) -> Result<(), ProgramError> { - if instruction_data.len() < 8 { - return Err(ProgramError::InvalidInstructionData); - } - - let (disc, data) = instruction_data.split_at(8); - let disc: [u8; 8] = disc.try_into().unwrap(); - - match disc { - // your custom program logic... - discriminators::INITIALIZE => process_initialize(accounts, data), - discriminators::SWAP => process_swap(accounts, data), - - // add this: - ProgramAccounts::INITIALIZE_COMPRESSION_CONFIG => { - ProgramAccounts::process_initialize_config(accounts, data) // generated - } - ProgramAccounts::UPDATE_COMPRESSION_CONFIG => { - ProgramAccounts::process_update_config(accounts, data) - } - ProgramAccounts::COMPRESS_ACCOUNTS_IDEMPOTENT => { - ProgramAccounts::process_compress(accounts, data) - } - ProgramAccounts::DECOMPRESS_ACCOUNTS_IDEMPOTENT => { - ProgramAccounts::process_decompress(accounts, data) - } - _ => Err(ProgramError::InvalidInstructionData), - } -} -``` - -## Step 5: Init Handler - -Update your init instruction. Use `light_token_pinocchio` CPI builders to create rent-free token accounts. - - - -```rust -use light_account_pinocchio::CreateTokenAccountCpi; - -CreateTokenAccountCpi { - payer: ctx.payer, - account: vault, - mint, - owner: *pool_authority.key(), -} -.rent_free( - ctx.light_token_config, - ctx.light_token_rent_sponsor, - ctx.system_program, - &crate::ID, -) -.invoke_signed(&[ - POOL_VAULT_SEED, - pool_key.as_ref(), - mint_key.as_ref(), - &[bump], -])?; -``` - - -```rust -use light_account_pinocchio::{CreateMints, CreateMintsStaticAccounts, SingleMintParams}; - -let sdk_mints: [SingleMintParams<'_>; 2] = [ - SingleMintParams { - decimals: 9, - mint_authority: authority_key, - mint_bump: None, - freeze_authority: None, - mint_seed_pubkey: mint_signer_a_key, - authority_seeds: None, - mint_signer_seeds: Some(mint_signer_a_seeds), - token_metadata: None, - }, - // ... -]; - -CreateMints { - mints: &sdk_mints, - proof_data: ¶ms.create_accounts_proof, - mint_seed_accounts: ctx.mint_signers, - mint_accounts: ctx.mints, - static_accounts: CreateMintsStaticAccounts { - fee_payer: ctx.payer, - compressible_config: ctx.light_token_config, - rent_sponsor: ctx.light_token_rent_sponsor, - cpi_authority: ctx.cpi_authority, - }, - cpi_context_offset: 1, -} -.invoke(&cpi_accounts)?; -``` - - - - - -```rust -use light_account_pinocchio::{ - prepare_compressed_account_on_init, CompressedCpiContext, CpiAccounts, CpiAccountsConfig, - CpiContextWriteAccounts, CreateMints, CreateMintsStaticAccounts, CreateTokenAccountCpi, - InstructionDataInvokeCpiWithAccountInfo, InvokeLightSystemProgram, LightAccount, LightConfig, - SingleMintParams, -}; -use pinocchio::sysvars::{clock::Clock, Sysvar}; - -pub fn process( - ctx: &InitializeAccounts<'_>, - params: &InitializeParams, - remaining_accounts: &[AccountInfo], -) -> Result<(), LightSdkTypesError> { - // 1. Build CPI accounts - let config = CpiAccountsConfig::new_with_cpi_context(crate::LIGHT_CPI_SIGNER); - let cpi_accounts = CpiAccounts::new_with_config( - ctx.payer, - &remaining_accounts[params.create_accounts_proof.system_accounts_offset as usize..], - config, - ); - - // 2. Get address tree info + config - let address_tree_info = ¶ms.create_accounts_proof.address_tree_info; - let address_tree_pubkey = address_tree_info.get_tree_pubkey(&cpi_accounts)?; - let light_config = LightConfig::load_checked(ctx.compressible_config, &crate::ID)?; - let current_slot = Clock::get()?.slot; - - // 3. Create pool PDA (write to CPI context) - { - let cpi_context = CompressedCpiContext::first(); - let mut new_address_params = Vec::with_capacity(1); - let mut account_infos = Vec::with_capacity(1); - let pool_key = *ctx.pool.key(); - - prepare_compressed_account_on_init( - &pool_key, &address_tree_pubkey, address_tree_info, - params.create_accounts_proof.output_state_tree_index, - 0, &crate::ID, - &mut new_address_params, &mut account_infos, - )?; - - // Initialize pool state (zero-copy) - { - let mut data = ctx.pool.try_borrow_mut_data()?; - let pool_state: &mut PoolState = bytemuck::from_bytes_mut( - &mut data[8..8 + core::mem::size_of::()] - ); - pool_state.set_decompressed(&light_config, current_slot); - pool_state.token_a_mint = *ctx.mint_a().key(); - pool_state.token_b_mint = *ctx.mint_b().key(); - // ... remaining fields - } - - // Write to CPI context - let instruction_data = InstructionDataInvokeCpiWithAccountInfo { - mode: 1, - bump: crate::LIGHT_CPI_SIGNER.bump, - invoking_program_id: crate::LIGHT_CPI_SIGNER.program_id.into(), - proof: params.create_accounts_proof.proof.0, - new_address_params, - account_infos, - // ... - }; - instruction_data.invoke_write_to_cpi_context_first( - CpiContextWriteAccounts { - fee_payer: cpi_accounts.fee_payer(), - authority: cpi_accounts.authority()?, - cpi_context: cpi_accounts.cpi_context()?, - cpi_signer: crate::LIGHT_CPI_SIGNER, - } - )?; - } - - // 4. Create mints - CreateMints { /* ... */ }.invoke(&cpi_accounts)?; - - // 5. Create vaults (rent-free) - CreateTokenAccountCpi { /* ... */ }.rent_free(/* ... */).invoke_signed(/* ... */)?; - - Ok(()) -} -``` - - - - - - - - ---- - -## Client SDK - -Implement `LightProgramInterface` so clients can detect cold accounts and build load instructions. - - - -```rust -use light_client::interface::{ - AccountInterface, AccountSpec, ColdContext, LightProgramInterface, PdaSpec, -}; -use light_account::token::Token; -use pinocchio_swap::{LightAccountVariant, PoolState, PoolStateSeeds, VaultSeeds}; - -/// Flat SDK struct. All fields populated at construction from pool state data. -pub struct SwapSdk { - pub pool_state_pubkey: Pubkey, - pub token_a_mint: Pubkey, - pub token_b_mint: Pubkey, - pub token_a_vault: Pubkey, - pub token_b_vault: Pubkey, - pub pool_authority: Pubkey, -} - -impl SwapSdk { - pub fn new(pool_state_pubkey: Pubkey, pool_data: &[u8]) -> Result { - let pool = PoolState::deserialize(&mut &pool_data[8..])?; - // ... derive addresses from pool state - Ok(Self { pool_state_pubkey, /* ... */ }) - } -} - -impl LightProgramInterface for SwapSdk { - type Variant = LightAccountVariant; - type Instruction = SwapInstruction; - - fn program_id() -> Pubkey { PROGRAM_ID } - - fn instruction_accounts(&self, ix: &Self::Instruction) -> Vec { - match ix { - SwapInstruction::Swap => vec![ - self.pool_state_pubkey, - self.token_a_vault, - self.token_b_vault, - self.token_a_mint, - self.token_b_mint, - ], - // ... - } - } - - fn load_specs( - &self, - cold_accounts: &[AccountInterface], - ) -> Result>, Box> { - let mut specs = Vec::new(); - for account in cold_accounts { - if account.key == self.pool_state_pubkey { - let pool = PoolState::deserialize(&mut &account.data()[8..])?; - let variant = LightAccountVariant::PoolState { - seeds: PoolStateSeeds { /* ... */ }, - data: pool, - }; - specs.push(AccountSpec::Pda(PdaSpec::new(account.clone(), variant, PROGRAM_ID))); - } else if account.key == self.token_a_vault { - let token: Token = Token::deserialize(&mut &account.data()[..])?; - let variant = LightAccountVariant::Vault(TokenDataWithSeeds { - seeds: VaultSeeds { pool: /* ... */, mint: /* ... */ }, - token_data: token, - }); - specs.push(AccountSpec::Pda(PdaSpec::new(account.clone(), variant, PROGRAM_ID))); - } - // ... token_b_vault, mints - } - Ok(specs) - } -} -``` - - -| Resource | Link | -|----------|------| -| Full SDK implementation | [sdk.rs](https://github.com/Lightprotocol/examples-light-token/blob/simplify-trait/pinocchio/swap/tests/sdk.rs) | - ---- - -## Testing - - - -```rust -use light_program_test::{LightProgramTest, Rpc}; -use light_client::interface::{ - create_load_instructions, get_create_accounts_proof, - AccountSpec, CreateAccountsProofInput, LightProgramInterface, -}; - - -#[tokio::test] -async fn test_pool_lifecycle() { - let mut rpc = LightProgramTest::new(config).await.unwrap(); - - // 1. Initialize pool (rent-free: pool PDA, 2 mints, 2 vaults) - let proof = get_create_accounts_proof(&rpc, &program_id, vec![ - CreateAccountsProofInput::pda(pool_state), - CreateAccountsProofInput::mint(mint_a_signer), - CreateAccountsProofInput::mint(mint_b_signer), - ]).await.unwrap(); - - rpc.create_and_send_transaction(&[init_ix], &payer.pubkey(), &[&payer, &authority]) - .await.unwrap(); - - // 2. Swap (hot path) - rpc.create_and_send_transaction(&[swap_ix], &user.pubkey(), &[&user]) - .await.unwrap(); - - // 3. Trigger compression for the purpose of the test. - const SLOTS_PER_EPOCH: u64 = 13500; - rpc.warp_slot_forward(SLOTS_PER_EPOCH * 30).await.unwrap(); - - // 4. Build SDK from pool state, fetch cold accounts - let pool_iface = rpc.get_account_interface(&pool_state, None).await.unwrap().value.unwrap(); - assert!(pool_iface.is_cold()); - - let sdk = SwapSdk::new(pool_state, pool_iface.data()).unwrap(); - let pubkeys = sdk.instruction_accounts(&SwapInstruction::Swap); - let accounts = rpc.get_multiple_account_interfaces(pubkeys.iter().collect(), None) - .await.unwrap().value; - let cold: Vec<_> = accounts.into_iter().flatten().filter(|a| a.is_cold()).collect(); - - // 5. Load cold accounts - let mut specs = sdk.load_specs(&cold).unwrap(); - // Add user ATAs - let ata_a = rpc.get_associated_token_account_interface(&user.pubkey(), &mint_a, None) - .await.unwrap().value.unwrap(); - let ata_b = rpc.get_associated_token_account_interface(&user.pubkey(), &mint_b, None) - .await.unwrap().value.unwrap(); - specs.push(AccountSpec::Ata(ata_a)); - specs.push(AccountSpec::Ata(ata_b)); - - let load_ixs = create_load_instructions(&specs, payer.pubkey(), config_pda, &rpc) - .await.unwrap(); - - - // 6. Load and Swap - let mut all_ixs = load_ixs; - all_ixs.push(swap_ix); - rpc.create_and_send_transaction(&all_ixs, &user.pubkey(), &[&user]) - .await.unwrap(); -} -``` - - -| Resource | Link | -|----------|------| -| Full test | [test_lifecycle.rs](https://github.com/Lightprotocol/examples-light-token/blob/simplify-trait/pinocchio/swap/tests/test_lifecycle.rs) | - - ---- -## How it works - -The SDK pays the rent-exemption cost. After extended inactivity, cold accounts auto-compress. Your program only ever -interacts with hot accounts. Clients can safely load cold accounts back into the -onchain Solana account space when needed via `create_load_instructions`. - -Under the hood, clients use `AccountInterface` - a superset of Solana's -`Account` that unifies hot and cold state. See [Router Integration](./routers) -for details. - -| | Hot (active) | Cold (inactive) | -|---|---|---| -| Storage | On-chain | Compressed | -| Latency/CU | No change | +load instruction | -| Your program code | No change | No change | - -## Existing programs - -If you want to migrate your program to rent-free accounts and would like hands-on support, [join our tech Discord](https://discord.com/invite/7cJ8BhAXhu), -or [email us](mailto:support@lightprotocol.com). - - -## FAQ - - -No. `LightProgramPinocchio` generates the handlers. Simply add the generated handlers to your entrypoint, and update your init instruction. - - - When creating an -account for the first time, the SDK provides a proof that the account doesn't -exist in the cold address space. The SVM already verifies this for the onchain -space. Both address spaces are checked before creation, preventing re-init -attacks, even if the account is currently cold. - - -Miners (Forester nodes) compress accounts that have been inactive for an extended period of time (when their virtual rent balance drops below threshold). -In practice, having to load cold accounts should be rare. The common path (hot) has no extra overhead and does not increase CU or txn size. - - - -When accounts compress after extended inactivity, the on-chain rent-exemption is released back -to the rent sponsor. This creates a revolving lifecycle: active "hot" accounts hold a -rent-exempt lamports balance, inactive "cold" accounts release it back. The -rent sponsor must be derived from the program owner. For all mint, ATA, and -token accounts, the Light Token Program is the rent sponsor. For your own program-owned PDAs, the SDK derives a rent sponsor address automatically. - - - -**Hot path (e.g. swap, deposit, withdraw):** No. Active accounts do not add CU overhead to your instructions. - -**First time init + loading cold accounts:** Yes, adds up to 15k-400k CU, -depending on number and type of accounts being initialized or loaded. - - - - - ---- - - -Questions or need hands-on support? [Telegram](https://t.me/swen_light) | [email](mailto:support@lightprotocol.com) | [Discord](https://discord.com/invite/7cJ8BhAXhu) - diff --git a/light-token/defi/programs.mdx b/light-token/defi/programs.mdx deleted file mode 100644 index a807d877..00000000 --- a/light-token/defi/programs.mdx +++ /dev/null @@ -1,556 +0,0 @@ ---- -title: "Program Integration" -description: "Build high-performance DeFi programs with rent-free accounts" ---- - -import AgentSkillDefi from "/snippets/setup/agent-skill-defi.mdx"; -import DefiAnchorAiPrompt from "/snippets/ai-prompts/anchor-programs/defi-anchor.mdx"; - -The Light-SDK sponsors rent-exemption for your PDAs, token accounts, and mints. Your program logic stays the same. - -| | Before | After | -|------------------------|--------|-------| -| Rent (avg. DeFi pool) | ~$2 | ~$0.02 | - -## What Changes - - -| Area | Change | -|------|--------| -| State struct | Derive `LightAccount` and add a `compression_info: Option` field | -| Accounts | Derive `LightAccounts` and add `#[light_account]` on init accounts | -| Program module | Add `#[light_program]` on top of `#[program]` | -| Instructions (swap, deposit, withdraw, ...) | No changes | - -Audit overhead is minimal as your program logic is mostly untouched. The rest is -macro-generated. - -If you don't use Anchor, see the [Pinocchio Programs](./programs-pinocchio) guide. - ---- - - - - -You can find a complete rent-free AMM reference implementation [here](https://github.com/Lightprotocol/cp-swap-reference). - - - - - -## Step 1: Dependencies - -```toml -[dependencies] - -light-sdk = { version = "0.23.0", features = ["anchor", "v2", "cpi-context"] } -light-sdk-macros = "0.23.0" -light-token = { version = "0.23.0", features = ["anchor"] } -light-anchor-spl = "0.31" # TokenInterface uses light_token::ID -anchor-lang = "0.31" -``` - - -## Step 2: State Struct - -Add `compression_info` field and derive `LightAccount`: - -```rust -use light_sdk::compressible::CompressionInfo; -use light_sdk_macros::LightAccount; - -#[derive(Default, Debug, InitSpace, LightAccount)] -#[account] -pub struct PoolState { - /// Add this: - pub compression_info: Option, - - /// Your existing fields - /// ... -} -``` - -## Step 3: Program - -Add `#[light_program]` above `#[program]`: - -```rust -use light_sdk_macros::light_program; - -#[light_program] -#[program] -pub mod my_amm { - use super::*; - - pub fn initialize_pool(ctx: Context, params: InitializeParams) -> Result<()> { - process_initialize_pool(ctx, params) - } - - // These don't change - pub fn swap(ctx: Context, amount_in: u64, min_out: u64) -> Result<()> { - process_swap(ctx, amount_in, min_out) - } -} -``` - -## Step 4: Accounts Struct - -Derive `LightAccounts` on your `Accounts` struct and add `#[light_account(...)]` next to `#[account(...)]`. - - - -```rust -#[account( - init, - seeds = [...], - bump, - payer = creator, - space = 8 + PoolState::INIT_SPACE -)] -#[light_account(init)] -pub pool_state: Box>, -``` - - -```rust -#[account( - mut, - seeds = [b"vault", pool_state.key().as_ref(), mint.key().as_ref()], - bump, - payer = creator, - space = 8 + TokenAccount::INIT_SPACE -)] -#[light_account( - init, - token, - authority = [AUTH_SEED.as_bytes()], - mint = token_mint, - owner = authority, -)] -pub token_vault: UncheckedAccount<'info>, -``` - - - - -```rust -#[account( - mut, - seeds = [b"vault", pool_state.key().as_ref(), mint.key().as_ref()], - bump, - payer = creator, - space = 8 + TokenAccount::INIT_SPACE -)] -#[light_account( - token, - authority = [AUTH_SEED.as_bytes()], - mint = token_mint, - owner = authority, -)] -pub token_vault: UncheckedAccount<'info>, -``` -Use without `init` to create manually in the instruction handler via -`CreateTokenAccountCpi`. - - - - - -```rust -#[light_account( - init, - associated_token, - owner = creator, mint = lp_mint, -)] -pub creator_lp_token: UncheckedAccount<'info>, -``` - - - -```rust -#[account(mut)] -#[light_account( - init, - mint, - mint_signer = lp_mint_signer, - authority = authority, - decimals = 9, - mint_seeds = &[LP_MINT_SIGNER_SEED, pool_state.key().as_ref(), &[params.mint_signer_bump]], - authority_seeds = &[AUTH_SEED.as_bytes(), &[params.authority_bump]] -)] -pub lp_mint: UncheckedAccount<'info>, -``` - - - -```rust -#[light_account( - init, - mint, - mint_signer = mint_signer, - authority = fee_payer, - decimals = 9, - mint_seeds = &[MINT_SIGNER_SEED, authority.key().as_ref(), &[params.mint_signer_bump]], - name = params.name.clone(), - symbol = params.symbol.clone(), - uri = params.uri.clone(), - // Optional - update_authority = authority, - additional_metadata = params.additional_metadata.clone() -)] -pub mint: UncheckedAccount<'info>, -``` - - - - - -We also need to add `light_token_interface_config`, `rent_sponsor`, and `light_token_cpi_authority`. - -```rust -use light_sdk::interface::CreateAccountsProof; -use light_sdk_macros::LightAccounts; -use light_token::instruction::{COMPRESSIBLE_CONFIG_V1, RENT_SPONSOR as LIGHT_TOKEN_RENT_SPONSOR}; - -#[derive(AnchorSerialize, AnchorDeserialize, Clone)] -pub struct InitializeParams { - pub create_accounts_proof: CreateAccountsProof, - pub lp_mint_signer_bump: u8, - pub creator_lp_token_bump: u8, - pub authority_bump: u8, -} - -#[derive(Accounts, LightAccounts)] -#[instruction(params: InitializeParams)] -pub struct InitializePool<'info> { - #[account(mut)] - pub creator: Signer<'info>, - - #[account(mut, seeds = [AUTH_SEED.as_bytes()], bump)] - pub authority: UncheckedAccount<'info>, - - #[account( - init, - seeds = [POOL_SEED.as_bytes(), token_0_mint.key().as_ref(), token_1_mint.key().as_ref()], - bump, - payer = creator, - space = 8 + PoolState::INIT_SPACE - )] - #[light_account(init)] - pub pool_state: Box>, - - pub token_0_mint: Box>, - pub token_1_mint: Box>, - - #[account(seeds = [POOL_LP_MINT_SIGNER_SEED, pool_state.key().as_ref()], bump)] - pub lp_mint_signer: UncheckedAccount<'info>, - - #[account(mut)] - #[light_account(init, mint, - mint_signer = lp_mint_signer, - authority = authority, - decimals = 9, - mint_seeds = &[POOL_LP_MINT_SIGNER_SEED, self.pool_state.to_account_info().key.as_ref(), &[params.lp_mint_signer_bump]], - authority_seeds = &[AUTH_SEED.as_bytes(), &[params.authority_bump]] - )] - pub lp_mint: UncheckedAccount<'info>, - - #[account(mut, seeds = [POOL_VAULT_SEED.as_bytes(), pool_state.key().as_ref(), token_0_mint.key().as_ref()], bump)] - #[light_account(token, authority = [AUTH_SEED.as_bytes()])] - pub token_0_vault: UncheckedAccount<'info>, - - #[account(mut, seeds = [POOL_VAULT_SEED.as_bytes(), pool_state.key().as_ref(), token_1_mint.key().as_ref()], bump)] - #[light_account(token, authority = [AUTH_SEED.as_bytes()])] - pub token_1_vault: UncheckedAccount<'info>, - - #[account(mut)] - pub creator_lp_token: UncheckedAccount<'info>, - - - pub light_interface_config: AccountInfo<'info>, - #[account(address = COMPRESSIBLE_CONFIG_V1)] - pub light_token_interface_config: AccountInfo<'info>, - #[account(mut, address = LIGHT_TOKEN_RENT_SPONSOR)] - pub rent_sponsor: AccountInfo<'info>, - pub light_token_program: AccountInfo<'info>, - pub light_token_cpi_authority: AccountInfo<'info>, - pub system_program: Program<'info, System>, -} -``` - - -## Step 5: Instructions -Replace `spl_token` with `light_token` instructions as you need. The API is a superset of SPL-token so switching is straightforward. - -Examples include: `MintToCpi`, `TransferCpi`, `TransferInterfaceCpi`, -`CreateTokenAccountCpi`, and `CreateTokenAtaCpi`. - - - -```rust -use light_token::instruction::{CreateTokenAccountCpi, CreateTokenAtaCpi, MintToCpi}; - -pub fn process_initialize_pool(ctx: Context, params: InitializeParams) -> Result<()> { - let pool_key = ctx.accounts.pool_state.key(); - - // Create rent-free token vault - CreateTokenAccountCpi { - payer: ctx.accounts.creator.to_account_info(), - account: ctx.accounts.token_0_vault.to_account_info(), - mint: ctx.accounts.token_0_mint.to_account_info(), - owner: ctx.accounts.authority.key(), - } - .rent_free( - ctx.accounts.light_token_interface_config.to_account_info(), - ctx.accounts.rent_sponsor.to_account_info(), - ctx.accounts.system_program.to_account_info(), - &crate::ID, - ) - .invoke_signed(&[ - POOL_VAULT_SEED.as_bytes(), - pool_key.as_ref(), - ctx.accounts.token_0_mint.key().as_ref(), - &[ctx.bumps.token_0_vault], - ])?; - - // Create rent-free ATA for LP tokens - CreateTokenAtaCpi { - payer: ctx.accounts.creator.to_account_info(), - owner: ctx.accounts.creator.to_account_info(), - mint: ctx.accounts.lp_mint.to_account_info(), - ata: ctx.accounts.creator_lp_token.to_account_info(), - bump: params.creator_lp_token_bump, - } - .idempotent() - .rent_free( - ctx.accounts.light_token_interface_config.to_account_info(), - ctx.accounts.rent_sponsor.to_account_info(), - ctx.accounts.system_program.to_account_info(), - ) - .invoke()?; - - // Mint LP tokens (standard CPI, no changes) - MintToCpi { - mint: ctx.accounts.lp_mint.to_account_info(), - destination: ctx.accounts.creator_lp_token.to_account_info(), - amount: 1000, - authority: ctx.accounts.authority.to_account_info(), - system_program: ctx.accounts.system_program.to_account_info(), - max_top_up: None, - } - .invoke_signed(&[&[AUTH_SEED.as_bytes(), &[ctx.bumps.authority]]])?; - - // Populate pool state (unchanged) - let pool = &mut ctx.accounts.pool_state; - pool.token_0_vault = ctx.accounts.token_0_vault.key(); - pool.lp_mint = ctx.accounts.lp_mint.key(); - // ... - - Ok(()) -} -``` - - - - - - - - - ---- - -## Client SDK - -To make it easy for clients to integrate with your program, implement the -`LightProgramInterface` trait in your program's SDK crate. - -For a detailed example of how clients use this trait, check out the [Router Integration](./routers.mdx) page. - - - -```rust -pub struct AmmSdk { - pub pool_state_pubkey: Pubkey, - pub observation_key: Pubkey, - pub token_0_vault: Pubkey, - pub token_1_vault: Pubkey, - pub token_0_mint: Pubkey, - pub token_1_mint: Pubkey, - pub lp_mint: Pubkey, - pub amm_config: Pubkey, -} - -pub enum AmmInstruction { - Swap, - Deposit, - Withdraw, -} - -impl LightProgramInterface for AmmSdk { - type Variant = LightAccountVariant; - type Instruction = AmmInstruction; - - fn program_id() -> Pubkey { - PROGRAM_ID - } - - fn instruction_accounts(&self, ix: &Self::Instruction) -> Vec { - match ix { - AmmInstruction::Swap => vec![ - self.pool_state_pubkey, - self.observation_key, - self.token_0_vault, - self.token_1_vault, - self.token_0_mint, - self.token_1_mint, - ], - AmmInstruction::Deposit | AmmInstruction::Withdraw => vec![ - self.pool_state_pubkey, - self.observation_key, - self.token_0_vault, - self.token_1_vault, - self.token_0_mint, - self.token_1_mint, - self.lp_mint, - ], - } - } - - fn load_specs( - &self, - cold_accounts: &[AccountInterface], - ) -> Result>, Box> { - // Build AccountSpec for each cold account by matching pubkey - // and deserializing its data into the macro-generated variant. - let mut specs = Vec::new(); - for account in cold_accounts { - let pubkey = account.key(); - if pubkey == self.pool_state_pubkey || pubkey == self.observation_key { - let parsed: PoolState = AnchorDeserialize::deserialize(&mut &account.data()[8..])?; - specs.push(AccountSpec::Pda(PdaSpec { interface: account.clone(), variant: parsed.into() })); - } else if pubkey == self.token_0_vault || pubkey == self.token_1_vault { - specs.push(AccountSpec::Token(account.clone())); - } - // ... - } - Ok(specs) - } -} -``` - - - -| Resource | Link | -|----------|------| -| Trait Implementation Example | [CpSwapSdk](https://github.com/Lightprotocol/cp-swap-reference/blob/main/programs/cp-swap/tests/program.rs#L409) | - ---- - -## Testing - - - -```rust -use light_program_test::{LightProgramTest, ProgramTestConfig, Rpc}; -use light_sdk::interface::rent::SLOTS_PER_EPOCH; -use light_client::interface::{create_load_instructions, LightProgramInterface}; - -#[tokio::test] -async fn test_pool_lifecycle() { - let config = ProgramTestConfig::new_v2(true, Some(vec![("my_amm", MY_AMM_ID)])); - let mut rpc = LightProgramTest::new(config).await.unwrap(); - - // 1. Init pool (rent-free) - // ... build and send init instruction ... - - // 2. Swap (hot path - works normally) - // ... build and send swap instruction ... - - // 3. Trigger compression (advance time) - rpc.warp_slot_forward(SLOTS_PER_EPOCH * 30).await.unwrap(); - - let pool_interface = rpc - .get_account_interface(&pool_address, None) - .await - .unwrap() - .value - .unwrap(); - assert!(pool_interface.is_cold()); - - // 4. Build SDK and get load instructions - let sdk = AmmSdk::new(pool_address, pool_interface.data()).unwrap(); - let pubkeys = sdk.instruction_accounts(&AmmInstruction::Deposit); - let accounts = rpc.get_multiple_account_interfaces(pubkeys.iter().collect(), None).await.unwrap().value; - let cold: Vec<_> = accounts.into_iter().flatten().filter(|a| a.is_cold()).collect(); - - let specs = sdk.load_specs(&cold).unwrap(); - let load_ixs = create_load_instructions(&specs, payer.pubkey(), config_pda, &rpc).await.unwrap(); - - // 5. Send transaction - rpc.create_and_send_transaction(&load_ixs, &payer.pubkey(), &[&payer]).await.unwrap(); -} -``` - - - -| Resource | Link | -|----------|------| -| Test example | [program.rs](https://github.com/Lightprotocol/cp-swap-reference/blob/main/programs/cp-swap/tests/program.rs) | - ---- -## How it works - -The SDK pays the rent-exemption cost. After extended inactivity, cold accounts auto-compress. Your program only ever -interacts with hot accounts. Clients can safely load cold accounts back into the -onchain Solana account space when needed via `create_load_instructions`. - -Under the hood, clients use `AccountInterface` - a superset of Solana's -`Account` that unifies hot and cold state. See [Router Integration](./routers) -for details. - -| | Hot (active) | Cold (inactive) | -|---|---|---| -| Storage | On-chain | Compressed | -| Latency/CU | No change | +load instruction | -| Your program code | No change | No change | - -## Existing programs - -If you want to migrate your program to rent-free accounts and would like hands-on support, [join our tech Discord](https://discord.com/invite/7cJ8BhAXhu), -or [email us](mailto:support@lightprotocol.com). - - -## FAQ - - When creating an -account for the first time, the SDK provides a proof that the account doesn't -exist in the cold address space. The SVM already verifies this for the onchain -space. Both address spaces are checked before creation, preventing re-init -attacks, even if the account is currently cold. - - -Miners (Forester nodes) compress accounts that have been inactive for an extended period of time (when their virtual rent balance drops below threshold). -In practice, having to load cold accounts should be rare. The common path (hot) has no extra overhead and does not increase CU or txn size. - - - -When accounts compress after extended inactivity, the on-chain rent-exemption is released back -to the rent sponsor. This creates a revolving lifecycle: active "hot" accounts hold a -rent-exempt lamports balance, inactive "cold" accounts release it back. The -rent sponsor must be derived from the program owner. For all mint, ATA, and -token accounts, the Light Token Program is the rent sponsor. For your own program-owned PDAs, the SDK derives a rent sponsor address automatically. - - - -**Hot path (e.g. swap, deposit, withdraw):** No. Active accounts do not add CU overhead to your instructions. - -**First time init + loading cold accounts:** Yes, adds up to 15k-400k CU, -depending on number and type of accounts being initialized or loaded. - - ---- - - -Questions or need hands-on support? [Telegram](https://t.me/swen_light) | [email](mailto:support@lightprotocol.com) | [Discord](https://discord.com/invite/7cJ8BhAXhu) - diff --git a/light-token/defi/routers.mdx b/light-token/defi/routers.mdx deleted file mode 100644 index cdb7ca0c..00000000 --- a/light-token/defi/routers.mdx +++ /dev/null @@ -1,320 +0,0 @@ ---- -title: "Router Integration" -description: "Add support for rent-free AMMs on Solana." ---- - -import AgentSkillRouter from "/snippets/setup/agent-skill-router.mdx"; -import RoutersAiPrompt from "/snippets/ai-prompts/defi/routers.mdx"; - -Your existing quoting, routing, and swap logic stays the same. -The only addition: when a market has cold accounts, detect them, and prepend load instructions before the swap. - -## What changes - -| | Hot market (99%+) | Cold market | -|---|---|---| -| Quoting | No change | No change | -| Swap instruction | No change | No change | -| Transaction | No change | Prepend `create_load_instructions` | - ---- - - - - - - -## Detecting cold accounts - -Add a cache for cold accounts. This can be independent from your regular account cache. - -```rust -cold_cache: HashMap<[u8; 32], AccountInterface>, // Accounts that are currently cold (used for loading) -``` - -If you stream, subscribe to accounts and transactions with the Light Token Program. - -| Subscription | Detects | -|:-------------|:--------| -| Account sub (`owner: cToken...`) | Hot state + cold-to-hot | -| Transaction sub (`account_include: cToken...`) | Hot-to-cold | - -**Hot-to-cold** -- in your transaction handler, listen to accounts whose balance dropped to zero. Async-fetch the `AccountInterface` -(which includes the `ColdContext` needed for load instructions): - -```rust -Some(UpdateOneof::Transaction(tx_update)) => { - if let Some(ref tx_info) = tx_update.transaction { - for pubkey in find_closed_accounts(tx_info) { - if cache.remove(&pubkey).is_some() { - let rpc = rpc.clone(); - let cold_cache = cold_cache.clone(); - tokio::spawn(async move { - if let Ok(Some(iface)) = rpc.get_account_interface(&pubkey, None).await { - cold_cache.insert(pubkey, iface); - } - }); - } - } - } -} -``` - -`find_closed_accounts` checks `pre_balances[i] > 0 && post_balances[i] == 0` across all transaction -keys (including ALT-loaded addresses). See [full implementation](/light-token/streaming/tokens#detecting-transitions). - -**Cold-to-hot** -- your existing account subscription picks up the hot account again. No cache changes needed because account state does not change while cold. - -```rust -Some(UpdateOneof::Account(account_update)) => { - if let Some(account) = account_update.account { - let pubkey: [u8; 32] = account.pubkey.as_slice().try_into().unwrap(); - // remove from cold cache. - cold_cache.remove(&pubkey); - } -} -``` - -For the full streaming guide, see [Streaming Token Accounts](/light-token/streaming/tokens) -and [Streaming Mints](/light-token/streaming/mints). - -If you don't stream, call `get_multiple_account_interfaces` at swap time and check `is_cold()` to detect cold accounts. - ---- - -## Building swap transactions with cold accounts - -When you detect cold accounts in a market (via your `cold_set` or via `is_cold()` on fetched accounts), -fetch their `ColdContext` via `get_account_interface` and build load instructions. - -```rust -use light_client::interface::{create_load_instructions, LightProgramInterface}; - -// 1. Identify which accounts the swap touches -let pubkeys = sdk.instruction_accounts(&AmmInstruction::Swap); - -// 2. Check which are cold (from your streaming cache, or fetch) -let cold_pubkeys: Vec<_> = pubkeys.iter().filter(|p| cold_set.contains(p)).collect(); - -// 3. If any are cold, fetch their ColdContext and build load instructions -let mut ixs = vec![]; -if !cold_pubkeys.is_empty() { - let interfaces = rpc - .get_multiple_account_interfaces(cold_pubkeys, None) - .await? - .value; - let cold: Vec<_> = interfaces.into_iter().flatten().collect(); - let specs = sdk.load_specs(&cold)?; - ixs.extend(create_load_instructions(&specs, payer, config_pda, &rpc).await?); -} - -// 4. Swap instruction is unchanged -ixs.push(sdk.swap_ix(&swap_params)?); -``` - ---- - -## The LightProgramInterface trait - -Each rent-free AMM SDK exposes this trait. It tells you which accounts an instruction -touches and how to build load specs for cold ones. - -```rust -pub trait LightProgramInterface { - type Variant: Pack + Clone + Debug; - type Instruction; - - fn program_id() -> Pubkey; - fn instruction_accounts(&self, ix: &Self::Instruction) -> Vec; - fn load_specs( - &self, - cold_accounts: &[AccountInterface], - ) -> Result>, Box>; -} -``` - -- `instruction_accounts` -- returns the pubkeys the instruction reads/writes. -- `load_specs` -- given cold `AccountInterface`s (with `ColdContext`), returns the `AccountSpec`s - that `create_load_instructions` needs to load them. - ---- - -## Full example - -### Dependencies - -```toml -[dependencies] -light-client = { version = "0.23.0", features = ["v2"] } - -# AMM SDK that implements LightProgramInterface (provided by the AMM team) -example-amm-sdk = "0.1" -``` - -### Code - -```rust expandable -use light_client::interface::{create_load_instructions, LightProgramInterface}; -use example_amm_sdk::{ExampleAmmSdk, AmmInstruction}; - -// Construct SDK from pool data (same as before -- pool data is always available, -// hot or cold, via get_account_interface or your cache). -let sdk = ExampleAmmSdk::new(pool_address, pool_data)?; - -// Quote works the same regardless of hot/cold. -let quote = sdk.quote(amount_in, min_out)?; - -// Build transaction. -let mut ixs = vec![]; - -// Check if any swap accounts are cold. -let pubkeys = sdk.instruction_accounts(&AmmInstruction::Swap); -let cold_pubkeys: Vec<_> = pubkeys.iter().filter(|p| cold_set.contains(p)).collect(); - -if !cold_pubkeys.is_empty() { - // Fetch ColdContext for cold accounts. - let interfaces = rpc - .get_multiple_account_interfaces(cold_pubkeys, None) - .await? - .value; - let cold: Vec<_> = interfaces.into_iter().flatten().collect(); - let specs = sdk.load_specs(&cold)?; - ixs.extend(create_load_instructions(&specs, payer.pubkey(), config_pda, &rpc).await?); -} - -// Swap instruction is the same as without rent-free accounts. -ixs.push(sdk.swap_ix(&swap_params)?); - -rpc.send_transaction(&ixs, &payer).await?; -``` - -### Key types - -| Type | Source | Purpose | -|------|--------|---------| -| `AccountInterface` | `light-client` | Account data with optional `ColdContext` | -| `LightProgramInterface` | `light-client` | Trait that AMM SDKs implement | -| `AccountSpec` | `light-client` | Input to `create_load_instructions` | - -### Reference implementation - -| Resource | Link | -|----------|------| -| AMM Program | [cp-swap-reference](https://github.com/Lightprotocol/cp-swap-reference) | -| LightProgramInterface Trait Impl | [CpSwapSdk](https://github.com/Lightprotocol/cp-swap-reference/blob/main/programs/cp-swap/tests/program.rs#L409) | - ---- - -## Hot vs Cold - -| | Hot | Cold | -|---|-----|------| -| On-chain | Yes | Ledger (compressed) | -| Quote | Works | Works | -| Swap | Direct | Load first / Bundle | -| Latency | Normal | +0-200ms* | -| Tx size | Normal | +100-2400 bytes*| -| CU | Normal | +15k-400k CU*| - -*Depends on the number and type of cold accounts.* - -### When does a market go cold? - -Accounts go cold after extended inactivity. Their virtual rent balance drops -below a threshold and miners compress them onto the Solana ledger. - -They stay cold until any client loads them back in-flight via `create_load_instructions`. - -**Touching cold markets is rare.** The hot path has zero overhead. - ---- - -## FAQ - - -No. Swap instructions are identical. If the market is hot, the transaction -is the same as today. If cold, you prepend `create_load_instructions`. - - - -Yes. You regular account cache stays the same even if a market is cold, so you can keep quoting with it. - - - -**Hot (common path)**: No. - -**Cold**: Loading accounts adds 1-200ms depending on whether a validity proof -is needed. If load + swap exceed Solana's 1232 byte limit, use Jito bundles. - - - -Until they go inactive again. Each write resets the timer. The inactivity -threshold is configurable by the program owner (e.g. 24h of no writes). - - - - -Send as a Jito bundle: - -```rust expandable -use solana_sdk::{instruction::Instruction, pubkey::Pubkey, system_instruction}; - -const JITO_TIP_ACCOUNTS: &[&str] = &[ - "96gYZGLnJYVFmbjzopPSU6QiEV5fGqZNyN9nmNhvrZU5", - "HFqU5x63VTqvQss8hp11i4wVV8bD44PvwucfZ2bU7gRe", - "Cw8CFyM9FkoMi7K7Crf6HNQqf4uEMzpKw6QNghXLvLkY", - "ADaUMid9yfUytqMBgopwjb2DTLSokTSzL1zt6iGPaS49", - "DfXygSm4jCyNCybVYYK6DwvWqjKee8pbDmJGcLWNDXjh", - "ADuUkR4vqLUMWXxW9gh6D6L8pMSawimctcNZ5pGwDcEt", - "DttWaMuVvTiduZRnguLF7jNxTgiMBZ1hyAumKUiL2KRL", - "3AVi9Tg9Uo68tJfuvoKvqKNWKkC5wPdSSdeBnizKZ6jT", -]; - -fn jito_tip_ix(payer: &Pubkey, tip_lamports: u64) -> Instruction { - let tip_account = JITO_TIP_ACCOUNTS[rand::random::() % JITO_TIP_ACCOUNTS.len()] - .parse::().unwrap(); - system_instruction::transfer(payer, &tip_account, tip_lamports) -} - -let tip_ix = jito_tip_ix(&payer.pubkey(), 10_000); -swap_ixs.push(tip_ix); - -let bundle = vec![load_tx_base64, swap_tx_base64]; -let resp = client - .post("https://mainnet.block-engine.jito.wtf/api/v1/bundles") - .json(&serde_json::json!({ - "jsonrpc": "2.0", - "id": 1, - "method": "sendBundle", - "params": [bundle, {"encoding": "base64"}] - })) - .send().await?; -``` - - - -Yes. Supported by Helius and Triton. Can also be self-hosted via the -open-source Photon indexer. - - - Hot markets work all the same -as long as Solana is up. Cold accounts can't be loaded until the indexer -recovers. Compression is cryptographically verifiable, and safety -does not depend on the indexer. - - Yes. -To read state, and to build txns, simply use `get_multiple_account_interfaces` -for the instruction's accounts and check `is_cold()`. This adds a RPC round-trip -but requires no streaming setup. - ---- - -Questions or need hands-on support? [Telegram](https://t.me/swen_light) | [email](mailto:support@lightprotocol.com) | [Discord](https://discord.com/invite/7cJ8BhAXhu) - - - - - - - - diff --git a/light-token/examples/client.mdx b/light-token/examples/client.mdx deleted file mode 100644 index dd935794..00000000 --- a/light-token/examples/client.mdx +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: "Client examples" -sidebarTitle: "Client" -description: "TypeScript and Rust client examples for light-token SDK." ---- - -import ClientExamplesTable from "/snippets/overview-tables/light-token-client-examples-table.mdx"; -import AgentSkillGeneric from "/snippets/setup/agent-skill-generic.mdx"; - -Find all examples on Github: [examples-light-token](https://github.com/Lightprotocol/examples-light-token) - - - - - - diff --git a/light-token/examples/program.mdx b/light-token/examples/program.mdx deleted file mode 100644 index 2cc58ce0..00000000 --- a/light-token/examples/program.mdx +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: "Program examples" -sidebarTitle: "Program" -description: "Anchor program examples for light-token CPI." ---- - -import ProgramExamplesTable from "/snippets/overview-tables/light-token-program-examples-table.mdx"; -import AgentSkillGeneric from "/snippets/setup/agent-skill-generic.mdx"; - -Find all examples on Github: [examples-light-token](https://github.com/Lightprotocol/examples-light-token) - - - - - - diff --git a/light-token/extensions/overview.mdx b/light-token/extensions/overview.mdx deleted file mode 100644 index 35565bdf..00000000 --- a/light-token/extensions/overview.mdx +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: "Token 2022 Extensions with Light Token" -sidebarTitle: "Extensions" -description: "Most Token 2022 extensions are supported by Light Token to add features through extra instructions to a token mint or token account." -keywords: ["token 2022 extensions light token", "token extensions solana", "metadata pointer light token", "transfer fee config light token", "confidential transfers light token"] ---- - -import SupportFooter from "/snippets/support-footer.mdx"; -import ExtensionsTable from "/snippets/extensions-table.mdx"; - -## How extensions work with Light Token - -1. **Create** a Token-2022 mint with one or more extensions -2. **[Register an interface PDA](/light-token/cookbook/add-interface-pda)** to hold balances from that mint in Light Token accounts -3. **Use** the same Light Token APIs (`transferInterface`, `wrap`, `unwrap`) as any other token - -Each extension adds specific state that's generally initialized during mint or token account creation. -When initializing either account, you can enable specific extensions simultaneously for different functionality. -Most extensions can't be added after an account is initialized. Use the Solana documentation to learn more about Token 2022 extensions. - -## Supported extensions - - - -## Not supported - -The following Token-2022 extensions are not supported by Light Token: Scaled UI Amount, Non-Transferable Tokens, Memo Transfer, Immutable Owner, CPI Guard. - - diff --git a/light-token/payments/basic-payment.mdx b/light-token/payments/basic-payment.mdx deleted file mode 100644 index dc05e532..00000000 --- a/light-token/payments/basic-payment.mdx +++ /dev/null @@ -1,225 +0,0 @@ ---- -title: "Basic Payment" -sidebarTitle: "Basic Payment" -description: "Send a single token transfer with Light Token APIs with comparison to SPL. If the recipient is receiving this token for the first time, their token account can be created as part of the same transaction." -keywords: ["stablecoin transfer solana", "light token transfer", "send payment solana", "rent free transfer"] ---- - -import FullSetup from "/snippets/setup/full-setup.mdx"; -import SupportFooter from "/snippets/support-footer.mdx"; -import AgentSkillPayments from "/snippets/setup/agent-skill-payments.mdx"; -import PaymentsAiPrompt from "/snippets/ai-prompts/toolkits/payments.mdx"; -import PaymentsSetupHelper from "/snippets/setup/payments-setup-helper.mdx"; -import TokenInterfaceSdk2Callout from "/snippets/light-token-guides/token-interface-sdk2-callout.mdx"; -import SendInstructionCode from "/snippets/code-snippets/payments/send/basic-send-instruction.mdx"; -import SendActionCode from "/snippets/code-snippets/payments/send/basic-send-action.mdx"; -import SendTokenInterfaceInstructionCode from "/snippets/code-snippets/payments/send/basic-send-token-interface-instruction.mdx"; - -1. The light-token API matches the SPL-token API almost entirely, and extends their functionality to include the light token program in addition to the SPL-token and Token-2022 programs. -2. Your users use the same stablecoins, just stored more efficiently. - - - - - - - - - - - - - - - - -
SPLLight
**Transfer**createTransferInstruction()createTransferInterfaceInstructions()
- - - - - - - - -## Setup - - - -Snippets below assume `rpc`, `payer`, `mint`, `owner`, `recipient`, and `amount` are defined. -See the [full examples](https://github.com/Lightprotocol/examples-light-token/tree/main/toolkits/payments) for runnable setup. - -```typescript -import { createRpc } from "@lightprotocol/stateless.js"; - -import { - createTransferInterfaceInstructions, - transferInterface -} from "@lightprotocol/compressed-token/unified"; - -const rpc = createRpc(RPC_ENDPOINT); -``` - - - - -Find full runnable code examples: -[instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/send/basic-send-instruction.ts) | -[action](https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/send/basic-send-action.ts). - - - - -## Send a Payment - -Use `createTransferInterfaceInstructions` to transfer tokens between wallets. The method: -- automatically derives Associated Token Accounts for the sender and recipient. If the recipient's ATA doesn't exist, the instruction to create the account is automatically added to the same transaction. -- determines whether the sender's account has a cold balance and adds load instructions if needed. - - -**About loading**: Light Token accounts reduce account rent ~200x by auto-compressing inactive -accounts. Before any action, the SDK detects cold balances and adds -instructions to load them. This almost always fits in a single -atomic transaction with your regular transfer. APIs return `TransactionInstruction[][]` so the same -loop handles the rare multi-transaction case automatically. - - - - - - - - - - - -```typescript -import { - getAssociatedTokenAddressSync, - createAssociatedTokenAccountIdempotentInstruction, - createTransferInstruction, -} from "@solana/spl-token"; - -const sourceAta = getAssociatedTokenAddressSync(mint, owner.publicKey); -const destinationAta = getAssociatedTokenAddressSync(mint, recipient); - -const tx = new Transaction().add( - createAssociatedTokenAccountIdempotentInstruction( - payer.publicKey, destinationAta, recipient, mint - ), - createTransferInstruction(sourceAta, destinationAta, owner.publicKey, amount) -); -``` - - - -Your app logic may require you to create a single sign request for your user: - - - -```typescript -const transactions = instructions.map((ixs) => new Transaction().add(...ixs)); - -// One approval for all -const signed = await wallet.signAllTransactions(transactions); - -for (const tx of signed) { - await sendAndConfirmTransaction(rpc, tx); -} -``` - - - -While almost always you will have only one transfer transaction, you can -optimize sending in the rare cases where you have multiple transactions. -Parallelize the loads, confirm them, and then send the transfer instruction -after. - - - -```typescript -import { - createTransferInterfaceInstructions, - sliceLast, -} from "@lightprotocol/compressed-token/unified"; - -const instructions = await createTransferInterfaceInstructions( - rpc, - payer.publicKey, - mint, - amount, - owner.publicKey, - recipient -); -const { rest: loadInstructions, last: transferInstructions } = sliceLast(instructions); -// empty = nothing to load, will no-op. -await Promise.all( - loadInstructions.map((ixs) => { - const tx = new Transaction().add(...ixs); - tx.sign(payer, owner); - return sendAndConfirmTransaction(rpc, tx); - }) -); - -const transferTx = new Transaction().add(...transferInstructions); -transferTx.sign(payer, owner); -await sendAndConfirmTransaction(rpc, transferTx); -``` - - - - - - - - - - - - - - - -```typescript -import { - getAssociatedTokenAddressSync, - getOrCreateAssociatedTokenAccount, - transfer, -} from "@solana/spl-token"; - -await getOrCreateAssociatedTokenAccount(connection, payer, mint, recipient); - -const sourceAta = getAssociatedTokenAddressSync(mint, owner.publicKey); -const destinationAta = getAssociatedTokenAddressSync(mint, recipient); -await transfer(connection, payer, sourceAta, destinationAta, owner, amount); -``` - - - - - - - - - - - - - - - -## Related guides - - - - Pack multiple transfers to multiple recipients into one transaction. - - - Abstract SOL fees from the user. Sponsor top-ups and transaction fees. - - - Query balances and transaction history. - - - - diff --git a/light-token/payments/batch-payments.mdx b/light-token/payments/batch-payments.mdx deleted file mode 100644 index a04965c4..00000000 --- a/light-token/payments/batch-payments.mdx +++ /dev/null @@ -1,113 +0,0 @@ ---- -title: "Batch Payments" -sidebarTitle: "Batch Payments" -description: "Send payments to multiple recipients in a single transaction or sequentially." -keywords: ["batch payments solana", "multiple transfers solana", "light token batch", "multi-recipient transfer"] ---- - -import FullSetup from "/snippets/setup/full-setup.mdx"; -import SupportFooter from "/snippets/support-footer.mdx"; -import AgentSkillPayments from "/snippets/setup/agent-skill-payments.mdx"; -import PaymentsAiPrompt from "/snippets/ai-prompts/toolkits/payments.mdx"; -import PaymentsSetupHelper from "/snippets/setup/payments-setup-helper.mdx"; -import TokenInterfaceSdk2Callout from "/snippets/light-token-guides/token-interface-sdk2-callout.mdx"; -import BatchSendCode from "/snippets/code-snippets/payments/send/batch-send.mdx"; -import SplBatchSend from "/snippets/code-snippets/payments/spl/batch-send.mdx"; - ---- - -A Solana transaction can contain one or more instructions that are executed sequentially and atomically by the network. -This way, you can pack multiple transfers into a single transaction instead of sending e.g. three separate transactions. - You send one transaction with three transfer instructions. Use just like with SPL token: - - - - - - - - - - - - - - - - -
SPLLight
**Transfer**createTransferInstruction()createTransferInterfaceInstructions()
- - - - - - - - -## Setup - - - -```typescript -import { createRpc } from "@lightprotocol/stateless.js"; - -const rpc = createRpc(RPC_ENDPOINT); -``` - - - - -Find full code examples: -[batch transfer](https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/send/batch-send.ts). - - - - -## Send to Multiple Recipients in One Transaction - -Batching multiple transfers requires building each instruction separately, then combining them into a single transaction. - -The method `createTransferInterfaceInstructions` determines whether the sender's account has a cold balance and adds load instructions if needed. - - -**About loading**: Light Token accounts reduce account rent ~200x by auto-compressing inactive -accounts. Before any action, the SDK detects cold balances and adds -instructions to load them. This almost always fits in a single -atomic transaction with your regular transfer. APIs return `TransactionInstruction[][]` - so the same -loop handles the rare multi-transaction case automatically. - - - - - - - - - - - - - - - - - - - - -## Related guides - - - - Send a single transfer. - - - Separate the fee payer from the token owner. - - - Query balances and transaction history. - - - - diff --git a/light-token/payments/overview.mdx b/light-token/payments/overview.mdx deleted file mode 100644 index 5b20f1a8..00000000 --- a/light-token/payments/overview.mdx +++ /dev/null @@ -1,127 +0,0 @@ ---- -title: Payment Flows on Solana with Light Token -sidebarTitle: Overview -description: Learn how the Light Token SDK reduces SPL account creation cost for payment infrastructure by 99%. -tags: ["stablecoin payments for enterprises", "infrastructure for stablecoin payments on solana", "payment rails for stablecoins on solana", "usdc payments for merchants on solana", "payment infrastructure for fintechs", "micropayments for apps on solana", "token extensions for payment companies", "rent free tokens for payment apps"] ---- - ---- - -import { CodeCompare } from "/snippets/jsx/code-compare.jsx"; -import { - splCreateAtaIxCode, - lightCreateAtaIxCode, - splCreateAtaRustCode, - lightCreateAtaRustCode, - splCreateAtaMacroCode, - lightCreateAtaMacroCode, - splCreateAtaCpiCode, - lightCreateAtaCpiCode, -} from "/snippets/code-samples/code-compare-snippets.jsx"; -import SupportFooter from "/snippets/support-footer.mdx"; -import RentSponsorship from "/snippets/rent-sponsorship-explained.mdx"; -import AgentSkillPayments from "/snippets/setup/agent-skill-payments.mdx"; -import PaymentCostUsd from "/snippets/cost-tables/payment-cost-usd.mdx"; - - -Payment flows on Solana include five core concepts: -1. wallets for sender and recipient -2. stablecoins as transferred asset type (USDC, USDG, ...) -3. token accounts to hold balances -4. fees for transactions and account creation -5. transactions to execute the transfer - -Our token APIs optimize the account creation cost component. You typically create an account (1) when onboarding a new user, and (2) when the recipient does not hold the transferred token yet. - - - -While transfer cost is identical, you can expect ~\$0.29 total when creating a new token account using SPL/Token 2022. -With Light Token, the total cost will be around \$0.001, regardless of whether a new account is created. Your users use the same stablecoins, just stored more efficiently. - - -The token standard pays rent-exemption cost for you. To prevent griefing, “rent” is paid over time to keep an account in memory. This is dealt with under the hood in a way that doesn’t disrupt the UX of what your users are used to with SPL-token. - - - - -You can abstract fees entirely so users never interact with SOL. See [gasless transactions](/light-token/wallets/gasless-transactions) -to sponsor rent top-ups and transaction fees. - - -## API Comparison -Transactions with Light Token APIs mirror SPL / Token 2022, so you can build transactions with a similar developer experience. -For example, here is the creation of an associated token account: - - - -## Interoperability - - -The Light Token APIs cover every SPL Token operation and adds extra capabilities: - - - - - - - - - - - - - - - - - - - - - - -
CategoryWhat it does
**Cross-program dispatch**`Interface` methods (e.g., `transferInterface`) auto-detect the token program and dispatch to SPL, Token 2022, or Light Token.
**Unified balance**`getAtaInterface` returns a unified balance for a given mint, aggregating Light Token (hot + cold), SPL, and Token 2022 sources.
**Wrap / Unwrap**For interoperability with applications that don't support Light Token yet, you can wrap / unwrap SPL or Token 2022 tokens into Light Token associated token accounts and back.
- -## Token Extensions - -Token extensions introduce optional features you can add to a token mint or token account through -extra instructions. Light Token supports most Token 2022 extensions. - - - -## Start Integrating - -### Payment Skill for Agents - - - -### Payment Flows - - - - - - - - - - - - - -### Fee Abstraction - - -### Signing - - - -### Go to Production - - - diff --git a/light-token/payments/payment-with-memo.mdx b/light-token/payments/payment-with-memo.mdx deleted file mode 100644 index 2294842a..00000000 --- a/light-token/payments/payment-with-memo.mdx +++ /dev/null @@ -1,135 +0,0 @@ ---- -title: "Payment with Memo" -sidebarTitle: "Payment with Memo" -description: "Attach invoice IDs, payment references, or notes to Light Token transfers using Solana's memo program." -keywords: ["memo payment solana", "invoice reconciliation solana", "payment reference light token", "memo instruction"] ---- - -import FullSetup from "/snippets/setup/full-setup.mdx"; -import SupportFooter from "/snippets/support-footer.mdx"; -import AgentSkillPayments from "/snippets/setup/agent-skill-payments.mdx"; -import PaymentsAiPrompt from "/snippets/ai-prompts/toolkits/payments.mdx"; -import PaymentsSetupHelper from "/snippets/setup/payments-setup-helper.mdx"; -import TokenInterfaceSdk2Callout from "/snippets/light-token-guides/token-interface-sdk2-callout.mdx"; -import MemoCode from "/snippets/code-snippets/payments/send/payment-with-memo.mdx"; -import SplMemo from "/snippets/code-snippets/payments/spl/payment-with-memo.mdx"; - ---- - -Solana's memo program lets you attach invoice numbers, order IDs, or custom references -to any payment. These memos are permanently recorded on-chain and visible in transaction - logs, making it easy to match payments to your internal systems. -Use just like with SPL token: - - - - - - - - - - - - - - - - -
SPLLight
**Transfer**createTransferInstruction()createTransferInterfaceInstructions()
- - - - - - - - -## Setup - - - -Additionally install the memo program package: - -```bash -npm install @solana/spl-memo -``` - -```typescript -import { createRpc } from "@lightprotocol/stateless.js"; - -const rpc = createRpc(RPC_ENDPOINT); -``` - - - - - -## Send a Payment with Memo - -1. Create the transfer instructions with `createTransferInterfaceInstructions()`. Load transactions are handled under the hood. -2. Create a memo instruction with a message. This message will be visible in the program logs of the transaction. -3. Both instructions execute atomically in the same transaction. - -After the transaction confirms, fetch it to view the memo in the logs. The memo appears as a log message from the Memo program. - - -**About loading**: Light Token accounts reduce account rent ~200x by auto-compressing inactive -accounts. Before any action, the SDK detects cold balances and adds -instructions to load them. This almost always fits in a single -atomic transaction with your regular transfer. APIs return `TransactionInstruction[][]` - so the same -loop handles the rare multi-transaction case automatically. - - - - - - - - - - - - - -## Read Memo from Transaction Logs - -After the transaction confirms, the memo appears in the transaction logs: - -``` markdown Example Transaction Logs -"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [1]", -"Program log: Instruction: Transfer", -"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 1682 of 200000 compute units", -"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success", -"Program MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr invoke [1]", -'Program log: Memo (len 46): "Payment for services rendered - Invoice #12345"', -"Program MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr consumed 18097 of 198318 compute units", -"Program MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr success", -"Program ComputeBudget111111111111111111111111111111 invoke [1]", -"Program ComputeBudget111111111111111111111111111111 success" -``` - - - - - - - - - -## Related guides - - - - Send a single transfer without memo. - - - Query balances and transaction history. - - - Pack multiple transfers into one transaction. - - - - \ No newline at end of file diff --git a/light-token/payments/production-readiness.mdx b/light-token/payments/production-readiness.mdx deleted file mode 100644 index e83c30cf..00000000 --- a/light-token/payments/production-readiness.mdx +++ /dev/null @@ -1,73 +0,0 @@ ---- -title: "Production Readiness" -sidebarTitle: "Production Readiness" -description: "Non-exhaustive checklist for deploying Light Token payment flows to production, including RPC infrastructure, error handling, and security." -keywords: ["production readiness solana", "light token production", "photon indexer", "mainnet deployment solana"] ---- - -import SupportFooter from "/snippets/support-footer.mdx"; -import AgentSkillPayments from "/snippets/setup/agent-skill-payments.mdx"; -import PaymentsAiPrompt from "/snippets/ai-prompts/toolkits/payments.mdx"; - - - - - - -## RPC infrastructure - -Light Token requires a Photon-compatible RPC endpoint for cold account lookups and balance queries. - -| Provider | Photon support | Notes | -|:---------|:---------------|:------| -| [Helius](https://helius.dev) | Yes | Recommended. Maintains the Photon indexer. | -| [Triton](https://triton.one) | Yes | Alternative provider. | - -## Transaction landing - -Light Token transactions follow standard Solana patterns for landing: - -- **Priority fees**: Use `ComputeBudgetProgram.setComputeUnitPrice()` to increase transaction priority. See [Solana priority fees](https://solana.com/docs/core/fees). -- **Compute units**: Set appropriate compute unit limits with `ComputeBudgetProgram.setComputeUnitLimit()`. -- **Retry logic**: Implement retries with fresh blockhashes for failed transactions. - -## Confirmation levels - -| Level | When to use | -|:------|:------------| -| `processed` | Fastest. Use for UI updates. Not guaranteed to finalize. | -| `confirmed` | Recommended for most payment flows. Confirmed by supermajority of validators. | -| `finalized` | Highest certainty. Use for high-value transfers or irreversible actions. | - -## Error handling - -Handle both standard Solana errors and Light Token-specific scenarios: - -- **[Cold account](/light-token/payments/receive-payments) load failures**: Retry the load if the indexer returns stale data. -- **Associated token account creation**: Idempotent — safe to retry. -- **Rent top-up failures**: Ensure the fee payer has sufficient SOL balance. See [gasless transactions](/light-token/wallets/gasless-transactions) for cost breakdown. -- **Transaction size limits**: If `TransactionInstruction[][]` returns [multiple batches](/light-token/payments/basic-payment), process them sequentially. - -## Fee sponsorship - -Set your application as the fee payer so users never interact with SOL: - -1. **Rent top-ups and transaction fees**: Set `payer` parameter on Light Token instructions. See [gasless transactions](/light-token/wallets/gasless-transactions). -2. **Rent sponsor funding**: Ensure the rent sponsor PDA is funded. See the [cost breakdown](/light-token/wallets/gasless-transactions) for required amounts. - -## Pre-launch checklist - -- [ ] Photon-compatible RPC endpoint configured and tested -- [ ] Fee payer wallet funded with sufficient SOL -- [ ] Error handling covers load failures, tx size limits, and retries -- [ ] Confirmation level appropriate for your use case -- [ ] [Address verification](/light-token/payments/verify-recipient-address) implemented -- [ ] [Wrap/unwrap](/light-token/payments/wrap-unwrap) flows tested for SPL / Token 2022 interoperability (if applicable) - - - - - - - - \ No newline at end of file diff --git a/light-token/payments/receive-payments.mdx b/light-token/payments/receive-payments.mdx deleted file mode 100644 index 79c014cb..00000000 --- a/light-token/payments/receive-payments.mdx +++ /dev/null @@ -1,30 +0,0 @@ ---- -title: "Receive Payments" -sidebarTitle: "Receive Payments" -description: "On Solana, share your wallet address, not your token account. It is typical for the sender to derive the appropriate associated token account for whatever token they're sending." -keywords: ["receive stablecoin solana", "light token receive"] ---- - -import SupportFooter from "/snippets/support-footer.mdx"; - ---- - -1. Receiving payments work just like with SPL. -2. After receiving a payment use `getAtaInterface()` to verify your token balance: [Verify Payments](light-token/payments/verify-payments). -3. See the [Solana documentation](https://solana.com/docs/payments/accept-payments) for examples of drop-in components, the Solana Pay protocol, or direct RPC integration. - -## Related guides - - - - Check balances and transaction history. - - - Abstract SOL fees so users never hold SOL. - - - Send a single token transfer. - - - - diff --git a/light-token/payments/spend-permissions.mdx b/light-token/payments/spend-permissions.mdx deleted file mode 100644 index b2c8ccee..00000000 --- a/light-token/payments/spend-permissions.mdx +++ /dev/null @@ -1,221 +0,0 @@ ---- -title: "Spend Permissions via Delegation" -sidebarTitle: "Spend Permissions" -description: "Delegate token spending to a third party with an amount cap. The delegate can transfer tokens on behalf of the owner up to the approved amount, without the owner signing each transaction." -keywords: ["delegate tokens solana", "token delegation light token", "spend permissions solana", "recurring payments solana"] ---- - -import FullSetup from "/snippets/setup/full-setup.mdx"; -import SupportFooter from "/snippets/support-footer.mdx"; -import AgentSkillPayments from "/snippets/setup/agent-skill-payments.mdx"; -import PaymentsAiPrompt from "/snippets/ai-prompts/toolkits/payments.mdx"; -import SplDelegateApprove from "/snippets/code-snippets/payments/spl/delegate-approve.mdx"; -import SplDelegateCheck from "/snippets/code-snippets/payments/spl/delegate-check.mdx"; -import SplDelegateTransfer from "/snippets/code-snippets/payments/spl/delegate-transfer.mdx"; -import SplDelegateRevoke from "/snippets/code-snippets/payments/spl/delegate-revoke.mdx"; - ---- - -Delegation with Light Token works similar to SPL. -When you approve a delegate, you're authorizing a specific account to transfer tokens on your behalf: - -- **Owner retains custody**: You still own the tokens and can transfer or revoke at any time. Delegation is non-custodial. -- **Capped spending**: The delegate can spend tokens up to the limit, but cannot access or drain the account beyond the approved amount. -- **Single delegate per account**: Each token account can only have one active delegate. The owner can revoke at any time. -- **New approval replaces old**: Approving a new delegate automatically revokes the previous one - - - - - - - - - - - - - - - - - - - - - - - - - - -
SPLLight
**Approve**approve()approveInterface()
**Delegated Transfer**transfer() (delegate signs)transferInterface(..., ownerPubkey, delegateSigner, ...)
**Revoke**revoke()revokeInterface()
- - - - - - -## Use cases - -| Use case | How delegation helps | -|:---------|:--------------------| -| **Subscriptions** | Approve a monthly cap. The service provider transfers the fee each period. | -| **Recurring payments** | Approve a spending limit. The payment processor draws funds as needed. | -| **Managed spending** | A parent or admin approves a cap for a sub-account. | -| **Agent wallets** | An AI agent operates within a delegated spending limit. | - -## Setup - - - -```typescript -import { createRpc } from "@lightprotocol/stateless.js"; - -const rpc = createRpc(RPC_ENDPOINT); -``` - -## Approve a delegate - -Grant a delegate permission to spend up to a capped amount: - -```typescript -import { approveInterface } from "@lightprotocol/compressed-token/unified"; - -const tx = await approveInterface( - rpc, - payer, - senderAta, - mint, - delegate.publicKey, // who gets permission - 500_000, // amount cap - owner // token owner (signs) -); - -console.log("Approved:", tx); -``` - - - - - - - -## Check delegation status - -Check the delegation status of an account: - -```typescript -import { getAtaInterface } from "@lightprotocol/compressed-token"; - -const account = await getAtaInterface(rpc, senderAta, owner.publicKey, mint); - -console.log("Delegate:", account.parsed.delegate?.toBase58() ?? "none"); -console.log("Delegated amount:", account.parsed.delegatedAmount.toString()); -``` - - - - - - - -## Transfer as Delegate - -Once approved, the delegate can transfer tokens on behalf of the owner. The delegate is the transaction authority. Only the delegate and fee payer sign; the owner's signature is not required. - -`transferInterface` takes a recipient wallet address and creates the recipient's associated token account internally. For delegated transfers, pass the **source token-account owner** as **`owner`** (pubkey) and the **delegate** as **`authority`** (signer). Do not use removed **`InterfaceOptions.owner`** — there is no `{ owner: ... }` options bag for this flow. - -```typescript -import { transferInterface } from "@lightprotocol/compressed-token/unified"; - -const tx = await transferInterface( - rpc, - payer, - senderAta, - mint, - recipient.publicKey, // recipient wallet (associated token account created internally) - owner.publicKey, // source account owner (does not sign) - delegate, // delegate authority (signer) - 200_000 // must be within approved cap -); - -console.log("Delegated transfer:", tx); -``` - - - - - - - - - -`createTransferInterfaceInstructions` returns `TransactionInstruction[][]` for manual transaction control. Pass the **token-account owner** pubkey as the flat **`owner`** argument; for delegate-signed transactions, set **`options.delegatePubkey`**. - -```typescript -import { - Transaction, - sendAndConfirmTransaction, -} from "@solana/web3.js"; -import { createTransferInterfaceInstructions } from "@lightprotocol/compressed-token/unified"; - -const instructions = await createTransferInterfaceInstructions( - rpc, - payer.publicKey, - mint, - 200_000, - owner.publicKey, - recipient.publicKey, - 9, // decimals - { delegatePubkey: delegate.publicKey } -); - -for (const ixs of instructions) { - const tx = new Transaction().add(...ixs); - await sendAndConfirmTransaction(rpc, tx, [payer, delegate]); -} -``` - - - -## Revoke a delegate - -Remove all spending permissions from the current delegate. -If you need to reduce the limit, approve the same delegate with a lower amount. - -```typescript -import { revokeInterface } from "@lightprotocol/compressed-token/unified"; - -const tx = await revokeInterface(rpc, payer, senderAta, mint, owner); - -console.log("Revoked:", tx); -``` - - - - - - - - - - - - - -## Related guides - - - - Send a single token transfer. - - - Separate the fee payer from the token owner. - - - Query balances and transaction history. - - - - diff --git a/light-token/payments/verify-payments.mdx b/light-token/payments/verify-payments.mdx deleted file mode 100644 index d56d0f06..00000000 --- a/light-token/payments/verify-payments.mdx +++ /dev/null @@ -1,127 +0,0 @@ ---- -title: "Verify Payments" -sidebarTitle: "Get Token Balance and Transaction History" -description: "Query token balances and transaction history to verify incoming payments." -keywords: ["verify payment solana", "token balance solana", "transaction history light token", "payment verification"] ---- - -import FullSetup from "/snippets/setup/full-setup.mdx"; -import SupportFooter from "/snippets/support-footer.mdx"; -import AgentSkillPayments from "/snippets/setup/agent-skill-payments.mdx"; -import PaymentsAiPrompt from "/snippets/ai-prompts/toolkits/payments.mdx"; -import PaymentsSetupHelper from "/snippets/setup/payments-setup-helper.mdx"; -import GetBalanceCode from "/snippets/code-snippets/payments/verify/get-balance.mdx"; -import GetHistoryCode from "/snippets/code-snippets/payments/verify/get-history.mdx"; - - - - - - - - - - - - - - - - - - - - - -
SPLLight
**Get Balance**getAccount()getAtaInterface()
**Tx History**getSignaturesForAddress()rpc.getSignaturesForOwnerInterface()
- - - - - - -## Setup - - - -```typescript -import { createRpc } from "@lightprotocol/stateless.js"; - -const rpc = createRpc(RPC_ENDPOINT); -``` - - - -## Query balance - -`getAtaInterface` returns a unified balance aggregating Light Token (hot + cold), SPL, and Token 2022 sources in `parsed.amount`. - - -Find a full code example [here](https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/verify/get-balance.ts). - - - - - - -| | SPL | Light | -|------|-----|-------| -| Connection | `new Connection(endpoint)` | `createRpc()` | -| Derive ATA | `getAssociatedTokenAddress(mint, owner)` | `getAssociatedTokenAddressInterface(mint, owner)` | -| Fetch account | `getAccount(connection, ata)` | `getAtaInterface(rpc, ata, owner, mint)` | -| Read balance | `account.amount` | `account.parsed.amount` | - -```typescript - import { Connection, PublicKey } from "@solana/web3.js"; - import { getAssociatedTokenAddress, getAccount } from "@solana/spl-token"; - - const connection = new Connection("https://api.mainnet-beta.solana.com"); - const mint = new PublicKey("YOUR_MINT_ADDRESS"); - const owner = new PublicKey("YOUR_OWNER_ADDRESS"); - - const ata = getAssociatedTokenAddress(mint, owner); - const account = await getAccount(connection, ata); - console.log("Balance:", account.amount.toString()); -``` - - - -## Transaction history - - -Find a full code example [here](https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/verify/get-history.ts). - - -Query all transactions for an owner across both on-chain and compressed state: - - - - - -```typescript -const signatures = await connection.getSignaturesForAddress(ata); -``` - - - - - - - - - -## Related guides - - - - Load cold accounts and prepare to receive. - - - Send a single token transfer. - - - Validate recipient addresses before sending. - - - - diff --git a/light-token/payments/verify-recipient-address.mdx b/light-token/payments/verify-recipient-address.mdx deleted file mode 100644 index 28f2f279..00000000 --- a/light-token/payments/verify-recipient-address.mdx +++ /dev/null @@ -1,94 +0,0 @@ ---- -title: "Verify Address" -sidebarTitle: "Verify Recipients Address" -description: "Verify recipient addresses before sending payments. Address validation prevents sending tokens to invalid or unexpected account types." -keywords: ["verify address solana", "address validation light token", "solana address check", "payment safety"] ---- - -import FullSetup from "/snippets/setup/full-setup.mdx"; -import SupportFooter from "/snippets/support-footer.mdx"; -import AgentSkillPayments from "/snippets/setup/agent-skill-payments.mdx"; -import PaymentsAiPrompt from "/snippets/ai-prompts/toolkits/payments.mdx"; - - - - - - - - - - - - - - - - - - -
SPLLight
**Get Account**getAccount()getAtaInterface()
- - - - - - -## Verification flow - -Before sending a payment: - -1. Check if the address is on-curve (wallet) or off-curve (PDA). -2. If the address has an on-chain account, check the account owner and type. -3. For Light Token, derive the associated token account to verify it matches the expected mint. - -```typescript -import { - getAssociatedTokenAddressInterface, - getAtaInterface, -} from "@lightprotocol/compressed-token/unified"; - -// Derive the expected associated token account for this recipient and mint -const expectedAta = getAssociatedTokenAddressInterface(mint, recipientWallet); - -// Check if the account exists and is active -try { - const account = await getAtaInterface(rpc, expectedAta, recipientWallet, mint); - console.log("Account exists, balance:", account.parsed.amount); -} catch { - console.log("Account does not exist yet — will be created on first transfer"); -} -``` - - -Use `getAssociatedTokenAddressInterface()` instead of SPL's `getAssociatedTokenAddressSync()` to derive -Light Token associated token account addresses. The derivation uses the Light Token Program ID. - - - -When you send a payment with `transferInterface()` or `createTransferInterfaceInstructions()`, -the SDK automatically creates the recipient's associated token account if it doesn't exist. -Address verification is a safety check, not a prerequisite. - - - - - - - - -## Related guides - - - - Send a single token transfer. - - - Load cold accounts and prepare to receive. - - - Query balances and transaction history. - - - - \ No newline at end of file diff --git a/light-token/payments/wrap-unwrap.mdx b/light-token/payments/wrap-unwrap.mdx deleted file mode 100644 index f60aed6e..00000000 --- a/light-token/payments/wrap-unwrap.mdx +++ /dev/null @@ -1,168 +0,0 @@ ---- -title: "Wrap and Unwrap" -sidebarTitle: "Wrap and Unwrap" -description: "Move tokens between SPL / Token 2022 and Light Token accounts. Use wrap/unwrap to interoperate with applications that only support SPL or Token 2022." -keywords: ["wrap tokens solana", "unwrap tokens solana", "spl to light token", "cex onramp solana", "token interoperability"] ---- - -import RegisterSplMint from "/snippets/setup/register-spl-mint.mdx"; -import FullSetup from "/snippets/setup/full-setup.mdx"; -import WrapTokenInterfaceInstructionCode from "/snippets/code-snippets/light-token/wrap/token-interface-instruction.mdx"; -import UnwrapTokenInterfaceInstructionCode from "/snippets/code-snippets/light-token/unwrap/token-interface-instruction.mdx"; -import SupportFooter from "/snippets/support-footer.mdx"; -import AgentSkillPayments from "/snippets/setup/agent-skill-payments.mdx"; -import PaymentsAiPrompt from "/snippets/ai-prompts/toolkits/payments.mdx"; - - - - - - -## Setup - - - -```typescript -import { createRpc } from "@lightprotocol/stateless.js"; - -const rpc = createRpc(RPC_ENDPOINT); -``` - -## Wrap from SPL - - -Find a full code example [here](https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/interop/wrap.ts). - - - - - -```typescript -import { Transaction } from "@solana/web3.js"; -import { getAssociatedTokenAddressSync } from "@solana/spl-token"; -import { - createWrapInstruction, - getAssociatedTokenAddressInterface, -} from "@lightprotocol/compressed-token/unified"; -import { getSplInterfaceInfos } from "@lightprotocol/compressed-token"; - -const splAta = getAssociatedTokenAddressSync(mint, owner.publicKey); -const tokenAta = getAssociatedTokenAddressInterface(mint, owner.publicKey); - -const splInterfaceInfos = await getSplInterfaceInfos(rpc, mint); -const splInterfaceInfo = splInterfaceInfos.find((i) => i.isInitialized); - -const tx = new Transaction().add( - createWrapInstruction( - splAta, - tokenAta, - owner.publicKey, - mint, - amount, - splInterfaceInfo, - decimals, - payer.publicKey - ) -); -``` - - - - - - - - - -```typescript -import { getAssociatedTokenAddressSync } from "@solana/spl-token"; -import { - wrap, - getAssociatedTokenAddressInterface, -} from "@lightprotocol/compressed-token/unified"; - -const splAta = getAssociatedTokenAddressSync(mint, owner.publicKey); -const tokenAta = getAssociatedTokenAddressInterface(mint, owner.publicKey); - -await wrap(rpc, payer, splAta, tokenAta, owner, mint, amount); -``` - - - - -## Unwrap to SPL - - -Find a full code example [here](https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/interop/unwrap.ts). - - -Unwrap moves the token balance from a Light Token associated token account to an SPL associated token account. -Use this to compose with applications that do not yet support Light Token. - - - - -```typescript -import { Transaction, sendAndConfirmTransaction } from "@solana/web3.js"; -import { getAssociatedTokenAddressSync } from "@solana/spl-token"; -import { createUnwrapInstructions } from "@lightprotocol/compressed-token/unified"; - -const splAta = getAssociatedTokenAddressSync(mint, owner.publicKey); - -// Each inner array = one transaction. Handles loading + unwrapping together. -const instructions = await createUnwrapInstructions( - rpc, - splAta, - owner.publicKey, - mint, - amount, - payer.publicKey -); - -for (const ixs of instructions) { - const tx = new Transaction().add(...ixs); - await sendAndConfirmTransaction(rpc, tx, [payer, owner]); -} -``` - - - - - - - - - -```typescript -import { getAssociatedTokenAddressSync } from "@solana/spl-token"; -import { unwrap } from "@lightprotocol/compressed-token/unified"; - -const splAta = getAssociatedTokenAddressSync(mint, owner.publicKey); - -await unwrap(rpc, payer, splAta, owner, mint, amount); -``` - - - - - - - - - - -## Related guides - - - - Send a single token transfer. - - - Abstract SOL fees from the user. - - - Query balances and transaction history. - - - - diff --git a/light-token/quickstart.mdx b/light-token/quickstart.mdx deleted file mode 100644 index dfbaa9e6..00000000 --- a/light-token/quickstart.mdx +++ /dev/null @@ -1,41 +0,0 @@ ---- -title: Quickstart -description: Mint SPL tokens, wrap to Light Token, and transfer in under 3 minutes. -sidebarTitle: Quickstart -keywords: ["create rent-free tokens on solana tutorial", "mint rent-free tokens on solana guide", "light token quickstart for developers", "light token sdk for solana apps"] ---- - -import FullSetup from "/snippets/setup/full-setup.mdx"; -import MintSplAndWrapAction from "/snippets/code-snippets/light-token/mint-spl-and-wrap/action.mdx"; -import AgentSkillGeneric from "/snippets/setup/agent-skill-generic.mdx"; - - - - - - -## Prerequisites - - - - - - -## Mint SPL tokens, wrap them to a rent-free account and transfer them to a recipient - - - - - - -# Next Steps - - - Find answers to frequently answered questions. - - - diff --git a/light-token/streaming/mints.mdx b/light-token/streaming/mints.mdx deleted file mode 100644 index 27a2a592..00000000 --- a/light-token/streaming/mints.mdx +++ /dev/null @@ -1,269 +0,0 @@ ---- -title: "Streaming Mint Accounts" -sidebarTitle: "Mint Accounts" -description: "Stream light-mint accounts and metadata via Laserstream." -keywords: ["streaming mint accounts solana", "laserstream light mint", "grpc mint streaming"] ---- - -import FindClosedAccounts from '/snippets/code-snippets/streaming/find-closed-accounts.mdx'; -import AgentSkillStreaming from "/snippets/setup/agent-skill-streaming.mdx"; -import StreamingMintsAiPrompt from "/snippets/ai-prompts/streaming/mints.mdx"; -import SupportFooter from "/snippets/support-footer.mdx"; - -| Event | Description | -|:------|:------------| -| **New mints** | Raw mint data | -| **Mint updates** | Supply changes, authority changes | -| **TokenMetadata** | Name, symbol, URI, additional_metadata | -| **Cold/hot transitions** | Mint compressed or decompressed | - - -This guide is for teams building custom data pipelines (aggregators, market makers). -If you just need account lookups, use [`get_account_interface`](/light-token/defi/routers) instead. - - - - - - - -## Architecture - -Light mints are Solana accounts owned by the Light Token Program. The streaming -setup requires two gRPC subscriptions: - -| Subscription | Detects | How | -|:-------------|:--------|:----| -| Account sub (`owner: cToken...`, `account_type == 1`) | Hot state + cold-to-hot | Pubkey cache lookup | -| Transaction sub (`account_include: cToken...`) | Hot-to-cold | Balance heuristic (`pre > 0, post == 0`) | - -The account subscription delivers all state changes while mints are hot. -The transaction subscription is needed to detect mints going cold -(`CompressAndCloseMint` changes the owner to System Program, which the account -subscription no longer matches). - -## Setup - -```toml Cargo.toml -[dependencies] -helius-laserstream = "0.1" -tokio = { version = "1", features = ["full"] } -futures = "0.3" -bs58 = "0.5" -borsh = "0.10" -light-token-interface = "0.5.0" -``` - -```rust -use borsh::BorshDeserialize; -use futures::StreamExt; -use helius_laserstream::grpc::subscribe_request_filter_accounts_filter::Filter; -use helius_laserstream::grpc::subscribe_request_filter_accounts_filter_memcmp::Data; -use helius_laserstream::grpc::{ - SubscribeRequestFilterAccounts, SubscribeRequestFilterAccountsFilter, - SubscribeRequestFilterAccountsFilterMemcmp, SubscribeRequestFilterTransactions, -}; -use helius_laserstream::{subscribe, LaserstreamConfig}; -use light_token_interface::state::{ExtensionStruct, Mint}; - -const LIGHT_TOKEN_PROGRAM_ID: &str = "cTokenmWW8bLPjZEBAUgYy3zKxQZW6VKi7bqNFEVv3m"; -const ACCOUNT_TYPE_OFFSET: u64 = 165; -``` - - - - -### Connect - - - - -```rust -let config = LaserstreamConfig::new( - "https://laserstream-mainnet-ewr.helius-rpc.com".to_string(), - std::env::var("HELIUS_API_KEY")?, -); -``` - - - - -```rust -let config = LaserstreamConfig::new( - "https://laserstream-devnet-ewr.helius-rpc.com".to_string(), - std::env::var("HELIUS_API_KEY")?, -); -``` - - - - - - - -### Subscribe - -```rust -let mut request = helius_laserstream::grpc::SubscribeRequest::default(); - -// 1. Account sub: mint state tracking + cold-to-hot detection. -// account_type == 1 (Mint) at byte offset 165. -request.accounts.insert( - "light_mints".to_string(), - SubscribeRequestFilterAccounts { - owner: vec![LIGHT_TOKEN_PROGRAM_ID.to_string()], - filters: vec![SubscribeRequestFilterAccountsFilter { - filter: Some(Filter::Memcmp(SubscribeRequestFilterAccountsFilterMemcmp { - offset: ACCOUNT_TYPE_OFFSET, - data: Some(Data::Bytes(vec![1])), - })), - }], - nonempty_txn_signature: Some(true), - ..Default::default() - }, -); - -// 2. Transaction sub: hot-to-cold detection. -request.transactions.insert( - "light_token_txns".to_string(), - SubscribeRequestFilterTransactions { - vote: Some(false), - failed: Some(false), - account_include: vec![LIGHT_TOKEN_PROGRAM_ID.to_string()], - ..Default::default() - }, -); - -let (stream, _handle) = subscribe(config, request); -tokio::pin!(stream); -``` - - - - -### Deserialize mint accounts - -```rust -use helius_laserstream::grpc::subscribe_update::UpdateOneof; - -Some(UpdateOneof::Account(account_update)) => { - if let Some(account_info) = account_update.account { - let pubkey: [u8; 32] = account_info.pubkey.as_slice().try_into().unwrap(); - - match Mint::deserialize(&mut account_info.data.as_slice()) { - Ok(mint) => { - cold_cache.remove(&pubkey); // no longer cold - cache.insert(pubkey, mint); - } - Err(e) => { - eprintln!( - "Failed to deserialize mint {}: {}", - bs58::encode(&pubkey).into_string(), - e - ); - } - } - } -} -``` - - - - -### Detect mints going cold - - - - - - -### Extract TokenMetadata - -```rust -fn extract_metadata(mint: &Mint) -> Option<(String, String, String)> { - let extensions = mint.extensions.as_ref()?; - - for ext in extensions { - if let ExtensionStruct::TokenMetadata(m) = ext { - let name = String::from_utf8_lossy(&m.name).to_string(); - let symbol = String::from_utf8_lossy(&m.symbol).to_string(); - let uri = String::from_utf8_lossy(&m.uri).to_string(); - return Some((name, symbol, uri)); - } - } - None -} -``` - - - - - -## Data Layouts - -### Mint - -```rust -#[repr(C)] -pub struct Mint { - pub base: BaseMint, - pub metadata: MintMetadata, - pub reserved: [u8; 16], - pub account_type: u8, - pub compression: CompressionInfo, - pub extensions: Option>, -} - -#[repr(C)] -pub struct BaseMint { - pub mint_authority: Option, - pub supply: u64, - pub decimals: u8, - pub is_initialized: bool, - pub freeze_authority: Option, -} - -#[repr(C)] -pub struct MintMetadata { - pub version: u8, - pub mint_decompressed: bool, - pub mint: Pubkey, - pub mint_signer: [u8; 32], - pub bump: u8, -} -``` - -### TokenMetadata - -```rust -#[repr(C)] -pub struct TokenMetadata { - pub update_authority: Pubkey, // [0u8; 32] = immutable - pub mint: Pubkey, - pub name: Vec, - pub symbol: Vec, - pub uri: Vec, - pub additional_metadata: Vec, -} - -pub struct AdditionalMetadata { - pub key: Vec, - pub value: Vec, -} -``` - - - - - - - - - - diff --git a/light-token/streaming/tokens.mdx b/light-token/streaming/tokens.mdx deleted file mode 100644 index 37962308..00000000 --- a/light-token/streaming/tokens.mdx +++ /dev/null @@ -1,276 +0,0 @@ ---- -title: "Streaming Token Accounts" -sidebarTitle: "Token Accounts" -description: "Stream light-token accounts via Laserstream. Same base layout as SPL Token." -keywords: ["streaming token accounts solana", "laserstream light token", "grpc token streaming"] ---- - -import FindClosedAccounts from '/snippets/code-snippets/streaming/find-closed-accounts.mdx'; -import AgentSkillStreaming from "/snippets/setup/agent-skill-streaming.mdx"; -import StreamingTokensAiPrompt from "/snippets/ai-prompts/streaming/tokens.mdx"; -import SupportFooter from "/snippets/support-footer.mdx"; - - -This guide is for teams building custom data pipelines (aggregators, market makers). -If you just need account lookups, use [`get_account_interface`](/light-token/defi/routers) instead. - - - - - - - -## Architecture - -Light token accounts share the same base layout as SPL Token (165 bytes), so you can -use your existing parser. The streaming setup requires two gRPC subscriptions, both -targeting the Light Token Program: - -| Subscription | Detects | How | -|:-------------|:--------|:----| -| Account sub (`owner: cToken...`) | Hot state + cold-to-hot | Pubkey cache lookup | -| Transaction sub (`account_include: cToken...`) | Hot-to-cold | Balance heuristic (`pre > 0, post == 0`) | - -The account subscription delivers all state changes while accounts are hot. -The transaction subscription is needed to detect accounts going cold -(`compress_and_close` changes the owner to System Program, which the account -subscription no longer matches). - -## Parsing - -```rust -use spl_pod::bytemuck::pod_from_bytes; -use spl_token_2022_interface::pod::PodAccount; // works for SPL-token, SPL-token-2022, and Light-token - -let parsed: &PodAccount = pod_from_bytes(&data[..165])?; -``` - -For accounts with extensions, truncate to 165 bytes before parsing. - -## Streaming - -```toml Cargo.toml -[dependencies] -helius-laserstream = "0.1" -tokio = { version = "1", features = ["full"] } -futures = "0.3" -bs58 = "0.5" -borsh = "0.10" -light-token-interface = "0.5.0" -``` - -```rust -use futures::StreamExt; -use helius_laserstream::grpc::subscribe_request_filter_accounts_filter::Filter; -use helius_laserstream::grpc::subscribe_request_filter_accounts_filter_memcmp::Data; -use helius_laserstream::grpc::{ - SubscribeRequestFilterAccounts, SubscribeRequestFilterAccountsFilter, - SubscribeRequestFilterAccountsFilterMemcmp, SubscribeRequestFilterTransactions, -}; -use helius_laserstream::{subscribe, LaserstreamConfig}; - -const LIGHT_TOKEN_PROGRAM_ID: &str = "cTokenmWW8bLPjZEBAUgYy3zKxQZW6VKi7bqNFEVv3m"; -const TOKEN_ACCOUNT_SIZE: u64 = 165; -const ACCOUNT_TYPE_OFFSET: u64 = 165; -const ACCOUNT_TYPE_TOKEN: u8 = 2; -``` - - - - -### Connect - - - - -```rust -let config = LaserstreamConfig::new( - "https://laserstream-mainnet-ewr.helius-rpc.com".to_string(), - std::env::var("HELIUS_API_KEY")?, -); -``` - - - - -```rust -let config = LaserstreamConfig::new( - "https://laserstream-devnet-ewr.helius-rpc.com".to_string(), - std::env::var("HELIUS_API_KEY")?, -); -``` - - - - - - - -### Subscribe - -```rust -let mut request = helius_laserstream::grpc::SubscribeRequest::default(); - -// 1. Account sub: hot state tracking + cold-to-hot detection. -request.accounts.insert( - "light_tokens".to_string(), - SubscribeRequestFilterAccounts { - owner: vec![LIGHT_TOKEN_PROGRAM_ID.to_string()], - filters: vec![SubscribeRequestFilterAccountsFilter { - filter: Some(Filter::Datasize(TOKEN_ACCOUNT_SIZE)), - }], - nonempty_txn_signature: Some(true), - ..Default::default() - }, -); -request.accounts.insert( - "light_tokens_extended".to_string(), - SubscribeRequestFilterAccounts { - owner: vec![LIGHT_TOKEN_PROGRAM_ID.to_string()], - filters: vec![SubscribeRequestFilterAccountsFilter { - filter: Some(Filter::Memcmp(SubscribeRequestFilterAccountsFilterMemcmp { - offset: ACCOUNT_TYPE_OFFSET, - data: Some(Data::Bytes(vec![ACCOUNT_TYPE_TOKEN])), - })), - }], - nonempty_txn_signature: Some(true), - ..Default::default() - }, -); - -// 2. Transaction sub: hot-to-cold detection. -request.transactions.insert( - "light_token_txns".to_string(), - SubscribeRequestFilterTransactions { - vote: Some(false), - failed: Some(false), - account_include: vec![LIGHT_TOKEN_PROGRAM_ID.to_string()], - ..Default::default() - }, -); - -let (stream, _handle) = subscribe(config, request); -tokio::pin!(stream); -``` - - - - - -## Detecting transitions - -### Hot-to-cold - -For each transaction update, find accounts whose lamport balance dropped to zero. -The `cache.remove` call ensures only accounts you're already tracking are processed: - - - -### Cold-to-hot - -When a token account is decompressed, the account subscription delivers the -re-created account. Match its pubkey against `cold_cache`: - -```rust -Some(UpdateOneof::Account(account_update)) => { - if let Some(account) = account_update.account { - let pubkey: [u8; 32] = account.pubkey.as_slice().try_into().unwrap(); - let parsed: &PodAccount = pod_from_bytes(&account.data[..165])?; - - cold_cache.remove(&pubkey); // no longer cold - cache.insert(pubkey, *parsed); - } -} -``` - -## Point queries - -`getAccountInfo` returns null for cold accounts. `get_account_interface()` races -hot and cold lookups and returns raw account bytes that work with your standard SPL parser: - -```rust -use light_client::rpc::{LightClient, LightClientConfig, Rpc}; -use spl_pod::bytemuck::pod_from_bytes; -use spl_token_2022_interface::pod::PodAccount; - -let config = LightClientConfig::new( - "https://api.devnet.solana.com".to_string(), - Some("https://photon.helius.com?api-key=YOUR_KEY".to_string()), -); -let client = LightClient::new(config).await?; -let result = client.get_account_interface(&pubkey, None).await?; - -if let Some(account) = result.value { - let parsed: &PodAccount = pod_from_bytes(&account.data()[..165])?; - if account.is_cold() { - // Compressed -- still valid for routing. - } -} -``` - -## Data layout - -165 bytes base, identical to SPL Token Account. - -| Field | Offset | Size | -|:------|:-------|:-----| -| `mint` | 0 | 32 | -| `owner` | 32 | 32 | -| `amount` | 64 | 8 | -| `delegate` | 72 | 36 | -| `state` | 108 | 1 | -| `is_native` | 109 | 12 | -| `delegated_amount` | 121 | 8 | -| `close_authority` | 129 | 36 | -| `account_type` | 165 | 1 | - -`account_type = 2` at byte 165 indicates extensions follow (borsh-encoded `Option>`). - - - -These are not needed for indexing or trading. - -```rust -use borsh::BorshDeserialize; -use light_token_interface::state::{Token, ExtensionStruct}; - -let token = Token::deserialize(&mut data.as_slice())?; - -if let Some(exts) = &token.extensions { - for ext in exts { - if let ExtensionStruct::Compressible(info) = ext { - // info.compression_authority, info.rent_sponsor, info.last_claimed_slot - } - } -} -``` - -| Variant | Description | -|:--------|:------------| -| `TokenMetadata(TokenMetadata)` | Name, symbol, URI, additional metadata | -| `PausableAccount(PausableAccountExtension)` | Marker: mint is pausable (no data; pause state lives on mint) | -| `PermanentDelegateAccount(PermanentDelegateAccountExtension)` | Marker: mint has permanent delegate | -| `TransferFeeAccount(TransferFeeAccountExtension)` | Withheld fees from transfers | -| `TransferHookAccount(TransferHookAccountExtension)` | Marker: mint has transfer hook | -| `CompressedOnly(CompressedOnlyExtension)` | Compressed-only token (stores delegated amount) | -| `Compressible(CompressibleExtension)` | Compression config: authority, rent sponsor, timing | - -Source: [`light-token-interface`](https://github.com/Lightprotocol/light-protocol/tree/main/program-libs/token-interface/src/state/extensions) - - - - - - - - - - - - diff --git a/light-token/wallets/gasless-transactions.mdx b/light-token/wallets/gasless-transactions.mdx deleted file mode 100644 index 8ba77054..00000000 --- a/light-token/wallets/gasless-transactions.mdx +++ /dev/null @@ -1,218 +0,0 @@ ---- -title: Gasless Transactions -sidebarTitle: Gasless transactions -description: Abstract SOL fees so users never hold SOL. The Light SDK sponsors rent-exemption for Solana accounts and keeps accounts active through periodic top-ups paid by the fee payer. Sponsor top-ups and transaction fees by setting your application as the fee payer. -keywords: ["gasless transactions solana", "fee abstraction solana", "rent sponsorship light token", "gasless solana tokens", "rent free tokens on solana"] ---- - -import TransferInstructionCode from "/snippets/code-snippets/light-token/gasless-transactions/ts-instruction.mdx"; -import RustInstructionCode from "/snippets/code-snippets/light-token/gasless-transactions/rust-instruction.mdx"; -import RentSponsorshipExplained from "/snippets/rent-sponsorship-explained.mdx"; -import GaslessTransactionsAiPrompt from "/snippets/ai-prompts/wallets/gasless-transactions.mdx"; -import SupportFooter from "/snippets/support-footer.mdx"; -import PaymentCostUsd from "/snippets/cost-tables/payment-cost-usd.mdx"; - ---- - -## Sponsor Top-ups and Transaction Fees - - -Rent sponsorship is a built-in feature of the Light SDK’s that sponsors rent-exemption. -This is dealt with under the hood in a way that doesn’t disrupt the UX of what your users are used to with SPL-token. - - - -Solana transactions have a designated fee payer, the account that pays the -network fee. By default, this is the first signer. You can specify a -different account as the fee payer, allowing a third party (the "sponsor") to -cover fees on behalf of the sender. - -Light Token extends this: The `payer` parameter on any Light Token -instruction determines who pays rent top-ups in addition to transaction fees. -Set your application as the payer so users never interact with SOL. - -In total, your sponsor covers three costs: - - - - -| | | | -|:-----|:-------|:----| -| **Account creation** | 17,400 lamports | Initial bump on virtual rent balance. Rent-exemption is sponsored. | -| **Rent top-ups** | ~766 lamports per write | Fee payer bumps the virtual rent balance on each write to keep accounts active. Set `payer` parameter on any Light Token instruction. | -| **Transaction fees**
+ Priority Fee | 5,000 lamports
+ Priority Fee per tx | Standard Solana fee payer. Set `feePayer` on the transaction. | - -
- -## Send a gasless transfer - - -Find a full code example [here](https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/gasless-transactions/typescript/gasless-transfer.ts). - - - - - - - - - -Generate or load a keypair for the sponsor who will pay transaction fees and rent top-ups. -The sponsor needs SOL but doesn't need to hold the tokens being transferred. - -```typescript -import { Keypair } from "@solana/web3.js"; -import { createRpc } from "@lightprotocol/stateless.js"; - -const rpc = createRpc(RPC_ENDPOINT); - -// Sponsor: your application server -const sponsor = Keypair.fromSecretKey(/* your server keypair */); - -// User: only signs to authorize the transfer -const sender = Keypair.fromSecretKey(/* user's keypair */); -``` - - - - - -Create the transfer instruction with the sponsor as `payer` and the sender as `authority`. -The sender owns the tokens and must sign the transfer. - -```typescript -import { createTransferInterfaceInstructions } from "@lightprotocol/compressed-token/unified"; - -const instructions = await createTransferInterfaceInstructions( - rpc, - sponsor.publicKey, // payer: covers rent top-ups and transaction fees - mint, - amount, - sender.publicKey, // authority: user signs to authorize - recipient.publicKey -); -``` - - - - - -Both the sponsor and sender must sign the transaction: - -| | Parameter | What it does | -|:-----|:----------|:-------------| -| **Payer** (fee payer) | First positional arg | Signs to authorize payment of rent top-ups and transaction fees. Can be your application server. | -| **Authority** (owner) | `owner` / authority arg | Signs to authorize the token transfer. The account holder. | - - -```typescript -import { Transaction, sendAndConfirmTransaction } from "@solana/web3.js"; - -for (const ixs of instructions) { - const tx = new Transaction().add(...ixs); - // Both sponsor and sender must sign - await sendAndConfirmTransaction(rpc, tx, [sponsor, sender]); -} -``` - - - - - - - - - - - - - - - - -Load or generate a keypair for the sponsor. The sponsor needs SOL but doesn't need to hold the tokens being transferred. - -```rust -use solana_sdk::{pubkey::Pubkey, signature::Keypair, signer::Signer}; - -// Sponsor: your application server -let sponsor: Keypair = /* your server keypair */; - -// User: only signs to authorize the transfer -let sender: Keypair = /* user's keypair */; -let recipient: Pubkey = /* recipient address */; -let mint: Pubkey = /* e.g. USDC mint */; -``` - - - - - -Build the transfer instruction with the sponsor as `payer` and the sender as `authority`. - -```rust -use light_token::instruction::{ - get_associated_token_address, TransferInterface, LIGHT_TOKEN_PROGRAM_ID, -}; - -let sender_ata = get_associated_token_address(&sender.pubkey(), &mint); -let recipient_ata = get_associated_token_address(&recipient, &mint); - -let transfer_ix = TransferInterface { - source: sender_ata, - destination: recipient_ata, - amount: 500_000, - decimals: 6, - authority: sender.pubkey(), // user signs to authorize - payer: sponsor.pubkey(), // sponsor covers rent top-ups and transaction fees - spl_interface: None, - source_owner: LIGHT_TOKEN_PROGRAM_ID, - destination_owner: LIGHT_TOKEN_PROGRAM_ID, -} -.instruction()?; -``` - - - - - -Both the sponsor and sender must sign the transaction. - -```rust -let sig = rpc - .create_and_send_transaction( - &[transfer_ix], - &sponsor.pubkey(), // fee payer - &[&sponsor, &sender], // both sign - ) - .await?; - -println!("Tx: {sig}"); -``` - - - - - - - - - - - - - - - -## Related guides - - - - Query balances and transaction history. - - - Pack multiple transfers into one transaction. - - - - diff --git a/light-token/wallets/overview.mdx b/light-token/wallets/overview.mdx deleted file mode 100644 index 64476f70..00000000 --- a/light-token/wallets/overview.mdx +++ /dev/null @@ -1,490 +0,0 @@ ---- -title: "Integration Guide for Wallet Applications" -sidebarTitle: "Integration Guide" -description: "Guide for Wallet Applications to add Light-token support." -keywords: ["wallet infrastructure on solana", "scalable wallet infrastructure on solana", "token wallet for developers", "rent free tokens for wallets"] ---- - -import { CodeCompare } from "/snippets/jsx/code-compare.jsx"; -import ToolkitsSetup from "/snippets/setup/toolkits-setup.mdx"; -import LoadAtaTokenInterfaceInstructionCode from "/snippets/code-snippets/light-token/load-ata/token-interface-instruction.mdx"; -import SendTokenInterfaceInstructionCode from "/snippets/code-snippets/payments/send/basic-send-token-interface-instruction.mdx"; -import WrapTokenInterfaceInstructionCode from "/snippets/code-snippets/light-token/wrap/token-interface-instruction.mdx"; -import UnwrapTokenInterfaceInstructionCode from "/snippets/code-snippets/light-token/unwrap/token-interface-instruction.mdx"; -import AgentSkillPayments from "/snippets/setup/agent-skill-payments.mdx"; -import TokenInterfaceSdk2Callout from "/snippets/light-token-guides/token-interface-sdk2-callout.mdx"; -import WalletsAiPrompt from "/snippets/ai-prompts/toolkits/wallets.mdx"; -import SupportFooter from "/snippets/support-footer.mdx"; -import TokenAccountCost from "/snippets/cost-tables/token-account-cost.mdx"; - -1. The Light-token API matches the SPL-token API almost entirely, and extends their functionality to include the light token program in addition to the SPL-token and Token-2022 programs. -2. Your users hold and receive tokens of the same mints, just stored more efficiently. - - - -### What you will implement - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SPLLight
**Receive**getOrCreateAssociatedTokenAccount()createLoadAtaInstructions() / loadAta()
**Transfer**createTransferInstruction()createTransferInterfaceInstructions() / transferInterface()
**Get Balance**getAccount()getAtaInterface()
**Tx History**getSignaturesForAddress()rpc.getSignaturesForOwnerInterface()
**Wrap from SPL**N/Awrap() / createWrapInstruction()
**Unwrap to SPL**N/AcreateUnwrapInstructions() / unwrap()
- - - Find full runnable code examples - [here](https://github.com/Lightprotocol/examples-light-token/tree/main/toolkits/payments). - - - - - - - -## Setup - - - -Snippets below assume `rpc`, `payer`, `mint`, `owner`, `recipient`, and `amount` are defined. -See the [full examples](https://github.com/Lightprotocol/examples-light-token/tree/main/toolkits/payments) for runnable setup. - -```typescript -import { createRpc } from "@lightprotocol/stateless.js"; - -import { - createLoadAtaInstructions, - loadAta, - createTransferInterfaceInstructions, - transferInterface, - createUnwrapInstructions, - unwrap, - getAssociatedTokenAddressInterface, - getAtaInterface, - wrap, -} from "@lightprotocol/compressed-token/unified"; - -const rpc = createRpc(RPC_ENDPOINT); -``` - - -**About loading**: Light Token accounts reduce account rent ~200x by auto-compressing inactive -accounts. Before any action, the SDK detects cold balances and adds -instructions to load them. This almost always fits in a single -atomic transaction with your regular transfer. APIs return `TransactionInstruction[][]` so the same -loop handles the rare multi-transaction case automatically. - - - -## Receive Payments - - -Find a full code example [here](https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/receive/receive.ts). - - -Load creates the associated token account (ATA) if needed and loads any compressed state into it. Share the ATA address with the sender. - - - - -```typescript -import { Transaction, sendAndConfirmTransaction } from "@solana/web3.js"; -import { - createLoadAtaInstructions, - getAssociatedTokenAddressInterface, -} from "@lightprotocol/compressed-token/unified"; - -const ata = getAssociatedTokenAddressInterface(mint, recipient); - -// Returns TransactionInstruction[][]. -// Each inner array is one transaction. -// Almost always returns just one. -const instructions = await createLoadAtaInstructions( - rpc, - ata, - recipient, - mint, - payer.publicKey -); - -for (const ixs of instructions) { - const tx = new Transaction().add(...ixs); - await sendAndConfirmTransaction(rpc, tx, [payer]); -} -``` - - - - - - - - - -```typescript -import { - loadAta, - getAssociatedTokenAddressInterface, -} from "@lightprotocol/compressed-token/unified"; - -const ata = getAssociatedTokenAddressInterface(mint, recipient); - -const sig = await loadAta(rpc, ata, recipient, mint, payer); -if (sig) console.log("Loaded:", sig); -``` - - - - - - -```typescript -import { - createAssociatedTokenAccountInstruction, - getAssociatedTokenAddressSync, - getOrCreateAssociatedTokenAccount, -} from "@solana/spl-token"; - -const ata = getAssociatedTokenAddressSync(mint, recipient); - -// Instruction: -const tx = new Transaction().add( - createAssociatedTokenAccountInstruction(payer.publicKey, ata, recipient, mint) -); - -// Action: -const ata = await getOrCreateAssociatedTokenAccount( - connection, payer, mint, recipient -); -``` - - - -## Send Payments - - -Find a full code example: [instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/send/basic-send-instruction.ts) | [action](https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/send/basic-send-action.ts). - - - - - -```typescript -import { Transaction, sendAndConfirmTransaction } from "@solana/web3.js"; -import { createTransferInterfaceInstructions } from "@lightprotocol/compressed-token/unified"; - -// Returns TransactionInstruction[][]. -// Each inner array is one transaction. -// Almost always returns just one. -const instructions = await createTransferInterfaceInstructions( - rpc, - payer.publicKey, - mint, - amount, - owner.publicKey, - recipient -); - -for (const ixs of instructions) { - const tx = new Transaction().add(...ixs); - await sendAndConfirmTransaction(rpc, tx, [payer, owner]); -} -``` - - - -```typescript -import { - getAssociatedTokenAddressSync, - createAssociatedTokenAccountIdempotentInstruction, - createTransferInstruction, -} from "@solana/spl-token"; - -const sourceAta = getAssociatedTokenAddressSync(mint, owner.publicKey); -const destinationAta = getAssociatedTokenAddressSync(mint, recipient); - -const tx = new Transaction().add( - createAssociatedTokenAccountIdempotentInstruction( - payer.publicKey, destinationAta, recipient, mint - ), - createTransferInstruction(sourceAta, destinationAta, owner.publicKey, amount) -); -``` - - - - - - - - - - - -```typescript -import { - getAssociatedTokenAddressInterface, - transferInterface, -} from "@lightprotocol/compressed-token/unified"; - -const sourceAta = getAssociatedTokenAddressInterface(mint, owner.publicKey); - -// Handles loading, creates recipient ATA, transfers. -await transferInterface( - rpc, - payer, - sourceAta, - mint, - recipient, - owner.publicKey, - owner, - amount -); -``` - - - -```typescript -import { - getAssociatedTokenAddressSync, - getOrCreateAssociatedTokenAccount, - transfer, -} from "@solana/spl-token"; - -await getOrCreateAssociatedTokenAccount(connection, payer, mint, recipient); - -const sourceAta = getAssociatedTokenAddressSync(mint, owner.publicKey); -const destinationAta = getAssociatedTokenAddressSync(mint, recipient); -await transfer(connection, payer, sourceAta, destinationAta, owner, amount); -``` - - - - - - -## Show Balance - - -Find a full code example [here](https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/verify/get-balance.ts). - - -```typescript -import { - getAssociatedTokenAddressInterface, - getAtaInterface, -} from "@lightprotocol/compressed-token/unified"; - -const ata = getAssociatedTokenAddressInterface(mint, owner); -const account = await getAtaInterface(rpc, ata, owner, mint); - -console.log(account.parsed.amount); -``` - - - -```typescript -import { getAccount } from "@solana/spl-token"; - -const account = await getAccount(connection, ata); - -console.log(account.amount); -``` - - - -## Transaction History - - -Find a full code example [here](https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/verify/get-history.ts). - - -```typescript -const result = await rpc.getSignaturesForOwnerInterface(owner); - -console.log(result.signatures); // Merged + deduplicated -console.log(result.solana); // On-chain txs only -console.log(result.compressed); // Compressed txs only -``` - -Use `getSignaturesForAddressInterface(address)` if you want address-specific rather than owner-wide history. - - - -```typescript -const signatures = await connection.getSignaturesForAddress(ata); -``` - - - -## Wrap from SPL - -Wrap tokens from SPL/Token-2022 accounts to light-token ATA. - - -Find a full code example [here](https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/interop/wrap.ts). - - - - - -```typescript -import { Transaction } from "@solana/web3.js"; -import { getAssociatedTokenAddressSync } from "@solana/spl-token"; -import { - createWrapInstruction, - getAssociatedTokenAddressInterface, -} from "@lightprotocol/compressed-token/unified"; -import { getSplInterfaceInfos } from "@lightprotocol/compressed-token"; - -const splAta = getAssociatedTokenAddressSync(mint, owner.publicKey); -const tokenAta = getAssociatedTokenAddressInterface(mint, owner.publicKey); - -const splInterfaceInfos = await getSplInterfaceInfos(rpc, mint); -const splInterfaceInfo = splInterfaceInfos.find((i) => i.isInitialized); - -const tx = new Transaction().add( - createWrapInstruction( - splAta, - tokenAta, - owner.publicKey, - mint, - amount, - splInterfaceInfo, - decimals, - payer.publicKey - ) -); -``` - - - - - - - - - -```typescript -import { getAssociatedTokenAddressSync } from "@solana/spl-token"; -import { - wrap, - getAssociatedTokenAddressInterface, -} from "@lightprotocol/compressed-token/unified"; - -const splAta = getAssociatedTokenAddressSync(mint, owner.publicKey); -const tokenAta = getAssociatedTokenAddressInterface(mint, owner.publicKey); - -await wrap(rpc, payer, splAta, tokenAta, owner, mint, amount); -``` - - - - -## Unwrap to SPL - -Unwrap moves the token balance from a light-token account to a SPL-token account. -Use this to compose with applications that do not yet support light-token. - - -Find a full code example [here](https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/interop/unwrap.ts). - - - - - -```typescript -import { Transaction } from "@solana/web3.js"; -import { getAssociatedTokenAddressSync } from "@solana/spl-token"; -import { createUnwrapInstructions } from "@lightprotocol/compressed-token/unified"; - -const splAta = getAssociatedTokenAddressSync(mint, owner.publicKey); - -// Each inner array = one transaction. Handles loading + unwrapping together. -const instructions = await createUnwrapInstructions( - rpc, - splAta, - owner.publicKey, - mint, - amount, - payer.publicKey -); - -for (const ixs of instructions) { - const tx = new Transaction().add(...ixs); - await sendAndConfirmTransaction(rpc, tx, [payer, owner]); -} -``` - - - - - - - - - -```typescript -import { getAssociatedTokenAddressSync } from "@solana/spl-token"; -import { unwrap } from "@lightprotocol/compressed-token/unified"; - -const splAta = getAssociatedTokenAddressSync(mint, owner.publicKey); - -await unwrap(rpc, payer, splAta, owner, mint, amount); -``` - - - - - - - - - - -## More wallet guides - - - - - - - - - - - diff --git a/light-token/wallets/privy.mdx b/light-token/wallets/privy.mdx deleted file mode 100644 index 7f1d81f8..00000000 --- a/light-token/wallets/privy.mdx +++ /dev/null @@ -1,418 +0,0 @@ ---- -title: "Sign with Privy" -sidebarTitle: "Sign with Privy Wallet" -description: "Integrate light-token with Privy embedded wallets for rent-free token accounts and transfers." -keywords: ["privy solana", "privy light token", "embedded wallet light token", "rent-free tokens privy"] ---- -import ToolkitsSetup from "/snippets/setup/toolkits-setup.mdx"; -import RegisterSplMint from "/snippets/setup/register-spl-mint.mdx"; -import AgentSkillPayments from "/snippets/setup/agent-skill-payments.mdx"; -import TransferNodejs from "/snippets/code-snippets/privy/transfer/nodejs.mdx"; -import TransferReact from "/snippets/code-snippets/privy/transfer/react.mdx"; -import SignAndSendBatchesHelper from "/snippets/code-snippets/privy/helpers/sign-and-send-batches.mdx"; -import SupportFooter from "/snippets/support-footer.mdx"; -import ReceiveNodejs from "/snippets/code-snippets/privy/receive/nodejs.mdx"; -import ReceiveReact from "/snippets/code-snippets/privy/receive/react.mdx"; -import WrapNodejs from "/snippets/code-snippets/privy/wrap/nodejs.mdx"; -import WrapReact from "/snippets/code-snippets/privy/wrap/react.mdx"; -import UnwrapNodejs from "/snippets/code-snippets/privy/unwrap/nodejs.mdx"; -import UnwrapReact from "/snippets/code-snippets/privy/unwrap/react.mdx"; -import BalancesNodejs from "/snippets/code-snippets/privy/balances/nodejs.mdx"; -import BalancesReact from "/snippets/code-snippets/privy/balances/react.mdx"; -import TransactionHistoryNodejs from "/snippets/code-snippets/privy/transaction-history/nodejs.mdx"; -import TransactionHistoryReact from "/snippets/code-snippets/privy/transaction-history/react.mdx"; -import PrivyAiPrompt from "/snippets/ai-prompts/wallets/privy.mdx"; -import TokenAccountCost from "/snippets/cost-tables/token-account-cost.mdx"; - - - -Privy handles user authentication and wallet management. You build transactions with light-token and Privy signs them: - -1. Authenticate with Privy -2. Build unsigned transaction -3. Sign transaction using Privy's wallet provider -4. Send signed transaction to RPC - -## What you will implement - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SPLLight
[**Transfer**](#full-code-examples)createTransferInstruction()createTransferInterfaceInstructions()
[**Receive**](#full-code-examples)getOrCreateAssociatedTokenAccount()createLoadAtaInstructions()
[**Wrap from SPL**](#full-code-examples)N/AcreateWrapInstruction()
[**Unwrap to SPL**](#full-code-examples)N/AcreateUnwrapInstructions()
[**Get Balance**](#get-balances)getAccount()getAtaInterface()
[**Tx History**](#get-transaction-history)getSignaturesForAddress()getSignaturesForOwnerInterface()
- - - - - - - -### Prerequisites - - - -Connect to an RPC endpoint that supports ZK Compression (Helius, Triton): - -```typescript -import { createRpc } from "@lightprotocol/stateless.js"; - -import { - createTransferInterfaceInstructions, - createLoadAtaInstructions, - createWrapInstruction, - createUnwrapInstructions, - getAssociatedTokenAddressInterface, - getAtaInterface, -} from "@lightprotocol/compressed-token/unified"; - -const rpc = createRpc(RPC_ENDPOINT); -``` - - - - -## Sign with Privy - - -Find complete examples on GitHub: [Node.js](https://github.com/Lightprotocol/examples-light-token/tree/main/toolkits/sign-with-privy/nodejs) and [React](https://github.com/Lightprotocol/examples-light-token/tree/main/toolkits/sign-with-privy/react). - - - - - -Transfer light-tokens between wallets. Auto-loads cold (compressed) light-token, SPL or -Token-2022 balance before sending. - - -**About loading:** Light Token accounts reduce account rent ~200x by auto-compressing inactive accounts. -Before any action, the SDK detects cold balances and adds instructions to load them. -This almost always fits in a single atomic transaction with your regular transfer. -APIs return `TransactionInstruction[][]` so the same loop handles the rare multi-transaction case -automatically. - - - - - - -Your app logic may require you to sign all transactions in sequence. Here's how: - - - -```typescript -for (const ixs of instructions) { - const tx = new Transaction().add(...ixs); - const { blockhash } = await connection.getLatestBlockhash(); - tx.recentBlockhash = blockhash; - tx.feePayer = fromPubkey; - - const { signed_transaction } = await privy.wallets().solana().signTransaction( - walletId, { - transaction: tx.serialize({ requireAllSignatures: false }), - authorization_context: { authorization_private_keys: [authorizationKey] }, - }, - ) as any; - - const sig = await connection.sendRawTransaction( - Buffer.from(signed_transaction, 'base64'), - { skipPreflight: false, preflightCommitment: 'confirmed' }, - ); - await connection.confirmTransaction(sig, 'confirmed'); -} -``` - - - -While almost always you will have only one transfer transaction, you can -optimize sending in the rare cases where you have multiple transactions. -Parallelize the loads, confirm them, and then send the transfer instruction -after. - - - -```typescript -import { - createTransferInterfaceInstructions, - sliceLast, -} from "@lightprotocol/compressed-token/unified"; - -const instructions = await createTransferInterfaceInstructions( - connection, fromPubkey, mint, amount, fromPubkey, recipient -); -const { rest: loadInstructions, last: transferInstructions } = sliceLast(instructions); -// empty = nothing to load, will no-op. -await Promise.all( - loadInstructions.map(async (ixs) => { - const tx = new Transaction().add(...ixs); - const { blockhash } = await connection.getLatestBlockhash(); - tx.recentBlockhash = blockhash; - tx.feePayer = fromPubkey; - - const { signed_transaction } = await privy.wallets().solana().signTransaction( - walletId, { - transaction: tx.serialize({ requireAllSignatures: false }), - authorization_context: { authorization_private_keys: [authorizationKey] }, - }, - ) as any; - - const sig = await connection.sendRawTransaction( - Buffer.from(signed_transaction, 'base64'), - { skipPreflight: false, preflightCommitment: 'confirmed' }, - ); - await connection.confirmTransaction(sig, 'confirmed'); - }) -); - -const transferTx = new Transaction().add(...transferInstructions); -const { blockhash } = await connection.getLatestBlockhash(); -transferTx.recentBlockhash = blockhash; -transferTx.feePayer = fromPubkey; - -const { signed_transaction } = await privy.wallets().solana().signTransaction( - walletId, { - transaction: transferTx.serialize({ requireAllSignatures: false }), - authorization_context: { authorization_private_keys: [authorizationKey] }, - }, -) as any; - -await connection.sendRawTransaction( - Buffer.from(signed_transaction, 'base64'), - { skipPreflight: false, preflightCommitment: 'confirmed' }, -); -``` - - - - - - - -All React hooks use a shared `signAndSendBatches` helper that handles serialization, signing, sending, and confirming for each instruction batch: - - - - - -Your app logic may require you to sign all transactions in sequence. Here's how: - - - -```typescript -for (const ixs of instructions) { - const tx = new Transaction().add(...ixs); - const { blockhash } = await rpc.getLatestBlockhash(); - tx.recentBlockhash = blockhash; - tx.feePayer = owner; - - const unsigned = tx.serialize({ requireAllSignatures: false }); - const signed = await signTransaction({ transaction: unsigned, wallet, chain: 'solana:devnet' }); - - const sig = await rpc.sendRawTransaction(Buffer.from(signed.signedTransaction), { - skipPreflight: false, preflightCommitment: 'confirmed', - }); - await rpc.confirmTransaction(sig, 'confirmed'); -} -``` - - - -While almost always you will have only one transfer transaction, you can -optimize sending in the rare cases where you have multiple transactions. -Parallelize the loads, confirm them, and then send the transfer instruction -after. - - - -```typescript -import { - createTransferInterfaceInstructions, - sliceLast, -} from "@lightprotocol/compressed-token/unified"; - -const instructions = await createTransferInterfaceInstructions( - rpc, owner, mint, amount, owner, recipient -); -const { rest: loadInstructions, last: transferInstructions } = sliceLast(instructions); -// empty = nothing to load, will no-op. -await Promise.all( - loadInstructions.map(async (ixs) => { - const tx = new Transaction().add(...ixs); - const { blockhash } = await rpc.getLatestBlockhash(); - tx.recentBlockhash = blockhash; - tx.feePayer = owner; - - const unsigned = tx.serialize({ requireAllSignatures: false }); - const signed = await signTransaction({ transaction: unsigned, wallet, chain: 'solana:devnet' }); - const sig = await rpc.sendRawTransaction(Buffer.from(signed.signedTransaction), { - skipPreflight: false, preflightCommitment: 'confirmed', - }); - await rpc.confirmTransaction(sig, 'confirmed'); - }) -); - -const transferTx = new Transaction().add(...transferInstructions); -const { blockhash } = await rpc.getLatestBlockhash(); -transferTx.recentBlockhash = blockhash; -transferTx.feePayer = owner; - -const unsigned = transferTx.serialize({ requireAllSignatures: false }); -const signed = await signTransaction({ transaction: unsigned, wallet, chain: 'solana:devnet' }); -await rpc.sendRawTransaction(Buffer.from(signed.signedTransaction), { - skipPreflight: false, preflightCommitment: 'confirmed', -}); -``` - - - - - - - - - - -Load creates the associated token account (ATA) if needed and loads any compressed state into it. -Share the ATA address with the sender. - - - - - - - - - - - - - - -Wrap SPL or Token-2022 tokens into a light-token associated token account. - - - - - - - - - - - - - - -Unwrap light-token balance to SPL or Token-2022. Use unwrap to interact with applications that only support SPL/Token-2022. - - - - - - - - - - - - - - - - - -## Show Balance - -Query token balances to show a unified balance of SOL, -Light, SPL, and Token-2022. - -```typescript -import { - getAssociatedTokenAddressInterface, - getAtaInterface, -} from "@lightprotocol/compressed-token/unified"; - -const ata = getAssociatedTokenAddressInterface(mint, owner); -const account = await getAtaInterface(rpc, ata, owner, mint); -console.log(account.parsed.amount); -``` - - - - - - - - - - - - -## Get Transaction History - -Fetch light-token transaction history for an owner. - -```typescript -import { createRpc } from "@lightprotocol/stateless.js"; - -const result = await rpc.getSignaturesForOwnerInterface(owner); -console.log(result.signatures); // Merged + deduplicated -console.log(result.solana); // On-chain txs only -console.log(result.compressed); // Compressed txs only -``` - - - - - - - - - - - - - - - - - - - - - - diff --git a/light-token/wallets/wallet-adapter.mdx b/light-token/wallets/wallet-adapter.mdx deleted file mode 100644 index d0679a71..00000000 --- a/light-token/wallets/wallet-adapter.mdx +++ /dev/null @@ -1,289 +0,0 @@ ---- -title: "Sign with Wallet Adapter" -sidebarTitle: "Sign with Wallet Adapter" -description: "Integrate light-token with Solana Wallet Adapter for rent-free token accounts and transfers." -keywords: ["solana wallet adapter", "light token wallet adapter", "rent-free tokens", "solana react wallet"] ---- -import ToolkitsSetup from "/snippets/setup/toolkits-setup.mdx"; -import RegisterSplMint from "/snippets/setup/register-spl-mint.mdx"; -import AgentSkillPayments from "/snippets/setup/agent-skill-payments.mdx"; -import TransferReact from "/snippets/code-snippets/wallet-adapter/transfer/react.mdx"; -import SignAndSendBatchesHelper from "/snippets/code-snippets/wallet-adapter/helpers/sign-and-send-batches.mdx"; -import ReceiveReact from "/snippets/code-snippets/wallet-adapter/receive/react.mdx"; -import WrapReact from "/snippets/code-snippets/wallet-adapter/wrap/react.mdx"; -import UnwrapReact from "/snippets/code-snippets/wallet-adapter/unwrap/react.mdx"; -import BalancesReact from "/snippets/code-snippets/wallet-adapter/balances/react.mdx"; -import TransactionHistoryReact from "/snippets/code-snippets/wallet-adapter/transaction-history/react.mdx"; -import WalletAdapterAiPrompt from "/snippets/ai-prompts/wallets/wallet-adapter.mdx"; -import SupportFooter from "/snippets/support-footer.mdx"; -import TokenAccountCost from "/snippets/cost-tables/token-account-cost.mdx"; - - - -Solana Wallet Adapter handles wallet connection and transaction signing. You build transactions with light-token and the wallet signs them: - -1. Connect wallet via `useWallet()` -2. Build unsigned transaction -3. Sign transaction using `signTransaction` -4. Send signed transaction to RPC - -## What you will implement - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SPLLight
[**Transfer**](#full-code-examples)createTransferInstruction()createTransferInterfaceInstructions()
[**Receive**](#full-code-examples)getOrCreateAssociatedTokenAccount()createLoadAtaInstructions()
[**Wrap from SPL**](#full-code-examples)N/AcreateWrapInstruction()
[**Unwrap to SPL**](#full-code-examples)N/AcreateUnwrapInstructions()
[**Get Balance**](#show-balance)getAccount()getAtaInterface()
[**Tx History**](#get-transaction-history)getSignaturesForAddress()getSignaturesForOwnerInterface()
- - - - - - - -### Prerequisites - - - -Install wallet adapter packages: - -```bash -npm install @solana/wallet-adapter-base \ - @solana/wallet-adapter-react \ - @solana/wallet-adapter-react-ui \ - @solana/wallet-adapter-wallets -``` - -Connect to an RPC endpoint that supports ZK Compression (Helius, Triton): - -```typescript -import { createRpc } from "@lightprotocol/stateless.js"; - -import { - createTransferInterfaceInstructions, - createLoadAtaInstructions, - createWrapInstruction, - createUnwrapInstructions, - getAssociatedTokenAddressInterface, - getAtaInterface, -} from "@lightprotocol/compressed-token/unified"; - -const rpc = createRpc(RPC_ENDPOINT); -``` - - - - -## Sign with Wallet Adapter - - -Find the complete example on GitHub: [React](https://github.com/Lightprotocol/examples-light-token/tree/main/toolkits/sign-with-wallet-adapter/react). - - -Use `signTransaction` from `useWallet()` to sign light-token transactions: - -```typescript -import { useWallet } from "@solana/wallet-adapter-react"; - -const { publicKey, signTransaction } = useWallet(); -``` - - - - -Transfer light-tokens between wallets. Auto-loads cold (compressed) light-token, SPL or -Token-2022 balance before sending. - - -**About loading:** Light Token accounts reduce account rent ~200x by auto-compressing inactive accounts. -Before any action, the SDK detects cold balances and adds instructions to load them. -This almost always fits in a single atomic transaction with your regular transfer. -APIs return `TransactionInstruction[][]` so the same loop handles the rare multi-transaction case -automatically. - - - - -Your app logic may require you to create a single sign request for your user. Here's how to do this: - - - -```typescript -const transactions = instructions.map((ixs) => new Transaction().add(...ixs)); - -// One approval for all -const signed = await wallet.signAllTransactions(transactions); - -for (const tx of signed) { - // send... - await sendAndConfirmTransaction(rpc, tx); -} -``` - - - -While almost always you will have only one transfer transaction, you can -optimize sending in the rare cases where you have multiple transactions. -parallelize the loads, confirm them, and then send the transfer instruction -after. - - -```typescript -import { - createTransferInterfaceInstructions, - sliceLast, -} from "@lightprotocol/compressed-token/unified"; - -const instructions = await createTransferInterfaceInstructions( - rpc, owner, mint, amount, owner, recipient -); -const { rest: loadInstructions, last: transferInstructions } = sliceLast(instructions); -// empty = nothing to load, will no-op. -await Promise.all( - loadInstructions.map(async (ixs) => { - const tx = new Transaction().add(...ixs); - const { blockhash } = await rpc.getLatestBlockhash(); - tx.recentBlockhash = blockhash; - tx.feePayer = owner; - const signed = await signTransaction(tx); - const sig = await rpc.sendRawTransaction(signed.serialize(), { - skipPreflight: false, preflightCommitment: 'confirmed', - }); - await rpc.confirmTransaction(sig, 'confirmed'); - }) -); - -// Then send the transfer -const transferTx = new Transaction().add(...transferInstructions); -const { blockhash } = await rpc.getLatestBlockhash(); -transferTx.recentBlockhash = blockhash; -transferTx.feePayer = owner; -const signedTransfer = await signTransaction(transferTx); -await rpc.sendRawTransaction(signedTransfer.serialize(), { - skipPreflight: false, preflightCommitment: 'confirmed', -}); -``` - - - - - -All hooks in this toolkit use a shared `signAndSendBatches` helper that handles blockhash, signing, sending, and confirming for each instruction batch: - - - - - - - - - -Load creates the associated token account (ATA) if needed and loads any compressed state into it. -Share the ATA address with the sender. - - - - - - - -Wrap SPL or Token-2022 tokens into a light-token associated token account. - - - - - - - -Unwrap light-token balance to SPL or Token-2022. Use unwrap to interact with applications that only support SPL/Token-2022. - - - - - - - - - - -## Show Balance - -Query token balances to show a unified balance of SOL, -Light, SPL, and Token-2022. - -```typescript -import { - getAssociatedTokenAddressInterface, - getAtaInterface, -} from "@lightprotocol/compressed-token/unified"; - -const ata = getAssociatedTokenAddressInterface(mint, owner); -const account = await getAtaInterface(rpc, ata, owner, mint); -console.log(account.parsed.amount); -``` - - - - - -## Get transaction history - -Fetch light-token transaction history for an owner. - -```typescript -import { createRpc } from "@lightprotocol/stateless.js"; - -const result = await rpc.getSignaturesForOwnerInterface(owner); -console.log(result.signatures); // Merged + deduplicated -console.log(result.solana); // On-chain txs only -console.log(result.compressed); // Compressed txs only -``` - - - - - - - - - - - - - - diff --git a/light-token/welcome.mdx b/light-token/welcome.mdx deleted file mode 100644 index 91cbdb4b..00000000 --- a/light-token/welcome.mdx +++ /dev/null @@ -1,294 +0,0 @@ ---- -title: The Light Token Program -sidebarTitle: Overview -description: High-performance token standard that is functionally equivalent to SPL while reducing account creation cost by 200x and being more CU efficient on hot paths. The Light Token SDK keeps code changes minimal and is a superset of the SPL-token API. -keywords: ["rent free tokens on solana", "rent free solana accounts", "spl token alternative for developers", "token 2022 alternative for solana", "infrastructure for stablecoin payments on solana", "scalable solana infrastructure", "token infrastructure for fintechs", "scalable infrastructure for solana apps"] ---- - -import LightTokenPrompts from "/snippets/ai-prompts/light-token-prompts.mdx"; -import AgentSkillPayments from "/snippets/setup/agent-skill-payments.mdx"; -import AgentSkillGeneric from "/snippets/setup/agent-skill-generic.mdx"; -import AgentSkillDefi from "/snippets/setup/agent-skill-defi.mdx"; -import AgentSkillStreaming from "/snippets/setup/agent-skill-streaming.mdx"; -import CookbookGuidesTable from "/snippets/overview-tables/cookbook-guides-table.mdx"; -import WelcomePageInstall from "/snippets/setup/welcome-page-install.mdx"; -import SdkReference from "/snippets/overview-tables/sdk-reference.mdx"; -import { CodeCompare } from "/snippets/jsx/code-compare.jsx"; -import MintAccountCost from "/snippets/cost-tables/mint-account-cost.mdx"; -import TokenAccountCost from "/snippets/cost-tables/token-account-cost.mdx"; -import CuPerformance from "/snippets/cost-tables/cu-performance.mdx"; -import { - splCreateMintCode, - lightCreateMintCode, - splCreateMintRustCode, - lightCreateMintRustCode, - splCreateMintCpiCode, - lightCreateMintCpiCode, - splCreateMintMacroCode, - lightCreateMintMacroCode, - splCreateAtaCode, - lightCreateAtaCode, - splCreateAtaRustCode, - lightCreateAtaRustCode, - splCreateAtaCpiCode, - lightCreateAtaCpiCode, - splCreateAtaMacroCode, - lightCreateAtaMacroCode, -} from "/snippets/code-samples/code-compare-snippets.jsx"; - - -### Mint Accounts - -Light-mint accounts represent a unique mint and optionally can store token-metadata. -Functionally equivalent to SPL mints. - - - - - - - - - - - - - - - - - - -View the [guide](/light-token/cookbook/create-mint) to create Light Token mints, or enable interoperability for existing SPL and Token 2022 mints. - - -### Token Accounts -Light-token accounts can hold balances from any light, SPL, or Token-2022 mint, without the need -to pay rent-exemption. - - - - - - - - - - - - - - - - - - -View the [guide](/light-token/cookbook/create-ata) to create associated token accounts. - - - - - - -# Quickstart - - - - -### Installation - - - - - -### Get Started - - - - - - - -### Payment Skill for Agents - - - -### Payment Flows - - - - - - - - - - - - - - -### Fee Abstraction - - -### Signing - - - -### Go to Production - - - - - -### Agent Skill for DeFi - - - -### Guides - - - - Build rent-free AMMs and DeFi programs. - - - Add support for rent-free AMMs to your aggregator. - - - High-performance DeFi programs with Pinocchio. - - - - - - -### Agent Skill for Data Streaming - - - -### Guides - - - - Stream mint events from the network in real-time. - - - Stream token events from the network in real-time. - - - - - - -### Agent Skills for Tokens - - - -## Cookbook - - - -## Examples - -### Client - -| | | -| :--- | :--- | -| [**Toolkits**](/light-token/examples/client#toolkits) | Payments, wallets, Privy integration, SPL-to-Light transfer | -| [**TypeScript**](/light-token/examples/client#typescript) | Actions and instructions for all token operations | -| [**Rust**](/light-token/examples/client#rust) | Actions and instructions for all token operations | - -### Program - -| | | -| :--- | :--- | -| [**Examples**](/light-token/examples/program#examples) | AMM reference, CPI create-and-transfer, Pinocchio swap | -| [**Macros**](/light-token/examples/program#macros) | Counter PDA, ATA, mint, and token account creation | -| [**Instructions**](/light-token/examples/program#instructions) | All CPI instructions: approve, burn, close, freeze, mint-to, transfer, and more | - - - - - - - - - -## API Reference - - - - SDK overview, Anchor constraints, and JSON RPC methods for Light Token and ZK Compression. - - - Instruction-by-instruction mapping from SPL and Solana to Light Token. - - - -## SDK Reference - -Structs, types, and generated docs. TypeScript and Rust client SDKs, plus program SDKs (light-sdk, light-token, macros). - - - -# Next Steps - - diff --git a/llms.txt b/llms.txt index 4f2484aa..53a55f4e 100644 --- a/llms.txt +++ b/llms.txt @@ -1,7 +1,7 @@ # ZK Compression by Light Protocol and Helius Labs -> ZK Compression is a framework on Solana for stablecoin payment rails, agent commerce, consumer apps, defi protocols, depin, and more. -> The Light SDK and APIs let you create mint, token and PDA accounts >99% cheaper with familiar Solana developer experience. +> ZK Compression is a framework on Solana for token distribution, stablecoin payments, consumer apps, per-user state, and more. +> The Light SDK and APIs let you create token and PDA accounts without rent-exemption, with a familiar Solana developer experience. This documentation provides guides, references and tutorials for developers building on Solana. @@ -10,41 +10,29 @@ This documentation provides guides, references and tutorials for developers buil - [AI Agent Resources](#ai-agent-resources) - [Getting Started](#getting-started) - [SDK Reference](#sdk-reference) -- [Solana to Light Reference](#solana-to-light-reference) -- [Anchor Reference](#anchor-reference) -- [For Payments and Wallets](#for-payments-and-wallets) -- [For DeFi](#for-defi) -- [For Data Streaming](#for-data-streaming) -- [Light Token Basics](#light-token-basics) -- [PDA Account basics for Solana programs](#pda-account-basics-for-solana-programs) -- [For Other Use Cases](#for-other-use-cases) +- [Compressed Tokens](#compressed-tokens) +- [Compressed PDA](#compressed-pda) +- [Custom ZK Applications](#custom-zk-applications) - [Learn](#learn) - [Resources](#resources) - [JSON RPC Methods](#json-rpc-methods) - [Support](#support) -- [Examples for DeFi](#examples-for-defi) -- [Examples for Payments and Wallets](#examples-for-payments-and-wallets) +- [Examples](#examples) - [OpenAPI Specs](#openapi-specs) ## Primitives -| Primitive | Use case | Constraints | -| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------ | -| Light Token | Most token use cases (Payment Rails, Consumer Apps, DeFi). Rent-free mint and token accounts. More compute-unit efficient on the hot path. | | -| Light-PDA | DeFi program state such as AMM pools and vaults. Can be implemented with minimal code changes. | | -| Compressed Token | Only for Airdrops and token distribution. Prefer Light Token for other purposes. Used by Light Token under the hood for rent-free storage of inactive Light Tokens. Supported by Phantom and Backpack. | Do not use for general-purpose token features. Use Light Token instead. | -| Compressed PDA | User state and app state, nullifiers (payments and ZK applications), DePIN nodes, and stake accounts. Similar to program-derived addresses without a rent-exempt balance. | Not for shared state, pool accounts, or config accounts. Use Light-PDA instead | +| Primitive | Use case | Constraints | +| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | +| Compressed Token | Token use cases such as token distribution, stablecoin payments, and storing balances rent-free. Always compressed and rent-free. Works with SPL and Token-2022. Supported by Phantom and Backpack. | The SPL mint and interface PDA pay rent; individual token accounts do not. | +| Compressed PDA | Per-user and app state, nullifiers (payments and ZK applications), DePIN nodes, and stake accounts. Similar to program-derived addresses without a rent-exempt balance. | Programs invoke the Light System Program (not the System Program) with a validity proof. | -View a complete API comparison to SPL and Solana: [https://www.zkcompression.com/api-reference/solana-to-light-comparison](https://www.zkcompression.com/api-reference/solana-to-light-comparison). +View the SDK reference: [https://www.zkcompression.com/api-reference/sdk](https://www.zkcompression.com/api-reference/sdk). -Comparing creation cost and CU usage: +Comparing creation cost: -| | Light-Token | SPL-Token | -| :----------------------- | --------------: | ---------: | -| **Mint Account** | **0.00001 SOL** | 0.0015 SOL | -| **Token Account** | **0.00001 SOL** | 0.0029 SOL | -| **Associated token account creation** | **4,348 CU** | 14,194 CU | -| **Transfer** | **312 CU** | 4,645 CU | -| **Transfer** (rent-free) | **1,885 CU** | 4,645 CU | +| Creation | Solana | Compressed | +| :---------------- | :------------------ | :----------------- | +| **Token Account** | ~2,000,000 lamports | **5,000** lamports | ## AI Agent Resources Install orchestrator agent skill or view [skill.md](https://www.zkcompression.com/skill.md): @@ -62,129 +50,81 @@ npx skills add Lightprotocol/skills - [MCP](https://www.zkcompression.com/ai-tools/mcp.md): Connect AI apps to Light Protocol data sources and tools via the Model Context Protocol (MCP). Includes installation for Claude Code, Codex, Cursor, and more. - [AI Prompts](https://www.zkcompression.com/ai-tools/prompts.md): Ready-to-use AI prompts for Light Protocol. Copy a prompt, paste into your AI coding agent, and let it implement the recipe in your project. - [Orchestration Skill](https://www.zkcompression.com/skill.md): Full agent skill for AI coding agents. -- **Agent Skills:** [light-sdk](https://github.com/Lightprotocol/skills/tree/main/skills/light-sdk): For Solana program development with tokens and PDAs, Light is 200x cheaper than SPL/ Solana and has minimal code differences -- **Agent Skills:** [light-token-client](https://github.com/Lightprotocol/skills/tree/main/skills/light-token-client): For client development with tokens on Solana, Light Token is 200x cheaper than SPL and has minimal changes -- **Agent Skills:** [data-streaming](https://github.com/Lightprotocol/skills/tree/main/skills/data-streaming): For data pipelines, aggregators, or indexers, real-time account state streaming on Solana with light account hot/cold lifecycle tracking -- **Agent Skills:** [payments](https://github.com/Lightprotocol/skills/tree/main/skills/payments): Skill for payment flows using Light Token APIs for sponsored rent-exemption. -- **Agent Skills:** [token-distribution](https://github.com/Lightprotocol/skills/tree/main/skills/token-distribution): For token distribution on Solana 5000x cheaper than SPL (rewards, airdrops, depins, ...) -- **Agent Skills:** [zk-nullifier](https://github.com/Lightprotocol/skills/tree/main/skills/zk-nullifier): For custom ZK Solana programs and privacy-preserving applications to prevent double spending. -- **Agent Skills:** [testing](https://github.com/Lightprotocol/skills/tree/main/skills/testing): For testing with Light Protocol programs and clients on localnet, devnet, and mainnet validation -- **Agent Skills:** [solana-compression](https://github.com/Lightprotocol/skills/tree/main/skills/solana-compression): For program development on Solana with infrequently accessed state, such as per-user state, DePIN registrations, ... -- **Agent Skills:** [ask-mcp](https://github.com/Lightprotocol/skills/tree/main/skills/ask-mcp): For questions about compressed accounts, Light SDK, Solana development, Claude Code features, or agent skills +- **Agent Skills:** [compressed-token](https://github.com/Lightprotocol/skills/tree/main/skills/compressed-token): For token use cases on Solana, such as token distribution, stablecoin payments and more. Works with Token-2022, Privy, Wallet Adapter similarly to SPL. +- **Agent Skills:** [compressed-pda](https://github.com/Lightprotocol/skills/tree/main/skills/compressed-pda): For program development on Solana with infrequently accessed state, such as per-user state, DePIN registrations, nullifiers, or custom compressed accounts. +- **Agent Skills:** [zk](https://github.com/Lightprotocol/skills/tree/main/skills/zk): For custom ZK Solana programs and privacy-preserving applications to prevent double spending. +- **Agent Skills:** [testing](https://github.com/Lightprotocol/skills/tree/main/skills/testing): For testing with Light Protocol programs and clients on localnet, devnet, and mainnet validation. +- **Agent Skills:** [ask-mcp](https://github.com/Lightprotocol/skills/tree/main/skills/ask-mcp): For questions about compressed accounts, Light SDK, Solana development, Claude Code features, or agent skills. ## Getting Started - [Welcome to ZK Compression](https://www.zkcompression.com/home.md) -- [FAQ](https://www.zkcompression.com/faq.md): Frequently asked questions about light token, PDA accounts, and use cases. ## SDK Reference -- [SDK Reference](https://www.zkcompression.com/api-reference/sdk.md): Client and program SDKs for Light Token and ZK Compression. - -## Solana to Light Reference -- [Solana to Light Reference](https://www.zkcompression.com/api-reference/solana-to-light-comparison.md): Side-by-side mapping of every Light Token instruction against its SPL/Solana equivalent. Covers RPC, TypeScript client, Rust client, program CPI, and Anchor macros. - -## Anchor Reference -- [Anchor Constraints LightAccount](https://www.zkcompression.com/api-reference/anchor.md): Syntax reference for #[light_account] constraints with sponsored rent-exemption. - -## For Payments and Wallets -- [Payment Flows on Solana with Light Token](https://www.zkcompression.com/light-token/payments/overview.md): Learn how the Light Token APIs reduce account creation cost for stablecoin payment infrastructure by 99% with similar developer experience to SPL / Token 2022. -- **Send Payments:** [Basic Payment](https://www.zkcompression.com/light-token/payments/basic-payment.md): Send a single token transfer with Light Token APIs with comparison to SPL. If the recipient is receiving this token for the first time, their token account can be created as part of the same transaction. -- **Send Payments:** [Batch Payments](https://www.zkcompression.com/light-token/payments/batch-payments.md): Send payments to multiple recipients in a single transaction or sequentially. -- **Send Payments:** [Payment with Memo](https://www.zkcompression.com/light-token/payments/payment-with-memo.md): Attach invoice IDs, payment references, or notes to Light Token transfers using Solana's memo program. -- [Receive Payments](https://www.zkcompression.com/light-token/payments/receive-payments.md): Prepare to receive token payments by loading cold accounts and sharing your associated token account address. -- **Verify Payments:** [Verify Payments](https://www.zkcompression.com/light-token/payments/verify-payments.md): Query token balances and transaction history to verify incoming payments. -- **Verify Payments:** [Verify Address](https://www.zkcompression.com/light-token/payments/verify-recipient-address.md): Verify recipient addresses before sending payments. Address validation prevents sending tokens to invalid or unexpected account types. -- [Spend Permissions via Delegation](https://www.zkcompression.com/light-token/payments/spend-permissions.md): Delegate token spending to a third party with an amount cap. The delegate can transfer tokens on behalf of the owner up to the approved amount, without the owner signing each transaction. -- [Wrap and Unwrap](https://www.zkcompression.com/light-token/payments/wrap-unwrap.md): Move tokens between SPL / Token 2022 and Light Token accounts. Use wrap/unwrap to interoperate with applications that only support SPL or Token 2022. -- [Create Nullifier PDAs](https://www.zkcompression.com/pda/compressed-pdas/nullifier-pda.md): Create rent-free nullifier PDAs to prevent duplicate actions. -- [Production Readiness](https://www.zkcompression.com/light-token/payments/production-readiness.md): Non-exhaustive checklist for deploying Light Token payment flows to production, including RPC infrastructure, error handling, and security. -- [Integration Guide for Wallet Applications](https://www.zkcompression.com/light-token/wallets/overview.md): Guide for Wallet Applications to add Light-token support. -- [Sign with Privy](https://www.zkcompression.com/light-token/wallets/privy.md): Integrate light-token with Privy embedded wallets for rent-free token accounts and transfers. -- [Sign with Wallet Adapter](https://www.zkcompression.com/light-token/wallets/wallet-adapter.md): Integrate light-token with Solana Wallet Adapter for rent-free token accounts and transfers. -- [Gasless Transactions](https://www.zkcompression.com/light-token/wallets/gasless-transactions.md): Abstract SOL fees so users never hold SOL. The Light SDK sponsors rent-exemption for Solana accounts and keeps accounts active through periodic top-ups paid by the fee payer. Sponsor top-ups and transaction fees by setting your application as the fee payer. - -## For DeFi -- [Router Integration](https://www.zkcompression.com/light-token/defi/routers.md): Add support for rent-free AMMs on Solana. -- [Program Integration](https://www.zkcompression.com/light-token/defi/programs.md): Build high-performance DeFi programs with rent-free accounts -- [Pinocchio Programs](https://www.zkcompression.com/light-token/defi/programs-pinocchio.md): Build high-performance DeFi programs with rent-free accounts using Pinocchio - -## For Data Streaming -- [Streaming Mint Accounts](https://www.zkcompression.com/light-token/streaming/mints.md): Stream light-mint accounts and metadata via Laserstream. -- [Streaming Token Accounts](https://www.zkcompression.com/light-token/streaming/tokens.md): Stream light-token accounts via Laserstream. Same base layout as SPL Token. - -## Light Token Basics -- [The Light Token Program](https://www.zkcompression.com/light-token/welcome.md): High-performance token standard that is functionally equivalent to SPL while reducing account creation cost by 200x and being more CU efficient on hot paths. The Light Token SDK keeps code changes minimal and is a superset of the SPL-token API. -- **Mint Accounts:** [Create Mint Account with Token Metadata](https://www.zkcompression.com/light-token/cookbook/create-mint.md): Create a Light mint with token metadata, or create SPL and Token 2022 mints with interface PDA for interoperability. -- **Mint Accounts:** [Add Interface PDA to Existing SPL / Token 2022 Mints](https://www.zkcompression.com/light-token/cookbook/add-interface-pda.md): Create an interface PDA for an existing SPL or Token 2022 mint for interoperability with Light Token. Does not require mint authority. -- [Create Associated Light Token Accounts](https://www.zkcompression.com/light-token/cookbook/create-ata.md): Client and program guide to create associated Light Token accounts. Includes step-by-step implementation and full code examples. -- [Create Light Token Account](https://www.zkcompression.com/light-token/cookbook/create-token-account.md): Client and program guide to create Light Token accounts. Includes step-by-step implementation and full code examples. -- [Mint to Light Token Accounts](https://www.zkcompression.com/light-token/cookbook/mint-to.md): Client and program guide to mint tokens to a account. Includes step-by-step implementation and full code examples. -- [Transfer Interface](https://www.zkcompression.com/light-token/cookbook/transfer-interface.md): Transfer tokens between Light Token, SPL and Token 2022 accounts. The interface checks decimals under the hood and detects account types to invoke the right programs. -- [Transfer Checked](https://www.zkcompression.com/light-token/cookbook/transfer-checked.md): Program CPI guide for Light Token transfer with decimal validation. Includes step-by-step implementation and full code examples. -- **Delegates:** [Approve and Revoke Delegates](https://www.zkcompression.com/light-token/cookbook/approve-revoke.md): Guide to approve and revoke delegates for Light Token accounts. Includes step-by-step implementation and full code examples. -- **Delegates:** [Delegated Transfer](https://www.zkcompression.com/light-token/cookbook/transfer-delegated.md): Transfer tokens as an approved delegate. The delegate signs instead of the owner, spending within the approved allowance. -- [Freeze and Thaw Light Token Accounts](https://www.zkcompression.com/light-token/cookbook/freeze-thaw.md): Rust client guide to freeze and thaw Light Token accounts. Includes step-by-step implementation and full code examples. -- [Wrap & Unwrap SPL/Token 2022 <> Light Token](https://www.zkcompression.com/light-token/cookbook/wrap-unwrap.md): Move tokens between SPL/Token 2022 token and Light Token accounts. Use to interact with applications that only support SPL/Token 2022. -- [Load Token Balances to Light Associated Token Account](https://www.zkcompression.com/light-token/cookbook/load-ata.md): Unify token balances from compressed tokens (cold Light Tokens), SPL, and Token 2022 to one light ATA. -- [Close Light Token Account](https://www.zkcompression.com/light-token/cookbook/close-token-account.md): Program guide to close Light Token accounts via CPI. Includes step-by-step implementation and full code examples. -- [Burn Light Tokens](https://www.zkcompression.com/light-token/cookbook/burn.md): Rust client guide to burn Light Tokens. Includes step-by-step implementation and full code examples. -- [Token 2022 Extensions with Light Token](https://www.zkcompression.com/light-token/extensions/overview.md): Most Token 2022 extensions are supported by Light Token to add features through extra instructions to a token mint or token account. -- [Client examples](https://www.zkcompression.com/light-token/examples/client.md): TypeScript and Rust client examples for light-token SDK. -- [Program examples](https://www.zkcompression.com/light-token/examples/program.md): Anchor program examples for light-token CPI. - -## PDA Account basics for Solana programs -- [PDA accounts](https://www.zkcompression.com/pda/overview.md): Overview to Light-PDAs (Solana accounts with sponsored rent-exemption) and compressed PDAs (compressed accounts without rent-exemption cost). -- [Light PDA](https://www.zkcompression.com/pda/light-pda/overview.md): Create Solana PDA accounts with sponsored rent-exemption and minimal code changes. Use like any Solana PDA, e.g. for DeFi pools, vaults, pool accounts, or other shared state. -- **Compressed PDA:** [Overview & Program Template](https://www.zkcompression.com/pda/compressed-pdas/overview.md): Compressed PDAs provide full composability and functionality of accounts at PDAs, without rent-exemption cost per account. Suited for accounts where each user or entity gets their own PDA and state is infrequently accessed. -- **Compressed PDA:** [Client Guide](https://www.zkcompression.com/pda/compressed-pdas/guides/client-guide.md): Rust and Typescript client guides with step-by-step implementation and full code examples. -- **Compressed PDA > Program Guides:** [Overview](https://www.zkcompression.com/pda/compressed-pdas/guides.md): Overview to guides for Solana programs to create, update, close, reinitialize, and burn permanently compressed accounts. -- **Compressed PDA:** [Program Examples](https://www.zkcompression.com/pda/compressed-pdas/program-examples.md): Program example repository for compressed accounts with tests. - -## For Other Use Cases -- [Token Distribution](https://www.zkcompression.com/token-distribution.md): Complete client and program guides to create an airdrop – with or without code. ZK compression is the most efficient way to distribute SPL tokens. -- [Solana Attestation Service (Devnet)](https://www.zkcompression.com/pda/compressed-pdas/solana-attestation-service.md): Credential system for KYC verification, professional badges, and compliance credentials in minutes. Currently undergoing audit. -- **Custom ZK Applications:** [Primitives for ZK on Solana](https://www.zkcompression.com/zk/overview.md): Overview how to build a ZK program on Solana. -- **Custom ZK Applications:** [Examples](https://www.zkcompression.com/zk/examples.md): Example projects for building ZK programs on Solana. +- [SDK Reference](https://www.zkcompression.com/api-reference/sdk.md): Client and program SDKs for Compressed Tokens and ZK Compression. + +## Compressed Tokens +- [Overview](https://www.zkcompression.com/compressed-tokens/overview.md): Overview to compressed tokens and guides with full code examples. Use for distributing tokens (eg rewards, airdrops) or creating associated token accounts for users. +### Cookbook +- [Create Compressed Token Accounts](https://www.zkcompression.com/compressed-tokens/guides/create-compressed-token-accounts.md): Short guide to compressed token account creation with ZK Compression on Solana and difference to regular token accounts. +- [Mint Compressed Tokens](https://www.zkcompression.com/compressed-tokens/guides/mint-compressed-tokens.md): "Mint tokens to compressed token accounts for recipients and increases a mint's token supply. Only the mint authority can perform this operation. +- [Transfer Compressed Tokens](https://www.zkcompression.com/compressed-tokens/guides/transfer-compressed-tokens.md): Transfer compressed tokens between accounts. Transfers consume input accounts and create new output accounts with updated balances. +- [Compress and Decompress SPL Tokens](https://www.zkcompression.com/compressed-tokens/guides/compress-decompress.md): Convert SPL tokens between compressed and regular format with compress() and decompress(). +- [Compress Complete SPL Token Accounts](https://www.zkcompression.com/compressed-tokens/guides/compress-spl-token-account.md): Compress the entire balance of an SPL token account to reclaim rent. Optionally leave some tokens in SPL format. +- [Create a Mint Account with Interface PDA for Compression](https://www.zkcompression.com/compressed-tokens/guides/create-mint-with-token-pool.md): Create an SPL token mint with an interface PDA for compression. The interface PDA locks tokens while compressed and releases them when decompressed. +- [Create Interface PDAs for Compression to Existing Mints](https://www.zkcompression.com/compressed-tokens/guides/add-token-pools-to-mint-accounts.md): Create an interface PDA for an existing SPL mint. Requires only fee_payer with no mint authority constraint. +- [Merge Compressed Token Accounts](https://www.zkcompression.com/compressed-tokens/guides/merge-compressed-token-accounts.md): Consolidate multiple compressed token accounts of the same mint into a single account to reduce fragmentation. +- [Approve and Revoke Delegate Authority](https://www.zkcompression.com/compressed-tokens/guides/delegate.md): Grant and remove delegate spending authority for compressed tokens with approve() and revoke(). Only the token owner can perform these operations. +- [Combine Instructions in One Transaction](https://www.zkcompression.com/compressed-tokens/combine-instructions.md): Guide to combine multiple instructions in a single transaction. Full code example for interface PDA creation and for first-time compression of existing SPL tokens. +### Integration Guides +- [Rent-Free SPL Accounts with Privy](https://www.zkcompression.com/compressed-tokens/privy.md): Integrate compressed tokens with Privy embedded wallets for rent-free SPL token accounts and transfers. +- [Token Distribution Guide](https://www.zkcompression.com/compressed-tokens/token-distribution.md): Complete client and program guides to create an airdrop – with or without code. ZK compression is the most efficient way to distribute SPL tokens. +- [Add Wallet Support for Compressed Tokens](https://www.zkcompression.com/compressed-tokens/wallet-integration.md): Guide to add Compressed Token Support to Your Wallet Application +- [Use Token-2022 with Compression](https://www.zkcompression.com/compressed-tokens/token-2022.md): Complete guide to mint, compress and transfer tokens with Token-2022 Metadata with ZK Compression. + +## Compressed PDA +- [Overview & Program Template](https://www.zkcompression.com/compressed-pdas/overview.md): Compressed PDAs provide full composability and functionality of accounts at PDAs, without rent-exemption cost per account. Suited for accounts where each user or entity gets their own PDA and state is infrequently accessed. +- [Client Guide](https://www.zkcompression.com/compressed-pdas/guides/client-guide.md): Rust and Typescript client guides with step-by-step implementation and full code examples. +- [Program Examples](https://www.zkcompression.com/compressed-pdas/program-examples.md): Program example repository for compressed accounts with tests. +- [Create Nullifier PDAs](https://www.zkcompression.com/compressed-pdas/nullifier-pda.md): For some use cases, such as sending payments, you might want to prevent your on chain instruction from being executed more than once. +- [Solana Attestation Service (Devnet)](https://www.zkcompression.com/compressed-pdas/solana-attestation-service.md): Credential system for KYC verification, professional badges, and compliance credentials in minutes. Currently undergoing audit. On mainnet today, you can integrate compressed PDAs to achieve similar functionality. +### Program Guides +- [Overview](https://www.zkcompression.com/compressed-pdas/guides.md): Overview to guides for Solana programs to create, update, close, reinitialize, and burn permanently compressed accounts. +- [Create Compressed Accounts](https://www.zkcompression.com/compressed-pdas/guides/how-to-create-compressed-accounts.md): Guide to create compressed accounts in Solana programs with full code examples. +- [Update Compressed Accounts](https://www.zkcompression.com/compressed-pdas/guides/how-to-update-compressed-accounts.md): Guide to update compressed accounts in Solana programs with full code examples. +- [Close Compressed Accounts](https://www.zkcompression.com/compressed-pdas/guides/how-to-close-compressed-accounts.md): Guide to close compressed accounts in Solana programs with full code examples. +- [Reinitialize Compressed Accounts](https://www.zkcompression.com/compressed-pdas/guides/how-to-reinitialize-compressed-accounts.md): Guide to reinitialize compressed accounts in Solana programs with full code examples. +- [Burn Compressed Accounts](https://www.zkcompression.com/compressed-pdas/guides/how-to-burn-compressed-accounts.md): Guide to burn compressed accounts in Solana programs with full code examples. + +## Custom ZK Applications +- [Primitives for ZK on Solana](https://www.zkcompression.com/zk/overview.md): Overview how to build a ZK program on Solana. +- [Examples](https://www.zkcompression.com/zk/examples.md): Example projects for building ZK programs on Solana. ## Learn -- [Overview of core concepts](https://www.zkcompression.com/learn/overview.md): Learn about Light Token and ZK Compression Core. -- [Core concepts of the Light Token program](https://www.zkcompression.com/learn/light-token-standard.md): The Light Token Program is a high performance token program that reduces the cost of account creations by 200x, while being more CU efficient than SPL on hot paths. -- **Core Concepts (ZK Compression):** [High-level System Overview](https://www.zkcompression.com/learn/core-concepts.md): Overview to ZK Compression's Core Concepts. Get a high-level system overview and learn about the compressed account model, lifecycle of a transaction, and considerations. -- **Core Concepts (ZK Compression):** [Compressed Account Model](https://www.zkcompression.com/learn/core-concepts/compressed-account-model.md): Overview to compressed accounts and comparison to Solana accounts. -- **Core Concepts (ZK Compression):** [Merkle trees and Validity Proofs](https://www.zkcompression.com/learn/core-concepts/merkle-trees-validity-proofs.md): Learn the core concepts of state trees, address trees, and validity proofs for compressed accounts. -- **Core Concepts (ZK Compression):** [Lifecycle of a Transaction](https://www.zkcompression.com/learn/core-concepts/transaction-lifecycle.md): Overview to the lifecycle of a transaction that interacts with compressed accounts. -- **Core Concepts (ZK Compression):** [Considerations](https://www.zkcompression.com/learn/core-concepts/considerations.md): Overview to considerations of ZK Compression, namely larger transaction size, higher compute unit usage, and per-transaction state cost. +### Core Concepts +- [High-level System Overview](https://www.zkcompression.com/learn/overview.md): Overview to ZK Compression's Core Concepts. Get a high-level system overview and learn about the compressed account model, lifecycle of a transaction, and considerations. +- [Compressed Account Model](https://www.zkcompression.com/learn/compressed-account-model.md): Overview to compressed accounts and comparison to Solana accounts. +- [Merkle trees and Validity Proofs](https://www.zkcompression.com/learn/merkle-trees-validity-proofs.md): Learn the core concepts of state trees, address trees, and validity proofs for compressed accounts. +- [Lifecycle of a Transaction](https://www.zkcompression.com/learn/transaction-lifecycle.md): Overview to the lifecycle of a transaction that interacts with compressed accounts. +- [Considerations](https://www.zkcompression.com/learn/considerations.md): Overview to considerations of ZK Compression, namely larger transaction size, higher compute unit usage, and per-transaction state cost. ## Resources -- [CLI installation & commands](https://www.zkcompression.com/resources/cli.md): Steps to set up your local environment for Light Protocol development. CLI to interact with Light Tokens and compressed accounts on Solana. - [Guide to Migrate from v1 to v2 Merkle trees](https://www.zkcompression.com/resources/migration-v1-to-v2.md): V2 reduces CU consumption by up to 70%. V1 remains supported for existing deployments. - [Addresses and URLs](https://www.zkcompression.com/resources/addresses-and-urls.md): Overview to all of ZK Compression's RPC URLs, Program IDs & Accounts and Lookup Tables. -- **Error Cheatsheet:** [Error Cheatsheet](https://www.zkcompression.com/resources/error-cheatsheet.md): Complete error code reference for ZK Compression. Search error codes with hex values and messages. -- **Error Cheatsheet:** [Debug ProofVerificationFailed (0x179b)](https://www.zkcompression.com/resources/error-cheatsheet/debug-0x179b-6043-proofverificationfailed.md): Common cause and debug steps for ProofVerificationFailed (0x179B / 6043) -- [Legacy Compressed Tokens](https://www.zkcompression.com/resources/legacy-compressed-tokens.md): Compressed tokens are the most efficient way to distribute SPL tokens (eg rewards, airdrops). For other token purposes use Light Token. - [Security](https://www.zkcompression.com/resources/security.md): Overview to Light Protocol's bug bounty program, third party security audits, and formal verification of circuits. +### Error Cheatsheet +- [Error Cheatsheet](https://www.zkcompression.com/resources/error-cheatsheet.md): Complete error code reference for ZK Compression. Search error codes with hex values and messages. +- [Debug ProofVerificationFailed (0x179b)](https://www.zkcompression.com/resources/error-cheatsheet/debug-0x179b-6043-proofverificationfailed.md): Common cause and debug steps for ProofVerificationFailed (0x179B / 6043) ## JSON RPC Methods - [JSON RPC Methods](https://www.zkcompression.com/api-reference/json-rpc-methods/overview.md): Photon indexer methods for querying compressed state on Solana. ## Support -- [Support](https://www.zkcompression.com/support.md): Get expert help with Light-Token and ZK Compression. Discord community, Telegram, and Email support available. - -## Examples for DeFi -- [cp-swap-reference](https://github.com/Lightprotocol/cp-swap-reference): Fork of Raydium AMM that creates markets without paying rent-exemption. -- [pinocchio-swap](https://github.com/Lightprotocol/examples-light-token/tree/main/pinocchio/swap): Light Token swap reference implementation. -- [token-swap](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/token-swap): AMM with liquidity pools and swaps. -- [escrow](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/escrow): Peer-to-peer light-token swap with offer/accept flow. -- [fundraiser](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/fundraiser): Token fundraiser with target, deadline, and refunds. -- [create-and-transfer](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/create-and-transfer): Create account via macro and transfer via CPI. -- [light-token-minter](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/light-token-minter): Create light-mints with metadata, mint tokens. - -## Examples for Payments and Wallets -- [payments](https://github.com/Lightprotocol/examples-light-token/tree/main/toolkits/payments): Wallet integrations and payment flows. -- [sign-with-privy](https://github.com/Lightprotocol/examples-light-token/tree/main/toolkits/sign-with-privy): Light-token operations signed with Privy wallets. -- [sign-with-wallet-adapter](https://github.com/Lightprotocol/examples-light-token/tree/main/toolkits/sign-with-wallet-adapter): Light-token operations signed with Wallet Adapter. -- [gasless-transactions](https://github.com/Lightprotocol/examples-light-token/tree/main/toolkits/gasless-transactions): Abstract SOL fees so users never hold SOL. Sponsor rent top-ups and transaction fees. -- [spl-to-light](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/instructions/spl_to_light_transfer.rs): Transfer from SPL to Light via TransferInterface. -- [streaming-tokens](https://github.com/Lightprotocol/examples-light-token/tree/main/toolkits/streaming-tokens): Stream mint events using Laserstream. +- [Support](https://www.zkcompression.com/support.md): Get expert help with Compressed Tokens and ZK Compression. Discord community, Telegram, and Email support available. + +## Examples +- [compressed-token-cookbook](https://github.com/Lightprotocol/examples-zk-compression/tree/main/compressed-token-cookbook): Action-level and instruction-level examples for every compressed token operation, plus wallet integration. +- [example-token-distribution](https://github.com/Lightprotocol/examples-zk-compression/tree/main/example-token-distribution): Simple and optimized batched airdrop flows, with a decompress-on-claim pattern. +- [program-examples](https://github.com/Lightprotocol/program-examples): Compressed PDA programs (counter, basic operations, create-and-update, nullifier, zk-id) in Anchor, native, and Pinocchio. ## OpenAPI Specs - [api](https://www.zkcompression.com/openapi/api.yaml) diff --git a/pda/light-pda/overview.mdx b/pda/light-pda/overview.mdx deleted file mode 100644 index fd5d0ac8..00000000 --- a/pda/light-pda/overview.mdx +++ /dev/null @@ -1,209 +0,0 @@ ---- -title: "Light PDA" -description: "Create Solana PDA accounts with sponsored rent-exemption and minimal code changes. Use like any Solana PDA, e.g. for DeFi pools, vaults, pool accounts, or other shared state." ---- - -import FullCounterExample from '/snippets/code-snippets/light-token/counter/anchor-macro/full-example.mdx'; -import AgentSkillGeneric from "/snippets/setup/agent-skill-generic.mdx"; -import LightPdaAiPrompt from "/snippets/ai-prompts/program-cookbook/light-pda.mdx"; -import LightPdaCost from "/snippets/cost-tables/light-pda-cost.mdx"; - - - -A Light-PDA is a standard Solana PDA. Seeds, bump derivation, and -`invoke_signed` work the same way. Your instruction handlers for reads, -updates, and closes don't change. - -## What changes - -Audit overhead is minimal as your program logic is mostly untouched. The rest is macro-generated. - -| Area | Change | -|------|--------| -| State struct | Derive `LightAccount`, add `compression_info: CompressionInfo` | -| Accounts struct | Derive `LightAccounts`, add `#[light_account]` on init accounts | -| Program module | Add `#[light_program]` above `#[program]` | -| Instructions (reads, updates, closes) | No program changes. Client prepends a load instruction if account is cold. | - ---- - - - - - - -## Step 1: Dependencies - -```toml -[dependencies] -light-account = { version = "0.23.0", features = ["anchor"] } -light-sdk = { version = "0.23.0", features = ["anchor", "v2", "cpi-context"] } -anchor-lang = "0.31" -``` - -## Step 2: State struct - -Add `compression_info` field and derive `LightAccount`: - -```rust -use light_account::{CompressionInfo, LightAccount}; - -#[derive(Default, Debug, InitSpace, LightAccount)] -#[account] -pub struct Counter { - /// Add this: - pub compression_info: CompressionInfo, - - pub owner: Pubkey, - pub count: u64, -} -``` - -## Step 3: Program module - -Add `#[light_program]` above `#[program]`. Define the CPI signer constant with your program ID: - -```rust -use light_account::{derive_light_cpi_signer, light_program, CpiSigner}; - -pub const LIGHT_CPI_SIGNER: CpiSigner = - derive_light_cpi_signer!("YourProgramId11111111111111111111111111111111"); - -#[light_program] -#[program] -pub mod counter { - use super::*; - - pub fn create_counter<'info>( - ctx: Context<'_, '_, '_, 'info, CreateCounter<'info>>, - params: CreateCounterParams, - ) -> Result<()> { - ctx.accounts.counter.owner = ctx.accounts.owner.key(); - ctx.accounts.counter.count = params.count; - Ok(()) - } - - /// Standard Anchor — no Light-specific changes. - pub fn increment(ctx: Context) -> Result<()> { - ctx.accounts.counter.count = ctx.accounts.counter.count.checked_add(1).unwrap(); - Ok(()) - } - - /// Standard Anchor — no Light-specific changes. - pub fn close_counter(_ctx: Context) -> Result<()> { - Ok(()) - } -} -``` - -## Step 4: Accounts struct - -Derive `LightAccounts` on your `Accounts` struct and add `#[light_account(...)]` next to `#[account(...)]`. - -Only the `init` struct derives `LightAccounts`. The increment and close structs -are standard Anchor: - -```rust -use light_account::{CreateAccountsProof, LightAccounts}; - -#[derive(AnchorSerialize, AnchorDeserialize, Clone)] -pub struct CreateCounterParams { - pub create_accounts_proof: CreateAccountsProof, - pub count: u64, -} - -#[derive(Accounts, LightAccounts)] -#[instruction(params: CreateCounterParams)] -pub struct CreateCounter<'info> { - #[account(mut)] - pub fee_payer: Signer<'info>, - - /// CHECK: Read-only, used for PDA derivation. - pub owner: AccountInfo<'info>, - - /// CHECK: Validated by Light Protocol CPI. - pub compression_config: AccountInfo<'info>, - - /// CHECK: PDA rent sponsor for compression rent reimbursement. - #[account(mut)] - pub pda_rent_sponsor: AccountInfo<'info>, - - #[account( - init, - payer = fee_payer, - space = 8 + ::INIT_SPACE, - seeds = [COUNTER_SEED, owner.key().as_ref()], - bump, - )] - #[light_account(init)] - pub counter: Account<'info, Counter>, - - pub system_program: Program<'info, System>, -} -``` - -## Full Example - - - - -View counter example on GitHub: [counter](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-macros/counter) - - - - - - - - ---- - -## How it works - -The SDK sponsors rent-exemption so you -don't pay the full rent-exempt balance upfront. After extended inactivity, the account -compresses to cold state and returns the rent-exempt balance to the rent -sponsor. Clients call `create_load_instructions` to load a cold account back -on-chain when it's needed again. Your program only ever interacts with hot accounts. - -| | Hot (active) | Cold (inactive) | -|---|---|---| -| Storage | On-chain | Compressed | -| Latency/CU | No change | +load instruction | -| Your program code | No change | No change | - -## FAQ - - When creating an -account for the first time, the SDK provides a proof that the account doesn't -exist in the cold address space. The SVM already verifies this for the onchain -space. Both address spaces are checked before creation, preventing re-init -attacks, even if the account is currently cold. - - -Miners (Forester nodes) compress accounts that have been inactive for an extended period of time (when their virtual rent balance drops below threshold). -In practice, having to load cold accounts should be rare. The common path (hot) has no extra overhead and does not increase CU or txn size. - - - -When accounts compress after extended inactivity, the on-chain rent-exemption is released back -to the rent sponsor. This creates a revolving lifecycle: active "hot" accounts hold a -rent-exempt lamports balance, inactive "cold" accounts release it back. The -rent sponsor must be derived from the program owner. For all mint, ATA, and -token accounts, the Light Token Program is the rent sponsor. For your own program-owned PDAs, the SDK derives a rent sponsor address automatically. - - - -**Hot path (e.g. reads, updates, closes):** No. Active accounts do not add CU overhead to your instructions. - -**First time init + loading cold accounts:** Yes, adds up to 15k-400k CU, -depending on number and type of accounts being initialized or loaded. - - ---- - - -Questions or need hands-on support? [Telegram](https://t.me/swen_light) | [email](mailto:support@lightprotocol.com) | [Discord](https://discord.com/invite/7cJ8BhAXhu) - - - diff --git a/pda/overview.mdx b/pda/overview.mdx deleted file mode 100644 index 75db0248..00000000 --- a/pda/overview.mdx +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: "PDA accounts" -sidebarTitle: "Overview" -description: "Overview to Light-PDAs (Solana accounts with sponsored rent-exemption) and compressed PDAs (compressed accounts without rent-exemption cost)." ---- -import CompressibleRentExplained from "/snippets/compressible-rent-explained.mdx"; -import LightPdaCost from "/snippets/cost-tables/light-pda-cost.mdx"; -import CompressedPdaCost from "/snippets/cost-tables/compressed-pda-cost.mdx"; - -## Light-PDA - -Light-PDAs are Solana PDAs with sponsored rent-exemption and can be implemented with minimal code changes to your existing Solana program. -Your program logic stays mostly untouched, which keeps audit overhead minimal. - - - -> Use Light-PDA's like any Solana PDA, e.g. for DeFi pools, vaults, pool accounts, or other shared state. - - - - - - - ---- - -## Advanced: Compressed PDA - -Compressed PDAs are compressed accounts with an address. -Programs invoke the Light System program to create and update compressed accounts, instead of the System program. -Fully compatible with existing Solana programs, but requires custom logic. - - - -> Use for accounts where each user or entity gets their own PDA and state is infrequently accessed: -> - Per-user state (profiles, preferences, credentials) -> - DePIN node accounts and stake accounts -> - Nullifiers to prevent an on-chain instruction from -> being executed twice (little implementation overhead and useful e.g. for [payments](/pda/compressed-pdas/nullifier-pda) or [ZK programs](zk/overview)) -> - App state that is written to and read from infrequently - - \ No newline at end of file diff --git a/resources/addresses-and-urls.mdx b/resources/addresses-and-urls.mdx index 958aea20..4cc5289a 100644 --- a/resources/addresses-and-urls.mdx +++ b/resources/addresses-and-urls.mdx @@ -111,7 +111,7 @@ Find all JSON RPC Methods for ZK Compression [here](/api-reference/json-rpc-meth The account to convert format between: * compressed token ↔ SPL token -* light-token ↔ SPL token +* compressed token ↔ SPL token | | | |:-|:-| diff --git a/resources/cli.mdx b/resources/cli.mdx deleted file mode 100644 index 9f72b115..00000000 --- a/resources/cli.mdx +++ /dev/null @@ -1,304 +0,0 @@ ---- -title: "CLI installation & commands" -description: "Steps to set up your local environment for Light Protocol development. CLI to interact with Light Tokens and compressed accounts on Solana." -keywords: ["light protocol cli", "zk compression cli"] ---- - - -Make sure you have a wallet set up at `~/.config/solana/id.json`. [Get one here](https://docs.solanalabs.com/cli/wallets/file-system), if you don't have one.\ -The CLI will use this wallet as the default fee payer and mint authority. - - -# Installation - - - - -### Install the CLI - - -Ensure you have Node >= v20.9.0 installed on your machine. Windows users do not require WSL. - - -Run this single command to install the CLI. - -```bash -npm i -g @lightprotocol/zk-compression-cli -``` - - - - -If you prefer to build the CLI from source, follow the steps below to install the necessary prerequisites. - -**1. Activate the Development Environment** - -Ensure you are at the root of the monorepo. - -```bash -. ./scripts/devenv -``` - -**2. Install and build the monorepo from source. This also builds the CLI.** - -```bash -./scripts/install.sh -``` - -```bash -./scripts/build.sh -``` - -**3. Make your CLI available globally** - -```bash -pnpm link --global -``` - -```bash -# Verify the CLI was correctly installed -which light -``` - - - - - - -### Set up your environment - -By default, the CLI interacts with localnet. You can view the current config by running: - -```bash -light config --get -``` - -**1. Once globally installed, start the Light test validator** - -```bash -light test-validator -``` - -This starts a Solana test-validator with the Light System programs and accounts, a prover server, and the Photon indexer as background processes against a clean ledger. - -```bash -# Pass --skip-indexer to start without the indexer -light test-validator --skip-indexer - -# Pass --skip-prover to start without the prover -light test-validator --skip-prover - -``` - -**Note:** - -The CLI currently runs the photon indexer and light-prover as background processes at port: `8784` and `3001` respectively. - - -**2. Ensure you have sufficient localnet funds** - -```bash -# Airdrop 1 SOL -solana airdrop 1 - -# Print your address -solana address - -# Print your balance -solana balance -``` - -Now you're all set up to run CLI commands! - - - -To switch to Devnet, point the URLs to an RPC supporting ZK Compression. For example, run: - -```bash - light config --indexerUrl "https://devnet.helius-rpc.com/?api-key=" \ - --proverUrl "https://devnet.helius-rpc.com/?api-key=" \ - --solanaRpcUrl "https://devnet.helius-rpc.com/?api-key=" -``` - -Also adjust your solana config: - -```bash -# Set config -solana config set --url "https://devnet.helius-rpc.com/?api-key=" - -# Airdrop 1 SOL -solana airdrop 1 - -# Print your address -solana address -``` - - - - - -# Commands - -### Create a Light Token mint - -```bash -light create-mint -``` - -```bash -USAGE - $ light create-mint [--mint-keypair ] [--mint-authority ] - [--mint-decimals ] - -FLAGS - --mint-authority= Path to the mint authority keypair file. - Defaults to the fee payer. - --mint-decimals= Number of base 10 digits to the right - of the decimal place [default: 9]. - --mint-keypair= Path to a mint keypair file. Defaults to a - random keypair. -``` - -### Mint Light Tokens to a Solana wallet - -```bash -light mint-to --mint "YOUR_MINT_ADDRESS" --to "YOUR_WALLET_ADDRESS" --amount 4200000000 -``` - -```bash -USAGE - $ light mint-to --mint --to --amount - [--mint-authority ] - -FLAGS - --amount= (required) Amount to mint. - --mint= (required) Mint address. - --mint-authority= File path of the mint authority keypair. - Defaults to local Solana wallet. - --to= (required) Recipient address. -``` - -### Transfer Light Tokens from one wallet to another - -```bash -light transfer --mint "YOUR_MINT_ADDRESS" --to "RECIPIENT_WALLET_ADDRESS" --amount 4200000000 -``` - -```bash -USAGE - $ light transfer --mint --to --amount - [--fee-payer ] - -FLAGS - --amount= (required) Amount to send. - --fee-payer= Fee payer account. Defaults to the client - keypair. - --mint= (required) Mint to transfer - --to= (required) Recipient address - -``` - -### Enable Light Token Interoperability for existing SPL mint - -```bash -light create-interface-pda --mint "YOUR_MINT_ADDRESS" -``` - -```bash -USAGE - $ light create-interface-pda --mint - -FLAGS - --mint= (required) Base58 encoded mint address to register. -``` - -### Create a Light Token associated token account - -```bash -light create-token-account "YOUR_MINT_ADDRESS" -``` - -```bash -USAGE - $ light create-token-account MINT [--owner ] - -ARGUMENTS - MINT (required) Base58 encoded mint address. - -FLAGS - --owner= Owner of the token account. Defaults to the fee - payer's public key. -``` - -### Wrap SPL tokens into a Light Token account - -```bash -light wrap-spl --mint "YOUR_MINT_ADDRESS" --to "RECIPIENT_ADDRESS" --amount 1000 -``` - -```bash -USAGE - $ light wrap-spl --mint --to --amount - -FLAGS - --amount= (required) Amount to wrap, in tokens. - --mint= (required) Mint address. - --to= (required) Recipient address (owner of destination - Light Token account). -``` - -### Unwrap Light Tokens into an SPL token account - -```bash -light unwrap-spl --mint "YOUR_MINT_ADDRESS" --to "RECIPIENT_ADDRESS" --amount 1000 -``` - -```bash -USAGE - $ light unwrap-spl --mint --to --amount - -FLAGS - --amount= (required) Amount to unwrap, in tokens. - --mint= (required) Mint address. - --to= (required) Recipient address (owner of destination - SPL token account). -``` - -### Check Light Token balance - -```bash -light token-balance --mint "YOUR_MINT_ADDRESS" --owner "YOUR_WALLET_ADDRESS" -``` - -```bash -USAGE - $ light token-balance --mint --owner - -FLAGS - --mint= (required) Mint address of the token account. - --owner= (required) Address of the token owner. -``` - -### Check wrapped SOL balance - -```bash -light balance --owner "YOUR_WALLET_ADDRESS" -``` - -```bash -USAGE - $ light balance --owner - -FLAGS - --owner= (required) Address of the owner. -``` - -# Next Steps - - diff --git a/resources/legacy-compressed-tokens.mdx b/resources/legacy-compressed-tokens.mdx index 827eb3e1..aab6fbd5 100644 --- a/resources/legacy-compressed-tokens.mdx +++ b/resources/legacy-compressed-tokens.mdx @@ -1,6 +1,6 @@ --- title: "Legacy Compressed Tokens" -description: "Compressed tokens are the most efficient way to distribute SPL tokens (eg rewards, airdrops). For other token purposes use Light Token." +description: "Compressed tokens are the most efficient way to distribute SPL tokens (eg rewards, airdrops)." keywords: ["compressed tokens on solana", "scalable token distribution on solana", "infrastructure for token distribution", "airdrop infrastructure on solana", "launchpad infrastructure on solana"] --- @@ -15,18 +15,17 @@ import AgentSkillAirdrop from "/snippets/setup/agent-skill-airdrop.mdx"; -The [Light Token Program](/light-token/welcome) is live on Solana mainnet. -Use Light Token for most purposes except airdrops and other forms of token distribution. -The compressed token SDK remains supported for token distribution use cases. +See [Compressed Tokens](/compressed-tokens/overview) for the current guides and full code examples. +This page is kept for reference; the compressed token SDK is fully supported. | Creation | Solana | Compressed | | :---------------- | :------------------ | :----------------- | | **Token Account** | ~2,000,000 lamports | **5,000** lamports | -1. Compressed token accounts store token balance, owner, and other information of tokens like SPL and light-tokens. +1. Compressed token accounts store token balance, owner, and other information of tokens like SPL and Token 2022. 2. Compressed token accounts are rent-free. -3. Any light-token or SPL token can be compressed/decompressed at will. +3. Any SPL or Token 2022 token can be compressed and decompressed at will. **Compressed Tokens are supported by leading Solana wallets such as Phantom and Backpack.** @@ -41,7 +40,7 @@ The compressed token SDK remains supported for token distribution use cases. title="Guide" icon="chevron-right" color="#0066ff" - href="/token-distribution" + href="/compressed-tokens/token-distribution" horizontal /> @@ -72,8 +71,7 @@ The Photon API provides ZK Compression methods that extend the default Solana JS ## Guides -The SDK for compressed tokens can be used but is not maintained. -Use [Light Token](/light-token/welcome) for other purposes than token distribution or storage of inactive tokens. +For the current compressed token guides and full code examples, see [Compressed Tokens](/compressed-tokens/overview). | | | |---------|------| diff --git a/resources/migration-v1-to-v2.mdx b/resources/migration-v1-to-v2.mdx index 5bc991f8..a1f971c9 100644 --- a/resources/migration-v1-to-v2.mdx +++ b/resources/migration-v1-to-v2.mdx @@ -330,7 +330,7 @@ const remainingAccounts = PackedAccounts.newWithSystemAccountsV2(systemAccountCo title="Program examples" icon="chevron-right" color="#0066ff" - href="/pda/compressed-pdas/program-examples" + href="/compressed-pdas/program-examples" horizontal /> diff --git a/resources/terminology.mdx b/resources/terminology.mdx index 436d75bb..c17f1e67 100644 --- a/resources/terminology.mdx +++ b/resources/terminology.mdx @@ -1,6 +1,6 @@ --- title: "Terminology" -description: "Overview of terminology related to ZK Compression, Light Token, and Solana" +description: "Overview of terminology related to ZK Compression and Solana" --- import CompressibleRentExplained from "/snippets/compressible-rent-explained.mdx"; @@ -31,15 +31,14 @@ A PDA that signs CPI calls from the Light System Program to the Account Compress ## Agent skills Folders of instructions, scripts, and resources that AI agents can discover and use to build on Light Protocol more accurately and efficiently. -Light Protocol provides agent skills for rent-free Solana development: Light-PDA, token and mint accounts. +Light Protocol provides agent skills for rent-free Solana development: token and mint accounts. Skills for compressed PDAs and more are in development. | Use case | Skill | |----------|-------| | Build rent-free Solana programs with Light SDK (Anchor or Pinocchio). Includes router integration. | [light-sdk](https://github.com/Lightprotocol/skills/tree/main/skills/light-sdk) | -| Use Light Token client SDKs (TypeScript and Rust) for mints, ATAs, transfers | [light-token-client](https://github.com/Lightprotocol/skills/tree/main/skills/light-token-client) | | Stream account state via Laserstream gRPC | [data-streaming](https://github.com/Lightprotocol/skills/tree/main/skills/data-streaming) | -| Skill for payment flows using Light Token APIs for sponsored rent-exemption. | [payments](https://github.com/Lightprotocol/skills/tree/main/skills/payments) | +| Skill for payment flows with sponsored rent-exemption. | [payments](https://github.com/Lightprotocol/skills/tree/main/skills/payments) | | Airdrops, DePIN, token distribution | [token-distribution](https://github.com/Lightprotocol/skills/tree/main/skills/token-distribution) | | Anti-double-spend nullifiers for privacy-preserving ZK programs | [zk-nullifier](https://github.com/Lightprotocol/skills/tree/main/skills/zk-nullifier) | | Testing programs and clients on localnet, devnet, mainnet | [testing](https://github.com/Lightprotocol/skills/tree/main/skills/testing) | @@ -82,11 +81,11 @@ A set of [validators](https://solana.com/docs/references/terminology#validator) ## Cold account -A Light Token account, Light Token mint, or Light-PDA that has been compressed after extended inactivity. The account's state is cryptographically preserved on the Solana ledger as a compressed account. On-chain lookups return `is_initialized: false`. Clients call `create_load_instructions` to load the account. +An account whose state has been compressed after extended inactivity. The account's state is cryptographically preserved on the Solana ledger as a compressed account. On-chain lookups return `is_initialized: false`. Clients call `create_load_instructions` to load the account. ## Compressible account -A Solana account (Light Token account, Light Token mint, or Light-PDA) that automatically compresses when its rent balance drops below threshold. Forester nodes execute the compression. The account can be loaded when accessed again. +A Solana account that automatically compresses when its rent balance drops below threshold. Forester nodes execute the compression. The account can be loaded when accessed again. ## Compressed account @@ -101,7 +100,7 @@ A 32-byte identifier that uniquely represents a compressed account's state, stor Compressed accounts with an address stored in an address Merkle tree. Full Solana PDA functionality and composability without rent-exemption cost. -> [Docs](/pda/compressed-pdas/overview) +> [Docs](/compressed-pdas/overview) ## Compressed token @@ -169,7 +168,7 @@ A hash is a digital fingerprint of a sequence of bytes representing arbitrary da ## Hot account -A Light Token account, Light Token mint, or Light-PDA that is active on-chain with a rent-exempt balance. Programs interact only with hot accounts. Clients call `create_load_instructions` to load cold accounts before use. +An account that is active on-chain with a rent-exempt balance. Programs interact only with hot accounts. Clients call `create_load_instructions` to load cold accounts before use. ## Indexer @@ -200,12 +199,6 @@ A helpful analogy to differentiate Solana ledger and state: - Ledger is the entire bank statement history. - State is the current account balance, derived from all transactions in the bank statement history. -## Light-PDA - -A Solana PDA with sponsored rent-exemption. Programs create Light-PDAs using Anchor `#[account(init)]` with `#[light_account(init)]`. Compresses automatically after extended inactivity; clients load the account when it's accessed again. Program logic does not change for reads, updates, or closes. Only the init instruction and state struct require additions. - -> [Docs](/pda/light-pda/overview) | [Overview](/pda/overview) | [Example](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-macros/counter) - ## Light System Program ZK Compression's core program that validates compressed account state transitions by verifying validity proofs and managing compressed state changes. @@ -214,47 +207,6 @@ The program enforces compressed account layout with ownership and sum checks, an > **Program ID**: `SySTEM1eSU2p4BGQfQpimFEWWSC1XDFeun3Nqzz3rT7` | [Source](https://github.com/Lightprotocol/light-protocol/tree/main/programs/system) -## Light Token - -A token standard that reduces the cost of mint and token accounts by 200x compared to SPL. Functionally equivalent to SPL but stores accounts more efficiently. The Light Token SDK API is a superset of the SPL-token API. - -Light Token accounts exist in two states: hot (active on-chain) and cold (compressed after inactivity). The Light Token Program sponsors rent-exemption for account creation. - -Different from ZK Compression, interactions with Light Token accounts do not require a validity proof for interactions. -ZK Compression is used under the hood for inactive token accounts (cold state). - -> [Docs](/light-token/welcome) | [Example](https://github.com/Lightprotocol/examples-light-token) - -## Light Token account - -A Solana account that holds a token balance for a specific mint (SPL, Token 2022, or Light Token). The Light Token Program sponsors the rent-exemption cost. Follows the same layout as SPL token accounts. Compresses automatically after extended inactivity and can be loaded when accessed. - -> [Docs](/light-token/cookbook/create-token-account) | [Example](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-instructions/create-token-account) - -## Light Token associated token account - -An associated token account created by the Light Token Program. The address is deterministically derived from the owner's address, Light Token Program ID, and mint address. Holds token balances of SPL, Token 2022, or Light Token mints with sponsored rent-exemption. - -> [Docs](/light-token/cookbook/create-ata) | [Example](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-instructions/create-associated-token-account) - -## Light Token mint - -An on-chain mint account owned by the Light Token Program. Functionally equivalent to an SPL mint but with sponsored rent-exemption. Stores a compressed address in an address Merkle tree at creation to preserve mint state when the account compresses. - -> [Docs](/light-token/cookbook/create-mint) | [Example](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-instructions/create-mint) | [Source Code](https://github.com/Lightprotocol/light-protocol/blob/main/sdk-libs/token-sdk/src/instruction/create_mint.rs) - -## Light Token Program - -Light Protocol's SPL-compatible token program. The Light Token Program compresses and decompresses token accounts, sponsors rent-exemption, and enforces SPL token layout standards. - -> **Program ID**: `cTokenmWW8bLPjZEBAUgYy3zKxQZW6VKi7bqNFEVv3m` | [Source](https://github.com/Lightprotocol/light-protocol/tree/main/programs/compressed-token) - -## Load associated token account - -Loads token balances into a Light Token associated token account (hot balance). `loadAta` unifies balances from compressed tokens, SPL, and Token 2022 into a single Light Token associated token account. Returns `null` if there's nothing to load (idempotent). Creates the associated token account if it doesn't exist. - -> [Docs](/light-token/cookbook/load-ata) | [Source Code](https://github.com/Lightprotocol/light-protocol/blob/0c4e2417b2df2d564721b89e18d1aad3665120e7/js/compressed-token/src/v3/actions/load-ata.ts) - ## Lookup table A Solana [address lookup table](https://solana.com/docs/advanced/lookup-tables) that reduces transaction size by referencing accounts by index instead of full public key. Light Protocol provides pre-initialized lookup tables covering program IDs and protocol accounts. @@ -301,7 +253,7 @@ The documentation provides two implementations with rent-free PDA accounts: | **Rust SDK** | [light-nullifier-program](https://crates.io/crates/light-nullifier-program) | | **TypeScript SDK** | [@lightprotocol/nullifier-program](https://www.npmjs.com/package/@lightprotocol/nullifier-program) | -> [Docs](/pda/compressed-pdas/nullifier-pda) | [Skill](https://github.com/Lightprotocol/skills/tree/main/skills/payments) | [Example](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/actions/create_nullifier.rs) +> [Docs](/compressed-pdas/nullifier-pda) | [Skill](https://github.com/Lightprotocol/skills/tree/main/skills/payments) | [Example](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/actions/create_nullifier.rs) **ZK nullifier** — For ZK or privacy-preserving programs on Solana to prevent double-spending. Can be integrated with minimal code changes. @@ -412,7 +364,7 @@ A [library of programs](https://spl.solana.com/) on Solana such as spl-token tha ## SPL interface PDA -A PDA owned by the Light Token Program's CPI authority that holds SPL tokens corresponding to compressed tokens and Light Token balances in circulation. Each SPL interface PDA is associated with a specific mint. +A PDA owned by the compressed token program's CPI authority that holds SPL tokens corresponding to compressed tokens in circulation. Each SPL interface PDA is associated with a specific mint. > **Address**: `GXtd2izAiMJPwMEjfgTRH3d7k9mjn4Jq3JrWFv9gySYy` @@ -493,12 +445,6 @@ The _validity proof_ is - verified against the respective on chain fingerprint to ensure the provided data was previously emitted - provided and generated by indexers that support the [ZK Compression RPC API](https://www.zkcompression.com/developers/json-rpc-methods) which extend Solana's [JSON RPC API](https://solana.com/docs/rpc) to interact with compressed accounts. -## Wrap and Unwrap SPL, Token-2022, and Light Token Accounts - -**Wrap** moves tokens from an SPL or Token 2022 account into a Light Token associated token account. **Unwrap** moves tokens from a Light Token associated token account back to an SPL or Token 2022 account. Use wrap/unwrap to interact with applications that only support SPL or Token 2022. - -> [Docs](/light-token/cookbook/wrap-unwrap) | [Source Code](https://github.com/Lightprotocol/light-protocol/blob/0c4e2417b2df2d564721b89e18d1aad3665120e7/js/compressed-token/src/v3/actions/wrap.ts) - ## Zero-knowledge proof (ZKP) A cryptographic proof to verify the validity of a statement without revealing the underlying data. @@ -516,7 +462,7 @@ A generalized compression framework to compress and verify arbitrary data with z - solve Solana's state growth problem, and - build a foundation for native zk compute. -The Light Token program uses ZK Compression under the hood for inactive token accounts (cold state). +Compressed tokens use ZK Compression under the hood for inactive token accounts (cold state). ## ZK-SNARK diff --git a/resources/whitepaper.mdx b/resources/whitepaper.mdx deleted file mode 100644 index 70b9bb3f..00000000 --- a/resources/whitepaper.mdx +++ /dev/null @@ -1,212 +0,0 @@ ---- -title: "Whitepaper" -description: "Whitepaper introducing ZK Compression" -keywords: ["light protocol whitepaper", "zk compression whitepaper"] ---- - -# Scaling the Design Space for On-chain Applications with ZK Compression - -Light Protocol Team - -#### Abstract - -This paper proposes Light Protocol, a set of smart contracts for Solana that introduces ZK Compression. - -Solana application developers can opt-in to compress their application's on-chain state via the Light Protocol smart contracts. This reduces state cost by orders of magnitude while preserving the Solana L1's security, performance, and composability. - -For the Solana validator network, widespread adoption of ZK Compression could help solve the state growth problem by limiting the state held in active memory by validators relative to the total state produced. - -Finally, Light Protocol opens up a new design space for zero-knowledge-based protocols and applications on Solana; because ZK Compression stores data in zero-knowledge-friendly data structures, applications can efficiently prove custom off-chain computations over ZK-compressed state. - -#### 1 The Problem: Expensive On-chain State - -For developers to scale their on-chain applications to large user bases, the marginal cost of data storage must be near zero. Solana has emerged as a leading Layer 1 blockchain, attracting application developers who aim to scale to large numbers of end users. - -However, storing data on the Solana L1 has become increasingly expensive for the network, and the cost trickles down to the application developer, limiting the design space for on-chain applications with low Lifetime Value (LTV) / Customer Acquisition Cost (CAC) ratios. - -#### 2 ZK Compression - -When a Solana account gets compressed, its data is hashed and stored as a leaf in a sparse binary Merkle tree structure. The tree's state root (i.e., a small fingerprint of all compressed accounts in the tree) is stored on the blockchain. - -The underlying compressed account data is stored off-chain, e.g., as call data in the cheaper Solana ledger space. To read or write compressed state, transactions provide the compressed off-chain data and a succinct zero-knowledge proof (validity proof). - -Light Protocol verifies the validity proof against the respective on-chain state root to ensure that the provided data was previously emitted via the protocol smart contracts. The succinctness property of the zero-knowledge proof (a Groth16 SNARK \[1]) ensures that the integrity of many compressed accounts can be verified on-chain with a constant proof size of 128 bytes, which is ideal for Solana's highly constrained 1232-byte transaction size limit. - -#### 3 Light Protocol System Architecture - -The transaction flow in Light Protocol consists of the following key components: - -1. **Off-chain state storage**: State is stored off-chain, e.g., as calldata in the Solana ledger. -2. **New Transactions specify state:** Transactions include the compressed data they read or write, the state tree accounts, a pointer to a recent on-chain state root, and a corresponding validity proof, all included in the transaction payload. -3. **Applications must invoke the Light Protocol system program to write compressed state.** - 1. The system program validates the state (verifies the validity proof, performing sum checks and ownership checks) - 2. It enforces an account schema resembling the layout of classic Solana accounts. - 3. The old compressed state is nullified (inserted into the nullifier queue). - 4. The new compressed state is appended to the state Merkle Tree and recorded as call data on the Solana ledger. - 5. Any newly created addresses are inserted into the address queue. -4. **Photon Indexer** nodes index and store events to make compressed account state available to clients. A new node can always sync with the latest compressed state by sequentially processing all historical transactions from Genesis. - - - A diagram illustrating the transaction flow in the Light Protocol system architecture. The off-chain client reads the compressed state from the indexer and constructs a transaction. The transaction, which includes the compressed state, state tree accounts, a pointer to a recent on-chain state root, and a validity proof, is sent to the caller program. The caller program invokes the Light System Program, which interacts with the Account Compression Program to validate the state, nullify the old compressed state, append the new compressed state to the state Merkle Tree, and record it as call data on the Solana ledger. The Account Compression Program also updates state roots and emits events. The indexer retrieves the compressed state and validity proof from the Solana ledger and makes this information available to the off-chain client, completing the transaction flow. - - -A simplified compressed state transition can be expressed as: - -(𝑠𝑡𝑎𝑡𝑒, 𝑣𝑎𝑙𝑖𝑑𝑖𝑡𝑦𝑃𝑟𝑜𝑜𝑓) → 𝑠𝑡𝑎𝑡𝑒 𝑡𝑟𝑎𝑛𝑠𝑖𝑡𝑖𝑜𝑛 → 𝑠𝑡𝑎𝑡𝑒' - -Here, _state'_ gets emitted onto the ledger. - -- In principle, new compressed account hashes (output state) get appended to specified state trees with each state transition. -- Old compressed account hashes (input state) get invalidated via insertion into a nullifier queue. -- Compressed state transitions are atomic and instantly final. - - - A diagram illustrating the compressed state transition process in the Light Protocol system. The process is initiated by atomic user interactions with the protocol. The user interacts with the Caller Program, which invokes the Light System Program. The Light System Program then interacts with the Account Compression Program to facilitate the state transition. The Account Compression Program performs three key actions: appending the output state to the state tree, invalidating the input state by inserting it into the nullifier queue, and adding new addresses to the address queue. The Forester node asynchronously empties the queues and updates the Merkle trees, maintaining the on-chain accounts, including the state tree and address space tree, which store the compressed state. The compressed state transition follows the sequence: (𝑠𝑡𝑎𝑡𝑒, 𝑣𝑎𝑙𝑖𝑑𝑖𝑡𝑦𝑃𝑟𝑜𝑜𝑓) → 𝑠𝑡𝑎𝑡𝑒 𝑡𝑟𝑎𝑛𝑠𝑖𝑡𝑖𝑜𝑛 → 𝑠𝑡𝑎𝑡𝑒', where state' gets emitted onto the ledger. - - -**Foresters and Liveness** - -In an asynchronous process, _Forester_ nodes empty the nullifier queues. They achieve this by updating the leaf of the state Merkle tree, corresponding to the account hash previously inserted into the nullifier queue, with zeros (nullification). - -These queues enable instant finality of compressed state transitions but have a capped size. _Foresters_ are critical for protocol liveness and need to consistently empty queues. A full queue causes a liveness failure for all state stored in its associated state tree. A liveness failure is recovered by _Foresters_ emptying the queue again. Hosting a _Forester_ and foresting one's trees is permissionless. - -**3.1 Compressed Account Model** - -The Light System Program enforces an account layout that largely resembles Solana's regular account model. Key differences include: - -- Each compressed account can be identified by its hash. -- Each write to a compressed account changes its hash. -- An address can optionally be set as a permanent unique ID of the compressed account. -- All compressed accounts are stored in sparse Merkle trees. Only the trees' sparse state structure and roots (small fingerprints of all compressed accounts) are stored in the on-chain account space. - -These differences allow the protocol to store the underlying data off-chain (e.g., in the less expensive Solana ledger space) instead of in the more expensive on-chain account space. - -**Compressed PDA Accounts** - -Like regular accounts, each compressed account with a program-derived address (PDA) can be identified by its unique persistent address, represented as 32 bytes in the format of a PublicKey. - -Like PDAs, compressed account addresses don't belong to a private key; instead, they're derived from the program that owns them. - - - A diagram illustrating the structure of a compressed account in the Light Protocol system. The compressed account is owned by a program and is associated with a compressed PDA (Program Derived Address) account. The compressed account contains data bytes, lamports (account balance), an owner (the program that owns the account), and an address (represented as a public key). The owner of the compressed account has the authority to modify its data and transfer lamports from it. The compressed account is identified by its unique hash, which changes with each write operation. An address can be optionally set as a permanent unique identifier for the compressed account. Compressed accounts are stored in sparse Merkle trees, with only the trees' sparse state structure and roots stored in the on-chain account space, while the underlying data is stored off-chain. - - -The compressed PDA account layout is similar to Solana's regular PDA account layout: Data, Lamports, Owner, and an address field. The data field stores program-owned state. In contrast to Solana's account data field, Light Protocol enshrines a specific AccountData structure: Discriminator, Data, DataHash: - - - A diagram depicting the structure of a compressed PDA (Program Derived Address) account in the Light Protocol system. The compressed PDA account consists of a data field, which stores program-owned state, lamports (account balance), an owner field indicating the program that owns the account, and an address field represented as a public key. The AccountData structure within the compressed PDA account is composed of a discriminator (a unique identifier for the account type), the actual data (program state), and a DataHash (a hash of the account data). This AccountData structure is specific to the Light Protocol and differs from Solana's regular account data field. - - -**Compressed PDA Account with AccountData** - -The Anchor framework reserves the first 8 bytes of a regular account's data field for the discriminator. This helps programs distinguish between different account types. The default compressed account layout is opinionated in this regard and enforces a discriminator in the Data field. - -The dataHash is what the Protocol uses to verify the integrity of program-owned data. This enables the protocol to be agnostic as to whether or how the data underlying the dataHash is stored or passed to the Light system program. The account owner program needs to ensure the correctness of the data hash. - -**Compressed Token Accounts** - -Light Protocol provides an implementation of a Light Token Program built on top of ZK Compression. - -The Light Token Program enforces a token layout that is compatible with the SPL Token standard. The program also supports SPL compression and decompression; existing SPL token accounts can be compressed and decompressed arbitrarily. - -**Fungible Compressed Accounts** - -Each compressed account can be identified by its hash, regardless of whether it has an address. By definition, whenever the data of a compressed account changes, its hash changes. - -In contrast to Solana's regular account model, the address field is optional for compressed accounts because ensuring that a new account's address is unique incurs additional computational overhead. Addresses are not needed for fungible compressed accounts (i.e., tokens). - -**3.2 The Light Forest: Merkle Trees** - -The protocol stores compressed state in a "forest" of multiple binary Merkle trees. - -**State Trees** - -A state tree is a binary concurrent Merkle tree \[2] that organizes data into a tree structure where each parent node is the hash of its two children nodes. This leads to a single unique root hash that allows for efficient cryptographic verification of the integrity of all the leaves in the tree. The hash of each compressed account is stored as a leaf in such a state tree: - - - A diagram illustrating a binary Merkle tree with a depth of 2. The tree consists of a root node, two intermediate nodes (Node 0 and Node 1), and four leaf nodes (Leaf 0, Leaf 1, Leaf 2, and Leaf 3). The root node is the parent of Node 0 and Node 1, while Node 0 is the parent of Leaf 0 and Leaf 1, and Node 1 is the parent of Leaf 2 and Leaf 3. The tree represents a hierarchical structure where each parent node is derived from the hash of its two child nodes. - - - -Each compressed account hash is a leaf in the state tree: - - - A diagram illustrating the composition of a compressed account hash, which is stored as a leaf in a state tree. The compressed account hash consists of the DataHash, Lamports (account balance), OwnerHash, Address, Discriminator, State tree hash, and Leaf Index. The DataHash represents the hash of the account data, Lamports store the account balance, OwnerHash is the hash of the account owner, Address is an optional unique identifier for the account, Discriminator helps distinguish between different account types, State tree hash identifies the specific state tree the account belongs to, and Leaf Index represents the position of the account within the state tree. The state tree hash and leaf index ensure that each compressed account hash is globally unique. - - - -Compressed account hashes include the Public Key of the State tree's respective on-chain account (State tree hash) and the compressed account's position in the tree (leafIndex). This ensures that each account hash is globally unique. - -Each state tree has a corresponding on-chain State tree account that stores only the tree's final root hash and other metadata. Storing the final tree root hash on-chain allows the protocol to efficiently verify the validity of any leaf in the tree without needing to access the underlying compressed account state. The actual account data can thus be stored off-chain, e.g., in the much cheaper Solana ledger space, while preserving the security guarantees of the Solana L1. - -**Continuous Merkle Trees: Rollover and Rollover fees** - -For each new compressed account state, a new leaf is stored in the respective state Merkle tree. Given a tree depth of 26, the tree can support up to approximately 67 million leaves and, thus, 67 million compressed account state transitions. - -Compressed account hashes are added to the state tree until a threshold is reached. Once this threshold is met, a new state tree account and an associated nullifier queue account can be created to ensure continuous compressed transactions, a process known as a rollover. - -The costs for creating new on-chain accounts during a rollover are amortized across all transactions that add new leaves to the state tree. This marginal cost, which funds the next on-chain accounts, is usually very low and depends on the tree's depth and other factors affecting the size of the state tree and nullifier accounts. - -**Address Space Trees** - -Light Protocol supports the creation of provably unique addresses across a 254-bit address space. This is useful for applications requiring PDA-like uniqueness properties with compressed accounts, such as token-gating or creating unique identifiers. - -Transactions that create new addresses must provide a validity proof of exclusion from a given address space tree. Multiple independent address spaces can exist at the same time. Address space trees are indexed-concurrent binary Merkle tree data structures \[3]. These trees store exclusion ranges as linked lists in the tree leaves, enabling exclusion proofs across the 254-bit address space with trees of arbitrarily small depth. - -**Parallelism** - -State and address space trees can optionally be derived from and owned by custom Solana programs. This is useful for applications that want to control the write locks to their state trees. State tree accounts and nullifier accounts are separated to help elevate unnecessary write-locks. - -Suppose a tree _A_ with queue _A'_ and a tree _B_ with queue _B'._ Further, suppose a transaction _T_ nullifies a compressed account from tree _A_ but writes only to tree B; the transaction only write-locks _A'_ and _B_. _A_ and _B'_ do not get write-locked. - -**Limitations** - -ZK Compression reduces the data storage cost of all accounts to near zero, allowing developers to scale their application state to larger user bases on Solana. However, the following notable characteristics of ZK Compression can impact their utility for specific applications. ZK Compression transactions have: - -1. **Larger Transaction Size:** The transaction payload must include the compressed state to be read on-chain and a constant-size 128-byte validity proof. -2. **High Compute Unit Usage:** The protocol uses ZK primitives and on-chain hashing, which incur a relatively high base CU cost. If blocks are full, this can impact the inclusion rate of transactions. Future approaches to reducing CU cost can include optimizing the Merkle tree updates and hardware acceleration of cryptographic primitives and Syscalls used by the protocol. -3. **Per-transaction cost:** operating a _Forester_ node incurs additional hardware and transaction costs. The mechanism for efficiently nullifying multiple leaves in one Solana transaction can be improved significantly over time. - -#### 4 A World with Light Protocol - -**4.1 Light Helps Developers Scale Their Applications** - -The set of applications and protocols that benefit from ZK Compression is quite broad, including: - -1. Token-based applications and marketplaces, including applications for large-scale token distribution. -2. Applications that issue large numbers of digital assets, PDA accounts, and unique identifiers, such as decentralized social applications, name-service programs, and staking protocols. -3. Applications serving a user base with a low LTV/CAC ratio. -4. Payments infrastructure and applications. - -**4.2 Light Enables ZK-Applications** - -Light Protocol is a shared bridge to merklelized, zk-friendly state. We believe that as more state becomes compressed via ZK Compression, Light Protocol will provide ZK-based applications and protocols with the option to bootstrap and scale on Solana across globally shared compressed state. - -We believe the design space for ZK-based applications is now wide open and will continue to expand. Some exciting technologies include: - -1. Identity Protocols, -2. ZK Coprocessors, -3. Based ZK Rollups - -#### 5 Summary - -1. Light Protocol enables Solana developers to reduce their application state by orders of magnitude by introducing the ZK Compression primitive, which allows secure on-chain composability with off-chain state. -2. ZK Compression can contribute to solving Solana's state growth problem. -3. Light seeks to enable a future with a thriving ZK ecosystem on Solana where new applications, marketplaces and computation designs can all interoperate, compose, and innovate permissionlessly over shared zk-compressed state. - -**Acknowledgments** - -We are grateful to Nicolas Pennie and Pedro Mantica for their extensive feedback, which has helped shape the design of ZK Compression, and to the team at Helius Labs as a whole for building the canonical ZK Compression Indexer implementation and RPC API. - -**Legal Disclaimer** - -Please read the entirety of this "Legal Disclaimer" section carefully. If you have any doubts about the action you should take, you should consult your own legal, financial, tax, or other professional advisor(s) before engaging in any activity herewith. This paper is for general information purposes only, to receive feedback and comments from the public. It does not constitute investment advice, a recommendation, or a solicitation to buy or sell any investment. It should not be used to evaluate the merits of making any investment decision. It should not be relied upon for accounting, legal, or tax advice or any investment recommendations. This paper reflects the current opinions of the Light Protocol Team. The opinions reflected herein outline current plans, which are subject to change at its discretion, without any guarantee of being updated. The success of outlined plans will depend on many factors outside the authors' or Light Protocol Labs' control, including but not limited to factors within the data and blockchain industries. Any statements about future events are based solely on the analysis of the issues described in this White Paper. That analysis might prove to be incorrect. - -**References** - -\[1] Groth, Jens. "On the size of pairing-based non-interactive arguments. " _Advances in Cryptology–EUROCRYPT 2016: 35th Annual International Conference on the Theory and Applications of Cryptographic Techniques, Vienna, Austria, May 8-12, 2016, Proceedings, Part II 35_. Springer Berlin Heidelberg, 2016. - -\[2] _Concurrent Merkle Tree whitepaper.pdf_. (n.d.). Google Docs. [https://drive.google.com/file/d/1BOpa5OFmara50fTvL0VIVYjtg-qzHCVc/view](https://drive.google.com/file/d/1BOpa5OFmara50fTvL0VIVYjtg-qzHCVc/view) - -\[3] _Indexed Merkle Tree | Privacy-First ZKRollup | Aztec Documentation_. (n.d.). [https://docs.aztec.network/aztec/concepts/storage/trees/indexed\_merkle\_tree#indexed-merkle-tree-constructions](https://docs.aztec.network/aztec/concepts/storage/trees/indexed_merkle_tree#indexed-merkle-tree-constructions) - diff --git a/scripts/generate-llms-txt.js b/scripts/generate-llms-txt.js index ccac1fd4..2893a8a0 100644 --- a/scripts/generate-llms-txt.js +++ b/scripts/generate-llms-txt.js @@ -85,12 +85,6 @@ function collectPages(entry, prefix) { } if (entry && entry.group) { const newPrefix = prefix ? `${prefix} > ${entry.group}` : entry.group; - // Program Guides: only include overview, not individual how-to pages - if (entry.group === 'Program Guides') { - const overview = entry.pages[0]; - if (typeof overview === 'string') return [formatPage(overview, newPrefix)]; - return []; - } return entry.pages.flatMap((p) => collectPages(p, newPrefix)); } return []; @@ -101,6 +95,28 @@ function collectFlatPages(pages) { return pages.flatMap((p) => collectPages(p)); } +// Render a top-level group's pages as a section body: direct (string) pages +// first as plain list items, then each subgroup under its own H3 heading (no +// inline prefix). Used for Documentation groups so subgroups read as ### blocks. +function collectGroupBody(group) { + const out = []; + for (const entry of group.pages) { + if (typeof entry === 'string') { + out.push(formatPage(entry)); + } + } + for (const entry of group.pages) { + if (entry && entry.group) { + const lines = entry.pages.flatMap((p) => collectPages(p)); + if (lines.length) { + out.push(`### ${entry.group}`); + out.push(...lines); + } + } + } + return out; +} + function slugify(text) { return text .toLowerCase() @@ -141,40 +157,24 @@ function buildAiTools(anchor) { const skills = [ [ - 'light-sdk', - 'For Solana program development with tokens and PDAs, Light is 200x cheaper than SPL/ Solana and has minimal code differences', - ], - [ - 'light-token-client', - 'For client development with tokens on Solana, Light Token is 200x cheaper than SPL and has minimal changes', - ], - [ - 'data-streaming', - 'For data pipelines, aggregators, or indexers, real-time account state streaming on Solana with light account hot/cold lifecycle tracking', - ], - [ - 'payments', - 'Skill for payment flows using Light Token APIs for sponsored rent-exemption.', + 'compressed-token', + 'For token use cases on Solana, such as token distribution, stablecoin payments and more. Works with Token-2022, Privy, Wallet Adapter similarly to SPL.', ], [ - 'token-distribution', - 'For token distribution on Solana 5000x cheaper than SPL (rewards, airdrops, depins, ...)', + 'compressed-pda', + 'For program development on Solana with infrequently accessed state, such as per-user state, DePIN registrations, nullifiers, or custom compressed accounts.', ], [ - 'zk-nullifier', + 'zk', 'For custom ZK Solana programs and privacy-preserving applications to prevent double spending.', ], [ 'testing', - 'For testing with Light Protocol programs and clients on localnet, devnet, and mainnet validation', - ], - [ - 'solana-compression', - 'For program development on Solana with infrequently accessed state, such as per-user state, DePIN registrations, ...', + 'For testing with Light Protocol programs and clients on localnet, devnet, and mainnet validation.', ], [ 'ask-mcp', - 'For questions about compressed accounts, Light SDK, Solana development, Claude Code features, or agent skills', + 'For questions about compressed accounts, Light SDK, Solana development, Claude Code features, or agent skills.', ], ]; for (const [name, desc] of skills) { @@ -186,36 +186,6 @@ function buildAiTools(anchor) { return { prefix, lines }; } -function splitLightTokenProgram(group) { - const basics = []; - const paymentsWallets = []; - const defi = []; - const streaming = []; - - for (const entry of group.pages) { - if (typeof entry === 'string') { - basics.push(formatPage(entry)); - } else if (entry.group === 'Cookbook' || entry.group === 'Examples') { - basics.push(...collectFlatPages(entry.pages)); - } else if (entry.group === 'For Stablecoin Payments') { - paymentsWallets.push(...collectFlatPages(entry.pages)); - } else if (entry.group === 'For Wallets') { - paymentsWallets.push(...collectFlatPages(entry.pages)); - } else if (entry.group === 'For DeFi') { - defi.push(...collectFlatPages(entry.pages)); - } else if (entry.group === 'For Data Streaming') { - streaming.push(...collectFlatPages(entry.pages)); - } - } - - return [ - { name: 'For Payments and Wallets', lines: paymentsWallets }, - { name: 'For DeFi', lines: defi }, - { name: 'For Data Streaming', lines: streaming }, - { name: 'Light Token Basics', lines: basics }, - ]; -} - // Each API Reference group becomes its own H2 section. // JSON RPC Methods: only the overview page (individual methods are in OpenAPI Specs). function buildApiReferenceSections(anchor) { @@ -233,14 +203,7 @@ function buildApiReferenceSections(anchor) { }); } } else { - const name = - group.group === 'SDK' - ? 'SDK Reference' - : group.group === 'Anchor' - ? 'Anchor Reference' - : group.group === 'Solana to Light' - ? 'Solana to Light Reference' - : group.group; + const name = group.group === 'SDK' ? 'SDK Reference' : group.group; sections.push({ name, lines: group.pages.map((p) => formatPage(p)), @@ -261,46 +224,27 @@ function buildOpenApiSpecs() { // ── Hardcoded examples ────────────────────────────────────────────── -const EXAMPLES_DEFI = [ - '- [cp-swap-reference](https://github.com/Lightprotocol/cp-swap-reference): Fork of Raydium AMM that creates markets without paying rent-exemption.', - '- [pinocchio-swap](https://github.com/Lightprotocol/examples-light-token/tree/main/pinocchio/swap): Light Token swap reference implementation.', - '- [token-swap](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/token-swap): AMM with liquidity pools and swaps.', - '- [escrow](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/escrow): Peer-to-peer light-token swap with offer/accept flow.', - '- [fundraiser](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/fundraiser): Token fundraiser with target, deadline, and refunds.', - '- [create-and-transfer](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/create-and-transfer): Create account via macro and transfer via CPI.', - '- [light-token-minter](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/light-token-minter): Create light-mints with metadata, mint tokens.', -]; - -const EXAMPLES_PAYMENTS = [ - '- [payments](https://github.com/Lightprotocol/examples-light-token/tree/main/toolkits/payments): Wallet integrations and payment flows.', - '- [sign-with-privy](https://github.com/Lightprotocol/examples-light-token/tree/main/toolkits/sign-with-privy): Light-token operations signed with Privy wallets.', - '- [sign-with-wallet-adapter](https://github.com/Lightprotocol/examples-light-token/tree/main/toolkits/sign-with-wallet-adapter): Light-token operations signed with Wallet Adapter.', - '- [gasless-transactions](https://github.com/Lightprotocol/examples-light-token/tree/main/toolkits/gasless-transactions): Abstract SOL fees so users never hold SOL. Sponsor rent top-ups and transaction fees.', - '- [spl-to-light](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/instructions/spl_to_light_transfer.rs): Transfer from SPL to Light via TransferInterface.', - '- [streaming-tokens](https://github.com/Lightprotocol/examples-light-token/tree/main/toolkits/streaming-tokens): Stream mint events using Laserstream.', +const EXAMPLES = [ + '- [compressed-token-cookbook](https://github.com/Lightprotocol/examples-zk-compression/tree/main/compressed-token-cookbook): Action-level and instruction-level examples for every compressed token operation, plus wallet integration.', + '- [example-token-distribution](https://github.com/Lightprotocol/examples-zk-compression/tree/main/example-token-distribution): Simple and optimized batched airdrop flows, with a decompress-on-claim pattern.', + '- [program-examples](https://github.com/Lightprotocol/program-examples): Compressed PDA programs (counter, basic operations, create-and-update, nullifier, zk-id) in Anchor, native, and Pinocchio.', ]; // ── Hardcoded primitives routing table ──────────────────────────────── const PRIMITIVES_SECTION = ` -| Primitive | Use case | Constraints | -| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------ | -| Light Token | Most token use cases (Payment Rails, Consumer Apps, DeFi). Rent-free mint and token accounts. More compute-unit efficient on the hot path. | | -| Light-PDA | DeFi program state such as AMM pools and vaults. Can be implemented with minimal code changes. | | -| Compressed Token | Only for Airdrops and token distribution. Prefer Light Token for other purposes. Used by Light Token under the hood for rent-free storage of inactive Light Tokens. Supported by Phantom and Backpack. | Do not use for general-purpose token features. Use Light Token instead. | -| Compressed PDA | User state and app state, nullifiers (payments and ZK applications), DePIN nodes, and stake accounts. Similar to program-derived addresses without a rent-exempt balance. | Not for shared state, pool accounts, or config accounts. Use Light-PDA instead | +| Primitive | Use case | Constraints | +| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | +| Compressed Token | Token use cases such as token distribution, stablecoin payments, and storing balances rent-free. Always compressed and rent-free. Works with SPL and Token-2022. Supported by Phantom and Backpack. | The SPL mint and interface PDA pay rent; individual token accounts do not. | +| Compressed PDA | Per-user and app state, nullifiers (payments and ZK applications), DePIN nodes, and stake accounts. Similar to program-derived addresses without a rent-exempt balance. | Programs invoke the Light System Program (not the System Program) with a validity proof. | -View a complete API comparison to SPL and Solana: [https://www.zkcompression.com/api-reference/solana-to-light-comparison](https://www.zkcompression.com/api-reference/solana-to-light-comparison). +View the SDK reference: [https://www.zkcompression.com/api-reference/sdk](https://www.zkcompression.com/api-reference/sdk). -Comparing creation cost and CU usage: +Comparing creation cost: -| | Light-Token | SPL-Token | -| :----------------------- | --------------: | ---------: | -| **Mint Account** | **0.00001 SOL** | 0.0015 SOL | -| **Token Account** | **0.00001 SOL** | 0.0029 SOL | -| **Associated token account creation** | **4,348 CU** | 14,194 CU | -| **Transfer** | **312 CU** | 4,645 CU | -| **Transfer** (rent-free) | **1,885 CU** | 4,645 CU |`.trim(); +| Creation | Solana | Compressed | +| :---------------- | :------------------ | :----------------- | +| **Token Account** | ~2,000,000 lamports | **5,000** lamports |`.trim(); // ── Main ──────────────────────────────────────────────────────────── @@ -321,7 +265,7 @@ function generate() { // 2. Documentation and API Reference — interleaved const docAnchor = anchors.find((a) => a.anchor === 'Documentation'); - const apiAnchor = anchors.find((a) => a.anchor === 'API Reference'); + const apiAnchor = anchors.find((a) => a.anchor === 'API & SDK Reference'); const apiSections = buildApiReferenceSections(apiAnchor); const sectionRenames = { @@ -338,24 +282,20 @@ function generate() { }); } - // API Reference sections (SDK, Solana to Light, Anchor) — before Light Token + // API Reference sections (SDK Reference) — before token content for (const s of apiSections) { if (s.name !== 'JSON RPC Methods') sections.push(s); } - // Light Token sections (payments, defi, streaming, then basics) - const ltGroup = docAnchor.groups.find( - (g) => g.group === 'Light Token APIs', - ); - if (ltGroup) sections.push(...splitLightTokenProgram(ltGroup)); - - // Remaining Documentation groups (PDA, Other Use Cases, Learn, Resources) + // Documentation groups — one H2 per docs.json group, mirroring nav structure. + // Subgroup names (Cookbook, Integration Guides, Program Guides, Core Concepts, + // Error Cheatsheet) are carried as a "**prefix:**" by collectPages(). + // 'Introduction' is already emitted above as "Getting Started". for (const group of docAnchor.groups) { - if (group.group === 'Introduction' || group.group === 'Light Token APIs') - continue; + if (group.group === 'Introduction') continue; sections.push({ name: sectionRenames[group.group] || group.group, - lines: group.pages.flatMap((p) => collectPages(p)), + lines: collectGroupBody(group), }); } @@ -373,11 +313,7 @@ function generate() { }); // 5. Hardcoded examples - sections.push({ name: 'Examples for DeFi', lines: EXAMPLES_DEFI }); - sections.push({ - name: 'Examples for Payments and Wallets', - lines: EXAMPLES_PAYMENTS, - }); + sections.push({ name: 'Examples', lines: EXAMPLES }); // 6. OpenAPI Specs sections.push({ name: 'OpenAPI Specs', lines: buildOpenApiSpecs() }); @@ -389,10 +325,10 @@ function generate() { out.push('# ZK Compression by Light Protocol and Helius Labs'); out.push(''); out.push( - '> ZK Compression is a framework on Solana for stablecoin payment rails, agent commerce, consumer apps, defi protocols, depin, and more. ', + '> ZK Compression is a framework on Solana for token distribution, stablecoin payments, consumer apps, per-user state, and more.', ); out.push( - "> The Light SDK and APIs let you create mint, token and PDA accounts >99% cheaper with familiar Solana developer experience.", + '> The Light SDK and APIs let you create token and PDA accounts without rent-exemption, with a familiar Solana developer experience.', ); out.push(''); out.push( diff --git a/skill.md b/skill.md index 5dcfc5e7..ee5f5b13 100644 --- a/skill.md +++ b/skill.md @@ -1,12 +1,11 @@ --- name: solana-rent-free-dev description: > - Skill for Solana development using rent-free primitives from Light Protocol. - Covers client development (TypeScript, Rust) and program development (Rust) - across Anchor, native Rust, and Pinocchio. Focus areas include DeFi and - Payments (Light Token, Light-PDA). Other use cases include airdrops and token - distribution (Compressed Token), and user/app state plus nullifiers for - payments and ZK applications (Compressed PDA). + Skill for Solana development using compressed accounts from Light Protocol. + Covers compressed token client development (TypeScript) and compressed PDA + program development (Rust) across Anchor, native Rust, and Pinocchio. Use cases + include token distribution, stablecoin payments, per-user and app state, + nullifiers, and ZK applications. compatibility: | Requires ZK Compression CLI, Solana CLI, Anchor CLI, and Node.js. metadata: @@ -29,39 +28,33 @@ allowed-tools: ## Capabilities -ZK Compression is a framework on Solana for stablecoin payment rails, consumer apps and defi. The Light SDK and APIs let you create mint, token and PDA accounts >99% cheaper with familiar Solana developer experience. +ZK Compression is a framework on Solana for token distribution, stablecoin payments, consumer apps, and per-user state. The Light SDK and APIs let you create token and PDA accounts without rent-exemption, with a familiar Solana developer experience. ### Primitives -| Primitive | Use case | Constraints | -| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------ | -| Light Token | Most token use cases (launchpads, DeFi, payments). Rent-free mint and token accounts. \~200x cheaper than SPL and more compute-unit efficient on the hot path. | | -| Light-PDA | DeFi program state such as AMM pools and vaults. \~98% cheaper than PDAs and can be implemented with minimal code changes. | | -| Compressed Token | Only for Airdrops and token distribution. Prefer Light Token for other purposes. Used by Light Token under the hood for rent-free storage of inactive Light Tokens. Supported by Phantom and Backpack. | Do not use for general-purpose token features. Use Light Token instead. | -| Compressed PDA | User state and app state, nullifiers (payments and ZK applications), DePIN nodes, and stake accounts. Similar to program-derived addresses without a rent-exempt balance. | Not for shared state, pool accounts, or config accounts. Use Light-PDA instead | +| Primitive | Use case | Constraints | +| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------ | +| Compressed Token | Token use cases such as token distribution, stablecoin payments, and storing balances rent-free. Always compressed and rent-free. Works with SPL and Token-2022. Supported by Phantom and Backpack. | The SPL mint and interface PDA pay rent; individual token accounts do not. | +| Compressed PDA | Per-user and app state, nullifiers (payments and ZK applications), DePIN nodes, and stake accounts. Derived like a program-derived address, without a rent-exempt balance. | Programs invoke the Light System Program (not the System Program) with a validity proof. | -View a complete API comparison to SPL and Solana: https://www.zkcompression.com/api-reference/solana-to-light-comparison. +View the SDK reference: https://www.zkcompression.com/api-reference/sdk. -### Creation cost and Compute Unit Consumption +### Creation cost -| Metric | Light | Standard Solana | -| ------------------------------------- | -----------------: | --------------: | -| **Mint Account** | **~0.00001 SOL** | ~0.0015 SOL | -| **Token Account** | **~0.00001 SOL** | ~0.0029 SOL | -| **PDA (100-byte)** | **~0.0000115 SOL** | ~0.0016 SOL | -| **Associated token account creation** | **4,348 CU** | 14,194 CU | -| **Transfer** | **312 CU** | 4,645 CU | -| **Transfer** (rent-free) | **1,885 CU** | 4,645 CU | +| Creation cost | Compressed | Standard Solana | +| ------------------ | -------------------: | -------------------: | +| **Token account** | **~5,000 lamports** | ~2,000,000 lamports | +| **PDA (100-byte)** | **~15,000 lamports** | ~1,600,000 lamports | ### Install -Install orchestrator agent skill or view [skill.md](https://www.zkcompression.com/skill.md): +Install the orchestrator agent skill or view [skill.md](https://www.zkcompression.com/skill.md): ```bash npx skills add https://zkcompression.com ``` -Install or view [dedicated agent skills](/ai-tools/overview#agent-skills). +Install or view [dedicated agent skills](/ai-tools/overview#agent-skills): ``` npx skills add Lightprotocol/skills @@ -74,8 +67,8 @@ npx skills add Lightprotocol/skills - Use `AskUserQuestion` to resolve blind spots - All questions must be resolved before execution 2. **Identify references and skills** - - Match task to available [skills](#defi) below - - Locate relevant [documentation and examples](#documentation-and-examples) + - Match the task to the available [skills](#skills) below + - Locate relevant documentation and examples 3. **Write plan file** (YAML task format) - Use `AskUserQuestion` for anything unclear — never guess or assume - Identify blockers: permissions, dependencies, unknowns @@ -84,179 +77,73 @@ npx skills add Lightprotocol/skills - Use `Task` tool with subagents for parallel research - Subagents load skills via `Skill` tool - Track progress with `TodoWrite` -5. **When stuck**: spawn subagent with `Read`, `Glob`, `Grep`, DeepWiki MCP access and load `skills/ask-mcp` +5. **When stuck**: spawn a subagent with `Read`, `Glob`, `Grep`, DeepWiki MCP access and load `skills/ask-mcp` ## Skills -| Use case | Skill | -| ---------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | -| Skill for payment flows using Light Token APIs for sponsored rent-exemption. | [payments](https://github.com/Lightprotocol/skills/tree/main/skills/payments) | -| For Solana program development with tokens and PDAs, Light is 200x cheaper than SPL/ Solana and has minimal code differences | [light-sdk](https://github.com/Lightprotocol/skills/tree/main/skills/light-sdk) | -| For client development with tokens on Solana, Light Token is 200x cheaper than SPL and has minimal changes | [light-token-client](https://github.com/Lightprotocol/skills/tree/main/skills/light-token-client) | -| For data pipelines, aggregators, or indexers, real-time account state streaming on Solana with light account hot/cold lifecycle tracking | [data-streaming](https://github.com/Lightprotocol/skills/tree/main/skills/data-streaming) | -| For token distribution on Solana 5000x cheaper than SPL (rewards, airdrops, depins, ...) | [token-distribution](https://github.com/Lightprotocol/skills/tree/main/skills/token-distribution) | -| For custom ZK Solana programs and privacy-preserving applications to prevent double spending | [zk-nullifier](https://github.com/Lightprotocol/skills/tree/main/skills/zk-nullifier) | -| For program development on Solana with infrequently accessed state, such as per-user state, DePIN registrations, ... | [solana-compression](https://github.com/Lightprotocol/skills/tree/main/skills/solana-compression) | -| For testing with Light Protocol programs and clients on localnet, devnet, and mainnet validation | [testing](https://github.com/Lightprotocol/skills/tree/main/skills/testing) | -| For questions about compressed accounts, Light SDK, Solana development, Claude Code features, or agent skills | [ask-mcp](https://github.com/Lightprotocol/skills/tree/main/skills/ask-mcp) | +| Use case | Skill | +| --------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | +| For token use cases on Solana, such as token distribution, stablecoin payments and more. Works with Token-2022, Privy, Wallet Adapter similarly to SPL. | [compressed-token](https://github.com/Lightprotocol/skills/tree/main/skills/compressed-token) | +| For program development on Solana with infrequently accessed state, such as per-user state, DePIN registrations, nullifiers, or custom compressed accounts | [compressed-pda](https://github.com/Lightprotocol/skills/tree/main/skills/compressed-pda) | +| For custom ZK Solana programs and privacy-preserving applications to prevent double spending | [zk](https://github.com/Lightprotocol/skills/tree/main/skills/zk) | +| For testing with Light Protocol programs and clients on localnet, devnet, and mainnet validation | [testing](https://github.com/Lightprotocol/skills/tree/main/skills/testing) | +| For questions about compressed accounts, Light SDK, Solana development, Claude Code features, or agent skills | [ask-mcp](https://github.com/Lightprotocol/skills/tree/main/skills/ask-mcp) | ## Context -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison +- SDK reference: https://zkcompression.com/api-reference/sdk -### light-token +### Compressed token -A token standard functionally equivalent to SPL that stores mint and token accounts more efficiently. +Compressed token accounts store balance, owner, mint, and delegate like SPL token accounts, without paying rent-exemption. Any SPL or Token-2022 token can be compressed and decompressed at will. Wallets like Phantom and Backpack display them alongside SPL tokens. -**Mint accounts** represent a unique mint and optionally store token-metadata. Functionally equivalent to SPL mints. +A compressed token uses a standard SPL (or Token-2022) mint plus an interface PDA. The interface PDA is an omnibus account that locks SPL tokens while they are compressed and releases them on decompression. The SPL mint and interface PDA pay rent like regular SPL accounts; individual compressed token accounts are rent-free. -**Token accounts** hold balances from any light, SPL, or Token-2022 mint, without paying rent-exemption. +Use for: token distribution and airdrops, stablecoin payments, and storing token balances rent-free. -The token program pays rent-exemption cost for you. When an account has no remaining sponsored rent, the account is automatically compressed. Your tokens are cryptographically preserved as a compressed token account (rent-free). The account is loaded into hot account state in-flight when someone interacts with it again. - -Use for: Stablecoin Orchestration, Cards, Agent Commerce, Defi, ... . - -### light-PDA - -The Light-SDK pays rent-exemption for your PDAs, token accounts, and mints (98% cost savings). Your program logic stays the same. - -After extended inactivity (multiple epochs without writes), accounts auto-compress to cold state. Your program only interacts with hot accounts. Clients load cold accounts back on-chain via `create_load_instructions`. +### Compressed PDA -| Area | Change | -| --------------- | --------------------------------------------------------------- | -| State struct | Derive `LightAccount`, add `compression_info: CompressionInfo` | -| Accounts struct | Derive `LightAccounts`, add `#[light_account]` on init accounts | -| Program module | Add `#[light_program]` above `#[program]` | -| Instructions | No changes | +Compressed PDAs are derived using a program address and seed, like regular PDAs. A program invokes the Light System Program (not the System Program) to create and update them. Creating an account requires a validity proof that the derived address does not yet exist; updates, closes, and burns require a proof that the account exists. -Use for: DeFi program state, AMM pools, vaults. +Persistent unique identification. Program ownership. CPI between compressed and regular PDAs. -### Compressed token (only use for token distribution) +Use for: per-user state, app state, nullifiers for payments and ZK applications, DePIN node accounts, and stake accounts. -Compressed token accounts store token balance, owner, and other information of tokens like SPL and light-tokens. Compressed token accounts are rent-free. Any light-token or SPL token can be compressed/decompressed at will. Supported by Phantom and Backpack. +## Examples -Only use for: airdrops, token distribution without paying upfront rent per recipient. +### Compressed token client (`@lightprotocol/compressed-token`) -### Compressed PDA +Operations use `@lightprotocol/compressed-token` with `createRpc()` from `@lightprotocol/stateless.js`. -Compressed PDAs are derived using a specific program address and seed, like regular PDAs. Custom programs invoke the Light System program to create and update accounts, instead of the System program. +| Operation | GitHub example | +| ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `createMint` | [create-mint](https://github.com/Lightprotocol/examples-zk-compression/blob/main/compressed-token-cookbook/actions/create-mint.ts) | +| `createTokenPool` | [create-token-pool](https://github.com/Lightprotocol/examples-zk-compression/blob/main/compressed-token-cookbook/actions/create-token-pool.ts) | +| `mintTo` | [mint-to](https://github.com/Lightprotocol/examples-zk-compression/blob/main/compressed-token-cookbook/actions/mint-to.ts) | +| `transfer` | [transfer](https://github.com/Lightprotocol/examples-zk-compression/blob/main/compressed-token-cookbook/actions/transfer.ts) | +| `approve` / `revoke` | [approve](https://github.com/Lightprotocol/examples-zk-compression/blob/main/compressed-token-cookbook/actions/approve.ts) \| [revoke](https://github.com/Lightprotocol/examples-zk-compression/blob/main/compressed-token-cookbook/actions/revoke.ts) | +| `compress` | [compress](https://github.com/Lightprotocol/examples-zk-compression/blob/main/compressed-token-cookbook/actions/compress.ts) | +| `decompress` | [decompress](https://github.com/Lightprotocol/examples-zk-compression/blob/main/compressed-token-cookbook/actions/decompress.ts) | +| `compressSplTokenAccount`| [compress-spl-account](https://github.com/Lightprotocol/examples-zk-compression/blob/main/compressed-token-cookbook/actions/compress-spl-account.ts) | +| `mergeTokenAccounts` | [merge-token-accounts](https://github.com/Lightprotocol/examples-zk-compression/blob/main/compressed-token-cookbook/actions/merge-token-accounts.ts) | -Persistent unique identification. Program ownership. CPI between compressed and regular PDAs. +### Token distribution -Use rent-free PDAs for: user state, app state, nullifiers for payments, DePIN node accounts, stake accounts, nullifiers for zk applications. Not for shared state, pool, and config accounts. - -### Guidelines - -- **light-token ≠ compressed token.** light-token is a Solana account in hot state. Compressed token is a compressed account, always compressed, rent-free. -- **light-PDA ≠ compressed PDA.** light-PDA is a Solana PDA that transitions to compressed state when inactive. Compressed PDA is always compressed, derived like a PDA and requires a validity proof. -- **light-token accounts hold SPL and Token-2022 balances**, not just light-mint balances. -- When sponsored rent on a light-token or light-PDA runs out, the account compresses. It decompresses on next interaction. - -## Payment Flows - -| Name | Description | Docs | Examples | -| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| Overview | Learn how the Light Token APIs reduce account creation cost for stablecoin payment infrastructure by 99% with similar developer experience to SPL / Token 2022. | [overview](https://zkcompression.com/light-token/payments/overview) | | -| Basic payment | Send a single token transfer with Light Token APIs for stablecoin payments with comparison to SPL. | [basic-payment](https://zkcompression.com/light-token/payments/basic-payment) | [basic-send-action](https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/send/basic-send-action.ts) \| [basic-send-instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/send/basic-send-instruction.ts) | -| Batch payments | Send payments to multiple recipients in a single transaction or sequentially. | [batch-payments](https://zkcompression.com/light-token/payments/batch-payments) | [batch-send](https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/send/batch-send.ts) | -| Payment with memo | Attach invoice IDs, payment references, or notes to Light Token transfers using Solana's memo program. The memo is recorded in the transaction logs for reconciliation. | [payment-with-memo](https://zkcompression.com/light-token/payments/payment-with-memo) | [payment-with-memo](https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/send/payment-with-memo.ts) | -| Receive payments | Prepare to receive token payments by loading cold accounts and sharing your associated token account address. | [receive-payments](https://zkcompression.com/light-token/payments/receive-payments) | [receive](https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/receive/receive.ts) | -| Verify payments | Query token balances and transaction history to verify incoming payments. | [verify-payments](https://zkcompression.com/light-token/payments/verify-payments) | [get-balance](https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/verify/get-balance.ts) \| [get-history](https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/verify/get-history.ts) | -| Verify address | Verify recipient addresses before sending payments. Address validation prevents sending tokens to invalid or unexpected account types. | [verify-recipient-address](https://zkcompression.com/light-token/payments/verify-recipient-address) | [verify-address](https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/verify/verify-address.ts) | -| Wrap and unwrap | Move tokens between SPL / Token 2022 and Light Token accounts for interoperability with applications that don't support Light Token yet. | [wrap-unwrap](https://zkcompression.com/light-token/payments/wrap-unwrap) | [wrap](https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/interop/wrap.ts) \| [unwrap](https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/interop/unwrap.ts) | -| Spend permissions | Delegate token spending to a third party with an amount cap. The delegate can transfer tokens on behalf of the owner up to the approved amount, without the owner signing each transaction. | [spend-permissions](https://zkcompression.com/light-token/payments/spend-permissions) | [delegate-full-flow](https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/spend-permissions/delegate-full-flow.ts) | -| Nullifier PDAs | Create rent-free nullifier PDAs to prevent duplicate actions. | [nullifier-pda](https://zkcompression.com/pda/compressed-pdas/nullifier-pda) | | -| Production readiness | Non-exhaustive checklist for deploying Light Token payment flows to production, including RPC infrastructure, error handling, and security. | [production-readiness](https://zkcompression.com/light-token/payments/production-readiness) | | -| Wallet integration | Guide for Wallet Applications to add Light-token support. | [wallets/overview](https://zkcompression.com/light-token/wallets/overview) | | -| Sign with Privy | Integrate light-token with Privy embedded wallets for rent-free token accounts and transfers. | [privy](https://zkcompression.com/light-token/wallets/privy) | [sign-with-privy](https://github.com/Lightprotocol/examples-light-token/tree/main/toolkits/sign-with-privy) | -| Sign with Wallet Adapter | Integrate light-token with Solana Wallet Adapter for rent-free token accounts and transfers. | [wallet-adapter](https://zkcompression.com/light-token/wallets/wallet-adapter) | [sign-with-wallet-adapter](https://github.com/Lightprotocol/examples-light-token/tree/main/toolkits/sign-with-wallet-adapter) | -| Gasless transactions | Abstract SOL fees so users never hold SOL. Sponsor top-ups and transaction fees by setting your application as the fee payer. | [gasless-transactions](https://zkcompression.com/light-token/wallets/gasless-transactions) | [gasless-transactions](https://github.com/Lightprotocol/examples-light-token/tree/main/toolkits/gasless-transactions) | +| Flow | GitHub example | +| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------- | +| Simple airdrop | [simple-airdrop](https://github.com/Lightprotocol/examples-zk-compression/tree/main/example-token-distribution/src/simple-airdrop) | +| Optimized airdrop | [optimized-airdrop](https://github.com/Lightprotocol/examples-zk-compression/tree/main/example-token-distribution/src/optimized-airdrop) | -## Examples +### Compressed PDA programs (`light-sdk`) -### TypeScript client (`@lightprotocol/compressed-token`) - -| Operation | Docs guide | GitHub example | -| ------------------------------ | --------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `createMintInterface` | [create-mint](https://zkcompression.com/light-token/cookbook/create-mint) | [action](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/actions/create-mint.ts) \| [instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/instructions/create-mint.ts) | -| `createAtaInterface` | [create-ata](https://zkcompression.com/light-token/cookbook/create-ata) | [action](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/actions/create-ata.ts) \| [instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/instructions/create-ata.ts) | -| `mintToInterface` | [mint-to](https://zkcompression.com/light-token/cookbook/mint-to) | [action](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/actions/mint-to.ts) \| [instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/instructions/mint-to.ts) | -| `transferInterface` | [transfer-interface](https://zkcompression.com/light-token/cookbook/transfer-interface) | [action](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/actions/transfer-interface.ts) \| [instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/instructions/transfer-interface.ts) | -| `approve` | [approve-revoke](https://zkcompression.com/light-token/cookbook/approve-revoke) | [action](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/actions/delegate-approve.ts) | -| `revoke` | [approve-revoke](https://zkcompression.com/light-token/cookbook/approve-revoke) | [action](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/actions/delegate-revoke.ts) | -| `delegateTransfer` | [transfer-delegated](https://zkcompression.com/light-token/cookbook/transfer-delegated) | [action](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/actions/delegate-transfer.ts) | -| `wrap` | [wrap-unwrap](https://zkcompression.com/light-token/cookbook/wrap-unwrap) | [action](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/actions/wrap.ts) \| [instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/instructions/wrap.ts) | -| `unwrap` | [wrap-unwrap](https://zkcompression.com/light-token/cookbook/wrap-unwrap) | [action](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/actions/unwrap.ts) \| [instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/instructions/unwrap.ts) | -| `loadAta` | [load-ata](https://zkcompression.com/light-token/cookbook/load-ata) | [action](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/actions/load-ata.ts) \| [instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/instructions/load-ata.ts) | -| `createAtaExplicitRentSponsor` | — | [action](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/actions/create-ata-explicit-rent-sponsor.ts) | -| `createSplInterface` | [add-interface-pda](https://zkcompression.com/light-token/cookbook/add-interface-pda) | [action](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/actions/create-spl-interface.ts) \| [instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/instructions/create-spl-interface.ts) | -| `createSplMint` | [create-mint](https://zkcompression.com/light-token/cookbook/create-mint) | [action](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/actions/create-spl-mint.ts) \| [instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/instructions/create-spl-mint.ts) | -| `createT22Mint` | [create-mint](https://zkcompression.com/light-token/cookbook/create-mint) | [action](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/actions/create-t22-mint.ts) \| [instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/instructions/create-t22-mint.ts) | -| `createTokenPool` | — | [instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/instructions/create-token-pool.ts) | - -### Rust client (`light-token-client`) - -| Operation | Docs guide | GitHub example | -| -------------------- | ------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `CreateMint` | [create-mint](https://zkcompression.com/light-token/cookbook/create-mint) | [action](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/actions/create_mint.rs) \| [instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/instructions/create_mint.rs) | -| `CreateAta` | [create-ata](https://zkcompression.com/light-token/cookbook/create-ata) | [action](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/actions/create_associated_token_account.rs) \| [instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/instructions/create_associated_token_account.rs) | -| `CreateTokenAccount` | [create-token-account](https://zkcompression.com/light-token/cookbook/create-token-account) | [instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/instructions/create_token_account.rs) | -| `MintTo` | [mint-to](https://zkcompression.com/light-token/cookbook/mint-to) | [action](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/actions/mint_to.rs) \| [instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/instructions/mint_to.rs) | -| `TransferInterface` | [transfer-interface](https://zkcompression.com/light-token/cookbook/transfer-interface) | [action](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/actions/transfer_interface.rs) \| [instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/instructions/transfer_interface.rs) | -| `TransferChecked` | [transfer-checked](https://zkcompression.com/light-token/cookbook/transfer-checked) | [action](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/actions/transfer_checked.rs) \| [instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/instructions/transfer_checked.rs) | -| `Approve` | [approve-revoke](https://zkcompression.com/light-token/cookbook/approve-revoke) | [action](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/actions/approve.rs) \| [instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/instructions/approve.rs) | -| `Revoke` | [approve-revoke](https://zkcompression.com/light-token/cookbook/approve-revoke) | [action](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/actions/revoke.rs) \| [instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/instructions/revoke.rs) | -| `Burn` | [burn](https://zkcompression.com/light-token/cookbook/burn) | [instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/instructions/burn.rs) | -| `BurnChecked` | [burn](https://zkcompression.com/light-token/cookbook/burn) | [instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/instructions/burn_checked.rs) | -| `Freeze` | [freeze-thaw](https://zkcompression.com/light-token/cookbook/freeze-thaw) | [instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/instructions/freeze.rs) | -| `Thaw` | [freeze-thaw](https://zkcompression.com/light-token/cookbook/freeze-thaw) | [instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/instructions/thaw.rs) | -| `Close` | [close-token-account](https://zkcompression.com/light-token/cookbook/close-token-account) | [instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/instructions/close.rs) | -| `Wrap` | [wrap-unwrap](https://zkcompression.com/light-token/cookbook/wrap-unwrap) | [action](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/actions/wrap.rs) | -| `Unwrap` | [wrap-unwrap](https://zkcompression.com/light-token/cookbook/wrap-unwrap) | [action](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/actions/unwrap.rs) | -| `MintToChecked` | [mint-to](https://zkcompression.com/light-token/cookbook/mint-to) | [instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/instructions/mint_to_checked.rs) | -| `SplToLightTransfer` | — | [instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/instructions/spl_to_light_transfer.rs) | - -### Program examples (`light_token`) - -| | Description | -| -------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- | -| [escrow](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/escrow) | Peer-to-peer light-token swap with offer/accept flow | -| [fundraiser](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/fundraiser) | Token fundraiser with target, deadline, and refunds | -| [light-token-minter](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/light-token-minter) | Create light-mints with metadata, mint tokens | -| [token-swap](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/token-swap) | AMM with liquidity pools and swaps (Anchor) | -| [cp-swap-reference](https://github.com/Lightprotocol/cp-swap-reference) | Fork of Raydium AMM that creates markets without paying rent-exemption | -| [pinocchio-swap](https://github.com/Lightprotocol/examples-light-token/tree/main/pinocchio/swap) | AMM with liquidity pools and swaps (Pinocchio) | -| [create-and-transfer](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/create-and-transfer) | Create account via macro and transfer via CPI | -| | | - -### Program macros (`light_token`) - -| | Description | -| ------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------- | -| [counter](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-macros/counter) | Create PDA with sponsored rent-exemption | -| [create-ata](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-macros/create-associated-token-account) | Create associated light-token account | -| [create-mint](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-macros/create-mint) | Create light-token mint | -| [create-token-account](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-macros/create-token-account) | Create light-token account | - -### CPI instructions (`light_token`) - -CPI calls can be combined with existing and/or light macros. The API is a superset of SPL-token. - -| Operation | Docs guide | GitHub example | -| ---------------------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | -| `CreateAssociatedAccountCpi` | [create-ata](https://zkcompression.com/light-token/cookbook/create-ata) | [src](https://github.com/Lightprotocol/examples-light-token/blob/main/programs/anchor/basic-instructions/create-associated-token-account/src/lib.rs) | -| `CreateTokenAccountCpi` | [create-token-account](https://zkcompression.com/light-token/cookbook/create-token-account) | [src](https://github.com/Lightprotocol/examples-light-token/blob/main/programs/anchor/basic-instructions/create-token-account/src/lib.rs) | -| `CreateMintCpi` | [create-mint](https://zkcompression.com/light-token/cookbook/create-mint) | [src](https://github.com/Lightprotocol/examples-light-token/blob/main/programs/anchor/basic-instructions/create-mint/src/lib.rs) | -| `MintToCpi` | [mint-to](https://zkcompression.com/light-token/cookbook/mint-to) | [src](https://github.com/Lightprotocol/examples-light-token/blob/main/programs/anchor/basic-instructions/mint-to/src/lib.rs) | -| `MintToCheckedCpi` | [mint-to](https://zkcompression.com/light-token/cookbook/mint-to) | [src](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-instructions/mint-to-checked) | -| `BurnCpi` | [burn](https://zkcompression.com/light-token/cookbook/burn) | [src](https://github.com/Lightprotocol/examples-light-token/blob/main/programs/anchor/basic-instructions/burn/src/lib.rs) | -| `TransferCheckedCpi` | [transfer-checked](https://zkcompression.com/light-token/cookbook/transfer-checked) | [src](https://github.com/Lightprotocol/examples-light-token/blob/main/programs/anchor/basic-instructions/transfer-checked/src/lib.rs) | -| `TransferInterfaceCpi` | [transfer-interface](https://zkcompression.com/light-token/cookbook/transfer-interface) | [src](https://github.com/Lightprotocol/examples-light-token/blob/main/programs/anchor/basic-instructions/transfer-interface/src/lib.rs) | -| `ApproveCpi` | [approve-revoke](https://zkcompression.com/light-token/cookbook/approve-revoke) | [src](https://github.com/Lightprotocol/examples-light-token/blob/main/programs/anchor/basic-instructions/approve/src/lib.rs) | -| `RevokeCpi` | [approve-revoke](https://zkcompression.com/light-token/cookbook/approve-revoke) | [src](https://github.com/Lightprotocol/examples-light-token/blob/main/programs/anchor/basic-instructions/revoke/src/lib.rs) | -| `FreezeCpi` | [freeze-thaw](https://zkcompression.com/light-token/cookbook/freeze-thaw) | [src](https://github.com/Lightprotocol/examples-light-token/blob/main/programs/anchor/basic-instructions/freeze/src/lib.rs) | -| `ThawCpi` | [freeze-thaw](https://zkcompression.com/light-token/cookbook/freeze-thaw) | [src](https://github.com/Lightprotocol/examples-light-token/blob/main/programs/anchor/basic-instructions/thaw/src/lib.rs) | -| `CloseAccountCpi` | [close-token-account](https://zkcompression.com/light-token/cookbook/close-token-account) | [src](https://github.com/Lightprotocol/examples-light-token/blob/main/programs/anchor/basic-instructions/close/src/lib.rs) | +| Example | Description | +| ---------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------ | +| [counter](https://github.com/Lightprotocol/program-examples/tree/main/counter) | Full lifecycle (create, update, close) in Anchor, native, and Pinocchio | +| [basic-operations](https://github.com/Lightprotocol/program-examples/tree/main/basic-operations) | Create, update, close, reinitialize, burn (Anchor and native) | +| [create-and-update](https://github.com/Lightprotocol/program-examples/tree/main/create-and-update) | Create and update with a single validity proof in one instruction | +| [account-comparison](https://github.com/Lightprotocol/program-examples/tree/main/account-comparison) | Compressed vs regular Solana accounts | +| [nullifier-program](https://github.com/Lightprotocol/nullifier-program) | Rent-free PDA for duplicate-execution prevention | +| [zk-id](https://github.com/Lightprotocol/program-examples/tree/main/zk/zk-id) | Identity verification with Groth16 proofs | ## SDK references @@ -273,13 +160,9 @@ CPI calls can be combined with existing and/or light macros. The API is a supers | ---------------------------- | -------------------------------------------------------------------------------- | | `light-sdk` | [docs.rs/light-sdk](https://docs.rs/light-sdk) | | `light-sdk-pinocchio` | [docs.rs/light-sdk-pinocchio](https://docs.rs/light-sdk-pinocchio) | -| `light-token` | [docs.rs/light-token](https://docs.rs/light-token) | -| `light-token-client` | [docs.rs/light-token-client](https://docs.rs/light-token-client) | | `light-compressed-token-sdk` | [docs.rs/light-compressed-token-sdk](https://docs.rs/light-compressed-token-sdk) | | `light-client` | [docs.rs/light-client](https://docs.rs/light-client) | | `light-program-test` | [docs.rs/light-program-test](https://docs.rs/light-program-test) | -| `light-account-pinocchio` | [docs.rs/light-account-pinocchio](https://docs.rs/light-account-pinocchio) | -| `light-token-pinocchio` | [docs.rs/light-token-pinocchio](https://docs.rs/light-token-pinocchio) | | `light-hasher` | [docs.rs/light-hasher](https://docs.rs/light-hasher) | | `light-account` | [docs.rs/light-account](https://docs.rs/light-account) | @@ -287,4 +170,3 @@ CPI calls can be combined with existing and/or light macros. The API is a supers > For additional documentation and navigation, see: [https://www.zkcompression.com/llms.txt](https://www.zkcompression.com/llms.txt) > For additional skills, see: [https://github.com/Lightprotocol/skills](https://github.com/Lightprotocol/skills) - diff --git a/snippets/accounts-list/close-account-infos-accounts-list.mdx b/snippets/accounts-list/close-account-infos-accounts-list.mdx deleted file mode 100644 index 927cbbaa..00000000 --- a/snippets/accounts-list/close-account-infos-accounts-list.mdx +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Token Program - -The light token program for CPI.
- Account - mutableThe light-token account to close.
- Destination - mutableReceives remaining lamports from the closed account.
- Owner - signer* - - Owner of the light-token account. -
- *Must be signer for `invoke()`. For `invoke_signed()`, program - signs via PDA seeds. -
- Rent Sponsor - mutable, optional - * light token program PDA that fronts rent exemption at creation. * - Claims rent when account compresses and/or is closed. -
diff --git a/snippets/accounts-list/light-mint-system-accounts-list.mdx b/snippets/accounts-list/light-mint-system-accounts-list.mdx deleted file mode 100644 index ad976a67..00000000 --- a/snippets/accounts-list/light-mint-system-accounts-list.mdx +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
AccountDescription
1Light System ProgramVerifies validity proofs and executes compressed account state transitions.
2CPI Authority PDAPDA that authorizes CPIs from the Light Token Program to the Light System Program.
3Registered Program PDAProves the Light Token Program is registered to use compression.
4Account Compression AuthoritySigns CPI calls from the Light System Program to the Account Compression Program.
5Account Compression ProgramWrites to state and address Merkle tree accounts.
6System ProgramSolana System Program.
\ No newline at end of file diff --git a/snippets/accounts-list/light-mint-to-light-token-accounts-list.mdx b/snippets/accounts-list/light-mint-to-light-token-accounts-list.mdx deleted file mode 100644 index e26aabef..00000000 --- a/snippets/accounts-list/light-mint-to-light-token-accounts-list.mdx +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
AccountTypeDescription
AuthoritysignerThe mint authority. Must match the light-mint's mint authority.
Payersigner, mutablePays transaction fees.
State TreemutableAccount of the state Merkle tree storing the light-mint.
Input QueuemutableAccount of the input queue associated with the state tree the light-mint is stored in. The existing hash of the light-mint is inserted to this queue to mark it as spent.
Output QueuemutableAccount of the output queue associated with the state tree the light-mint will be stored in. The updated hash of the light-mint is inserted to this queue.
light-token AccountsmutableDestination light-token Solana accounts to receive minted tokens.
System Accounts-See System Accounts List above.
CPI Contextoptional
(none for most)
Enables batched compressed account operations across multiple programs with a single validity proof. Set to `None` for most operations.
CPI Context Accountoptional, mutableOn-chain account that temporarily stores instruction data from multiple CPIs for combined execution. Set to `None` for most operations.
diff --git a/snippets/accounts-list/light-token-create-accounts-list-client.mdx b/snippets/accounts-list/light-token-create-accounts-list-client.mdx deleted file mode 100644 index c85d9193..00000000 --- a/snippets/accounts-list/light-token-create-accounts-list-client.mdx +++ /dev/null @@ -1,117 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ConstraintsDescription
0 - Payer - signer, mutable - - Pays transaction fee and compression incentive (prepaid epochs). -
- Does NOT pay rent exemption (fronted by `rent_sponsor`). -
1 - Token Account - signer*, mutable - - The light-token account being created. -
- *Must be signer for `invoke()`. - *For `invoke_signed()`, - program signs via PDA seeds. -
2 - Mint - - - The SPL or light-mint token mint. Defines which token this account - holds. -
3 - - - Compressible Config - - - -Protocol PDA that stores rent config and compression authorities.
4 - - - System Program - - - - - Solana System Program. Required for CPI to create the on-chain account. -
5 - - - Rent Sponsor - - - mutable - - light token program PDA that pays rent exemption at creation. -
- Claims rent when account compresses. -
6 - - - light token program - - - - - - Program to create and interact with light-mints, light-tokens and - compressed tokens. - Your program calls this to create the light-token - account. -
diff --git a/snippets/accounts-list/light-token-create-accounts-list.mdx b/snippets/accounts-list/light-token-create-accounts-list.mdx deleted file mode 100644 index 611fcf8b..00000000 --- a/snippets/accounts-list/light-token-create-accounts-list.mdx +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Payersigner, mutable - - Pays initial rent per epoch, transaction fee and compression incentive.
- - Does NOT pay rent exemption (paid by the light token program, `rent_sponsor`). -
light-token Accountsigner*, mutable - - The light-token account being created.
- - *Must be signer for `invoke()`. For `invoke_signed()`, program signs via PDA seeds. -
Mint-The SPL or light-mint token mint.
OwnerPubkeyThe owner of the token account. Controls transfers and other operations.
diff --git a/snippets/accounts-list/light-token-create-ata-accounts-list.mdx b/snippets/accounts-list/light-token-create-ata-accounts-list.mdx deleted file mode 100644 index d29eea47..00000000 --- a/snippets/accounts-list/light-token-create-ata-accounts-list.mdx +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Owner- - - The wallet that will own this light-ATA.
- - Used to derive the light-ATA address deterministically. -
Mint- - - The SPL or light-mint token mint.
- - Used to derive the light-ATA address deterministically. -
Payersigner, mutable - - Pays initial rent per epoch, transaction fee and compression incentive.
- - Does NOT pay rent exemption (paid by the light token program, `rent_sponsor`). -
light-ATA Accountmutable - - The light-ATA being created.
- - Address is derived from `[owner, light_token_program_id, mint]`. -
System Program-Solana System Program. Required for CPI to create the on-chain account.
Bumpu8The PDA bump seed for the light-ATA address derivation.
Idempotentbool - - When `true`, silently succeeds if account already exists.
- - When `false`, fails if account already exists. -
diff --git a/snippets/accounts-list/transfer-interface-accounts-list-light-token-1.mdx b/snippets/accounts-list/transfer-interface-accounts-list-light-token-1.mdx deleted file mode 100644 index 04be05cb..00000000 --- a/snippets/accounts-list/transfer-interface-accounts-list-light-token-1.mdx +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Source Account - mutableThe source account (SPL token account or light-token account).
- Destination Account - mutable - The destination account (SPL token account or light-token account). -
- Authority - signer* - - Owner of the source account. -
- *Must be signer for `invoke()`. For `invoke_signed()`, program - signs via PDA seeds. -
- Payer - signer, mutablePays transaction fees.
- Light Token Program Authority - -The light token program authority PDA.
diff --git a/snippets/accounts-list/transfer-interface-accounts-list-spl-2.mdx b/snippets/accounts-list/transfer-interface-accounts-list-spl-2.mdx index 4a2b17ea..f3081661 100644 --- a/snippets/accounts-list/transfer-interface-accounts-list-spl-2.mdx +++ b/snippets/accounts-list/transfer-interface-accounts-list-spl-2.mdx @@ -24,7 +24,7 @@ Interface PDA mutable - Interface PDA for SPL ↔ light-token transfers. + Interface PDA for SPL ↔ compressed token transfers. diff --git a/snippets/ai-prompts/all-prompts.mdx b/snippets/ai-prompts/all-prompts.mdx index 55b3b25a..66f9f4c0 100644 --- a/snippets/ai-prompts/all-prompts.mdx +++ b/snippets/ai-prompts/all-prompts.mdx @@ -1,10 +1,3 @@ -import LightTokenRecipes from "/snippets/ai-prompts/light-token-recipes.mdx"; - -{/* anchor-programs */} -import DefiAnchor from "/snippets/ai-prompts/anchor-programs/defi-anchor.mdx"; -import DefiPinocchio from "/snippets/ai-prompts/defi/defi-pinocchio.mdx"; -import LightPda from "/snippets/ai-prompts/program-cookbook/light-pda.mdx"; - {/* cpi-programs */} import CpiCreate from "/snippets/ai-prompts/cpi-programs/create.mdx"; import CpiUpdate from "/snippets/ai-prompts/cpi-programs/update.mdx"; @@ -13,131 +6,55 @@ import CpiReinitialize from "/snippets/ai-prompts/cpi-programs/reinitialize.mdx" import CpiBurn from "/snippets/ai-prompts/cpi-programs/burn.mdx"; import CpiClientGuide from "/snippets/ai-prompts/cpi-programs/client-guide.mdx"; -{/* defi - routers */} -import Routers from "/snippets/ai-prompts/defi/routers.mdx"; - -{/* streaming */} -import StreamingMints from "/snippets/ai-prompts/streaming/mints.mdx"; -import StreamingTokens from "/snippets/ai-prompts/streaming/tokens.mdx"; - {/* toolkits */} -import Payments from "/snippets/ai-prompts/toolkits/payments.mdx"; -import WalletsIntegration from "/snippets/ai-prompts/toolkits/wallets.mdx"; import Nullifiers from "/snippets/ai-prompts/toolkits/nullifiers.mdx"; import Airdrop from "/snippets/ai-prompts/toolkits/airdrop.mdx"; -{/* wallets */} -import WalletAdapter from "/snippets/ai-prompts/wallets/wallet-adapter.mdx"; -import Privy from "/snippets/ai-prompts/wallets/privy.mdx"; -import GaslessTransactions from "/snippets/ai-prompts/wallets/gasless-transactions.mdx"; - {/* migration */} import V1ToV2Migration from "/snippets/ai-prompts/v1-to-v2-migration.mdx"; -## Stablecoin Payments - - -Copy the prompt below or view the [guide](/light-token/payments/overview). - - - - -Copy the prompt below or view the [guide](/light-token/wallets/wallet-adapter). - - - - -Copy the prompt below or view the [guide](/light-token/wallets/privy). - - - - -Copy the prompt below or view the [guide](/light-token/wallets/gasless-transactions). - - - - -Copy the prompt below or view the [guide](/pda/compressed-pdas/nullifier-pda). - - - -## Light Token Recipes - - - ## Token Distribution -Copy the prompt below or view the [guide](/token-distribution). +Copy the prompt below or view the [guide](/compressed-tokens/token-distribution). -## DeFi - - -Copy the prompt below or view the [guide](/light-token/defi/programs). - - - - -Copy the prompt below or view the [guide](/light-token/defi/programs-pinocchio). - - - - -Copy the prompt below or view the [guide](/light-token/defi/routers). - - - -## Data Streaming - - -Copy the prompt below or view the [guide](/light-token/streaming/mints). - - - - -Copy the prompt below or view the [guide](/light-token/streaming/tokens). - - - -## Light-PDA +## Compressed PDA - -Copy the prompt below or view the [guide](/pda/light-pda/overview). - + +Copy the prompt below or view the [guide](/compressed-pdas/nullifier-pda). + -## Compressed PDA - -Copy the prompt below or view the [guide](/pda/compressed-pdas/guides/client-guide). +Copy the prompt below or view the [guide](/compressed-pdas/guides/client-guide). -Copy the prompt below or view the [guide](/pda/compressed-pdas/guides/how-to-create-compressed-accounts). +Copy the prompt below or view the [guide](/compressed-pdas/guides/how-to-create-compressed-accounts). -Copy the prompt below or view the [guide](/pda/compressed-pdas/guides/how-to-update-compressed-accounts). +Copy the prompt below or view the [guide](/compressed-pdas/guides/how-to-update-compressed-accounts). -Copy the prompt below or view the [guide](/pda/compressed-pdas/guides/how-to-close-compressed-accounts). +Copy the prompt below or view the [guide](/compressed-pdas/guides/how-to-close-compressed-accounts). -Copy the prompt below or view the [guide](/pda/compressed-pdas/guides/how-to-reinitialize-compressed-accounts). +Copy the prompt below or view the [guide](/compressed-pdas/guides/how-to-reinitialize-compressed-accounts). -Copy the prompt below or view the [guide](/pda/compressed-pdas/guides/how-to-burn-compressed-accounts). +Copy the prompt below or view the [guide](/compressed-pdas/guides/how-to-burn-compressed-accounts). @@ -145,4 +62,3 @@ Copy the prompt below or view the [guide](/pda/compressed-pdas/guides/how-to-bur Copy the prompt below or view the [guide](/resources/migration-v1-to-v2). - diff --git a/snippets/ai-prompts/anchor-program-template.mdx b/snippets/ai-prompts/anchor-program-template.mdx deleted file mode 100644 index b4949b47..00000000 --- a/snippets/ai-prompts/anchor-program-template.mdx +++ /dev/null @@ -1,57 +0,0 @@ -```text ---- -description: {{OPERATION_DESCRIPTION}} -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## {{OPERATION_DESCRIPTION}} - -Context: -- Guide: https://zkcompression.com/{{PAGE_PATH}} -- Skills and resources index: https://zkcompression.com/skill.md -- Crates: {{CRATES}} -{{EXTRA_REFS}} - -Key macros/APIs: {{KEY_MACROS}} - -### 1. Index project -- Grep `{{INDEX_GREP}}` across src/ -- Glob `**/*.rs` and `**/Cargo.toml` for project structure -- Identify: existing program module, account structs, PDA seeds, token accounts, init instructions -- Read Cargo.toml — note existing dependencies and framework version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new program from scratch, migrate existing program to rent-free, add rent-free accounts to specific instructions) -- AskUserQuestion: which account types need to be rent-free? (PDAs, token accounts, ATAs, mints) -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan -- Follow the guide's step order: {{STEP_ORDER}} -- Identify which existing structs need changes (CompressionInfo field, LightAccount derive, etc.) -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash `cargo add {{DEPS}}` -- Follow the guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash `{{BUILD_CMD}}` -- Bash `{{TEST_CMD}}` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work -``` diff --git a/snippets/ai-prompts/anchor-programs/defi-anchor.mdx b/snippets/ai-prompts/anchor-programs/defi-anchor.mdx deleted file mode 100644 index 2f53d874..00000000 --- a/snippets/ai-prompts/anchor-programs/defi-anchor.mdx +++ /dev/null @@ -1,117 +0,0 @@ - -{`--- -description: Add rent-free accounts to an Anchor DeFi program -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Add rent-free accounts to an Anchor DeFi program - -Context: -- Guide: https://zkcompression.com/light-token/defi/programs -- Skills and resources index: https://zkcompression.com/skill.md -- Dedicated skill: https://github.com/Lightprotocol/skills/tree/main/skills/light-sdk -- Crates: light-sdk (features: anchor, v2, cpi-context), light-sdk-macros, light-token (features: anchor), light-anchor-spl -- AMM reference: https://github.com/Lightprotocol/cp-swap-reference - -Key macros/APIs: #[light_program], LightAccount, LightAccounts, #[light_account(init)], CompressionInfo - -### 1. Index project -- Grep \`#\[program\]|anchor_lang|Account<|Accounts|InitSpace|seeds|init|payer\` across src/ -- Glob \`**/*.rs\` and \`**/Cargo.toml\` for project structure -- Identify: existing program module, account structs, PDA seeds, token accounts, init instructions -- Read Cargo.toml — note existing dependencies and framework version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new program from scratch, migrate existing program to rent-free, add rent-free accounts to specific instructions) -- AskUserQuestion: which account types need to be rent-free? (PDAs, token accounts, ATAs, mints) -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan -- Follow the guide's step order: Dependencies → State Struct → Program Module → Accounts Struct → Instructions -- Identify which existing structs need changes (CompressionInfo field, LightAccount derive, etc.) -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash \`cargo add light-sdk@0.23 --features anchor,v2,cpi-context\` and \`cargo add light-sdk-macros@0.23\` and \`cargo add light-token@0.23 --features anchor\` and \`cargo add light-anchor-spl@0.31\` -- Follow the guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash \`anchor build\` -- Bash \`anchor test\` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work`} - - -```text ---- -description: Add rent-free accounts to an Anchor DeFi program -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Add rent-free accounts to an Anchor DeFi program - -Context: -- Guide: https://zkcompression.com/light-token/defi/programs -- Skills and resources index: https://zkcompression.com/skill.md -- Dedicated skill: https://github.com/Lightprotocol/skills/tree/main/skills/light-sdk -- Crates: light-sdk (features: anchor, v2, cpi-context), light-sdk-macros, light-token (features: anchor), light-anchor-spl -- AMM reference: https://github.com/Lightprotocol/cp-swap-reference - -Key macros/APIs: #[light_program], LightAccount, LightAccounts, #[light_account(init)], CompressionInfo - -### 1. Index project -- Grep `#\[program\]|anchor_lang|Account<|Accounts|InitSpace|seeds|init|payer` across src/ -- Glob `**/*.rs` and `**/Cargo.toml` for project structure -- Identify: existing program module, account structs, PDA seeds, token accounts, init instructions -- Read Cargo.toml — note existing dependencies and framework version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new program from scratch, migrate existing program to rent-free, add rent-free accounts to specific instructions) -- AskUserQuestion: which account types need to be rent-free? (PDAs, token accounts, ATAs, mints) -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan -- Follow the guide's step order: Dependencies → State Struct → Program Module → Accounts Struct → Instructions -- Identify which existing structs need changes (CompressionInfo field, LightAccount derive, etc.) -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash `cargo add light-sdk@0.23 --features anchor,v2,cpi-context` and `cargo add light-sdk-macros@0.23` and `cargo add light-token@0.23 --features anchor` and `cargo add light-anchor-spl@0.31` -- Follow the guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash `anchor build` -- Bash `anchor test` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work -``` diff --git a/snippets/ai-prompts/cpi-program-template.mdx b/snippets/ai-prompts/cpi-program-template.mdx deleted file mode 100644 index 4df03bd6..00000000 --- a/snippets/ai-prompts/cpi-program-template.mdx +++ /dev/null @@ -1,57 +0,0 @@ -```text ---- -description: {{OPERATION_DESCRIPTION}} -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## {{OPERATION_DESCRIPTION}} - -Context: -- Guide: https://zkcompression.com/pda/compressed-pdas/guides/{{PAGE_SLUG}} -- Skills and resources index: https://zkcompression.com/skill.md -- Crate: light-sdk (LightAccount, CpiAccounts, LightSystemProgramCpi, derive_light_cpi_signer!) -{{EXTRA_REFS}} - -Key SDK API: {{KEY_API}} - -### 1. Index project -- Grep `declare_id|#\[program\]|entrypoint!|Pubkey|AccountInfo{{EXTRA_GREP}}` across src/ -- Glob `**/*.rs` and `**/Cargo.toml` for project structure -- Identify: program ID, existing instructions, account structs, framework (Anchor or native) -- Read Cargo.toml — note existing dependencies and Solana SDK version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — review both Anchor and Native Rust code samples -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new program from scratch, add {{OP_SHORT}} to existing program, migrate from regular accounts) -- AskUserQuestion: Anchor or Native Rust framework? -- AskUserQuestion: does the program already have compressed account instructions, or is this the first one? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Follow the guide's step order: Dependencies → Constants → Account Struct → Instruction Data → {{OP_SPECIFIC_STEPS}} → Light System Program CPI -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps: Bash `cargo add light-sdk@0.23` (add `anchor_lang@0.31` for Anchor or `solana-program@2.2` + `borsh@0.10` for Native Rust) -- Follow the guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash `cargo build-sbf` or `anchor build` -- Bash `cargo test-sbf` or `anchor test` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work -``` diff --git a/snippets/ai-prompts/cpi-programs/burn.mdx b/snippets/ai-prompts/cpi-programs/burn.mdx index 6daa1747..37551c8d 100644 --- a/snippets/ai-prompts/cpi-programs/burn.mdx +++ b/snippets/ai-prompts/cpi-programs/burn.mdx @@ -7,7 +7,7 @@ allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, T ## Build a program that permanently burns compressed accounts Context: -- Guide: https://zkcompression.com/pda/compressed-pdas/guides/how-to-burn-compressed-accounts +- Guide: https://zkcompression.com/compressed-pdas/guides/how-to-burn-compressed-accounts - Skills and resources index: https://zkcompression.com/skill.md - Crate: light-sdk (LightAccount, CpiAccounts, LightSystemProgramCpi, derive_light_cpi_signer!) - Anchor example: https://github.com/Lightprotocol/program-examples/tree/main/basic-operations/anchor/burn @@ -66,7 +66,7 @@ allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, T ## Build a program that permanently burns compressed accounts Context: -- Guide: https://zkcompression.com/pda/compressed-pdas/guides/how-to-burn-compressed-accounts +- Guide: https://zkcompression.com/compressed-pdas/guides/how-to-burn-compressed-accounts - Skills and resources index: https://zkcompression.com/skill.md - Crate: light-sdk (LightAccount, CpiAccounts, LightSystemProgramCpi, derive_light_cpi_signer!) - Anchor example: https://github.com/Lightprotocol/program-examples/tree/main/basic-operations/anchor/burn diff --git a/snippets/ai-prompts/cpi-programs/client-guide.mdx b/snippets/ai-prompts/cpi-programs/client-guide.mdx index cd8b2816..508a58c6 100644 --- a/snippets/ai-prompts/cpi-programs/client-guide.mdx +++ b/snippets/ai-prompts/cpi-programs/client-guide.mdx @@ -7,7 +7,7 @@ allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, T ## Write client code to interact with compressed PDA programs Context: -- Guide: https://zkcompression.com/pda/compressed-pdas/guides/client-guide +- Guide: https://zkcompression.com/compressed-pdas/guides/client-guide - Skills and resources index: https://zkcompression.com/skill.md - TS packages: @lightprotocol/stateless.js, @lightprotocol/compressed-token, @solana/web3.js - Rust crates: light-client, light-sdk @@ -71,7 +71,7 @@ allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, T ## Write client code to interact with compressed PDA programs Context: -- Guide: https://zkcompression.com/pda/compressed-pdas/guides/client-guide +- Guide: https://zkcompression.com/compressed-pdas/guides/client-guide - Skills and resources index: https://zkcompression.com/skill.md - TS packages: @lightprotocol/stateless.js, @lightprotocol/compressed-token, @solana/web3.js - Rust crates: light-client, light-sdk diff --git a/snippets/ai-prompts/cpi-programs/close.mdx b/snippets/ai-prompts/cpi-programs/close.mdx index a18f8371..99a443a0 100644 --- a/snippets/ai-prompts/cpi-programs/close.mdx +++ b/snippets/ai-prompts/cpi-programs/close.mdx @@ -7,7 +7,7 @@ allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, T ## Build a program that closes compressed accounts Context: -- Guide: https://zkcompression.com/pda/compressed-pdas/guides/how-to-close-compressed-accounts +- Guide: https://zkcompression.com/compressed-pdas/guides/how-to-close-compressed-accounts - Skills and resources index: https://zkcompression.com/skill.md - Crate: light-sdk (LightAccount, CpiAccounts, LightSystemProgramCpi, derive_light_cpi_signer!) - Anchor example: https://github.com/Lightprotocol/program-examples/tree/main/basic-operations/anchor/close @@ -66,7 +66,7 @@ allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, T ## Build a program that closes compressed accounts Context: -- Guide: https://zkcompression.com/pda/compressed-pdas/guides/how-to-close-compressed-accounts +- Guide: https://zkcompression.com/compressed-pdas/guides/how-to-close-compressed-accounts - Skills and resources index: https://zkcompression.com/skill.md - Crate: light-sdk (LightAccount, CpiAccounts, LightSystemProgramCpi, derive_light_cpi_signer!) - Anchor example: https://github.com/Lightprotocol/program-examples/tree/main/basic-operations/anchor/close diff --git a/snippets/ai-prompts/cpi-programs/create.mdx b/snippets/ai-prompts/cpi-programs/create.mdx index dd404d43..69e959c9 100644 --- a/snippets/ai-prompts/cpi-programs/create.mdx +++ b/snippets/ai-prompts/cpi-programs/create.mdx @@ -7,7 +7,7 @@ allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, T ## Build a program that creates compressed accounts with addresses Context: -- Guide: https://zkcompression.com/pda/compressed-pdas/guides/how-to-create-compressed-accounts +- Guide: https://zkcompression.com/compressed-pdas/guides/how-to-create-compressed-accounts - Skills and resources index: https://zkcompression.com/skill.md - Crate: light-sdk (LightAccount, CpiAccounts, LightSystemProgramCpi, derive_light_cpi_signer!) - Anchor example: https://github.com/Lightprotocol/program-examples/tree/main/basic-operations/anchor/create @@ -66,7 +66,7 @@ allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, T ## Build a program that creates compressed accounts with addresses Context: -- Guide: https://zkcompression.com/pda/compressed-pdas/guides/how-to-create-compressed-accounts +- Guide: https://zkcompression.com/compressed-pdas/guides/how-to-create-compressed-accounts - Skills and resources index: https://zkcompression.com/skill.md - Crate: light-sdk (LightAccount, CpiAccounts, LightSystemProgramCpi, derive_light_cpi_signer!) - Anchor example: https://github.com/Lightprotocol/program-examples/tree/main/basic-operations/anchor/create diff --git a/snippets/ai-prompts/cpi-programs/reinitialize.mdx b/snippets/ai-prompts/cpi-programs/reinitialize.mdx index 5c727c26..19e0d0fa 100644 --- a/snippets/ai-prompts/cpi-programs/reinitialize.mdx +++ b/snippets/ai-prompts/cpi-programs/reinitialize.mdx @@ -7,7 +7,7 @@ allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, T ## Build a program that reinitializes closed compressed accounts Context: -- Guide: https://zkcompression.com/pda/compressed-pdas/guides/how-to-reinitialize-compressed-accounts +- Guide: https://zkcompression.com/compressed-pdas/guides/how-to-reinitialize-compressed-accounts - Skills and resources index: https://zkcompression.com/skill.md - Crate: light-sdk (LightAccount, CpiAccounts, LightSystemProgramCpi, derive_light_cpi_signer!) - Anchor example: https://github.com/Lightprotocol/program-examples/tree/main/basic-operations/anchor/reinit @@ -66,7 +66,7 @@ allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, T ## Build a program that reinitializes closed compressed accounts Context: -- Guide: https://zkcompression.com/pda/compressed-pdas/guides/how-to-reinitialize-compressed-accounts +- Guide: https://zkcompression.com/compressed-pdas/guides/how-to-reinitialize-compressed-accounts - Skills and resources index: https://zkcompression.com/skill.md - Crate: light-sdk (LightAccount, CpiAccounts, LightSystemProgramCpi, derive_light_cpi_signer!) - Anchor example: https://github.com/Lightprotocol/program-examples/tree/main/basic-operations/anchor/reinit diff --git a/snippets/ai-prompts/cpi-programs/update.mdx b/snippets/ai-prompts/cpi-programs/update.mdx index 3607f852..0378936c 100644 --- a/snippets/ai-prompts/cpi-programs/update.mdx +++ b/snippets/ai-prompts/cpi-programs/update.mdx @@ -7,7 +7,7 @@ allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, T ## Build a program that updates compressed accounts Context: -- Guide: https://zkcompression.com/pda/compressed-pdas/guides/how-to-update-compressed-accounts +- Guide: https://zkcompression.com/compressed-pdas/guides/how-to-update-compressed-accounts - Skills and resources index: https://zkcompression.com/skill.md - Crate: light-sdk (LightAccount, CpiAccounts, LightSystemProgramCpi, derive_light_cpi_signer!) - Anchor example: https://github.com/Lightprotocol/program-examples/tree/main/basic-operations/anchor/update @@ -66,7 +66,7 @@ allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, T ## Build a program that updates compressed accounts Context: -- Guide: https://zkcompression.com/pda/compressed-pdas/guides/how-to-update-compressed-accounts +- Guide: https://zkcompression.com/compressed-pdas/guides/how-to-update-compressed-accounts - Skills and resources index: https://zkcompression.com/skill.md - Crate: light-sdk (LightAccount, CpiAccounts, LightSystemProgramCpi, derive_light_cpi_signer!) - Anchor example: https://github.com/Lightprotocol/program-examples/tree/main/basic-operations/anchor/update diff --git a/snippets/ai-prompts/defi/defi-anchor.mdx b/snippets/ai-prompts/defi/defi-anchor.mdx deleted file mode 100644 index 6209f4d3..00000000 --- a/snippets/ai-prompts/defi/defi-anchor.mdx +++ /dev/null @@ -1,217 +0,0 @@ - -{`--- -description: Add rent-free accounts to an Anchor DeFi program -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Add rent-free accounts to an Anchor DeFi program - -Context: -- Crates: light-sdk (features: anchor, v2, cpi-context), light-sdk-macros, light-token (features: anchor), light-anchor-spl -- Key macros/APIs: #[light_program], LightAccount, LightAccounts, #[light_account(init)], CompressionInfo - -### References -- Guide: https://zkcompression.com/light-token/defi/programs -- Basic AMM reference: https://github.com/Lightprotocol/cp-swap-reference -- Production examples (escrow, fundraiser, swap with all safety patterns): https://github.com/Lightprotocol/examples-light-token -- Skills and resources index: https://zkcompression.com/skill.md -- Dedicated skill: https://github.com/Lightprotocol/skills/tree/main/skills/light-sdk - -### 1. Index project -- Grep \`#\[program\]|anchor_lang|Account<|Accounts|InitSpace|seeds|init|payer\` across src/ -- Glob \`**/*.rs\` and \`**/Cargo.toml\` for project structure -- Identify: existing program module, account structs, PDA seeds, token accounts, init instructions -- Read Cargo.toml — note existing dependencies and framework version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- Read the production examples repo for correct patterns (especially token-swap/src/) -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new program from scratch, migrate existing program to rent-free, add rent-free accounts to specific instructions) -- AskUserQuestion: which account types need to be rent-free? (PDAs, token accounts, ATAs, mints) -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan -- Follow the guide's step order: Dependencies → State Struct → Program Module → Accounts Struct → Instructions -- Identify which existing structs need changes (CompressionInfo field, LightAccount derive, etc.) -- The plan and all generated code MUST satisfy the Code safety requirements below -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash \`cargo add light-sdk --features anchor,v2,cpi-context\` and \`cargo add light-sdk-macros\` and \`cargo add light-token --features anchor\` and \`cargo add light-anchor-spl\` -- Follow the guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash \`anchor build\` -- Bash \`anchor test\` if tests exist -- Grep \`.unwrap()\` in src/ — flag any unwrap on arithmetic (checked_mul, checked_div, etc.) -- Grep \`pub.*vault.*Pubkey|pub.*decimals.*u8\` in state structs — flag stored derivable data -- Verify all TransferInterfaceCpi calls include \`mint\` as 8th argument -- TaskUpdate to mark complete - -### Code safety requirements - -Violations are bugs. All generated code must satisfy these constraints. - -**Arithmetic safety:** -- All token math must use \`checked_mul\`/\`checked_div\`/\`checked_sub\`/\`checked_add\` -- Use \`u128\` for intermediate products to prevent silent overflow: \`(a as u128).checked_mul(b as u128).ok_or(Error::Overflow)? as u64\` -- Never \`.unwrap()\` on checked math — always \`.ok_or(CustomError::Variant)?\` -- Use \`I64F64\` (from \`fixed\` crate) for ratio/proportion calculations with \`.ok_or()\` error handling - -**Error handling:** -- Define \`#[error_code] pub enum\` with descriptive \`#[msg("...")]\` variants -- At minimum for DeFi: \`Overflow\`, \`Underflow\`, \`InvalidFee\`, \`DepositTooSmall\`, \`OutputTooSmall\`, \`InvariantViolated\` -- Propagate errors with \`?\` — never discard error context with \`map_err(|_| unrelated_error)\` - -**Account validation:** -- Vault accounts: validate with \`seeds = [SEED, pool.key().as_ref()], bump\` — not stored-pubkey constraints -- Pool accounts: use \`has_one = mint_a, has_one = mint_b\` to validate mints match the pool -- Mint accounts: use \`mint::token_program = token_program\` to validate program ownership -- Use Anchor declarative \`init\` for mint/account creation — avoid manual \`create_account\` + \`initialize_mint2\` CPI - -**Minimal state:** -- Do not store derivable addresses (vault pubkeys, mint addresses) — re-derive from PDA seeds -- Read balances from vault accounts via \`get_token_account_balance()\` — do not store pool balances in state -- Only store what cannot be derived: AMM config, mint pubkeys, LP supply (if using Light LP mints) - -**Transfer routing (TransferInterfaceCpi):** -- Constructor takes 9 args: \`(amount, decimals, source, destination, authority, fee_payer, light_token_cpi_authority, mint, system_program)\` -- Use \`Option\` for SPL interface PDA accounts -- Conditionally call \`.with_spl_interface(...)\` when \`spl_interface_pda.is_some()\` -- This enables cross-standard transfers (SPL/Token 2022 source to Light destination) - -**Authority pattern:** -- Single authority PDA owns all vaults: \`seeds = [AUTHORITY_SEED], bump\` -- Export constants from \`lib.rs\`: \`pub use constants::AUTHORITY_SEED;\` -- Use \`invoke_signed(&[authority_seeds])\` for vault operations (transfer, burn, mint_to) - -**DeFi safety (AMM-specific):** -- Invariant check after swap: \`new_a * new_b >= old_a * old_b\` (computed in u128) -- Minimum liquidity burn on first deposit (Uniswap v2 pattern, e.g. 100 tokens) -- Ratio-based deposit enforcement: maintain pool ratio for non-initial deposits -- Basis-point fees with max validation: \`constraint = fee < 10000 @ SwapError::InvalidFee\` - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work`} - - -```text ---- -description: Add rent-free accounts to an Anchor DeFi program -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Add rent-free accounts to an Anchor DeFi program - -Context: -- Crates: light-sdk (features: anchor, v2, cpi-context), light-sdk-macros, light-token (features: anchor), light-anchor-spl -- Key macros/APIs: #[light_program], LightAccount, LightAccounts, #[light_account(init)], CompressionInfo - -### References -- Guide: https://zkcompression.com/light-token/defi/programs -- Basic AMM reference: https://github.com/Lightprotocol/cp-swap-reference -- Production examples (escrow, fundraiser, swap with all safety patterns): https://github.com/Lightprotocol/examples-light-token -- Skills and resources index: https://zkcompression.com/skill.md -- Dedicated skill: https://github.com/Lightprotocol/skills/tree/main/skills/light-sdk - -### 1. Index project -- Grep `#\[program\]|anchor_lang|Account<|Accounts|InitSpace|seeds|init|payer` across src/ -- Glob `**/*.rs` and `**/Cargo.toml` for project structure -- Identify: existing program module, account structs, PDA seeds, token accounts, init instructions -- Read Cargo.toml — note existing dependencies and framework version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- Read the production examples repo for correct patterns (especially token-swap/src/) -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new program from scratch, migrate existing program to rent-free, add rent-free accounts to specific instructions) -- AskUserQuestion: which account types need to be rent-free? (PDAs, token accounts, ATAs, mints) -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan -- Follow the guide's step order: Dependencies → State Struct → Program Module → Accounts Struct → Instructions -- Identify which existing structs need changes (CompressionInfo field, LightAccount derive, etc.) -- The plan and all generated code MUST satisfy the Code safety requirements below -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash `cargo add light-sdk --features anchor,v2,cpi-context` and `cargo add light-sdk-macros` and `cargo add light-token --features anchor` and `cargo add light-anchor-spl` -- Follow the guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash `anchor build` -- Bash `anchor test` if tests exist -- Grep `.unwrap()` in src/ — flag any unwrap on arithmetic (checked_mul, checked_div, etc.) -- Grep `pub.*vault.*Pubkey|pub.*decimals.*u8` in state structs — flag stored derivable data -- Verify all TransferInterfaceCpi calls include `mint` as 8th argument -- TaskUpdate to mark complete - -### Code safety requirements - -Violations are bugs. All generated code must satisfy these constraints. - -**Arithmetic safety:** -- All token math must use `checked_mul`/`checked_div`/`checked_sub`/`checked_add` -- Use `u128` for intermediate products to prevent silent overflow: `(a as u128).checked_mul(b as u128).ok_or(Error::Overflow)? as u64` -- Never `.unwrap()` on checked math — always `.ok_or(CustomError::Variant)?` -- Use `I64F64` (from `fixed` crate) for ratio/proportion calculations with `.ok_or()` error handling - -**Error handling:** -- Define `#[error_code] pub enum` with descriptive `#[msg("...")]` variants -- At minimum for DeFi: `Overflow`, `Underflow`, `InvalidFee`, `DepositTooSmall`, `OutputTooSmall`, `InvariantViolated` -- Propagate errors with `?` — never discard error context with `map_err(|_| unrelated_error)` - -**Account validation:** -- Vault accounts: validate with `seeds = [SEED, pool.key().as_ref()], bump` — not stored-pubkey constraints -- Pool accounts: use `has_one = mint_a, has_one = mint_b` to validate mints match the pool -- Mint accounts: use `mint::token_program = token_program` to validate program ownership -- Use Anchor declarative `init` for mint/account creation — avoid manual `create_account` + `initialize_mint2` CPI - -**Minimal state:** -- Do not store derivable addresses (vault pubkeys, mint addresses) — re-derive from PDA seeds -- Read balances from vault accounts via `get_token_account_balance()` — do not store pool balances in state -- Only store what cannot be derived: AMM config, mint pubkeys, LP supply (if using Light LP mints) - -**Transfer routing (TransferInterfaceCpi):** -- Constructor takes 9 args: `(amount, decimals, source, destination, authority, fee_payer, light_token_cpi_authority, mint, system_program)` -- Use `Option` for SPL interface PDA accounts -- Conditionally call `.with_spl_interface(...)` when `spl_interface_pda.is_some()` -- This enables cross-standard transfers (SPL/Token 2022 source to Light destination) - -**Authority pattern:** -- Single authority PDA owns all vaults: `seeds = [AUTHORITY_SEED], bump` -- Export constants from `lib.rs`: `pub use constants::AUTHORITY_SEED;` -- Use `invoke_signed(&[authority_seeds])` for vault operations (transfer, burn, mint_to) - -**DeFi safety (AMM-specific):** -- Invariant check after swap: `new_a * new_b >= old_a * old_b` (computed in u128) -- Minimum liquidity burn on first deposit (Uniswap v2 pattern, e.g. 100 tokens) -- Ratio-based deposit enforcement: maintain pool ratio for non-initial deposits -- Basis-point fees with max validation: `constraint = fee < 10000 @ SwapError::InvalidFee` - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work -``` diff --git a/snippets/ai-prompts/defi/defi-pinocchio.mdx b/snippets/ai-prompts/defi/defi-pinocchio.mdx deleted file mode 100644 index 0dbb4eaa..00000000 --- a/snippets/ai-prompts/defi/defi-pinocchio.mdx +++ /dev/null @@ -1,117 +0,0 @@ - -{`--- -description: Add rent-free accounts to a Pinocchio DeFi program -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Add rent-free accounts to a Pinocchio DeFi program - -Context: -- Guide: https://zkcompression.com/light-token/defi/programs-pinocchio -- Skills and resources index: https://zkcompression.com/skill.md -- Dedicated skill: https://github.com/Lightprotocol/skills/tree/main/skills/light-sdk -- Crates: light-account-pinocchio (features: token, std), light-token-pinocchio, pinocchio -- Swap reference: https://github.com/Lightprotocol/examples-light-token/tree/simplify-trait/pinocchio/swap - -Key macros/APIs: LightPinocchioAccount, LightProgramPinocchio, CreateTokenAccountCpi, derive_light_cpi_signer! - -### 1. Index project -- Grep \`pinocchio|entrypoint!|ProgramError|AccountInfo|process_instruction\` across src/ -- Glob \`**/*.rs\` and \`**/Cargo.toml\` for project structure -- Identify: existing program module, account structs, PDA seeds, token accounts, init instructions -- Read Cargo.toml — note existing dependencies and framework version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new program from scratch, migrate existing program to rent-free, add rent-free accounts to specific instructions) -- AskUserQuestion: which account types need to be rent-free? (PDAs, token accounts, ATAs, mints) -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan -- Follow the guide's step order: Dependencies → State Struct → Program Enum → Entrypoint → Init Handler -- Identify which existing structs need changes (CompressionInfo field, LightPinocchioAccount derive, etc.) -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash \`cargo add light-account-pinocchio@0.23 --features token,std\` and \`cargo add light-token-pinocchio@0.23\` and \`cargo add pinocchio@0.9\` -- Follow the guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash \`cargo build-sbf\` -- Bash \`cargo test-sbf\` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work`} - - -```text ---- -description: Add rent-free accounts to a Pinocchio DeFi program -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Add rent-free accounts to a Pinocchio DeFi program - -Context: -- Guide: https://zkcompression.com/light-token/defi/programs-pinocchio -- Skills and resources index: https://zkcompression.com/skill.md -- Dedicated skill: https://github.com/Lightprotocol/skills/tree/main/skills/light-sdk -- Crates: light-account-pinocchio (features: token, std), light-token-pinocchio, pinocchio -- Swap reference: https://github.com/Lightprotocol/examples-light-token/tree/simplify-trait/pinocchio/swap - -Key macros/APIs: LightPinocchioAccount, LightProgramPinocchio, CreateTokenAccountCpi, derive_light_cpi_signer! - -### 1. Index project -- Grep `pinocchio|entrypoint!|ProgramError|AccountInfo|process_instruction` across src/ -- Glob `**/*.rs` and `**/Cargo.toml` for project structure -- Identify: existing program module, account structs, PDA seeds, token accounts, init instructions -- Read Cargo.toml — note existing dependencies and framework version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new program from scratch, migrate existing program to rent-free, add rent-free accounts to specific instructions) -- AskUserQuestion: which account types need to be rent-free? (PDAs, token accounts, ATAs, mints) -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan -- Follow the guide's step order: Dependencies → State Struct → Program Enum → Entrypoint → Init Handler -- Identify which existing structs need changes (CompressionInfo field, LightPinocchioAccount derive, etc.) -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash `cargo add light-account-pinocchio@0.23 --features token,std` and `cargo add light-token-pinocchio@0.23` and `cargo add pinocchio@0.9` -- Follow the guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash `cargo build-sbf` -- Bash `cargo test-sbf` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work -``` diff --git a/snippets/ai-prompts/defi/routers.mdx b/snippets/ai-prompts/defi/routers.mdx deleted file mode 100644 index 1d7cd659..00000000 --- a/snippets/ai-prompts/defi/routers.mdx +++ /dev/null @@ -1,125 +0,0 @@ - -{`--- -description: Integrate rent-free AMM markets into a router or aggregator -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Integrate rent-free AMM markets into a router or aggregator - -Context: -- Guide: https://zkcompression.com/light-token/defi/routers -- Skills and resources index: https://zkcompression.com/skill.md -- Dedicated skill: https://github.com/Lightprotocol/skills/tree/main/skills/light-sdk -- Crate: light-client (features: v2) — provides AccountInterface, LightProgramInterface, create_load_instructions -- AMM reference: https://github.com/Lightprotocol/cp-swap-reference -- Streaming guides: https://zkcompression.com/light-token/streaming/tokens - -Key APIs: create_load_instructions(), LightProgramInterface trait, get_account_interface(), get_multiple_account_interfaces(), is_cold() - -### 1. Index project -- Grep \`LightProgramInterface|create_load_instructions|AccountInterface|is_cold|get_account_interface|swap|amm|router|aggregator\` across src/ -- Glob \`**/*.rs\` and \`**/Cargo.toml\` for project structure -- Identify: existing routing/quoting logic, account caching, swap instruction building, streaming setup -- Read Cargo.toml — note existing dependencies and light-client version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (add cold market support to existing router, build new router with rent-free market support, integrate a specific AMM SDK) -- AskUserQuestion: does the project already stream account updates, or does it fetch at swap time? -- AskUserQuestion: does the project use Jito bundles for multi-transaction swaps? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan -- Follow the guide's progression: Cold Account Cache → Detecting Cold Accounts → Building Swap Transactions with Load Instructions -- If streaming: add account + transaction subscriptions for the Light Token Program -- If fetch-at-swap-time: add get_multiple_account_interfaces + is_cold() check before building swap tx -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash \`cargo add light-client@0.23 --features v2\` -- Add AMM SDK dependency per the approved plan -- Follow the guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash \`cargo check\` -- Bash \`cargo test\` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work`} - - -```text ---- -description: Integrate rent-free AMM markets into a router or aggregator -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Integrate rent-free AMM markets into a router or aggregator - -Context: -- Guide: https://zkcompression.com/light-token/defi/routers -- Skills and resources index: https://zkcompression.com/skill.md -- Dedicated skill: https://github.com/Lightprotocol/skills/tree/main/skills/light-sdk -- Crate: light-client (features: v2) — provides AccountInterface, LightProgramInterface, create_load_instructions -- AMM reference: https://github.com/Lightprotocol/cp-swap-reference -- Streaming guides: https://zkcompression.com/light-token/streaming/tokens - -Key APIs: create_load_instructions(), LightProgramInterface trait, get_account_interface(), get_multiple_account_interfaces(), is_cold() - -### 1. Index project -- Grep `LightProgramInterface|create_load_instructions|AccountInterface|is_cold|get_account_interface|swap|amm|router|aggregator` across src/ -- Glob `**/*.rs` and `**/Cargo.toml` for project structure -- Identify: existing routing/quoting logic, account caching, swap instruction building, streaming setup -- Read Cargo.toml — note existing dependencies and light-client version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (add cold market support to existing router, build new router with rent-free market support, integrate a specific AMM SDK) -- AskUserQuestion: does the project already stream account updates, or does it fetch at swap time? -- AskUserQuestion: does the project use Jito bundles for multi-transaction swaps? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan -- Follow the guide's progression: Cold Account Cache → Detecting Cold Accounts → Building Swap Transactions with Load Instructions -- If streaming: add account + transaction subscriptions for the Light Token Program -- If fetch-at-swap-time: add get_multiple_account_interfaces + is_cold() check before building swap tx -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash `cargo add light-client@0.23 --features v2` -- Add AMM SDK dependency per the approved plan -- Follow the guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash `cargo check` -- Bash `cargo test` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work -``` diff --git a/snippets/ai-prompts/light-token-prompts.mdx b/snippets/ai-prompts/light-token-prompts.mdx deleted file mode 100644 index 0408fe3b..00000000 --- a/snippets/ai-prompts/light-token-prompts.mdx +++ /dev/null @@ -1,89 +0,0 @@ -import LightTokenRecipes from "/snippets/ai-prompts/light-token-recipes.mdx"; - -{/* anchor-programs */} -import DefiAnchor from "/snippets/ai-prompts/anchor-programs/defi-anchor.mdx"; -import DefiPinocchio from "/snippets/ai-prompts/defi/defi-pinocchio.mdx"; - -{/* defi - routers */} -import Routers from "/snippets/ai-prompts/defi/routers.mdx"; - -{/* streaming */} -import StreamingMints from "/snippets/ai-prompts/streaming/mints.mdx"; -import StreamingTokens from "/snippets/ai-prompts/streaming/tokens.mdx"; - -{/* toolkits */} -import Payments from "/snippets/ai-prompts/toolkits/payments.mdx"; -import WalletsIntegration from "/snippets/ai-prompts/toolkits/wallets.mdx"; -import Nullifiers from "/snippets/ai-prompts/toolkits/nullifiers.mdx"; - -{/* wallets */} -import WalletAdapter from "/snippets/ai-prompts/wallets/wallet-adapter.mdx"; -import Privy from "/snippets/ai-prompts/wallets/privy.mdx"; -import GaslessTransactions from "/snippets/ai-prompts/wallets/gasless-transactions.mdx"; - -## Stablecoin Payments - - -Copy the prompt below or view the [guide](/light-token/payments/overview). - - - - -Copy the prompt below or view the [guide](/light-token/wallets/wallet-adapter). - - - - -Copy the prompt below or view the [guide](/light-token/wallets/privy). - - - - -Copy the prompt below or view the [guide](/light-token/wallets/gasless-transactions). - - - - -Copy the prompt below or view the [guide](/pda/compressed-pdas/nullifier-pda). - - - -## Light Token Recipes - - - -## DeFi - - -Copy the prompt below or view the [guide](/light-token/defi/programs). - - - - -Copy the prompt below or view the [guide](/light-token/defi/programs-pinocchio). - - - - -Copy the prompt below or view the [guide](/light-token/defi/routers). - - - -## Data Streaming - - -Copy the prompt below or view the [guide](/light-token/streaming/mints). - - - - -Copy the prompt below or view the [guide](/light-token/streaming/tokens). - - - -## Wallets - - -Copy the prompt below or view the [guide](/light-token/wallets/overview). - - diff --git a/snippets/ai-prompts/light-token-recipes.mdx b/snippets/ai-prompts/light-token-recipes.mdx deleted file mode 100644 index 17282e2f..00000000 --- a/snippets/ai-prompts/light-token-recipes.mdx +++ /dev/null @@ -1,197 +0,0 @@ -{/* ts-cookbook */} -import TsCreateMint from "/snippets/ai-prompts/ts-cookbook/create-mint.mdx"; -import TsCreateAta from "/snippets/ai-prompts/ts-cookbook/create-ata.mdx"; -import TsMintTo from "/snippets/ai-prompts/ts-cookbook/mint-to.mdx"; -import TsTransferInterface from "/snippets/ai-prompts/ts-cookbook/transfer-interface.mdx"; -import TsApproveRevoke from "/snippets/ai-prompts/ts-cookbook/approve-revoke.mdx"; -import TsWrapUnwrap from "/snippets/ai-prompts/ts-cookbook/wrap-unwrap.mdx"; -import TsAddInterfacePda from "/snippets/ai-prompts/ts-cookbook/add-interface-pda.mdx"; - -{/* rust-cookbook */} -import RustCreateMint from "/snippets/ai-prompts/rust-cookbook/create-mint.mdx"; -import RustCreateAta from "/snippets/ai-prompts/rust-cookbook/create-ata.mdx"; -import RustCreateTokenAccount from "/snippets/ai-prompts/rust-cookbook/create-token-account.mdx"; -import RustMintTo from "/snippets/ai-prompts/rust-cookbook/mint-to.mdx"; -import RustTransferInterface from "/snippets/ai-prompts/rust-cookbook/transfer-interface.mdx"; -import RustTransferChecked from "/snippets/ai-prompts/rust-cookbook/transfer-checked.mdx"; -import RustApproveRevoke from "/snippets/ai-prompts/rust-cookbook/approve-revoke.mdx"; -import RustFreezeThaw from "/snippets/ai-prompts/rust-cookbook/freeze-thaw.mdx"; -import RustWrapUnwrap from "/snippets/ai-prompts/rust-cookbook/wrap-unwrap.mdx"; -import RustCloseTokenAccount from "/snippets/ai-prompts/rust-cookbook/close-token-account.mdx"; -import RustBurn from "/snippets/ai-prompts/rust-cookbook/burn.mdx"; - -{/* program-cookbook */} -import ProgCreateMintCpi from "/snippets/ai-prompts/program-cookbook/create-mint-cpi.mdx"; -import ProgCreateMintMacros from "/snippets/ai-prompts/program-cookbook/create-mint-macros.mdx"; -import ProgCreateAtaCpi from "/snippets/ai-prompts/program-cookbook/create-ata-cpi.mdx"; -import ProgCreateAtaMacros from "/snippets/ai-prompts/program-cookbook/create-ata-macros.mdx"; -import ProgCreateTokenAccountCpi from "/snippets/ai-prompts/program-cookbook/create-token-account-cpi.mdx"; -import ProgCreateTokenAccountMacros from "/snippets/ai-prompts/program-cookbook/create-token-account-macros.mdx"; -import ProgMintTo from "/snippets/ai-prompts/program-cookbook/mint-to.mdx"; -import ProgTransferInterface from "/snippets/ai-prompts/program-cookbook/transfer-interface.mdx"; -import ProgTransferChecked from "/snippets/ai-prompts/program-cookbook/transfer-checked.mdx"; -import ProgApproveRevoke from "/snippets/ai-prompts/program-cookbook/approve-revoke.mdx"; -import ProgFreezeThaw from "/snippets/ai-prompts/program-cookbook/freeze-thaw.mdx"; -import ProgCloseTokenAccount from "/snippets/ai-prompts/program-cookbook/close-token-account.mdx"; -import ProgBurn from "/snippets/ai-prompts/program-cookbook/burn.mdx"; - - -Copy the prompt below or view the [guide](/light-token/cookbook/create-mint). - - - - - - - - - - - - - - - - - -Copy the prompt below or view the [guide](/light-token/cookbook/create-ata). - - - - - - - - - - - - - - - - - -Copy the prompt below or view the [guide](/light-token/cookbook/create-token-account). - - - - - - - - - - - - - - -Copy the prompt below or view the [guide](/light-token/cookbook/add-interface-pda). - - - - -Copy the prompt below or view the [guide](/light-token/cookbook/mint-to). - - - - - - - - - - - - - - -Copy the prompt below or view the [guide](/light-token/cookbook/transfer-interface). - - - - - - - - - - - - - - -Copy the prompt below or view the [guide](/light-token/cookbook/transfer-checked). - - - - - - - - - - - -Copy the prompt below or view the [guide](/light-token/cookbook/approve-revoke). - - - - - - - - - - - - - - -Copy the prompt below or view the [guide](/light-token/cookbook/freeze-thaw). - - - - - - - - - - - -Copy the prompt below or view the [guide](/light-token/cookbook/wrap-unwrap). - - - - - - - - - - - -Copy the prompt below or view the [guide](/light-token/cookbook/close-token-account). - - - - - - - - - - - -Copy the prompt below or view the [guide](/light-token/cookbook/burn). - - - - - - - - - diff --git a/snippets/ai-prompts/program-cookbook/approve-revoke.mdx b/snippets/ai-prompts/program-cookbook/approve-revoke.mdx deleted file mode 100644 index 37f312e3..00000000 --- a/snippets/ai-prompts/program-cookbook/approve-revoke.mdx +++ /dev/null @@ -1,117 +0,0 @@ - -{`--- -description: Add approve and revoke CPI to an Anchor program -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Add approve and revoke CPI to an Anchor program - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/approve-revoke -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Crate: light-token (ApproveCpi, RevokeCpi) -- Example: https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-instructions/approve - -Key CPI structs: \`light_token::instruction::ApproveCpi\`, \`light_token::instruction::RevokeCpi\` - -### 1. Index project -- Grep \`declare_id|#\[program\]|anchor_lang|Account<|Pubkey|invoke|approve|revoke|delegate\` across src/ -- Glob \`**/*.rs\` and \`**/Cargo.toml\` for project structure -- Identify: program ID, existing instructions, account structs, delegate accounts -- Read Cargo.toml — note existing dependencies and framework version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — review both Approve and Revoke CPI code samples -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (add approve/revoke to existing program, new program from scratch, migrate from SPL approve/revoke) -- AskUserQuestion: should the owner be an external signer or a PDA? (determines invoke vs invoke_signed) -- AskUserQuestion: do you need both approve and revoke, or just one? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Follow the guide's step order: Build ApproveCpi/RevokeCpi structs → call .invoke() or .invoke_signed() -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash \`cargo add light-token anchor-lang@0.31\` -- Follow the guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash \`anchor build\` -- Bash \`anchor test\` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work`} - - -```text ---- -description: Add approve and revoke CPI to an Anchor program -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Add approve and revoke CPI to an Anchor program - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/approve-revoke -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Crate: light-token (ApproveCpi, RevokeCpi) -- Example: https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-instructions/approve - -Key CPI structs: `light_token::instruction::ApproveCpi`, `light_token::instruction::RevokeCpi` - -### 1. Index project -- Grep `declare_id|#\[program\]|anchor_lang|Account<|Pubkey|invoke|approve|revoke|delegate` across src/ -- Glob `**/*.rs` and `**/Cargo.toml` for project structure -- Identify: program ID, existing instructions, account structs, delegate accounts -- Read Cargo.toml — note existing dependencies and framework version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — review both Approve and Revoke CPI code samples -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (add approve/revoke to existing program, new program from scratch, migrate from SPL approve/revoke) -- AskUserQuestion: should the owner be an external signer or a PDA? (determines invoke vs invoke_signed) -- AskUserQuestion: do you need both approve and revoke, or just one? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Follow the guide's step order: Build ApproveCpi/RevokeCpi structs → call .invoke() or .invoke_signed() -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash `cargo add light-token anchor-lang@0.31` -- Follow the guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash `anchor build` -- Bash `anchor test` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work -``` diff --git a/snippets/ai-prompts/program-cookbook/burn.mdx b/snippets/ai-prompts/program-cookbook/burn.mdx deleted file mode 100644 index 54359c3c..00000000 --- a/snippets/ai-prompts/program-cookbook/burn.mdx +++ /dev/null @@ -1,115 +0,0 @@ - -{`--- -description: Add burn CPI to an Anchor program -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Add burn CPI to an Anchor program - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/burn -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Crate: light-token (BurnCpi) -- Example: https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-instructions/burn - -Key CPI struct: \`light_token::instruction::BurnCpi\` - -### 1. Index project -- Grep \`declare_id|#\[program\]|anchor_lang|Account<|Pubkey|invoke|burn|destroy|supply\` across src/ -- Glob \`**/*.rs\` and \`**/Cargo.toml\` for project structure -- Identify: program ID, existing instructions, account structs, token accounts -- Read Cargo.toml — note existing dependencies and framework version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — review the Program tab CPI code samples -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (add burn to existing program, new program from scratch, migrate from SPL burn) -- AskUserQuestion: should the authority be an external signer or a PDA? (determines invoke vs invoke_signed) -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Follow the guide's step order: Build BurnCpi struct → call .invoke() or .invoke_signed() -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash \`cargo add light-token anchor-lang@0.31\` -- Follow the guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash \`anchor build\` -- Bash \`anchor test\` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work`} - - -```text ---- -description: Add burn CPI to an Anchor program -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Add burn CPI to an Anchor program - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/burn -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Crate: light-token (BurnCpi) -- Example: https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-instructions/burn - -Key CPI struct: `light_token::instruction::BurnCpi` - -### 1. Index project -- Grep `declare_id|#\[program\]|anchor_lang|Account<|Pubkey|invoke|burn|destroy|supply` across src/ -- Glob `**/*.rs` and `**/Cargo.toml` for project structure -- Identify: program ID, existing instructions, account structs, token accounts -- Read Cargo.toml — note existing dependencies and framework version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — review the Program tab CPI code samples -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (add burn to existing program, new program from scratch, migrate from SPL burn) -- AskUserQuestion: should the authority be an external signer or a PDA? (determines invoke vs invoke_signed) -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Follow the guide's step order: Build BurnCpi struct → call .invoke() or .invoke_signed() -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash `cargo add light-token anchor-lang@0.31` -- Follow the guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash `anchor build` -- Bash `anchor test` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work -``` diff --git a/snippets/ai-prompts/program-cookbook/close-token-account.mdx b/snippets/ai-prompts/program-cookbook/close-token-account.mdx deleted file mode 100644 index 1ead8eba..00000000 --- a/snippets/ai-prompts/program-cookbook/close-token-account.mdx +++ /dev/null @@ -1,115 +0,0 @@ - -{`--- -description: Add close-account CPI to an Anchor program -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Add close-account CPI to an Anchor program - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/close-token-account -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Crate: light-token (CloseAccountCpi) -- Example: https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-instructions/close - -Key CPI struct: \`light_token::instruction::CloseAccountCpi\` - -### 1. Index project -- Grep \`declare_id|#\[program\]|anchor_lang|Account<|Pubkey|invoke|close|destination|rent\` across src/ -- Glob \`**/*.rs\` and \`**/Cargo.toml\` for project structure -- Identify: program ID, existing instructions, account structs, token accounts -- Read Cargo.toml — note existing dependencies and framework version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — review the Program tab CPI code samples -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (add close-account to existing program, new program from scratch, migrate from SPL close_account) -- AskUserQuestion: should the owner be an external signer or a PDA? (determines invoke vs invoke_signed) -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Follow the guide's step order: Build CloseAccountCpi struct → call .invoke() or .invoke_signed() -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash \`cargo add light-token anchor-lang@0.31\` -- Follow the guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash \`anchor build\` -- Bash \`anchor test\` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work`} - - -```text ---- -description: Add close-account CPI to an Anchor program -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Add close-account CPI to an Anchor program - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/close-token-account -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Crate: light-token (CloseAccountCpi) -- Example: https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-instructions/close - -Key CPI struct: `light_token::instruction::CloseAccountCpi` - -### 1. Index project -- Grep `declare_id|#\[program\]|anchor_lang|Account<|Pubkey|invoke|close|destination|rent` across src/ -- Glob `**/*.rs` and `**/Cargo.toml` for project structure -- Identify: program ID, existing instructions, account structs, token accounts -- Read Cargo.toml — note existing dependencies and framework version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — review the Program tab CPI code samples -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (add close-account to existing program, new program from scratch, migrate from SPL close_account) -- AskUserQuestion: should the owner be an external signer or a PDA? (determines invoke vs invoke_signed) -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Follow the guide's step order: Build CloseAccountCpi struct → call .invoke() or .invoke_signed() -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash `cargo add light-token anchor-lang@0.31` -- Follow the guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash `anchor build` -- Bash `anchor test` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work -``` diff --git a/snippets/ai-prompts/program-cookbook/create-ata-cpi.mdx b/snippets/ai-prompts/program-cookbook/create-ata-cpi.mdx deleted file mode 100644 index 958cfca7..00000000 --- a/snippets/ai-prompts/program-cookbook/create-ata-cpi.mdx +++ /dev/null @@ -1,115 +0,0 @@ - -{`--- -description: Add create-ATA CPI to an Anchor program -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Add create-ATA CPI to an Anchor program - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/create-ata -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Crate: light-token (CreateAssociatedAccountCpi) -- Example: https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-instructions/create-associated-token-account - -Key CPI struct: \`light_token::instruction::CreateAssociatedAccountCpi\` - -### 1. Index project -- Grep \`declare_id|#\[program\]|anchor_lang|Account<|Pubkey|invoke|ata|associated|owner|mint\` across src/ -- Glob \`**/*.rs\` and \`**/Cargo.toml\` for project structure -- Identify: program ID, existing instructions, account structs, ATA derivation -- Read Cargo.toml — note existing dependencies and framework version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — review the CPI tab under Program: ATA creation with .rent_free() chain -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (add create-ATA to existing program, new program from scratch, migrate from SPL create_associated_token_account) -- AskUserQuestion: should the payer be an external signer or a PDA? (determines invoke vs invoke_signed) -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Follow the guide's step order: Build CreateAssociatedAccountCpi → .rent_free() → .invoke() or .invoke_signed() -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash \`cargo add light-token anchor-lang@0.31\` -- Follow the guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash \`anchor build\` -- Bash \`anchor test\` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work`} - - -```text ---- -description: Add create-ATA CPI to an Anchor program -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Add create-ATA CPI to an Anchor program - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/create-ata -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Crate: light-token (CreateAssociatedAccountCpi) -- Example: https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-instructions/create-associated-token-account - -Key CPI struct: `light_token::instruction::CreateAssociatedAccountCpi` - -### 1. Index project -- Grep `declare_id|#\[program\]|anchor_lang|Account<|Pubkey|invoke|ata|associated|owner|mint` across src/ -- Glob `**/*.rs` and `**/Cargo.toml` for project structure -- Identify: program ID, existing instructions, account structs, ATA derivation -- Read Cargo.toml — note existing dependencies and framework version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — review the CPI tab under Program: ATA creation with .rent_free() chain -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (add create-ATA to existing program, new program from scratch, migrate from SPL create_associated_token_account) -- AskUserQuestion: should the payer be an external signer or a PDA? (determines invoke vs invoke_signed) -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Follow the guide's step order: Build CreateAssociatedAccountCpi → .rent_free() → .invoke() or .invoke_signed() -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash `cargo add light-token anchor-lang@0.31` -- Follow the guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash `anchor build` -- Bash `anchor test` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work -``` diff --git a/snippets/ai-prompts/program-cookbook/create-ata-macros.mdx b/snippets/ai-prompts/program-cookbook/create-ata-macros.mdx deleted file mode 100644 index 3dc08f7f..00000000 --- a/snippets/ai-prompts/program-cookbook/create-ata-macros.mdx +++ /dev/null @@ -1,113 +0,0 @@ - -{`--- -description: Create a rent-free ATA with Anchor macros -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Create a rent-free ATA with Anchor macros - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/create-ata -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Crates: light-sdk, light-sdk-macros, light-compressible, anchor-lang -- Example: https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-macros/create-associated-token-account - -Key macros: \`#[light_program]\`, \`LightAccounts\`, \`#[light_account(init, associated_token::...)]\` - -### 1. Index project -- Grep \`#\[program\]|anchor_lang|Account<|Accounts|seeds|init|payer|ata|associated\` across src/ -- Glob \`**/*.rs\` and \`**/Cargo.toml\` for project structure -- Identify: existing program module, account structs, ATA patterns -- Read Cargo.toml — note existing dependencies and framework version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — review the Anchor Macros tab under Program -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new program from scratch, add rent-free ATA to existing program, migrate from SPL create_associated_token_account) -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan -- Follow the guide's step order: Dependencies → Program Module (#[light_program]) → Accounts Struct (#[light_account(init, associated_token::...)]) -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash \`cargo add light-sdk@0.23 --features anchor,v2,cpi-context\` and \`cargo add light-sdk-macros@0.23 light-compressible@0.6 anchor-lang@0.31\` -- Follow the guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash \`anchor build\` -- Bash \`anchor test\` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work`} - - -```text ---- -description: Create a rent-free ATA with Anchor macros -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Create a rent-free ATA with Anchor macros - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/create-ata -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Crates: light-sdk, light-sdk-macros, light-compressible, anchor-lang -- Example: https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-macros/create-associated-token-account - -Key macros: `#[light_program]`, `LightAccounts`, `#[light_account(init, associated_token::...)]` - -### 1. Index project -- Grep `#\[program\]|anchor_lang|Account<|Accounts|seeds|init|payer|ata|associated` across src/ -- Glob `**/*.rs` and `**/Cargo.toml` for project structure -- Identify: existing program module, account structs, ATA patterns -- Read Cargo.toml — note existing dependencies and framework version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — review the Anchor Macros tab under Program -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new program from scratch, add rent-free ATA to existing program, migrate from SPL create_associated_token_account) -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan -- Follow the guide's step order: Dependencies → Program Module (#[light_program]) → Accounts Struct (#[light_account(init, associated_token::...)]) -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash `cargo add light-sdk@0.23 --features anchor,v2,cpi-context` and `cargo add light-sdk-macros@0.23 light-compressible@0.6 anchor-lang@0.31` -- Follow the guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash `anchor build` -- Bash `anchor test` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work -``` diff --git a/snippets/ai-prompts/program-cookbook/create-mint-cpi.mdx b/snippets/ai-prompts/program-cookbook/create-mint-cpi.mdx deleted file mode 100644 index 889cd47f..00000000 --- a/snippets/ai-prompts/program-cookbook/create-mint-cpi.mdx +++ /dev/null @@ -1,117 +0,0 @@ - -{`--- -description: Add create-mint CPI to an Anchor program -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Add create-mint CPI to an Anchor program - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/create-mint -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Crate: light-token (CreateMintCpi, CreateMintParams, SystemAccountInfos) -- Example: https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-instructions/create-mint - -Key CPI struct: \`light_token::instruction::CreateMintCpi\` - -### 1. Index project -- Grep \`declare_id|#\[program\]|anchor_lang|Account<|Pubkey|invoke|mint|decimals|authority|metadata\` across src/ -- Glob \`**/*.rs\` and \`**/Cargo.toml\` for project structure -- Identify: program ID, existing instructions, account structs, mint seeds -- Read Cargo.toml — note existing dependencies and framework version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — review the CPI tab under Program: token metadata config, mint params, system accounts, invoke patterns -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (add create-mint to existing program, new program from scratch, migrate from SPL create_mint) -- AskUserQuestion: should the mint seed be an external keypair or a PDA? (determines invoke vs invoke_signed) -- AskUserQuestion: do you need token metadata (name, symbol, uri)? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Follow the guide's step order: Configure Token Metadata → Configure Mint Params → System Accounts → Build CPI and invoke -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash \`cargo add light-token anchor-lang@0.31\` -- Follow the guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash \`anchor build\` -- Bash \`anchor test\` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work`} - - -```text ---- -description: Add create-mint CPI to an Anchor program -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Add create-mint CPI to an Anchor program - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/create-mint -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Crate: light-token (CreateMintCpi, CreateMintParams, SystemAccountInfos) -- Example: https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-instructions/create-mint - -Key CPI struct: `light_token::instruction::CreateMintCpi` - -### 1. Index project -- Grep `declare_id|#\[program\]|anchor_lang|Account<|Pubkey|invoke|mint|decimals|authority|metadata` across src/ -- Glob `**/*.rs` and `**/Cargo.toml` for project structure -- Identify: program ID, existing instructions, account structs, mint seeds -- Read Cargo.toml — note existing dependencies and framework version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — review the CPI tab under Program: token metadata config, mint params, system accounts, invoke patterns -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (add create-mint to existing program, new program from scratch, migrate from SPL create_mint) -- AskUserQuestion: should the mint seed be an external keypair or a PDA? (determines invoke vs invoke_signed) -- AskUserQuestion: do you need token metadata (name, symbol, uri)? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Follow the guide's step order: Configure Token Metadata → Configure Mint Params → System Accounts → Build CPI and invoke -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash `cargo add light-token anchor-lang@0.31` -- Follow the guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash `anchor build` -- Bash `anchor test` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work -``` diff --git a/snippets/ai-prompts/program-cookbook/create-mint-macros.mdx b/snippets/ai-prompts/program-cookbook/create-mint-macros.mdx deleted file mode 100644 index c116201e..00000000 --- a/snippets/ai-prompts/program-cookbook/create-mint-macros.mdx +++ /dev/null @@ -1,115 +0,0 @@ - -{`--- -description: Create a rent-free mint with Anchor macros -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Create a rent-free mint with Anchor macros - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/create-mint -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Crates: light-sdk, light-sdk-macros, light-compressible, anchor-lang -- Example: https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-macros/create-mint - -Key macros: \`#[light_program]\`, \`LightAccounts\`, \`#[light_account(init, mint::...)]\` - -### 1. Index project -- Grep \`#\[program\]|anchor_lang|Account<|Accounts|seeds|init|payer|mint\` across src/ -- Glob \`**/*.rs\` and \`**/Cargo.toml\` for project structure -- Identify: existing program module, account structs, mint patterns, PDA seeds -- Read Cargo.toml — note existing dependencies and framework version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — review the Anchor Macros tab under Program -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new program from scratch, add rent-free mint to existing program, migrate from SPL create_mint) -- AskUserQuestion: do you need token metadata (name, symbol, uri)? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan -- Follow the guide's step order: Dependencies → Program Module (#[light_program]) → Accounts Struct (#[light_account(init, mint::...)]) -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash \`cargo add light-sdk@0.23 --features anchor,v2,cpi-context\` and \`cargo add light-sdk-macros@0.23 light-compressible@0.6 anchor-lang@0.31\` -- Follow the guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash \`anchor build\` -- Bash \`anchor test\` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work`} - - -```text ---- -description: Create a rent-free mint with Anchor macros -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Create a rent-free mint with Anchor macros - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/create-mint -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Crates: light-sdk, light-sdk-macros, light-compressible, anchor-lang -- Example: https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-macros/create-mint - -Key macros: `#[light_program]`, `LightAccounts`, `#[light_account(init, mint::...)]` - -### 1. Index project -- Grep `#\[program\]|anchor_lang|Account<|Accounts|seeds|init|payer|mint` across src/ -- Glob `**/*.rs` and `**/Cargo.toml` for project structure -- Identify: existing program module, account structs, mint patterns, PDA seeds -- Read Cargo.toml — note existing dependencies and framework version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — review the Anchor Macros tab under Program -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new program from scratch, add rent-free mint to existing program, migrate from SPL create_mint) -- AskUserQuestion: do you need token metadata (name, symbol, uri)? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan -- Follow the guide's step order: Dependencies → Program Module (#[light_program]) → Accounts Struct (#[light_account(init, mint::...)]) -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash `cargo add light-sdk@0.23 --features anchor,v2,cpi-context` and `cargo add light-sdk-macros@0.23 light-compressible@0.6 anchor-lang@0.31` -- Follow the guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash `anchor build` -- Bash `anchor test` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work -``` diff --git a/snippets/ai-prompts/program-cookbook/create-token-account-cpi.mdx b/snippets/ai-prompts/program-cookbook/create-token-account-cpi.mdx deleted file mode 100644 index 0e8f9315..00000000 --- a/snippets/ai-prompts/program-cookbook/create-token-account-cpi.mdx +++ /dev/null @@ -1,115 +0,0 @@ - -{`--- -description: Add create-token-account CPI to an Anchor program -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Add create-token-account CPI to an Anchor program - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/create-token-account -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Crate: light-token (CreateTokenAccountCpi) -- Example: https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-instructions/create-token-account - -Key CPI struct: \`light_token::instruction::CreateTokenAccountCpi\` - -### 1. Index project -- Grep \`declare_id|#\[program\]|anchor_lang|Account<|Pubkey|invoke|token_account|vault|owner|mint\` across src/ -- Glob \`**/*.rs\` and \`**/Cargo.toml\` for project structure -- Identify: program ID, existing instructions, account structs, vault/token account patterns -- Read Cargo.toml — note existing dependencies and framework version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — review the CPI tab under Program: token account creation with .rent_free() chain -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (add create-token-account to existing program, new program from scratch, migrate from SPL token account init) -- AskUserQuestion: should the payer be an external signer or a PDA? (determines invoke vs invoke_signed) -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Follow the guide's step order: Build CreateTokenAccountCpi → .rent_free() → .invoke() or .invoke_signed() -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash \`cargo add light-token anchor-lang@0.31\` -- Follow the guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash \`anchor build\` -- Bash \`anchor test\` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work`} - - -```text ---- -description: Add create-token-account CPI to an Anchor program -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Add create-token-account CPI to an Anchor program - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/create-token-account -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Crate: light-token (CreateTokenAccountCpi) -- Example: https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-instructions/create-token-account - -Key CPI struct: `light_token::instruction::CreateTokenAccountCpi` - -### 1. Index project -- Grep `declare_id|#\[program\]|anchor_lang|Account<|Pubkey|invoke|token_account|vault|owner|mint` across src/ -- Glob `**/*.rs` and `**/Cargo.toml` for project structure -- Identify: program ID, existing instructions, account structs, vault/token account patterns -- Read Cargo.toml — note existing dependencies and framework version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — review the CPI tab under Program: token account creation with .rent_free() chain -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (add create-token-account to existing program, new program from scratch, migrate from SPL token account init) -- AskUserQuestion: should the payer be an external signer or a PDA? (determines invoke vs invoke_signed) -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Follow the guide's step order: Build CreateTokenAccountCpi → .rent_free() → .invoke() or .invoke_signed() -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash `cargo add light-token anchor-lang@0.31` -- Follow the guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash `anchor build` -- Bash `anchor test` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work -``` diff --git a/snippets/ai-prompts/program-cookbook/create-token-account-macros.mdx b/snippets/ai-prompts/program-cookbook/create-token-account-macros.mdx deleted file mode 100644 index fcbed1a5..00000000 --- a/snippets/ai-prompts/program-cookbook/create-token-account-macros.mdx +++ /dev/null @@ -1,113 +0,0 @@ - -{`--- -description: Create a rent-free token account with Anchor macros -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Create a rent-free token account with Anchor macros - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/create-token-account -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Crates: light-sdk, light-sdk-macros, light-compressible, anchor-lang -- Example: https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-macros/create-token-account - -Key macros: \`#[light_program]\`, \`LightAccounts\`, \`#[light_account(init, token::...)]\` - -### 1. Index project -- Grep \`#\[program\]|anchor_lang|Account<|Accounts|seeds|init|payer|vault|token_account\` across src/ -- Glob \`**/*.rs\` and \`**/Cargo.toml\` for project structure -- Identify: existing program module, account structs, vault/token account patterns -- Read Cargo.toml — note existing dependencies and framework version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — review the Anchor Macros tab under Program -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new program from scratch, add rent-free token account to existing program, migrate from SPL token account init) -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan -- Follow the guide's step order: Dependencies → Program Module (#[light_program]) → Accounts Struct (#[light_account(init, token::...)]) -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash \`cargo add light-sdk@0.23 --features anchor,v2,cpi-context\` and \`cargo add light-sdk-macros@0.23 light-compressible@0.6 anchor-lang@0.31\` -- Follow the guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash \`anchor build\` -- Bash \`anchor test\` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work`} - - -```text ---- -description: Create a rent-free token account with Anchor macros -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Create a rent-free token account with Anchor macros - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/create-token-account -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Crates: light-sdk, light-sdk-macros, light-compressible, anchor-lang -- Example: https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-macros/create-token-account - -Key macros: `#[light_program]`, `LightAccounts`, `#[light_account(init, token::...)]` - -### 1. Index project -- Grep `#\[program\]|anchor_lang|Account<|Accounts|seeds|init|payer|vault|token_account` across src/ -- Glob `**/*.rs` and `**/Cargo.toml` for project structure -- Identify: existing program module, account structs, vault/token account patterns -- Read Cargo.toml — note existing dependencies and framework version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — review the Anchor Macros tab under Program -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new program from scratch, add rent-free token account to existing program, migrate from SPL token account init) -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan -- Follow the guide's step order: Dependencies → Program Module (#[light_program]) → Accounts Struct (#[light_account(init, token::...)]) -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash `cargo add light-sdk@0.23 --features anchor,v2,cpi-context` and `cargo add light-sdk-macros@0.23 light-compressible@0.6 anchor-lang@0.31` -- Follow the guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash `anchor build` -- Bash `anchor test` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work -``` diff --git a/snippets/ai-prompts/program-cookbook/freeze-thaw.mdx b/snippets/ai-prompts/program-cookbook/freeze-thaw.mdx deleted file mode 100644 index 172ca65c..00000000 --- a/snippets/ai-prompts/program-cookbook/freeze-thaw.mdx +++ /dev/null @@ -1,117 +0,0 @@ - -{`--- -description: Add freeze and thaw CPI to an Anchor program -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Add freeze and thaw CPI to an Anchor program - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/freeze-thaw -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Crate: light-token (FreezeCpi, ThawCpi) -- Example: https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-instructions/freeze - -Key CPI structs: \`light_token::instruction::FreezeCpi\`, \`light_token::instruction::ThawCpi\` - -### 1. Index project -- Grep \`declare_id|#\[program\]|anchor_lang|Account<|Pubkey|invoke|freeze|thaw|authority\` across src/ -- Glob \`**/*.rs\` and \`**/Cargo.toml\` for project structure -- Identify: program ID, existing instructions, account structs, freeze authority -- Read Cargo.toml — note existing dependencies and framework version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — review both Freeze and Thaw CPI code samples -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (add freeze/thaw to existing program, new program from scratch, migrate from SPL freeze/thaw) -- AskUserQuestion: should the freeze authority be an external signer or a PDA? (determines invoke vs invoke_signed) -- AskUserQuestion: do you need both freeze and thaw, or just one? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Follow the guide's step order: Build FreezeCpi/ThawCpi structs → call .invoke() or .invoke_signed() -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash \`cargo add light-token anchor-lang@0.31\` -- Follow the guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash \`anchor build\` -- Bash \`anchor test\` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work`} - - -```text ---- -description: Add freeze and thaw CPI to an Anchor program -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Add freeze and thaw CPI to an Anchor program - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/freeze-thaw -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Crate: light-token (FreezeCpi, ThawCpi) -- Example: https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-instructions/freeze - -Key CPI structs: `light_token::instruction::FreezeCpi`, `light_token::instruction::ThawCpi` - -### 1. Index project -- Grep `declare_id|#\[program\]|anchor_lang|Account<|Pubkey|invoke|freeze|thaw|authority` across src/ -- Glob `**/*.rs` and `**/Cargo.toml` for project structure -- Identify: program ID, existing instructions, account structs, freeze authority -- Read Cargo.toml — note existing dependencies and framework version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — review both Freeze and Thaw CPI code samples -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (add freeze/thaw to existing program, new program from scratch, migrate from SPL freeze/thaw) -- AskUserQuestion: should the freeze authority be an external signer or a PDA? (determines invoke vs invoke_signed) -- AskUserQuestion: do you need both freeze and thaw, or just one? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Follow the guide's step order: Build FreezeCpi/ThawCpi structs → call .invoke() or .invoke_signed() -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash `cargo add light-token anchor-lang@0.31` -- Follow the guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash `anchor build` -- Bash `anchor test` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work -``` diff --git a/snippets/ai-prompts/program-cookbook/light-pda.mdx b/snippets/ai-prompts/program-cookbook/light-pda.mdx deleted file mode 100644 index 3796957f..00000000 --- a/snippets/ai-prompts/program-cookbook/light-pda.mdx +++ /dev/null @@ -1,115 +0,0 @@ - -{`--- -description: Add rent-free PDAs to an Anchor program -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Add rent-free PDAs to an Anchor program - -Context: -- Guide: https://zkcompression.com/pda/light-pda/overview -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Crates: light-account (features: anchor), light-sdk (features: anchor, v2, cpi-context) -- Counter example: https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-macros/counter - -Key macros/APIs: #[light_program], LightAccount, LightAccounts, #[light_account(init)], CompressionInfo, CreateAccountsProof - -### 1. Index project -- Grep \`#\[program\]|anchor_lang|Account<|Accounts|InitSpace|seeds|init|payer\` across src/ -- Glob \`**/*.rs\` and \`**/Cargo.toml\` for project structure -- Identify: existing program module, account structs, PDA seeds, token accounts, init instructions -- Read Cargo.toml — note existing dependencies and framework version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new program from scratch, migrate existing program to rent-free, add rent-free accounts to specific instructions) -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan -- Follow the guide's step order: Dependencies → State Struct → Program Module → Accounts Struct -- Identify which existing structs need changes (CompressionInfo field, LightAccount derive, etc.) -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash \`cargo add light-account@0.23 --features anchor\` and \`cargo add light-sdk@0.23 --features anchor,v2,cpi-context\` -- Follow the guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash \`anchor build\` -- Bash \`anchor test\` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work`} - - -```text ---- -description: Add rent-free PDAs to an Anchor program -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Add rent-free PDAs to an Anchor program - -Context: -- Guide: https://zkcompression.com/pda/light-pda/overview -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Crates: light-account (features: anchor), light-sdk (features: anchor, v2, cpi-context) -- Counter example: https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-macros/counter - -Key macros/APIs: #[light_program], LightAccount, LightAccounts, #[light_account(init)], CompressionInfo, CreateAccountsProof - -### 1. Index project -- Grep `#\[program\]|anchor_lang|Account<|Accounts|InitSpace|seeds|init|payer` across src/ -- Glob `**/*.rs` and `**/Cargo.toml` for project structure -- Identify: existing program module, account structs, PDA seeds, token accounts, init instructions -- Read Cargo.toml — note existing dependencies and framework version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new program from scratch, migrate existing program to rent-free, add rent-free accounts to specific instructions) -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan -- Follow the guide's step order: Dependencies → State Struct → Program Module → Accounts Struct -- Identify which existing structs need changes (CompressionInfo field, LightAccount derive, etc.) -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash `cargo add light-account@0.23 --features anchor` and `cargo add light-sdk@0.23 --features anchor,v2,cpi-context` -- Follow the guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash `anchor build` -- Bash `anchor test` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work -``` diff --git a/snippets/ai-prompts/program-cookbook/mint-to.mdx b/snippets/ai-prompts/program-cookbook/mint-to.mdx deleted file mode 100644 index 6a018dae..00000000 --- a/snippets/ai-prompts/program-cookbook/mint-to.mdx +++ /dev/null @@ -1,115 +0,0 @@ - -{`--- -description: Add mint-to CPI to an Anchor program -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Add mint-to CPI to an Anchor program - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/mint-to -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Crate: light-token (MintToCpi) -- Example: https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-instructions/mint-to - -Key CPI struct: \`light_token::instruction::MintToCpi\` - -### 1. Index project -- Grep \`declare_id|#\[program\]|anchor_lang|Account<|Pubkey|invoke|mint|supply|amount\` across src/ -- Glob \`**/*.rs\` and \`**/Cargo.toml\` for project structure -- Identify: program ID, existing instructions, account structs, mint accounts -- Read Cargo.toml — note existing dependencies and framework version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — review the Program tab CPI code samples -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (add mint-to to existing program, new program from scratch, migrate from SPL mint_to) -- AskUserQuestion: should the authority be an external signer or a PDA? (determines invoke vs invoke_signed) -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Follow the guide's step order: Build MintToCpi struct → call .invoke() or .invoke_signed() -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash \`cargo add light-token anchor-lang@0.31\` -- Follow the guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash \`anchor build\` -- Bash \`anchor test\` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work`} - - -```text ---- -description: Add mint-to CPI to an Anchor program -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Add mint-to CPI to an Anchor program - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/mint-to -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Crate: light-token (MintToCpi) -- Example: https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-instructions/mint-to - -Key CPI struct: `light_token::instruction::MintToCpi` - -### 1. Index project -- Grep `declare_id|#\[program\]|anchor_lang|Account<|Pubkey|invoke|mint|supply|amount` across src/ -- Glob `**/*.rs` and `**/Cargo.toml` for project structure -- Identify: program ID, existing instructions, account structs, mint accounts -- Read Cargo.toml — note existing dependencies and framework version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — review the Program tab CPI code samples -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (add mint-to to existing program, new program from scratch, migrate from SPL mint_to) -- AskUserQuestion: should the authority be an external signer or a PDA? (determines invoke vs invoke_signed) -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Follow the guide's step order: Build MintToCpi struct → call .invoke() or .invoke_signed() -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash `cargo add light-token anchor-lang@0.31` -- Follow the guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash `anchor build` -- Bash `anchor test` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work -``` diff --git a/snippets/ai-prompts/program-cookbook/transfer-checked.mdx b/snippets/ai-prompts/program-cookbook/transfer-checked.mdx deleted file mode 100644 index b39a18de..00000000 --- a/snippets/ai-prompts/program-cookbook/transfer-checked.mdx +++ /dev/null @@ -1,121 +0,0 @@ - -{`--- -description: Add transfer-checked CPI to an Anchor program -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Add transfer-checked CPI to an Anchor program - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/transfer-checked -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Crate: light-token (TransferCheckedCpi) -- Example: https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-instructions/transfer-checked - -Key CPI struct: \`light_token::instruction::TransferCheckedCpi\` - -Note: TransferInterface uses TransferChecked under the hood for Light-to-Light transfers. -Use TransferChecked/TransferCheckedCpi directly only when you need Light-to-Light without interface routing. - -### 1. Index project -- Grep \`declare_id|#\[program\]|anchor_lang|Account<|Pubkey|invoke|transfer|decimals|amount\` across src/ -- Glob \`**/*.rs\` and \`**/Cargo.toml\` for project structure -- Identify: program ID, existing instructions, account structs, token accounts -- Read Cargo.toml — note existing dependencies and framework version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — review the Program tab CPI code samples -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (add transfer-checked to existing program, new program from scratch, migrate from SPL transfer_checked) -- AskUserQuestion: should the authority be an external signer or a PDA? (determines invoke vs invoke_signed) -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Follow the guide's step order: Build TransferCheckedCpi struct → call .invoke() or .invoke_signed() -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash \`cargo add light-token anchor-lang@0.31\` -- Follow the guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash \`anchor build\` -- Bash \`anchor test\` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work`} - - -```text ---- -description: Add transfer-checked CPI to an Anchor program -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Add transfer-checked CPI to an Anchor program - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/transfer-checked -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Crate: light-token (TransferCheckedCpi) -- Example: https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-instructions/transfer-checked - -Key CPI struct: `light_token::instruction::TransferCheckedCpi` - -Note: TransferInterface uses TransferChecked under the hood for Light-to-Light transfers. -Use TransferChecked/TransferCheckedCpi directly only when you need Light-to-Light without interface routing. - -### 1. Index project -- Grep `declare_id|#\[program\]|anchor_lang|Account<|Pubkey|invoke|transfer|decimals|amount` across src/ -- Glob `**/*.rs` and `**/Cargo.toml` for project structure -- Identify: program ID, existing instructions, account structs, token accounts -- Read Cargo.toml — note existing dependencies and framework version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — review the Program tab CPI code samples -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (add transfer-checked to existing program, new program from scratch, migrate from SPL transfer_checked) -- AskUserQuestion: should the authority be an external signer or a PDA? (determines invoke vs invoke_signed) -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Follow the guide's step order: Build TransferCheckedCpi struct → call .invoke() or .invoke_signed() -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash `cargo add light-token anchor-lang@0.31` -- Follow the guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash `anchor build` -- Bash `anchor test` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work -``` diff --git a/snippets/ai-prompts/program-cookbook/transfer-interface.mdx b/snippets/ai-prompts/program-cookbook/transfer-interface.mdx deleted file mode 100644 index 3eecb8f4..00000000 --- a/snippets/ai-prompts/program-cookbook/transfer-interface.mdx +++ /dev/null @@ -1,117 +0,0 @@ - -{`--- -description: Add transfer-interface CPI to an Anchor program -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Add transfer-interface CPI to an Anchor program - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/transfer-interface -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Crate: light-token (TransferInterfaceCpi) -- Example: https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-instructions/transfer-interface - -Key CPI struct: \`light_token::instruction::TransferInterfaceCpi\` - -### 1. Index project -- Grep \`declare_id|#\[program\]|anchor_lang|Account<|Pubkey|invoke|transfer|decimals|interface\` across src/ -- Glob \`**/*.rs\` and \`**/Cargo.toml\` for project structure -- Identify: program ID, existing instructions, account structs, token accounts -- Read Cargo.toml — note existing dependencies and framework version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — review the Program tab CPI code samples -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (add transfer-interface to existing program, new program from scratch, migrate from SPL transfer) -- AskUserQuestion: should the authority be an external signer or a PDA? (determines invoke vs invoke_signed) -- AskUserQuestion: which token types will be transferred? (SPL, Token 2022, Light Token, or all via interface) -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Follow the guide's step order: Build TransferInterfaceCpi → call .invoke() or .invoke_signed() -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash \`cargo add light-token anchor-lang@0.31\` -- Follow the guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash \`anchor build\` -- Bash \`anchor test\` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work`} - - -```text ---- -description: Add transfer-interface CPI to an Anchor program -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Add transfer-interface CPI to an Anchor program - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/transfer-interface -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Crate: light-token (TransferInterfaceCpi) -- Example: https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-instructions/transfer-interface - -Key CPI struct: `light_token::instruction::TransferInterfaceCpi` - -### 1. Index project -- Grep `declare_id|#\[program\]|anchor_lang|Account<|Pubkey|invoke|transfer|decimals|interface` across src/ -- Glob `**/*.rs` and `**/Cargo.toml` for project structure -- Identify: program ID, existing instructions, account structs, token accounts -- Read Cargo.toml — note existing dependencies and framework version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — review the Program tab CPI code samples -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (add transfer-interface to existing program, new program from scratch, migrate from SPL transfer) -- AskUserQuestion: should the authority be an external signer or a PDA? (determines invoke vs invoke_signed) -- AskUserQuestion: which token types will be transferred? (SPL, Token 2022, Light Token, or all via interface) -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Follow the guide's step order: Build TransferInterfaceCpi → call .invoke() or .invoke_signed() -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash `cargo add light-token anchor-lang@0.31` -- Follow the guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash `anchor build` -- Bash `anchor test` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work -``` diff --git a/snippets/ai-prompts/rust-cookbook/approve-revoke.mdx b/snippets/ai-prompts/rust-cookbook/approve-revoke.mdx deleted file mode 100644 index 9414a23d..00000000 --- a/snippets/ai-prompts/rust-cookbook/approve-revoke.mdx +++ /dev/null @@ -1,115 +0,0 @@ - -{`--- -description: Approve and revoke token delegates -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Approve and revoke token delegates - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/approve-revoke -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Crates: light-token-client (actions), light-token (instructions), light-client (RPC) - -SPL equivalent: spl_token::instruction::approve / revoke → Light Token: Approve / Revoke - -### 1. Index project -- Grep \`light_token::|light_token_client::|solana_sdk|Keypair|async|Approve|Revoke|delegate\` across src/ -- Glob \`**/*.rs\` for project structure -- Identify: RPC setup, existing token ops, entry point for delegation -- Check Cargo.toml for existing light-* dependencies and solana-sdk version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — follow the Rust Client tab -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new feature, migrate existing SPL code, add alongside existing) -- AskUserQuestion: does the project already have delegation operations to extend, or is this greenfield? -- AskUserQuestion: action-level API (high-level, fewer lines) or instruction-level API (low-level, full control)? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Verify existing Rpc/signer setup is compatible with the cookbook prerequisites (light_client::rpc::Rpc, solana_sdk::signature::Keypair) -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash \`cargo add light-token-client light-token light-client --features light-client/v2\` -- Follow the cookbook guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash \`cargo check\` -- Bash \`cargo test\` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work`} - - -```text ---- -description: Approve and revoke token delegates -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Approve and revoke token delegates - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/approve-revoke -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Crates: light-token-client (actions), light-token (instructions), light-client (RPC) - -SPL equivalent: spl_token::instruction::approve / revoke → Light Token: Approve / Revoke - -### 1. Index project -- Grep `light_token::|light_token_client::|solana_sdk|Keypair|async|Approve|Revoke|delegate` across src/ -- Glob `**/*.rs` for project structure -- Identify: RPC setup, existing token ops, entry point for delegation -- Check Cargo.toml for existing light-* dependencies and solana-sdk version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — follow the Rust Client tab -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new feature, migrate existing SPL code, add alongside existing) -- AskUserQuestion: does the project already have delegation operations to extend, or is this greenfield? -- AskUserQuestion: action-level API (high-level, fewer lines) or instruction-level API (low-level, full control)? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Verify existing Rpc/signer setup is compatible with the cookbook prerequisites (light_client::rpc::Rpc, solana_sdk::signature::Keypair) -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash `cargo add light-token-client light-token light-client --features light-client/v2` -- Follow the cookbook guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash `cargo check` -- Bash `cargo test` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work -``` diff --git a/snippets/ai-prompts/rust-cookbook/burn.mdx b/snippets/ai-prompts/rust-cookbook/burn.mdx deleted file mode 100644 index caf8c193..00000000 --- a/snippets/ai-prompts/rust-cookbook/burn.mdx +++ /dev/null @@ -1,115 +0,0 @@ - -{`--- -description: Burn Light Tokens -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Burn Light Tokens - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/burn -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Crates: light-token-client (actions), light-token (instructions), light-client (RPC) - -SPL equivalent: spl_token::instruction::burn → Light Token: Burn - -### 1. Index project -- Grep \`light_token::|light_token_client::|solana_sdk|Keypair|async|Burn|burn\` across src/ -- Glob \`**/*.rs\` for project structure -- Identify: RPC setup, existing token ops, entry point for burn -- Check Cargo.toml for existing light-* dependencies and solana-sdk version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — follow the Rust Client tab -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new feature, migrate existing SPL code, add alongside existing) -- AskUserQuestion: does the project already have burn operations to extend, or is this greenfield? -- AskUserQuestion: action-level API (high-level, fewer lines) or instruction-level API (low-level, full control)? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Verify existing Rpc/signer setup is compatible with the cookbook prerequisites (light_client::rpc::Rpc, solana_sdk::signature::Keypair) -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash \`cargo add light-token-client light-token light-client --features light-client/v2\` -- Follow the cookbook guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash \`cargo check\` -- Bash \`cargo test\` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work`} - - -```text ---- -description: Burn Light Tokens -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Burn Light Tokens - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/burn -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Crates: light-token-client (actions), light-token (instructions), light-client (RPC) - -SPL equivalent: spl_token::instruction::burn → Light Token: Burn - -### 1. Index project -- Grep `light_token::|light_token_client::|solana_sdk|Keypair|async|Burn|burn` across src/ -- Glob `**/*.rs` for project structure -- Identify: RPC setup, existing token ops, entry point for burn -- Check Cargo.toml for existing light-* dependencies and solana-sdk version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — follow the Rust Client tab -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new feature, migrate existing SPL code, add alongside existing) -- AskUserQuestion: does the project already have burn operations to extend, or is this greenfield? -- AskUserQuestion: action-level API (high-level, fewer lines) or instruction-level API (low-level, full control)? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Verify existing Rpc/signer setup is compatible with the cookbook prerequisites (light_client::rpc::Rpc, solana_sdk::signature::Keypair) -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash `cargo add light-token-client light-token light-client --features light-client/v2` -- Follow the cookbook guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash `cargo check` -- Bash `cargo test` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work -``` diff --git a/snippets/ai-prompts/rust-cookbook/close-token-account.mdx b/snippets/ai-prompts/rust-cookbook/close-token-account.mdx deleted file mode 100644 index e030788a..00000000 --- a/snippets/ai-prompts/rust-cookbook/close-token-account.mdx +++ /dev/null @@ -1,115 +0,0 @@ - -{`--- -description: Close Light Token account -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Close Light Token account - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/close-token-account -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Crates: light-token-client (actions), light-token (instructions), light-client (RPC) - -SPL equivalent: spl_token::instruction::close_account → Light Token: CloseAccount - -### 1. Index project -- Grep \`light_token::|light_token_client::|solana_sdk|Keypair|async|CloseAccount|close_account\` across src/ -- Glob \`**/*.rs\` for project structure -- Identify: RPC setup, existing token ops, entry point for close account -- Check Cargo.toml for existing light-* dependencies and solana-sdk version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — follow the Rust Client tab -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new feature, migrate existing SPL code, add alongside existing) -- AskUserQuestion: does the project already have close operations to extend, or is this greenfield? -- AskUserQuestion: action-level API (high-level, fewer lines) or instruction-level API (low-level, full control)? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Verify existing Rpc/signer setup is compatible with the cookbook prerequisites (light_client::rpc::Rpc, solana_sdk::signature::Keypair) -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash \`cargo add light-token-client light-token light-client --features light-client/v2\` -- Follow the cookbook guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash \`cargo check\` -- Bash \`cargo test\` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work`} - - -```text ---- -description: Close Light Token account -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Close Light Token account - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/close-token-account -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Crates: light-token-client (actions), light-token (instructions), light-client (RPC) - -SPL equivalent: spl_token::instruction::close_account → Light Token: CloseAccount - -### 1. Index project -- Grep `light_token::|light_token_client::|solana_sdk|Keypair|async|CloseAccount|close_account` across src/ -- Glob `**/*.rs` for project structure -- Identify: RPC setup, existing token ops, entry point for close account -- Check Cargo.toml for existing light-* dependencies and solana-sdk version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — follow the Rust Client tab -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new feature, migrate existing SPL code, add alongside existing) -- AskUserQuestion: does the project already have close operations to extend, or is this greenfield? -- AskUserQuestion: action-level API (high-level, fewer lines) or instruction-level API (low-level, full control)? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Verify existing Rpc/signer setup is compatible with the cookbook prerequisites (light_client::rpc::Rpc, solana_sdk::signature::Keypair) -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash `cargo add light-token-client light-token light-client --features light-client/v2` -- Follow the cookbook guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash `cargo check` -- Bash `cargo test` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work -``` diff --git a/snippets/ai-prompts/rust-cookbook/create-ata.mdx b/snippets/ai-prompts/rust-cookbook/create-ata.mdx deleted file mode 100644 index 31c2f2f1..00000000 --- a/snippets/ai-prompts/rust-cookbook/create-ata.mdx +++ /dev/null @@ -1,115 +0,0 @@ - -{`--- -description: Create rent-free associated token account -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Create rent-free associated token account - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/create-ata -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Crates: light-token-client (actions), light-token (instructions), light-client (RPC) - -SPL equivalent: spl_associated_token_account::create → Light Token: CreateAta - -### 1. Index project -- Grep \`light_token::|light_token_client::|solana_sdk|Keypair|async|CreateAta|create_associated_token_account\` across src/ -- Glob \`**/*.rs\` for project structure -- Identify: RPC setup, existing token ops, entry point for ATA creation -- Check Cargo.toml for existing light-* dependencies and solana-sdk version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — follow the Rust Client tab -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new feature, migrate existing SPL code, add alongside existing) -- AskUserQuestion: does the project already have ATA operations to extend, or is this greenfield? -- AskUserQuestion: action-level API (high-level, fewer lines) or instruction-level API (low-level, full control)? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Verify existing Rpc/signer setup is compatible with the cookbook prerequisites (light_client::rpc::Rpc, solana_sdk::signature::Keypair) -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash \`cargo add light-token-client light-token light-client --features light-client/v2\` -- Follow the cookbook guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash \`cargo check\` -- Bash \`cargo test\` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work`} - - -```text ---- -description: Create rent-free associated token account -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Create rent-free associated token account - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/create-ata -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Crates: light-token-client (actions), light-token (instructions), light-client (RPC) - -SPL equivalent: spl_associated_token_account::create → Light Token: CreateAta - -### 1. Index project -- Grep `light_token::|light_token_client::|solana_sdk|Keypair|async|CreateAta|create_associated_token_account` across src/ -- Glob `**/*.rs` for project structure -- Identify: RPC setup, existing token ops, entry point for ATA creation -- Check Cargo.toml for existing light-* dependencies and solana-sdk version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — follow the Rust Client tab -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new feature, migrate existing SPL code, add alongside existing) -- AskUserQuestion: does the project already have ATA operations to extend, or is this greenfield? -- AskUserQuestion: action-level API (high-level, fewer lines) or instruction-level API (low-level, full control)? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Verify existing Rpc/signer setup is compatible with the cookbook prerequisites (light_client::rpc::Rpc, solana_sdk::signature::Keypair) -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash `cargo add light-token-client light-token light-client --features light-client/v2` -- Follow the cookbook guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash `cargo check` -- Bash `cargo test` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work -``` diff --git a/snippets/ai-prompts/rust-cookbook/create-mint.mdx b/snippets/ai-prompts/rust-cookbook/create-mint.mdx deleted file mode 100644 index 9f12727d..00000000 --- a/snippets/ai-prompts/rust-cookbook/create-mint.mdx +++ /dev/null @@ -1,115 +0,0 @@ - -{`--- -description: Create rent-free mint with token metadata -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Create rent-free mint with token metadata - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/create-mint -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Crates: light-token-client (actions), light-token (instructions), light-client (RPC) - -SPL equivalent: spl_token::instruction::initialize_mint → Light Token: CreateMint - -### 1. Index project -- Grep \`light_token::|light_token_client::|solana_sdk|Keypair|async|CreateMint|initialize_mint\` across src/ -- Glob \`**/*.rs\` for project structure -- Identify: RPC setup, existing token ops, entry point for mint creation -- Check Cargo.toml for existing light-* dependencies and solana-sdk version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — follow the Rust Client tab -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new feature, migrate existing SPL code, add alongside existing) -- AskUserQuestion: does the project already have mint operations to extend, or is this greenfield? -- AskUserQuestion: action-level API (high-level, fewer lines) or instruction-level API (low-level, full control)? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Verify existing Rpc/signer setup is compatible with the cookbook prerequisites (light_client::rpc::Rpc, solana_sdk::signature::Keypair) -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash \`cargo add light-token-client light-token light-client --features light-client/v2\` -- Follow the cookbook guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash \`cargo check\` -- Bash \`cargo test\` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work`} - - -```text ---- -description: Create rent-free mint with token metadata -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Create rent-free mint with token metadata - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/create-mint -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Crates: light-token-client (actions), light-token (instructions), light-client (RPC) - -SPL equivalent: spl_token::instruction::initialize_mint → Light Token: CreateMint - -### 1. Index project -- Grep `light_token::|light_token_client::|solana_sdk|Keypair|async|CreateMint|initialize_mint` across src/ -- Glob `**/*.rs` for project structure -- Identify: RPC setup, existing token ops, entry point for mint creation -- Check Cargo.toml for existing light-* dependencies and solana-sdk version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — follow the Rust Client tab -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new feature, migrate existing SPL code, add alongside existing) -- AskUserQuestion: does the project already have mint operations to extend, or is this greenfield? -- AskUserQuestion: action-level API (high-level, fewer lines) or instruction-level API (low-level, full control)? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Verify existing Rpc/signer setup is compatible with the cookbook prerequisites (light_client::rpc::Rpc, solana_sdk::signature::Keypair) -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash `cargo add light-token-client light-token light-client --features light-client/v2` -- Follow the cookbook guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash `cargo check` -- Bash `cargo test` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work -``` diff --git a/snippets/ai-prompts/rust-cookbook/create-token-account.mdx b/snippets/ai-prompts/rust-cookbook/create-token-account.mdx deleted file mode 100644 index 5e08bb88..00000000 --- a/snippets/ai-prompts/rust-cookbook/create-token-account.mdx +++ /dev/null @@ -1,115 +0,0 @@ - -{`--- -description: Create Light Token account -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Create Light Token account - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/create-token-account -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Crates: light-token-client (actions), light-token (instructions), light-client (RPC) - -SPL equivalent: spl_token::instruction::initialize_account → Light Token: CreateTokenAccount - -### 1. Index project -- Grep \`light_token::|light_token_client::|solana_sdk|Keypair|async|CreateTokenAccount|initialize_account\` across src/ -- Glob \`**/*.rs\` for project structure -- Identify: RPC setup, existing token ops, entry point for token account creation -- Check Cargo.toml for existing light-* dependencies and solana-sdk version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — follow the Rust Client tab -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new feature, migrate existing SPL code, add alongside existing) -- AskUserQuestion: does the project already have token account operations to extend, or is this greenfield? -- AskUserQuestion: action-level API (high-level, fewer lines) or instruction-level API (low-level, full control)? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Verify existing Rpc/signer setup is compatible with the cookbook prerequisites (light_client::rpc::Rpc, solana_sdk::signature::Keypair) -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash \`cargo add light-token-client light-token light-client --features light-client/v2\` -- Follow the cookbook guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash \`cargo check\` -- Bash \`cargo test\` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work`} - - -```text ---- -description: Create Light Token account -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Create Light Token account - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/create-token-account -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Crates: light-token-client (actions), light-token (instructions), light-client (RPC) - -SPL equivalent: spl_token::instruction::initialize_account → Light Token: CreateTokenAccount - -### 1. Index project -- Grep `light_token::|light_token_client::|solana_sdk|Keypair|async|CreateTokenAccount|initialize_account` across src/ -- Glob `**/*.rs` for project structure -- Identify: RPC setup, existing token ops, entry point for token account creation -- Check Cargo.toml for existing light-* dependencies and solana-sdk version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — follow the Rust Client tab -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new feature, migrate existing SPL code, add alongside existing) -- AskUserQuestion: does the project already have token account operations to extend, or is this greenfield? -- AskUserQuestion: action-level API (high-level, fewer lines) or instruction-level API (low-level, full control)? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Verify existing Rpc/signer setup is compatible with the cookbook prerequisites (light_client::rpc::Rpc, solana_sdk::signature::Keypair) -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash `cargo add light-token-client light-token light-client --features light-client/v2` -- Follow the cookbook guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash `cargo check` -- Bash `cargo test` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work -``` diff --git a/snippets/ai-prompts/rust-cookbook/freeze-thaw.mdx b/snippets/ai-prompts/rust-cookbook/freeze-thaw.mdx deleted file mode 100644 index 4b4c0eb2..00000000 --- a/snippets/ai-prompts/rust-cookbook/freeze-thaw.mdx +++ /dev/null @@ -1,123 +0,0 @@ - -{`--- -description: Freeze and thaw Light Token accounts -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Freeze and thaw Light Token accounts - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/freeze-thaw -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Crates: light-token-client (actions), light-token (instructions), light-client (RPC) - -- Freeze: prevents all transfers or token burns from a specific Light Token account -- Thaw: re-enables transfers on a frozen Light Token account -- Only the freeze authority (set at mint creation) can freeze or thaw accounts - -SPL equivalent: spl_token::instruction::freeze_account / thaw_account → Light Token: Freeze / Thaw - -### 1. Index project -- Grep \`light_token::|light_token_client::|solana_sdk|Keypair|async|Freeze|Thaw|freeze_account|thaw_account\` across src/ -- Glob \`**/*.rs\` for project structure -- Identify: RPC setup, existing token ops, entry point for freeze/thaw -- Check Cargo.toml for existing light-* dependencies and solana-sdk version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — follow the Rust Client tab -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new feature, migrate existing SPL code, add alongside existing) -- AskUserQuestion: does the project already have freeze/thaw operations to extend, or is this greenfield? -- AskUserQuestion: action-level API (high-level, fewer lines) or instruction-level API (low-level, full control)? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Verify existing Rpc/signer setup is compatible with the cookbook prerequisites (light_client::rpc::Rpc, solana_sdk::signature::Keypair) -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash \`cargo add light-token-client light-token light-client --features light-client/v2\` -- Follow the cookbook guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash \`cargo check\` -- Bash \`cargo test\` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work`} - - -```text ---- -description: Freeze and thaw Light Token accounts -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Freeze and thaw Light Token accounts - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/freeze-thaw -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Crates: light-token-client (actions), light-token (instructions), light-client (RPC) - -- Freeze: prevents all transfers or token burns from a specific Light Token account -- Thaw: re-enables transfers on a frozen Light Token account -- Only the freeze authority (set at mint creation) can freeze or thaw accounts - -SPL equivalent: spl_token::instruction::freeze_account / thaw_account → Light Token: Freeze / Thaw - -### 1. Index project -- Grep `light_token::|light_token_client::|solana_sdk|Keypair|async|Freeze|Thaw|freeze_account|thaw_account` across src/ -- Glob `**/*.rs` for project structure -- Identify: RPC setup, existing token ops, entry point for freeze/thaw -- Check Cargo.toml for existing light-* dependencies and solana-sdk version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — follow the Rust Client tab -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new feature, migrate existing SPL code, add alongside existing) -- AskUserQuestion: does the project already have freeze/thaw operations to extend, or is this greenfield? -- AskUserQuestion: action-level API (high-level, fewer lines) or instruction-level API (low-level, full control)? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Verify existing Rpc/signer setup is compatible with the cookbook prerequisites (light_client::rpc::Rpc, solana_sdk::signature::Keypair) -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash `cargo add light-token-client light-token light-client --features light-client/v2` -- Follow the cookbook guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash `cargo check` -- Bash `cargo test` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work -``` diff --git a/snippets/ai-prompts/rust-cookbook/mint-to.mdx b/snippets/ai-prompts/rust-cookbook/mint-to.mdx deleted file mode 100644 index 6e5a411b..00000000 --- a/snippets/ai-prompts/rust-cookbook/mint-to.mdx +++ /dev/null @@ -1,115 +0,0 @@ - -{`--- -description: Mint tokens to Light Token account -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Mint tokens to Light Token account - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/mint-to -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Crates: light-token-client (actions), light-token (instructions), light-client (RPC) - -SPL equivalent: spl_token::instruction::mint_to → Light Token: MintTo - -### 1. Index project -- Grep \`light_token::|light_token_client::|solana_sdk|Keypair|async|MintTo|mint_to\` across src/ -- Glob \`**/*.rs\` for project structure -- Identify: RPC setup, existing token ops, entry point for minting -- Check Cargo.toml for existing light-* dependencies and solana-sdk version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — follow the Rust Client tab -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new feature, migrate existing SPL code, add alongside existing) -- AskUserQuestion: does the project already have mint operations to extend, or is this greenfield? -- AskUserQuestion: action-level API (high-level, fewer lines) or instruction-level API (low-level, full control)? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Verify existing Rpc/signer setup is compatible with the cookbook prerequisites (light_client::rpc::Rpc, solana_sdk::signature::Keypair) -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash \`cargo add light-token-client light-token light-client --features light-client/v2\` -- Follow the cookbook guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash \`cargo check\` -- Bash \`cargo test\` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work`} - - -```text ---- -description: Mint tokens to Light Token account -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Mint tokens to Light Token account - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/mint-to -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Crates: light-token-client (actions), light-token (instructions), light-client (RPC) - -SPL equivalent: spl_token::instruction::mint_to → Light Token: MintTo - -### 1. Index project -- Grep `light_token::|light_token_client::|solana_sdk|Keypair|async|MintTo|mint_to` across src/ -- Glob `**/*.rs` for project structure -- Identify: RPC setup, existing token ops, entry point for minting -- Check Cargo.toml for existing light-* dependencies and solana-sdk version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — follow the Rust Client tab -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new feature, migrate existing SPL code, add alongside existing) -- AskUserQuestion: does the project already have mint operations to extend, or is this greenfield? -- AskUserQuestion: action-level API (high-level, fewer lines) or instruction-level API (low-level, full control)? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Verify existing Rpc/signer setup is compatible with the cookbook prerequisites (light_client::rpc::Rpc, solana_sdk::signature::Keypair) -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash `cargo add light-token-client light-token light-client --features light-client/v2` -- Follow the cookbook guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash `cargo check` -- Bash `cargo test` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work -``` diff --git a/snippets/ai-prompts/rust-cookbook/transfer-checked.mdx b/snippets/ai-prompts/rust-cookbook/transfer-checked.mdx deleted file mode 100644 index 99accd0c..00000000 --- a/snippets/ai-prompts/rust-cookbook/transfer-checked.mdx +++ /dev/null @@ -1,119 +0,0 @@ - -{`--- -description: Transfer tokens with decimal validation -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Transfer tokens with decimal validation - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/transfer-checked -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Crates: light-token-client (actions), light-token (instructions), light-client (RPC) - -TransferChecked validates that the decimals parameter matches the mint's decimals. Use for Light→Light transfers when you need decimal verification. For transfers involving SPL or Token 2022 accounts, use TransferInterface instead. - -SPL equivalent: spl_token::instruction::transfer_checked → Light Token: TransferChecked - -### 1. Index project -- Grep \`light_token::|light_token_client::|solana_sdk|Keypair|async|TransferChecked|transfer_checked\` across src/ -- Glob \`**/*.rs\` for project structure -- Identify: RPC setup, existing token ops, entry point for transfer checked -- Check Cargo.toml for existing light-* dependencies and solana-sdk version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — follow the Rust Client tab -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new feature, migrate existing SPL code, add alongside existing) -- AskUserQuestion: does the project already have transfer operations to extend, or is this greenfield? -- AskUserQuestion: action-level API (high-level, fewer lines) or instruction-level API (low-level, full control)? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Verify existing Rpc/signer setup is compatible with the cookbook prerequisites (light_client::rpc::Rpc, solana_sdk::signature::Keypair) -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash \`cargo add light-token-client light-token light-client --features light-client/v2\` -- Follow the cookbook guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash \`cargo check\` -- Bash \`cargo test\` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work`} - - -```text ---- -description: Transfer tokens with decimal validation -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Transfer tokens with decimal validation - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/transfer-checked -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Crates: light-token-client (actions), light-token (instructions), light-client (RPC) - -TransferChecked validates that the decimals parameter matches the mint's decimals. Use for Light→Light transfers when you need decimal verification. For transfers involving SPL or Token 2022 accounts, use TransferInterface instead. - -SPL equivalent: spl_token::instruction::transfer_checked → Light Token: TransferChecked - -### 1. Index project -- Grep `light_token::|light_token_client::|solana_sdk|Keypair|async|TransferChecked|transfer_checked` across src/ -- Glob `**/*.rs` for project structure -- Identify: RPC setup, existing token ops, entry point for transfer checked -- Check Cargo.toml for existing light-* dependencies and solana-sdk version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — follow the Rust Client tab -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new feature, migrate existing SPL code, add alongside existing) -- AskUserQuestion: does the project already have transfer operations to extend, or is this greenfield? -- AskUserQuestion: action-level API (high-level, fewer lines) or instruction-level API (low-level, full control)? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Verify existing Rpc/signer setup is compatible with the cookbook prerequisites (light_client::rpc::Rpc, solana_sdk::signature::Keypair) -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash `cargo add light-token-client light-token light-client --features light-client/v2` -- Follow the cookbook guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash `cargo check` -- Bash `cargo test` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work -``` diff --git a/snippets/ai-prompts/rust-cookbook/transfer-interface.mdx b/snippets/ai-prompts/rust-cookbook/transfer-interface.mdx deleted file mode 100644 index fd107732..00000000 --- a/snippets/ai-prompts/rust-cookbook/transfer-interface.mdx +++ /dev/null @@ -1,125 +0,0 @@ - -{`--- -description: Transfer tokens between Light Token and SPL accounts -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Transfer tokens between Light Token and SPL accounts - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/transfer-interface -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Crates: light-token-client (actions), light-token (instructions), light-client (RPC) - -TransferInterface transfers tokens between token accounts (SPL, Token 2022, or Light Token) in a single call. -- Light Token → Light Token: transfers between Light Token accounts -- SPL → Light Token: locks SPL tokens in interface PDA, mints to Light Token account -- Light Token → SPL: burns Light Token balance, releases SPL tokens from interface PDA - -SPL equivalent: spl_token::instruction::transfer → Light Token: TransferInterface - -### 1. Index project -- Grep \`light_token::|light_token_client::|solana_sdk|Keypair|async|TransferInterface|transfer\` across src/ -- Glob \`**/*.rs\` for project structure -- Identify: RPC setup, existing token ops, entry point for transfers -- Check Cargo.toml for existing light-* dependencies and solana-sdk version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — follow the Rust Client tab -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new feature, migrate existing SPL code, add alongside existing) -- AskUserQuestion: does the project already have transfer operations to extend, or is this greenfield? -- AskUserQuestion: action-level API (high-level, fewer lines) or instruction-level API (low-level, full control)? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Verify existing Rpc/signer setup is compatible with the cookbook prerequisites (light_client::rpc::Rpc, solana_sdk::signature::Keypair) -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash \`cargo add light-token-client light-token light-client --features light-client/v2\` -- Follow the cookbook guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash \`cargo check\` -- Bash \`cargo test\` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work`} - - -```text ---- -description: Transfer tokens between Light Token and SPL accounts -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Transfer tokens between Light Token and SPL accounts - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/transfer-interface -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Crates: light-token-client (actions), light-token (instructions), light-client (RPC) - -TransferInterface transfers tokens between token accounts (SPL, Token 2022, or Light Token) in a single call. -- Light Token → Light Token: transfers between Light Token accounts -- SPL → Light Token: locks SPL tokens in interface PDA, mints to Light Token account -- Light Token → SPL: burns Light Token balance, releases SPL tokens from interface PDA - -SPL equivalent: spl_token::instruction::transfer → Light Token: TransferInterface - -### 1. Index project -- Grep `light_token::|light_token_client::|solana_sdk|Keypair|async|TransferInterface|transfer` across src/ -- Glob `**/*.rs` for project structure -- Identify: RPC setup, existing token ops, entry point for transfers -- Check Cargo.toml for existing light-* dependencies and solana-sdk version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — follow the Rust Client tab -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new feature, migrate existing SPL code, add alongside existing) -- AskUserQuestion: does the project already have transfer operations to extend, or is this greenfield? -- AskUserQuestion: action-level API (high-level, fewer lines) or instruction-level API (low-level, full control)? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Verify existing Rpc/signer setup is compatible with the cookbook prerequisites (light_client::rpc::Rpc, solana_sdk::signature::Keypair) -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash `cargo add light-token-client light-token light-client --features light-client/v2` -- Follow the cookbook guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash `cargo check` -- Bash `cargo test` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work -``` diff --git a/snippets/ai-prompts/rust-cookbook/wrap-unwrap.mdx b/snippets/ai-prompts/rust-cookbook/wrap-unwrap.mdx deleted file mode 100644 index 8202046e..00000000 --- a/snippets/ai-prompts/rust-cookbook/wrap-unwrap.mdx +++ /dev/null @@ -1,121 +0,0 @@ - -{`--- -description: Wrap and unwrap SPL tokens to Light Token -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Wrap and unwrap SPL tokens to Light Token - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/wrap-unwrap -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Crates: light-token-client (actions), light-token (instructions), light-client (RPC) - -- Wrap: move tokens from SPL or Token 2022 account → Light Token ATA (hot balance) -- Unwrap: move tokens from Light Token ATA (hot balance) → SPL or Token 2022 account - -No direct SPL equivalent — Wrap/Unwrap are Light Token operations → Light Token: Wrap / Unwrap - -### 1. Index project -- Grep \`light_token::|light_token_client::|solana_sdk|Keypair|async|Wrap|Unwrap|wrap|unwrap\` across src/ -- Glob \`**/*.rs\` for project structure -- Identify: RPC setup, existing token ops, entry point for wrap/unwrap -- Check Cargo.toml for existing light-* dependencies and solana-sdk version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — follow the Rust Client tab -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new feature, migrate existing SPL code, add alongside existing) -- AskUserQuestion: does the project already have wrap/unwrap operations to extend, or is this greenfield? -- AskUserQuestion: action-level API (high-level, fewer lines) or instruction-level API (low-level, full control)? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Verify existing Rpc/signer setup is compatible with the cookbook prerequisites (light_client::rpc::Rpc, solana_sdk::signature::Keypair) -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash \`cargo add light-token-client light-token light-client --features light-client/v2\` -- Follow the cookbook guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash \`cargo check\` -- Bash \`cargo test\` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work`} - - -```text ---- -description: Wrap and unwrap SPL tokens to Light Token -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Wrap and unwrap SPL tokens to Light Token - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/wrap-unwrap -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Crates: light-token-client (actions), light-token (instructions), light-client (RPC) - -- Wrap: move tokens from SPL or Token 2022 account → Light Token ATA (hot balance) -- Unwrap: move tokens from Light Token ATA (hot balance) → SPL or Token 2022 account - -No direct SPL equivalent — Wrap/Unwrap are Light Token operations → Light Token: Wrap / Unwrap - -### 1. Index project -- Grep `light_token::|light_token_client::|solana_sdk|Keypair|async|Wrap|Unwrap|wrap|unwrap` across src/ -- Glob `**/*.rs` for project structure -- Identify: RPC setup, existing token ops, entry point for wrap/unwrap -- Check Cargo.toml for existing light-* dependencies and solana-sdk version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — follow the Rust Client tab -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new feature, migrate existing SPL code, add alongside existing) -- AskUserQuestion: does the project already have wrap/unwrap operations to extend, or is this greenfield? -- AskUserQuestion: action-level API (high-level, fewer lines) or instruction-level API (low-level, full control)? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Verify existing Rpc/signer setup is compatible with the cookbook prerequisites (light_client::rpc::Rpc, solana_sdk::signature::Keypair) -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash `cargo add light-token-client light-token light-client --features light-client/v2` -- Follow the cookbook guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash `cargo check` -- Bash `cargo test` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work -``` diff --git a/snippets/ai-prompts/rust-template.mdx b/snippets/ai-prompts/rust-template.mdx deleted file mode 100644 index ed5021d5..00000000 --- a/snippets/ai-prompts/rust-template.mdx +++ /dev/null @@ -1,57 +0,0 @@ -```text ---- -description: {{OPERATION_DESCRIPTION}} -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## {{OPERATION_DESCRIPTION}} - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/{{PAGE_SLUG}} -- Skills and resources index: https://zkcompression.com/skill.md -- Crates: light-token-client (actions), light-token (instructions), light-client (RPC) -{{EXTRA_REFS}} - -SPL equivalent: {{SPL_FUNCTION}} → Light Token: {{LIGHT_FUNCTION}} - -### 1. Index project -- Grep `light_token::|light_token_client::|solana_sdk|Keypair|async{{EXTRA_GREP}}` across src/ -- Glob `**/*.rs` for project structure -- Identify: RPC setup, existing token ops, entry point for {{OP_SHORT}} -- Check Cargo.toml for existing light-* dependencies and solana-sdk version -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — follow the Rust Client tab -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new feature, migrate existing SPL code, add alongside existing) -- AskUserQuestion: does the project already have token operations to extend, or is this greenfield? -- AskUserQuestion: action-level API (high-level, fewer lines) or instruction-level API (low-level, full control)? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Verify existing Rpc/signer setup is compatible with the cookbook prerequisites (light_client::rpc::Rpc, solana_sdk::signature::Keypair) -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash `cargo add light-token-client light-token light-client --features light-client/v2` -- Follow the cookbook guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash `cargo check` -- Bash `cargo test` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work -``` diff --git a/snippets/ai-prompts/streaming/mints.mdx b/snippets/ai-prompts/streaming/mints.mdx deleted file mode 100644 index deef39ab..00000000 --- a/snippets/ai-prompts/streaming/mints.mdx +++ /dev/null @@ -1,117 +0,0 @@ - -{`--- -description: Stream light-mint accounts and metadata via Laserstream gRPC -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Stream light-mint accounts and metadata via Laserstream gRPC - -Context: -- Guide: https://zkcompression.com/light-token/streaming/mints -- Skills and resources index: https://zkcompression.com/skill.md -- Dedicated skill: https://github.com/Lightprotocol/skills/tree/main/skills/data-streaming -- Crates: helius-laserstream, light-token-interface, borsh, futures -- Token accounts streaming: https://zkcompression.com/light-token/streaming/tokens - -Key APIs: LaserstreamConfig, subscribe(), Mint::deserialize(), ExtensionStruct::TokenMetadata - -### 1. Index project -- Grep \`helius_laserstream|laserstream|subscribe|StreamExt|light_token_interface|Mint|cTokenmWW8bLPjZEBAUgYy3zKxQZW6VKi7bqNFEVv3m\` across src/ -- Glob \`**/*.rs\` and \`**/Cargo.toml\` for project structure -- Identify: existing gRPC streaming setup, account caching, deserialization logic -- Read Cargo.toml — note existing dependencies -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — follow the Steps (Connect, Subscribe, Deserialize, Detect cold, Extract metadata) -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new streaming pipeline for mints, add mint streaming to existing token streaming, specific use case like metadata indexing) -- AskUserQuestion: mainnet or devnet? -- AskUserQuestion: do you need cold/hot transition detection, or just live mint state? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan -- Follow the guide's step order: Connect → Subscribe (account + transaction subs) → Deserialize Mint → Detect Cold → Extract Metadata -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash \`cargo add helius-laserstream@0.1 light-token-interface@0.5 borsh@0.10 futures@0.3 bs58@0.5 tokio --features full\` -- Follow the guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash \`cargo check\` -- Bash \`cargo test\` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work`} - - -```text ---- -description: Stream light-mint accounts and metadata via Laserstream gRPC -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Stream light-mint accounts and metadata via Laserstream gRPC - -Context: -- Guide: https://zkcompression.com/light-token/streaming/mints -- Skills and resources index: https://zkcompression.com/skill.md -- Dedicated skill: https://github.com/Lightprotocol/skills/tree/main/skills/data-streaming -- Crates: helius-laserstream, light-token-interface, borsh, futures -- Token accounts streaming: https://zkcompression.com/light-token/streaming/tokens - -Key APIs: LaserstreamConfig, subscribe(), Mint::deserialize(), ExtensionStruct::TokenMetadata - -### 1. Index project -- Grep `helius_laserstream|laserstream|subscribe|StreamExt|light_token_interface|Mint|cTokenmWW8bLPjZEBAUgYy3zKxQZW6VKi7bqNFEVv3m` across src/ -- Glob `**/*.rs` and `**/Cargo.toml` for project structure -- Identify: existing gRPC streaming setup, account caching, deserialization logic -- Read Cargo.toml — note existing dependencies -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — follow the Steps (Connect, Subscribe, Deserialize, Detect cold, Extract metadata) -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new streaming pipeline for mints, add mint streaming to existing token streaming, specific use case like metadata indexing) -- AskUserQuestion: mainnet or devnet? -- AskUserQuestion: do you need cold/hot transition detection, or just live mint state? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan -- Follow the guide's step order: Connect → Subscribe (account + transaction subs) → Deserialize Mint → Detect Cold → Extract Metadata -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash `cargo add helius-laserstream@0.1 light-token-interface@0.5 borsh@0.10 futures@0.3 bs58@0.5 tokio --features full` -- Follow the guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash `cargo check` -- Bash `cargo test` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work -``` diff --git a/snippets/ai-prompts/streaming/tokens.mdx b/snippets/ai-prompts/streaming/tokens.mdx deleted file mode 100644 index e6c95435..00000000 --- a/snippets/ai-prompts/streaming/tokens.mdx +++ /dev/null @@ -1,123 +0,0 @@ - -{`--- -description: Stream light-token accounts via Laserstream gRPC -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Stream light-token accounts via Laserstream gRPC - -Context: -- Guide: https://zkcompression.com/light-token/streaming/tokens -- Skills and resources index: https://zkcompression.com/skill.md -- Dedicated skill: https://github.com/Lightprotocol/skills/tree/main/skills/data-streaming -- Crates: helius-laserstream, light-token-interface, spl-pod, spl-token-2022-interface, borsh, futures -- Mint accounts streaming: https://zkcompression.com/light-token/streaming/mints -- Point queries: light-client (LightClient, get_account_interface) - -Key APIs: LaserstreamConfig, subscribe(), PodAccount (pod_from_bytes), LightClient::get_account_interface() - -### 1. Index project -- Grep \`helius_laserstream|laserstream|subscribe|PodAccount|pod_from_bytes|spl_token_2022_interface|cTokenmWW8bLPjZEBAUgYy3zKxQZW6VKi7bqNFEVv3m\` across src/ -- Glob \`**/*.rs\` and \`**/Cargo.toml\` for project structure -- Identify: existing gRPC streaming setup, token account caching, SPL parser usage -- Read Cargo.toml — note existing dependencies -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — follow the Steps (Connect, Subscribe) and the transition detection sections -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new streaming pipeline for token accounts, add to existing pipeline, integrate cold/hot detection for routing) -- AskUserQuestion: mainnet or devnet? -- AskUserQuestion: do you need point queries (get_account_interface) in addition to streaming? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan -- Follow the guide's structure: Connect → Subscribe (account + transaction subs) → Detect Transitions (hot-to-cold, cold-to-hot) → Point Queries (optional) -- Token accounts use the same 165-byte SPL layout — existing SPL parsers work directly -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash \`cargo add helius-laserstream@0.1 light-token-interface@0.5 spl-pod spl-token-2022-interface borsh@0.10 futures@0.3 bs58@0.5 tokio --features full\` -- For point queries, also: Bash \`cargo add light-client@0.23 --features v2\` -- Follow the guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash \`cargo check\` -- Bash \`cargo test\` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work`} - - -```text ---- -description: Stream light-token accounts via Laserstream gRPC -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Stream light-token accounts via Laserstream gRPC - -Context: -- Guide: https://zkcompression.com/light-token/streaming/tokens -- Skills and resources index: https://zkcompression.com/skill.md -- Dedicated skill: https://github.com/Lightprotocol/skills/tree/main/skills/data-streaming -- Crates: helius-laserstream, light-token-interface, spl-pod, spl-token-2022-interface, borsh, futures -- Mint accounts streaming: https://zkcompression.com/light-token/streaming/mints -- Point queries: light-client (LightClient, get_account_interface) - -Key APIs: LaserstreamConfig, subscribe(), PodAccount (pod_from_bytes), LightClient::get_account_interface() - -### 1. Index project -- Grep `helius_laserstream|laserstream|subscribe|PodAccount|pod_from_bytes|spl_token_2022_interface|cTokenmWW8bLPjZEBAUgYy3zKxQZW6VKi7bqNFEVv3m` across src/ -- Glob `**/*.rs` and `**/Cargo.toml` for project structure -- Identify: existing gRPC streaming setup, token account caching, SPL parser usage -- Read Cargo.toml — note existing dependencies -- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel - -### 2. Read references -- WebFetch the guide above — follow the Steps (Connect, Subscribe) and the transition detection sections -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new streaming pipeline for token accounts, add to existing pipeline, integrate cold/hot detection for routing) -- AskUserQuestion: mainnet or devnet? -- AskUserQuestion: do you need point queries (get_account_interface) in addition to streaming? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan -- Follow the guide's structure: Connect → Subscribe (account + transaction subs) → Detect Transitions (hot-to-cold, cold-to-hot) → Point Queries (optional) -- Token accounts use the same 165-byte SPL layout — existing SPL parsers work directly -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash `cargo add helius-laserstream@0.1 light-token-interface@0.5 spl-pod spl-token-2022-interface borsh@0.10 futures@0.3 bs58@0.5 tokio --features full` -- For point queries, also: Bash `cargo add light-client@0.23 --features v2` -- Follow the guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash `cargo check` -- Bash `cargo test` if tests exist -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work -``` diff --git a/snippets/ai-prompts/template.mdx b/snippets/ai-prompts/template.mdx deleted file mode 100644 index 786f9661..00000000 --- a/snippets/ai-prompts/template.mdx +++ /dev/null @@ -1,55 +0,0 @@ -```text ---- -description: {{OPERATION_DESCRIPTION}} -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## {{OPERATION_DESCRIPTION}} - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/{{PAGE_SLUG}} -- Skills and resources index: https://zkcompression.com/skill.md -- Packages: @lightprotocol/compressed-token, @lightprotocol/stateless.js -{{EXTRA_REFS}} - -SPL equivalent: {{SPL_FUNCTION}} → Light Token: {{LIGHT_FUNCTION}} - -### 1. Index project -- Grep `@solana/spl-token|Connection|Keypair` across src/ -- Glob `**/*.ts` for project structure -- Identify: RPC setup, existing token ops, entry point for {{OP_SHORT}} -- Task subagent (Grep/Read/WebFetch) if project has multiple packages to scan in parallel - -### 2. Read references -- WebFetch the guide above — follow the TypeScript Client tab -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new feature, migrate existing SPL code, add alongside existing) -- AskUserQuestion: does the project already have token operations to extend, or is this greenfield? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Verify existing connection/signer setup is compatible with the cookbook prerequisites -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash `npm install @lightprotocol/compressed-token @lightprotocol/stateless.js` -- Follow the cookbook guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash `tsc --noEmit` -- Bash run existing test suite if present -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work -``` diff --git a/snippets/ai-prompts/toolkits/airdrop.mdx b/snippets/ai-prompts/toolkits/airdrop.mdx index b244aea0..1c166324 100644 --- a/snippets/ai-prompts/toolkits/airdrop.mdx +++ b/snippets/ai-prompts/toolkits/airdrop.mdx @@ -7,7 +7,7 @@ allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, T ## Distribute compressed tokens via airdrop Context: -- Guide: https://zkcompression.com/token-distribution +- Guide: https://zkcompression.com/compressed-tokens/token-distribution - Skills and resources index: https://zkcompression.com/skill.md - Dedicated skill: https://github.com/Lightprotocol/skills/tree/main/skills/airdrop - Packages: @lightprotocol/compressed-token, @lightprotocol/stateless.js, @solana/spl-token @@ -71,7 +71,7 @@ allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, T ## Distribute compressed tokens via airdrop Context: -- Guide: https://zkcompression.com/token-distribution +- Guide: https://zkcompression.com/compressed-tokens/token-distribution - Skills and resources index: https://zkcompression.com/skill.md - Dedicated skill: https://github.com/Lightprotocol/skills/tree/main/skills/airdrop - Packages: @lightprotocol/compressed-token, @lightprotocol/stateless.js, @solana/spl-token diff --git a/snippets/ai-prompts/toolkits/nullifiers.mdx b/snippets/ai-prompts/toolkits/nullifiers.mdx index f891403a..4868c338 100644 --- a/snippets/ai-prompts/toolkits/nullifiers.mdx +++ b/snippets/ai-prompts/toolkits/nullifiers.mdx @@ -7,7 +7,7 @@ allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, T ## Create rent-free nullifier PDAs to prevent duplicate actions Context: -- Guide: https://zkcompression.com/pda/compressed-pdas/nullifier-pda +- Guide: https://zkcompression.com/compressed-pdas/nullifier-pda - Skills and resources index: https://zkcompression.com/skill.md - Dedicated skill: https://github.com/Lightprotocol/skills/tree/main/skills/zk-nullifier - Rust crates: light-nullifier-program, light-client @@ -72,7 +72,7 @@ allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, T ## Create rent-free nullifier PDAs to prevent duplicate actions Context: -- Guide: https://zkcompression.com/pda/compressed-pdas/nullifier-pda +- Guide: https://zkcompression.com/compressed-pdas/nullifier-pda - Skills and resources index: https://zkcompression.com/skill.md - Dedicated skill: https://github.com/Lightprotocol/skills/tree/main/skills/zk-nullifier - Rust crates: light-nullifier-program, light-client diff --git a/snippets/ai-prompts/toolkits/payments.mdx b/snippets/ai-prompts/toolkits/payments.mdx deleted file mode 100644 index 4e7f9318..00000000 --- a/snippets/ai-prompts/toolkits/payments.mdx +++ /dev/null @@ -1,209 +0,0 @@ - -{`--- -description: Integrate light-token APIs for stablecoin payments -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Integrate light-token APIs for stablecoin payments - -Context: -- Guide: https://zkcompression.com/light-token/payments/overview -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Dedicated skill: https://github.com/Lightprotocol/skills/tree/main/skills/payments -- Packages: @lightprotocol/compressed-token, @lightprotocol/stateless.js -- Import from @lightprotocol/compressed-token/unified for all interface APIs - -SPL → Light Token API mapping: -| Operation | SPL | Light Token | -| Receive | getOrCreateAssociatedTokenAccount() | createLoadAtaInstructions() / loadAta() | -| Transfer | createTransferInstruction() | createTransferInterfaceInstructions() | -| Delegated Transfer | transfer() (delegate signs) | transferInterface(..., ownerPubkey, delegateSigner, ...) | -| Get Balance | getAccount() | getAtaInterface() | -| Tx History | getSignaturesForAddress() | getSignaturesForOwnerInterface() | -| Wrap SPL | N/A | createWrapInstruction() / wrap() | -| Unwrap | N/A | createUnwrapInstructions() / unwrap() | - -### 1. Index project -- Grep \`@solana/spl-token|@lightprotocol|createTransferInstruction|getAccount|Connection|Keypair|stablecoin|payment\` across src/ -- Glob \`**/*.ts\` and \`**/*.tsx\` for project structure -- Identify: RPC setup, existing token operations, payment flow, wallet signing pattern -- Check package.json for existing @lightprotocol/* or @solana/spl-token dependencies -- Task subagent (Grep/Read/WebFetch) if project has multiple packages to scan in parallel - -### 2. Read references -- WebFetch the guide above — review Instruction and Action tabs for each operation -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new payment integration, migrate existing SPL payment flow, add alongside existing SPL) -- AskUserQuestion: which operations? (receive, send, balance, history, wrap, unwrap — or all) -- AskUserQuestion: instruction-level API (build your own transactions) or action-level API (high-level, fewer lines)? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Verify existing connection/signer setup is compatible (createRpc with ZK Compression endpoint) -- Key pattern: import from \`@lightprotocol/compressed-token/unified\` for all interface APIs -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash \`npm install @lightprotocol/compressed-token @lightprotocol/stateless.js\` -- Set up RPC: \`createRpc(RPC_ENDPOINT)\` with a ZK Compression endpoint (Helius, Triton) -- Import from \`@lightprotocol/compressed-token/unified\` for the interface APIs -- Follow the guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash \`tsc --noEmit\` -- Bash run existing test suite if present -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work - -### Resources - -Guides: -- Basic payment: https://zkcompression.com/light-token/payments/basic-payment -- Batch payments: https://zkcompression.com/light-token/payments/batch-payments -- Payment with memo: https://zkcompression.com/light-token/payments/payment-with-memo -- Receive payments: https://zkcompression.com/light-token/payments/receive-payments -- Verify payments: https://zkcompression.com/light-token/payments/verify-payments -- Verify recipient address: https://zkcompression.com/light-token/payments/verify-recipient-address -- Spend permissions: https://zkcompression.com/light-token/payments/spend-permissions -- Wrap and unwrap: https://zkcompression.com/light-token/payments/wrap-unwrap -- Production readiness: https://zkcompression.com/light-token/payments/production-readiness -- FAQ: https://zkcompression.com/faq -- Sign with Privy: https://zkcompression.com/light-token/wallets/privy -- Sign with Wallet Adapter: https://zkcompression.com/light-token/wallets/wallet-adapter -- Gasless transactions: https://zkcompression.com/light-token/wallets/gasless-transactions - -Examples: -- All payments: https://github.com/Lightprotocol/examples-light-token/tree/main/toolkits/payments -- Send (instruction): https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/send/basic-send-instruction.ts -- Send (action): https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/send/basic-send-action.ts -- Batch send: https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/send/batch-send.ts -- Payment with memo: https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/send/payment-with-memo.ts -- Receive: https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/receive/receive.ts -- Get balance: https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/verify/get-balance.ts -- Get history: https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/verify/get-history.ts -- Verify address: https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/verify/verify-address.ts -- Wrap: https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/interop/wrap.ts -- Unwrap: https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/interop/unwrap.ts -- Privy (Node.js): https://github.com/Lightprotocol/examples-light-token/tree/main/toolkits/sign-with-privy/nodejs -- Privy (React): https://github.com/Lightprotocol/examples-light-token/tree/main/toolkits/sign-with-privy/react -- Wallet Adapter (React): https://github.com/Lightprotocol/examples-light-token/tree/main/toolkits/sign-with-wallet-adapter/react -- Gasless transfer: https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/gasless-transactions/typescript/gasless-transfer.ts`} - - -```text ---- -description: Integrate light-token APIs for stablecoin payments -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Integrate light-token APIs for stablecoin payments - -Context: -- Guide: https://zkcompression.com/light-token/payments/overview -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Dedicated skill: https://github.com/Lightprotocol/skills/tree/main/skills/payments -- Packages: @lightprotocol/compressed-token, @lightprotocol/stateless.js -- Import from @lightprotocol/compressed-token/unified for all interface APIs - -SPL → Light Token API mapping: -| Operation | SPL | Light Token | -| Receive | getOrCreateAssociatedTokenAccount() | createLoadAtaInstructions() / loadAta() | -| Transfer | createTransferInstruction() | createTransferInterfaceInstructions() | -| Delegated Transfer | transfer() (delegate signs) | transferInterface(..., ownerPubkey, delegateSigner, ...) | -| Get Balance | getAccount() | getAtaInterface() | -| Tx History | getSignaturesForAddress() | getSignaturesForOwnerInterface() | -| Wrap SPL | N/A | createWrapInstruction() / wrap() | -| Unwrap | N/A | createUnwrapInstructions() / unwrap() | - -### 1. Index project -- Grep `@solana/spl-token|@lightprotocol|createTransferInstruction|getAccount|Connection|Keypair|stablecoin|payment` across src/ -- Glob `**/*.ts` and `**/*.tsx` for project structure -- Identify: RPC setup, existing token operations, payment flow, wallet signing pattern -- Check package.json for existing @lightprotocol/* or @solana/spl-token dependencies -- Task subagent (Grep/Read/WebFetch) if project has multiple packages to scan in parallel - -### 2. Read references -- WebFetch the guide above — review Instruction and Action tabs for each operation -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new payment integration, migrate existing SPL payment flow, add alongside existing SPL) -- AskUserQuestion: which operations? (receive, send, balance, history, wrap, unwrap — or all) -- AskUserQuestion: instruction-level API (build your own transactions) or action-level API (high-level, fewer lines)? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Verify existing connection/signer setup is compatible (createRpc with ZK Compression endpoint) -- Key pattern: import from `@lightprotocol/compressed-token/unified` for all interface APIs -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash `npm install @lightprotocol/compressed-token @lightprotocol/stateless.js` -- Set up RPC: `createRpc(RPC_ENDPOINT)` with a ZK Compression endpoint (Helius, Triton) -- Import from `@lightprotocol/compressed-token/unified` for the interface APIs -- Follow the guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash `tsc --noEmit` -- Bash run existing test suite if present -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work - -### Resources - -Guides: -- Basic payment: https://zkcompression.com/light-token/payments/basic-payment -- Batch payments: https://zkcompression.com/light-token/payments/batch-payments -- Payment with memo: https://zkcompression.com/light-token/payments/payment-with-memo -- Receive payments: https://zkcompression.com/light-token/payments/receive-payments -- Verify payments: https://zkcompression.com/light-token/payments/verify-payments -- Verify recipient address: https://zkcompression.com/light-token/payments/verify-recipient-address -- Spend permissions: https://zkcompression.com/light-token/payments/spend-permissions -- Wrap and unwrap: https://zkcompression.com/light-token/payments/wrap-unwrap -- Production readiness: https://zkcompression.com/light-token/payments/production-readiness -- FAQ: https://zkcompression.com/faq -- Sign with Privy: https://zkcompression.com/light-token/wallets/privy -- Sign with Wallet Adapter: https://zkcompression.com/light-token/wallets/wallet-adapter -- Gasless transactions: https://zkcompression.com/light-token/wallets/gasless-transactions - -Examples: -- All payments: https://github.com/Lightprotocol/examples-light-token/tree/main/toolkits/payments -- Send (instruction): https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/send/basic-send-instruction.ts -- Send (action): https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/send/basic-send-action.ts -- Batch send: https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/send/batch-send.ts -- Payment with memo: https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/send/payment-with-memo.ts -- Receive: https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/receive/receive.ts -- Get balance: https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/verify/get-balance.ts -- Get history: https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/verify/get-history.ts -- Verify address: https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/verify/verify-address.ts -- Wrap: https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/interop/wrap.ts -- Unwrap: https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/interop/unwrap.ts -- Privy (Node.js): https://github.com/Lightprotocol/examples-light-token/tree/main/toolkits/sign-with-privy/nodejs -- Privy (React): https://github.com/Lightprotocol/examples-light-token/tree/main/toolkits/sign-with-privy/react -- Wallet Adapter (React): https://github.com/Lightprotocol/examples-light-token/tree/main/toolkits/sign-with-wallet-adapter/react -- Gasless transfer: https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/gasless-transactions/typescript/gasless-transfer.ts -``` diff --git a/snippets/ai-prompts/toolkits/wallets.mdx b/snippets/ai-prompts/toolkits/wallets.mdx deleted file mode 100644 index bd07e643..00000000 --- a/snippets/ai-prompts/toolkits/wallets.mdx +++ /dev/null @@ -1,141 +0,0 @@ - -{`--- -description: Add light-token support to a wallet application -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Add light-token support to a wallet application - -Context: -- Guide: https://zkcompression.com/light-token/wallets/overview -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Dedicated skill: https://github.com/Lightprotocol/skills/tree/main/skills/payments -- Packages: @lightprotocol/compressed-token, @lightprotocol/stateless.js -- Full examples: https://github.com/Lightprotocol/examples-light-token/tree/main/toolkits/payments - -SPL → Light Token API mapping: -| Operation | SPL | Light Token | -| Receive | getOrCreateAssociatedTokenAccount() | createLoadAtaInstructions() / loadAta() | -| Transfer | createTransferInstruction() | createTransferInterfaceInstructions() | -| Get Balance | getAccount() | getAtaInterface() | -| Tx History | getSignaturesForAddress() | getSignaturesForOwnerInterface() | -| Wrap SPL | N/A | createWrapInstruction() / wrap() | -| Unwrap | N/A | createUnwrapInstructions() / unwrap() | - -### 1. Index project -- Grep \`@solana/spl-token|@lightprotocol|createTransferInstruction|getAccount|wallet|signTransaction|signAllTransactions|Connection\` across src/ -- Glob \`**/*.ts\` and \`**/*.tsx\` for project structure -- Identify: RPC setup, existing token display/balance logic, wallet adapter, transaction signing pattern -- Check package.json for existing @lightprotocol/* or @solana/spl-token dependencies -- Task subagent (Grep/Read/WebFetch) if project has multiple packages to scan in parallel - -### 2. Read references -- WebFetch the guide above — review Instruction and Action tabs for each operation -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new wallet integration, migrate existing SPL wallet to light-token, add light-token alongside existing SPL) -- AskUserQuestion: which operations? (receive, send, balance, history, wrap, unwrap — or all) -- AskUserQuestion: instruction-level API (build your own transactions) or action-level API (high-level, fewer lines)? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Verify existing connection/signer setup is compatible (createRpc with ZK Compression endpoint) -- Key pattern: import from \`@lightprotocol/compressed-token/unified\` for all interface APIs -- APIs return TransactionInstruction[][] — handle multi-tx case with signAllTransactions -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash \`npm install @lightprotocol/compressed-token @lightprotocol/stateless.js\` -- Set up RPC: \`createRpc(RPC_ENDPOINT)\` with a ZK Compression endpoint (Helius, Triton) -- Import from \`@lightprotocol/compressed-token/unified\` for the interface APIs -- Follow the guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash \`tsc --noEmit\` -- Bash run existing test suite if present -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work`} - - -```text ---- -description: Add light-token support to a wallet application -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Add light-token support to a wallet application - -Context: -- Guide: https://zkcompression.com/light-token/wallets/overview -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Dedicated skill: https://github.com/Lightprotocol/skills/tree/main/skills/payments -- Packages: @lightprotocol/compressed-token, @lightprotocol/stateless.js -- Full examples: https://github.com/Lightprotocol/examples-light-token/tree/main/toolkits/payments - -SPL → Light Token API mapping: -| Operation | SPL | Light Token | -| Receive | getOrCreateAssociatedTokenAccount() | createLoadAtaInstructions() / loadAta() | -| Transfer | createTransferInstruction() | createTransferInterfaceInstructions() | -| Get Balance | getAccount() | getAtaInterface() | -| Tx History | getSignaturesForAddress() | getSignaturesForOwnerInterface() | -| Wrap SPL | N/A | createWrapInstruction() / wrap() | -| Unwrap | N/A | createUnwrapInstructions() / unwrap() | - -### 1. Index project -- Grep `@solana/spl-token|@lightprotocol|createTransferInstruction|getAccount|wallet|signTransaction|signAllTransactions|Connection` across src/ -- Glob `**/*.ts` and `**/*.tsx` for project structure -- Identify: RPC setup, existing token display/balance logic, wallet adapter, transaction signing pattern -- Check package.json for existing @lightprotocol/* or @solana/spl-token dependencies -- Task subagent (Grep/Read/WebFetch) if project has multiple packages to scan in parallel - -### 2. Read references -- WebFetch the guide above — review Instruction and Action tabs for each operation -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new wallet integration, migrate existing SPL wallet to light-token, add light-token alongside existing SPL) -- AskUserQuestion: which operations? (receive, send, balance, history, wrap, unwrap — or all) -- AskUserQuestion: instruction-level API (build your own transactions) or action-level API (high-level, fewer lines)? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Verify existing connection/signer setup is compatible (createRpc with ZK Compression endpoint) -- Key pattern: import from `@lightprotocol/compressed-token/unified` for all interface APIs -- APIs return TransactionInstruction[][] — handle multi-tx case with signAllTransactions -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash `npm install @lightprotocol/compressed-token @lightprotocol/stateless.js` -- Set up RPC: `createRpc(RPC_ENDPOINT)` with a ZK Compression endpoint (Helius, Triton) -- Import from `@lightprotocol/compressed-token/unified` for the interface APIs -- Follow the guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash `tsc --noEmit` -- Bash run existing test suite if present -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work -``` diff --git a/snippets/ai-prompts/ts-cookbook/add-interface-pda.mdx b/snippets/ai-prompts/ts-cookbook/add-interface-pda.mdx deleted file mode 100644 index 90bae744..00000000 --- a/snippets/ai-prompts/ts-cookbook/add-interface-pda.mdx +++ /dev/null @@ -1,111 +0,0 @@ - -{`--- -description: Add interface PDA to existing SPL / Token 2022 mint -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Add interface PDA to existing SPL / Token 2022 mint - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/add-interface-pda -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Packages: @lightprotocol/compressed-token, @lightprotocol/stateless.js - -SPL equivalent: (none) → Light Token: createSplInterface() - -### 1. Index project -- Grep \`@solana/spl-token|Connection|Keypair|createSplInterface|LightTokenProgram\` across src/ -- Glob \`**/*.ts\` for project structure -- Identify: RPC setup, existing mint references, entry point for interface PDA creation -- Task subagent (Grep/Read/WebFetch) if project has multiple packages to scan in parallel - -### 2. Read references -- WebFetch the guide above — follow the TypeScript Client tab -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (register existing SPL mint, register Token 2022 mint, or both) -- AskUserQuestion: does the project already have Light Token operations, or is this the first integration? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Verify existing connection/signer setup is compatible with the cookbook prerequisites -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash \`npm install @lightprotocol/compressed-token @lightprotocol/stateless.js\` -- Follow the cookbook guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash \`tsc --noEmit\` -- Bash run existing test suite if present -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work`} - - -```text ---- -description: Add interface PDA to existing SPL / Token 2022 mint -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Add interface PDA to existing SPL / Token 2022 mint - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/add-interface-pda -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Packages: @lightprotocol/compressed-token, @lightprotocol/stateless.js - -SPL equivalent: (none) → Light Token: createSplInterface() - -### 1. Index project -- Grep `@solana/spl-token|Connection|Keypair|createSplInterface|LightTokenProgram` across src/ -- Glob `**/*.ts` for project structure -- Identify: RPC setup, existing mint references, entry point for interface PDA creation -- Task subagent (Grep/Read/WebFetch) if project has multiple packages to scan in parallel - -### 2. Read references -- WebFetch the guide above — follow the TypeScript Client tab -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (register existing SPL mint, register Token 2022 mint, or both) -- AskUserQuestion: does the project already have Light Token operations, or is this the first integration? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Verify existing connection/signer setup is compatible with the cookbook prerequisites -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash `npm install @lightprotocol/compressed-token @lightprotocol/stateless.js` -- Follow the cookbook guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash `tsc --noEmit` -- Bash run existing test suite if present -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work -``` diff --git a/snippets/ai-prompts/ts-cookbook/approve-revoke.mdx b/snippets/ai-prompts/ts-cookbook/approve-revoke.mdx deleted file mode 100644 index 93ff435f..00000000 --- a/snippets/ai-prompts/ts-cookbook/approve-revoke.mdx +++ /dev/null @@ -1,111 +0,0 @@ - -{`--- -description: Approve and revoke token delegates -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Approve and revoke token delegates - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/approve-revoke -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Packages: @lightprotocol/compressed-token, @lightprotocol/stateless.js - -SPL equivalent: approve() / revoke() → Light Token: approve() / revoke() - -### 1. Index project -- Grep \`@solana/spl-token|Connection|Keypair|approve|revoke|delegate\` across src/ -- Glob \`**/*.ts\` for project structure -- Identify: RPC setup, existing delegation logic, entry point for delegation -- Task subagent (Grep/Read/WebFetch) if project has multiple packages to scan in parallel - -### 2. Read references -- WebFetch the guide above — follow the TypeScript Client tab -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new feature, migrate existing SPL code, add alongside existing) -- AskUserQuestion: does the project already have delegate operations to extend, or is this greenfield? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Verify existing connection/signer setup is compatible with the cookbook prerequisites -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash \`npm install @lightprotocol/compressed-token @lightprotocol/stateless.js\` -- Follow the cookbook guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash \`tsc --noEmit\` -- Bash run existing test suite if present -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work`} - - -```text ---- -description: Approve and revoke token delegates -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Approve and revoke token delegates - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/approve-revoke -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Packages: @lightprotocol/compressed-token, @lightprotocol/stateless.js - -SPL equivalent: approve() / revoke() → Light Token: approve() / revoke() - -### 1. Index project -- Grep `@solana/spl-token|Connection|Keypair|approve|revoke|delegate` across src/ -- Glob `**/*.ts` for project structure -- Identify: RPC setup, existing delegation logic, entry point for delegation -- Task subagent (Grep/Read/WebFetch) if project has multiple packages to scan in parallel - -### 2. Read references -- WebFetch the guide above — follow the TypeScript Client tab -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new feature, migrate existing SPL code, add alongside existing) -- AskUserQuestion: does the project already have delegate operations to extend, or is this greenfield? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Verify existing connection/signer setup is compatible with the cookbook prerequisites -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash `npm install @lightprotocol/compressed-token @lightprotocol/stateless.js` -- Follow the cookbook guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash `tsc --noEmit` -- Bash run existing test suite if present -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work -``` diff --git a/snippets/ai-prompts/ts-cookbook/create-ata.mdx b/snippets/ai-prompts/ts-cookbook/create-ata.mdx deleted file mode 100644 index e251e67a..00000000 --- a/snippets/ai-prompts/ts-cookbook/create-ata.mdx +++ /dev/null @@ -1,111 +0,0 @@ - -{`--- -description: Create rent-free associated token account -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Create rent-free associated token account - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/create-ata -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Packages: @lightprotocol/compressed-token, @lightprotocol/stateless.js - -SPL equivalent: createAssociatedTokenAccount() → Light Token: createAtaInterface() - -### 1. Index project -- Grep \`@solana/spl-token|Connection|Keypair|createAssociatedTokenAccount|createAtaInterface\` across src/ -- Glob \`**/*.ts\` for project structure -- Identify: RPC setup, existing ATA logic, entry point for ATA creation -- Task subagent (Grep/Read/WebFetch) if project has multiple packages to scan in parallel - -### 2. Read references -- WebFetch the guide above — follow the TypeScript Client tab -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new feature, migrate existing SPL code, add alongside existing) -- AskUserQuestion: does the project already have ATA operations to extend, or is this greenfield? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Verify existing connection/signer setup is compatible with the cookbook prerequisites -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash \`npm install @lightprotocol/compressed-token @lightprotocol/stateless.js\` -- Follow the cookbook guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash \`tsc --noEmit\` -- Bash run existing test suite if present -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work`} - - -```text ---- -description: Create rent-free associated token account -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Create rent-free associated token account - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/create-ata -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Packages: @lightprotocol/compressed-token, @lightprotocol/stateless.js - -SPL equivalent: createAssociatedTokenAccount() → Light Token: createAtaInterface() - -### 1. Index project -- Grep `@solana/spl-token|Connection|Keypair|createAssociatedTokenAccount|createAtaInterface` across src/ -- Glob `**/*.ts` for project structure -- Identify: RPC setup, existing ATA logic, entry point for ATA creation -- Task subagent (Grep/Read/WebFetch) if project has multiple packages to scan in parallel - -### 2. Read references -- WebFetch the guide above — follow the TypeScript Client tab -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new feature, migrate existing SPL code, add alongside existing) -- AskUserQuestion: does the project already have ATA operations to extend, or is this greenfield? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Verify existing connection/signer setup is compatible with the cookbook prerequisites -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash `npm install @lightprotocol/compressed-token @lightprotocol/stateless.js` -- Follow the cookbook guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash `tsc --noEmit` -- Bash run existing test suite if present -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work -``` diff --git a/snippets/ai-prompts/ts-cookbook/create-mint.mdx b/snippets/ai-prompts/ts-cookbook/create-mint.mdx deleted file mode 100644 index cf0f3e96..00000000 --- a/snippets/ai-prompts/ts-cookbook/create-mint.mdx +++ /dev/null @@ -1,111 +0,0 @@ - -{`--- -description: Add rent-free mint with token metadata -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Add rent-free mint with token metadata - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/create-mint -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Packages: @lightprotocol/compressed-token, @lightprotocol/stateless.js - -SPL equivalent: createMint() → Light Token: createMintInterface() - -### 1. Index project -- Grep \`@solana/spl-token|Connection|Keypair|createMint\` across src/ -- Glob \`**/*.ts\` for project structure -- Identify: RPC setup, existing mint logic, entry point for mint creation -- Task subagent (Grep/Read/WebFetch) if project has multiple packages to scan in parallel - -### 2. Read references -- WebFetch the guide above — follow the TypeScript Client tab -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new feature, migrate existing SPL code, add alongside existing) -- AskUserQuestion: does the project already have mint operations to extend, or is this greenfield? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Verify existing connection/signer setup is compatible with the cookbook prerequisites -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash \`npm install @lightprotocol/compressed-token @lightprotocol/stateless.js\` -- Follow the cookbook guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash \`tsc --noEmit\` -- Bash run existing test suite if present -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work`} - - -```text ---- -description: Add rent-free mint with token metadata -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Add rent-free mint with token metadata - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/create-mint -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Packages: @lightprotocol/compressed-token, @lightprotocol/stateless.js - -SPL equivalent: createMint() → Light Token: createMintInterface() - -### 1. Index project -- Grep `@solana/spl-token|Connection|Keypair|createMint` across src/ -- Glob `**/*.ts` for project structure -- Identify: RPC setup, existing mint logic, entry point for mint creation -- Task subagent (Grep/Read/WebFetch) if project has multiple packages to scan in parallel - -### 2. Read references -- WebFetch the guide above — follow the TypeScript Client tab -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new feature, migrate existing SPL code, add alongside existing) -- AskUserQuestion: does the project already have mint operations to extend, or is this greenfield? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Verify existing connection/signer setup is compatible with the cookbook prerequisites -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash `npm install @lightprotocol/compressed-token @lightprotocol/stateless.js` -- Follow the cookbook guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash `tsc --noEmit` -- Bash run existing test suite if present -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work -``` diff --git a/snippets/ai-prompts/ts-cookbook/mint-to.mdx b/snippets/ai-prompts/ts-cookbook/mint-to.mdx deleted file mode 100644 index e3e3a403..00000000 --- a/snippets/ai-prompts/ts-cookbook/mint-to.mdx +++ /dev/null @@ -1,111 +0,0 @@ - -{`--- -description: Mint tokens to Light Token account -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Mint tokens to Light Token account - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/mint-to -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Packages: @lightprotocol/compressed-token, @lightprotocol/stateless.js - -SPL equivalent: mintTo() → Light Token: mintToInterface() - -### 1. Index project -- Grep \`@solana/spl-token|Connection|Keypair|mintTo|mintToInterface\` across src/ -- Glob \`**/*.ts\` for project structure -- Identify: RPC setup, existing mint logic, entry point for minting -- Task subagent (Grep/Read/WebFetch) if project has multiple packages to scan in parallel - -### 2. Read references -- WebFetch the guide above — follow the TypeScript Client tab -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new feature, migrate existing SPL code, add alongside existing) -- AskUserQuestion: does the project already have mint operations to extend, or is this greenfield? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Verify existing connection/signer setup is compatible with the cookbook prerequisites -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash \`npm install @lightprotocol/compressed-token @lightprotocol/stateless.js\` -- Follow the cookbook guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash \`tsc --noEmit\` -- Bash run existing test suite if present -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work`} - - -```text ---- -description: Mint tokens to Light Token account -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Mint tokens to Light Token account - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/mint-to -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Packages: @lightprotocol/compressed-token, @lightprotocol/stateless.js - -SPL equivalent: mintTo() → Light Token: mintToInterface() - -### 1. Index project -- Grep `@solana/spl-token|Connection|Keypair|mintTo|mintToInterface` across src/ -- Glob `**/*.ts` for project structure -- Identify: RPC setup, existing mint logic, entry point for minting -- Task subagent (Grep/Read/WebFetch) if project has multiple packages to scan in parallel - -### 2. Read references -- WebFetch the guide above — follow the TypeScript Client tab -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new feature, migrate existing SPL code, add alongside existing) -- AskUserQuestion: does the project already have mint operations to extend, or is this greenfield? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Verify existing connection/signer setup is compatible with the cookbook prerequisites -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash `npm install @lightprotocol/compressed-token @lightprotocol/stateless.js` -- Follow the cookbook guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash `tsc --noEmit` -- Bash run existing test suite if present -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work -``` diff --git a/snippets/ai-prompts/ts-cookbook/transfer-interface.mdx b/snippets/ai-prompts/ts-cookbook/transfer-interface.mdx deleted file mode 100644 index 1fb531ae..00000000 --- a/snippets/ai-prompts/ts-cookbook/transfer-interface.mdx +++ /dev/null @@ -1,127 +0,0 @@ - -{`--- -description: Transfer tokens between Light Token and SPL accounts -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Transfer tokens between Light Token and SPL accounts - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/transfer-interface -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Packages: @lightprotocol/compressed-token, @lightprotocol/stateless.js - -transferInterface() transfers tokens in a single call. The recipient parameter is a wallet public key. -Pass the source token-account owner pubkey and the signing authority separately: owner-signed flows use (owner.publicKey, owner); delegated flows use (owner.publicKey, delegate). Do not use removed InterfaceOptions.owner. -The SDK derives and creates the destination ATA internally. All transfers use transferChecked under the hood. -- Light Token → Light Token: transfers between Light Token accounts -- SPL → Light Token: locks SPL tokens in interface PDA, mints to Light Token account -- Light Token → SPL: burns Light Token balance, releases SPL tokens from interface PDA - -Edge case: for explicit destination token accounts (PDA/program-owned), use transferToAccountInterface() -or createTransferToAccountInterfaceInstructions(). Most integrations should use transferInterface(). - -### 1. Index project -- Grep \`@solana/spl-token|Connection|Keypair|transfer|transferInterface\` across src/ -- Glob \`**/*.ts\` for project structure -- Identify: RPC setup, existing transfer logic, entry point for transfers -- Task subagent (Grep/Read/WebFetch) if project has multiple packages to scan in parallel - -### 2. Read references -- WebFetch the guide above — follow the TypeScript Client tab -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new feature, migrate existing SPL code, add alongside existing) -- AskUserQuestion: does the project already have transfer operations to extend, or is this greenfield? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Verify existing connection/signer setup is compatible with the cookbook prerequisites -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash \`npm install @lightprotocol/compressed-token @lightprotocol/stateless.js\` -- Follow the cookbook guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash \`tsc --noEmit\` -- Bash run existing test suite if present -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work`} - - -```text ---- -description: Transfer tokens between Light Token and SPL accounts -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Transfer tokens between Light Token and SPL accounts - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/transfer-interface -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Packages: @lightprotocol/compressed-token, @lightprotocol/stateless.js - -transferInterface() transfers tokens in a single call. The recipient parameter is a wallet public key. -Pass the source token-account owner pubkey and the signing authority separately: owner-signed flows use (owner.publicKey, owner); delegated flows use (owner.publicKey, delegate). Do not use removed InterfaceOptions.owner. -The SDK derives and creates the destination ATA internally. All transfers use transferChecked under the hood. -- Light Token → Light Token: transfers between Light Token accounts -- SPL → Light Token: locks SPL tokens in interface PDA, mints to Light Token account -- Light Token → SPL: burns Light Token balance, releases SPL tokens from interface PDA - -Edge case: for explicit destination token accounts (PDA/program-owned), use transferToAccountInterface() -or createTransferToAccountInterfaceInstructions(). Most integrations should use transferInterface(). - -### 1. Index project -- Grep `@solana/spl-token|Connection|Keypair|transfer|transferInterface` across src/ -- Glob `**/*.ts` for project structure -- Identify: RPC setup, existing transfer logic, entry point for transfers -- Task subagent (Grep/Read/WebFetch) if project has multiple packages to scan in parallel - -### 2. Read references -- WebFetch the guide above — follow the TypeScript Client tab -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new feature, migrate existing SPL code, add alongside existing) -- AskUserQuestion: does the project already have transfer operations to extend, or is this greenfield? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Verify existing connection/signer setup is compatible with the cookbook prerequisites -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash `npm install @lightprotocol/compressed-token @lightprotocol/stateless.js` -- Follow the cookbook guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash `tsc --noEmit` -- Bash run existing test suite if present -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work -``` diff --git a/snippets/ai-prompts/ts-cookbook/wrap-unwrap.mdx b/snippets/ai-prompts/ts-cookbook/wrap-unwrap.mdx deleted file mode 100644 index fa133309..00000000 --- a/snippets/ai-prompts/ts-cookbook/wrap-unwrap.mdx +++ /dev/null @@ -1,113 +0,0 @@ - -{`--- -description: Wrap and unwrap SPL tokens to Light Token -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Wrap and unwrap SPL tokens to Light Token - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/wrap-unwrap -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Packages: @lightprotocol/compressed-token, @lightprotocol/stateless.js - -- Wrap: Move tokens from SPL or Token 2022 account → Light Token associated token account (hot balance) -- Unwrap: Move tokens from Light Token associated token account (hot balance) → SPL or Token 2022 account - -### 1. Index project -- Grep \`@solana/spl-token|Connection|Keypair|wrap|unwrap|WrapTokens|UnwrapTokens\` across src/ -- Glob \`**/*.ts\` for project structure -- Identify: RPC setup, existing wrap/unwrap logic, entry point for wrap/unwrap -- Task subagent (Grep/Read/WebFetch) if project has multiple packages to scan in parallel - -### 2. Read references -- WebFetch the guide above — follow the TypeScript Client tab -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new feature, migrate existing SPL code, add alongside existing) -- AskUserQuestion: does the project already have wrap/unwrap operations to extend, or is this greenfield? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Verify existing connection/signer setup is compatible with the cookbook prerequisites -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash \`npm install @lightprotocol/compressed-token @lightprotocol/stateless.js\` -- Follow the cookbook guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash \`tsc --noEmit\` -- Bash run existing test suite if present -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work`} - - -```text ---- -description: Wrap and unwrap SPL tokens to Light Token -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Wrap and unwrap SPL tokens to Light Token - -Context: -- Guide: https://zkcompression.com/light-token/cookbook/wrap-unwrap -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Packages: @lightprotocol/compressed-token, @lightprotocol/stateless.js - -- Wrap: Move tokens from SPL or Token 2022 account → Light Token associated token account (hot balance) -- Unwrap: Move tokens from Light Token associated token account (hot balance) → SPL or Token 2022 account - -### 1. Index project -- Grep `@solana/spl-token|Connection|Keypair|wrap|unwrap|WrapTokens|UnwrapTokens` across src/ -- Glob `**/*.ts` for project structure -- Identify: RPC setup, existing wrap/unwrap logic, entry point for wrap/unwrap -- Task subagent (Grep/Read/WebFetch) if project has multiple packages to scan in parallel - -### 2. Read references -- WebFetch the guide above — follow the TypeScript Client tab -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new feature, migrate existing SPL code, add alongside existing) -- AskUserQuestion: does the project already have wrap/unwrap operations to extend, or is this greenfield? -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Verify existing connection/signer setup is compatible with the cookbook prerequisites -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash `npm install @lightprotocol/compressed-token @lightprotocol/stateless.js` -- Follow the cookbook guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash `tsc --noEmit` -- Bash run existing test suite if present -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work -``` diff --git a/snippets/ai-prompts/wallets/gasless-transactions.mdx b/snippets/ai-prompts/wallets/gasless-transactions.mdx deleted file mode 100644 index 1df29cfa..00000000 --- a/snippets/ai-prompts/wallets/gasless-transactions.mdx +++ /dev/null @@ -1,147 +0,0 @@ - -{`--- -description: Gasless transactions for Light Token users -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Gasless transactions for Light Token users - -Context: -- Guide: https://zkcompression.com/light-token/wallets/gasless-transactions -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Dedicated skill: https://github.com/Lightprotocol/skills/tree/main/skills/payments -- Packages: @lightprotocol/compressed-token, @lightprotocol/stateless.js - -How rent sponsorship works: -- A rent sponsor PDA pays the rent-exemption cost on account creation so creators never lock up SOL -- The fee payer bumps a small virtual rent balance (766 lamports) on each write to keep the account active (hot) -- Set your application as the fee payer so users never pay rent or top-ups - -Key APIs: -| Language | Function | Payer parameter | -| TypeScript | createLightTokenTransferInstruction() | 5th argument: \`sponsor.publicKey\` | -| TypeScript | createAtaInterface() | 2nd argument: \`sponsor\` (Keypair) | -| Rust | TransferInterface { ..., payer: sponsor.pubkey() } | \`payer\` field | -| Rust | CreateAssociatedTokenAccount::new(sponsor, ...) | 1st argument: sponsor pubkey | - -### 1. Index project -- Grep \`feePayer|payer|createTransferInstruction|createLightTokenTransferInstruction|@lightprotocol|@solana/spl-token|Connection\` across src/ -- Glob \`**/*.ts\` and \`**/*.tsx\` for project structure -- Identify: existing token operations, RPC config, fee payer setup, signing flow -- Check package.json for existing @lightprotocol/* dependencies -- Task subagent (Grep/Read/WebFetch) if project has multiple packages to scan in parallel - -### 2. Read references -- WebFetch the guide above — review TypeScript and Rust code examples -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (add sponsored top-ups to existing light-token code, new integration from scratch, migrate from user-pays to sponsor-pays) -- AskUserQuestion: TypeScript or Rust client? -- AskUserQuestion: which operations need sponsoring? (transfers only, ATA creation + transfers, all write operations) -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Key pattern: set the \`payer\` parameter to the sponsor's public key on transfer and ATA creation instructions -- The sponsor Keypair must sign the transaction alongside the user -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash \`npm install @lightprotocol/compressed-token @lightprotocol/stateless.js\` -- Set up RPC: \`createRpc(RPC_ENDPOINT)\` with a ZK Compression endpoint (Helius, Triton) -- Import from \`@lightprotocol/compressed-token\` for the token APIs -- Set sponsor as payer: \`createLightTokenTransferInstruction(senderAta, recipientAta, sender.publicKey, amount, sponsor.publicKey)\` -- Sign with both sponsor and sender: \`sendAndConfirmTransaction(rpc, tx, [sponsor, sender])\` -- Follow the guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash \`tsc --noEmit\` -- Bash run existing test suite if present -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work`} - - -```text ---- -description: Gasless transactions for Light Token users -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Gasless transactions for Light Token users - -Context: -- Guide: https://zkcompression.com/light-token/wallets/gasless-transactions -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Dedicated skill: https://github.com/Lightprotocol/skills/tree/main/skills/payments -- Packages: @lightprotocol/compressed-token, @lightprotocol/stateless.js - -How rent sponsorship works: -- A rent sponsor PDA pays the rent-exemption cost on account creation so creators never lock up SOL -- The fee payer bumps a small virtual rent balance (766 lamports) on each write to keep the account active (hot) -- Set your application as the fee payer so users never pay rent or top-ups - -Key APIs: -| Language | Function | Payer parameter | -| TypeScript | createLightTokenTransferInstruction() | 5th argument: `sponsor.publicKey` | -| TypeScript | createAtaInterface() | 2nd argument: `sponsor` (Keypair) | -| Rust | TransferInterface { ..., payer: sponsor.pubkey() } | `payer` field | -| Rust | CreateAssociatedTokenAccount::new(sponsor, ...) | 1st argument: sponsor pubkey | - -### 1. Index project -- Grep `feePayer|payer|createTransferInstruction|createLightTokenTransferInstruction|@lightprotocol|@solana/spl-token|Connection` across src/ -- Glob `**/*.ts` and `**/*.tsx` for project structure -- Identify: existing token operations, RPC config, fee payer setup, signing flow -- Check package.json for existing @lightprotocol/* dependencies -- Task subagent (Grep/Read/WebFetch) if project has multiple packages to scan in parallel - -### 2. Read references -- WebFetch the guide above — review TypeScript and Rust code examples -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (add sponsored top-ups to existing light-token code, new integration from scratch, migrate from user-pays to sponsor-pays) -- AskUserQuestion: TypeScript or Rust client? -- AskUserQuestion: which operations need sponsoring? (transfers only, ATA creation + transfers, all write operations) -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Key pattern: set the `payer` parameter to the sponsor's public key on transfer and ATA creation instructions -- The sponsor Keypair must sign the transaction alongside the user -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash `npm install @lightprotocol/compressed-token @lightprotocol/stateless.js` -- Set up RPC: `createRpc(RPC_ENDPOINT)` with a ZK Compression endpoint (Helius, Triton) -- Import from `@lightprotocol/compressed-token` for the token APIs -- Set sponsor as payer: `createLightTokenTransferInstruction(senderAta, recipientAta, sender.publicKey, amount, sponsor.publicKey)` -- Sign with both sponsor and sender: `sendAndConfirmTransaction(rpc, tx, [sponsor, sender])` -- Follow the guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash `tsc --noEmit` -- Bash run existing test suite if present -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work -``` \ No newline at end of file diff --git a/snippets/ai-prompts/wallets/privy.mdx b/snippets/ai-prompts/wallets/privy.mdx deleted file mode 100644 index 192e875c..00000000 --- a/snippets/ai-prompts/wallets/privy.mdx +++ /dev/null @@ -1,141 +0,0 @@ - -{`--- -description: Integrate light-token with Privy embedded wallets -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Integrate light-token with Privy embedded wallets - -Context: -- Guide: https://zkcompression.com/light-token/wallets/privy -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Dedicated skill: https://github.com/Lightprotocol/skills/tree/main/skills/payments -- Packages: @lightprotocol/compressed-token, @lightprotocol/stateless.js -- Node.js example: https://github.com/Lightprotocol/examples-light-token/tree/main/toolkits/sign-with-privy/nodejs -- React example: https://github.com/Lightprotocol/examples-light-token/tree/main/toolkits/sign-with-privy/react - -SPL → Light Token API mapping: -| Operation | SPL | Light Token | -| Transfer | createTransferInstruction() | createTransferInterfaceInstructions() | -| Receive | getOrCreateAssociatedTokenAccount() | createLoadAtaInstructions() | -| Wrap SPL→Light | N/A | createWrapInstruction() | -| Unwrap Light→SPL | N/A | createUnwrapInstructions() | -| Get balance | getAccount() | getAtaInterface() | -| Tx history | getSignaturesForAddress() | getSignaturesForOwnerInterface() | - -### 1. Index project -- Grep \`privy|@privy-io|usePrivy|PrivyProvider|createTransferInstruction|@solana/spl-token|Connection\` across src/ -- Glob \`**/*.ts\` and \`**/*.tsx\` for project structure -- Identify: Privy SDK version, existing wallet setup, RPC config, token operations -- Check package.json for existing @lightprotocol/* or @solana/spl-token dependencies -- Task subagent (Grep/Read/WebFetch) if project has multiple packages to scan in parallel - -### 2. Read references -- WebFetch the guide above — review both Node.js and React code examples -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: Node.js or React? -- AskUserQuestion: what is the goal? (new Privy integration, migrate existing Privy+SPL code, add light-token alongside existing SPL) -- AskUserQuestion: which operations? (transfer, wrap, unwrap, balances, tx history — or all) -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Verify existing Privy wallet setup is compatible (signTransaction or sendTransaction pattern) -- Key integration pattern: build unsigned tx with light-token SDK → sign with Privy → send to RPC -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash \`npm install @lightprotocol/compressed-token @lightprotocol/stateless.js\` -- Set up RPC: \`createRpc(RPC_ENDPOINT)\` with a ZK Compression endpoint (Helius, Triton) -- Import from \`@lightprotocol/compressed-token/unified\` for the interface APIs -- Follow the guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash \`tsc --noEmit\` -- Bash run existing test suite if present -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work`} - - -```text ---- -description: Integrate light-token with Privy embedded wallets -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Integrate light-token with Privy embedded wallets - -Context: -- Guide: https://zkcompression.com/light-token/wallets/privy -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Dedicated skill: https://github.com/Lightprotocol/skills/tree/main/skills/payments -- Packages: @lightprotocol/compressed-token, @lightprotocol/stateless.js -- Node.js example: https://github.com/Lightprotocol/examples-light-token/tree/main/toolkits/sign-with-privy/nodejs -- React example: https://github.com/Lightprotocol/examples-light-token/tree/main/toolkits/sign-with-privy/react - -SPL → Light Token API mapping: -| Operation | SPL | Light Token | -| Transfer | createTransferInstruction() | createTransferInterfaceInstructions() | -| Receive | getOrCreateAssociatedTokenAccount() | createLoadAtaInstructions() | -| Wrap SPL→Light | N/A | createWrapInstruction() | -| Unwrap Light→SPL | N/A | createUnwrapInstructions() | -| Get balance | getAccount() | getAtaInterface() | -| Tx history | getSignaturesForAddress() | getSignaturesForOwnerInterface() | - -### 1. Index project -- Grep `privy|@privy-io|usePrivy|PrivyProvider|createTransferInstruction|@solana/spl-token|Connection` across src/ -- Glob `**/*.ts` and `**/*.tsx` for project structure -- Identify: Privy SDK version, existing wallet setup, RPC config, token operations -- Check package.json for existing @lightprotocol/* or @solana/spl-token dependencies -- Task subagent (Grep/Read/WebFetch) if project has multiple packages to scan in parallel - -### 2. Read references -- WebFetch the guide above — review both Node.js and React code examples -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: Node.js or React? -- AskUserQuestion: what is the goal? (new Privy integration, migrate existing Privy+SPL code, add light-token alongside existing SPL) -- AskUserQuestion: which operations? (transfer, wrap, unwrap, balances, tx history — or all) -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Verify existing Privy wallet setup is compatible (signTransaction or sendTransaction pattern) -- Key integration pattern: build unsigned tx with light-token SDK → sign with Privy → send to RPC -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash `npm install @lightprotocol/compressed-token @lightprotocol/stateless.js` -- Set up RPC: `createRpc(RPC_ENDPOINT)` with a ZK Compression endpoint (Helius, Triton) -- Import from `@lightprotocol/compressed-token/unified` for the interface APIs -- Follow the guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash `tsc --noEmit` -- Bash run existing test suite if present -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work -``` diff --git a/snippets/ai-prompts/wallets/wallet-adapter.mdx b/snippets/ai-prompts/wallets/wallet-adapter.mdx deleted file mode 100644 index 4ab74974..00000000 --- a/snippets/ai-prompts/wallets/wallet-adapter.mdx +++ /dev/null @@ -1,137 +0,0 @@ - -{`--- -description: Integrate light-token with Solana Wallet Adapter -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Integrate light-token with Solana Wallet Adapter - -Context: -- Guide: https://zkcompression.com/light-token/wallets/wallet-adapter -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Dedicated skill: https://github.com/Lightprotocol/skills/tree/main/skills/payments -- Packages: @lightprotocol/compressed-token, @lightprotocol/stateless.js -- React example: https://github.com/Lightprotocol/examples-light-token/tree/main/toolkits/sign-with-wallet-adapter/react - -SPL → Light Token API mapping: -| Operation | SPL | Light Token | -| Transfer | createTransferInstruction() | createTransferInterfaceInstructions() | -| Wrap SPL→Light | N/A | createWrapInstruction() | -| Unwrap Light→SPL | N/A | createUnwrapInstructions() | -| Get balance | getAccount() | getAtaInterface() | -| Tx history | getSignaturesForAddress() | getSignaturesForOwnerInterface() | - -### 1. Index project -- Grep \`wallet-adapter|useWallet|WalletProvider|useConnection|createTransferInstruction|@solana/spl-token|Connection\` across src/ -- Glob \`**/*.ts\` and \`**/*.tsx\` for project structure -- Identify: wallet adapter packages, existing wallet setup, RPC config, token operations -- Check package.json for existing @lightprotocol/* or @solana/spl-token dependencies -- Task subagent (Grep/Read/WebFetch) if project has multiple packages to scan in parallel - -### 2. Read references -- WebFetch the guide above — review the React code examples -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new wallet adapter integration, migrate existing wallet-adapter+SPL code, add light-token alongside existing SPL) -- AskUserQuestion: which operations? (transfer, wrap, unwrap, balances, tx history — or all) -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Verify existing wallet adapter setup is compatible (signTransaction pattern from useWallet) -- Key integration pattern: build unsigned tx with light-token SDK → sign with \`signTransaction\` from \`useWallet()\` → send to RPC -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash \`npm install @lightprotocol/compressed-token @lightprotocol/stateless.js\` -- Set up RPC: \`createRpc(RPC_ENDPOINT)\` with a ZK Compression endpoint (Helius, Triton) -- Import from \`@lightprotocol/compressed-token/unified\` for the interface APIs -- Use \`useWallet()\` to get \`publicKey\` and \`signTransaction\` -- Follow the guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash \`tsc --noEmit\` -- Bash run existing test suite if present -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work`} - - -```text ---- -description: Integrate light-token with Solana Wallet Adapter -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression ---- - -## Integrate light-token with Solana Wallet Adapter - -Context: -- Guide: https://zkcompression.com/light-token/wallets/wallet-adapter -- Skills and resources index: https://zkcompression.com/skill.md -- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison -- Dedicated skill: https://github.com/Lightprotocol/skills/tree/main/skills/payments -- Packages: @lightprotocol/compressed-token, @lightprotocol/stateless.js -- React example: https://github.com/Lightprotocol/examples-light-token/tree/main/toolkits/sign-with-wallet-adapter/react - -SPL → Light Token API mapping: -| Operation | SPL | Light Token | -| Transfer | createTransferInstruction() | createTransferInterfaceInstructions() | -| Wrap SPL→Light | N/A | createWrapInstruction() | -| Unwrap Light→SPL | N/A | createUnwrapInstructions() | -| Get balance | getAccount() | getAtaInterface() | -| Tx history | getSignaturesForAddress() | getSignaturesForOwnerInterface() | - -### 1. Index project -- Grep `wallet-adapter|useWallet|WalletProvider|useConnection|createTransferInstruction|@solana/spl-token|Connection` across src/ -- Glob `**/*.ts` and `**/*.tsx` for project structure -- Identify: wallet adapter packages, existing wallet setup, RPC config, token operations -- Check package.json for existing @lightprotocol/* or @solana/spl-token dependencies -- Task subagent (Grep/Read/WebFetch) if project has multiple packages to scan in parallel - -### 2. Read references -- WebFetch the guide above — review the React code examples -- WebFetch skill.md — check for a dedicated skill and resources matching this task -- TaskCreate one todo per phase below to track progress - -### 3. Clarify intention -- AskUserQuestion: what is the goal? (new wallet adapter integration, migrate existing wallet-adapter+SPL code, add light-token alongside existing SPL) -- AskUserQuestion: which operations? (transfer, wrap, unwrap, balances, tx history — or all) -- Summarize findings and wait for user confirmation before implementing - -### 4. Create plan -- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes -- Verify existing wallet adapter setup is compatible (signTransaction pattern from useWallet) -- Key integration pattern: build unsigned tx with light-token SDK → sign with `signTransaction` from `useWallet()` → send to RPC -- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion) -- Present the plan to the user for approval before proceeding - -### 5. Implement -- Add deps if missing: Bash `npm install @lightprotocol/compressed-token @lightprotocol/stateless.js` -- Set up RPC: `createRpc(RPC_ENDPOINT)` with a ZK Compression endpoint (Helius, Triton) -- Import from `@lightprotocol/compressed-token/unified` for the interface APIs -- Use `useWallet()` to get `publicKey` and `signTransaction` -- Follow the guide and the approved plan -- Write/Edit to create or modify files -- TaskUpdate to mark each step done - -### 6. Verify -- Bash `tsc --noEmit` -- Bash run existing test suite if present -- TaskUpdate to mark complete - -### Tools -- mcp__zkcompression__SearchLightProtocol("") for API details -- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "") for architecture -- Task subagent with Grep/Read/WebFetch for parallel lookups -- TaskList to check remaining work -``` diff --git a/snippets/code-snippets/compressed-token/approve/action.mdx b/snippets/code-snippets/compressed-token/approve/action.mdx new file mode 100644 index 00000000..357a0996 --- /dev/null +++ b/snippets/code-snippets/compressed-token/approve/action.mdx @@ -0,0 +1,39 @@ +```typescript +import "dotenv/config"; +import { Keypair } from "@solana/web3.js"; +import { createRpc } from "@lightprotocol/stateless.js"; +import { createMint, mintTo, approve } from "@lightprotocol/compressed-token"; +import BN from "bn.js"; +import { homedir } from "os"; +import { readFileSync } from "fs"; + +// devnet: +const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +// localnet: +// const RPC_URL = undefined; +const payer = Keypair.fromSecretKey( + new Uint8Array( + JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) + ) +); + +(async function () { + // devnet: + const rpc = createRpc(RPC_URL); + // localnet: + // const rpc = createRpc(); + + // Setup: Create mint and mint tokens + const { mint } = await createMint(rpc, payer, payer.publicKey, 9); + const owner = Keypair.generate(); + await mintTo(rpc, payer, mint, owner.publicKey, payer, 1_000_000_000); + + // Approve delegate + const delegate = Keypair.generate(); + const tx = await approve(rpc, payer, mint, new BN(500_000_000), owner, delegate.publicKey); + + console.log("Mint:", mint.toBase58()); + console.log("Delegate:", delegate.publicKey.toBase58()); + console.log("Tx:", tx); +})(); +``` diff --git a/snippets/code-snippets/compressed-token/compress-spl-account/action.mdx b/snippets/code-snippets/compressed-token/compress-spl-account/action.mdx new file mode 100644 index 00000000..892342fb --- /dev/null +++ b/snippets/code-snippets/compressed-token/compress-spl-account/action.mdx @@ -0,0 +1,51 @@ +```typescript +import "dotenv/config"; +import { Keypair } from "@solana/web3.js"; +import { createRpc, bn } from "@lightprotocol/stateless.js"; +import { createMint, compressSplTokenAccount } from "@lightprotocol/compressed-token"; +import { createAssociatedTokenAccount, mintTo, TOKEN_PROGRAM_ID } from "@solana/spl-token"; +import { homedir } from "os"; +import { readFileSync } from "fs"; + +// devnet: +const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +// localnet: +// const RPC_URL = undefined; +const payer = Keypair.fromSecretKey( + new Uint8Array( + JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) + ) +); + +(async function () { + // devnet: + const rpc = createRpc(RPC_URL); + // localnet: + // const rpc = createRpc(); + + // Setup: Create mint and SPL token account with tokens + const { mint } = await createMint(rpc, payer, payer.publicKey, 9); + const owner = Keypair.generate(); + const tokenAccount = await createAssociatedTokenAccount( + rpc, + payer, + mint, + owner.publicKey, + undefined, + TOKEN_PROGRAM_ID + ); + await mintTo(rpc, payer, mint, tokenAccount, payer, bn(1_000_000_000).toNumber()); + + // Compress entire SPL token account balance + const tx = await compressSplTokenAccount( + rpc, + payer, + mint, + owner, + tokenAccount + ); + + console.log("Mint:", mint.toBase58()); + console.log("Tx:", tx); +})(); +``` diff --git a/snippets/code-snippets/compressed-token/compress/action.mdx b/snippets/code-snippets/compressed-token/compress/action.mdx new file mode 100644 index 00000000..d7d33b58 --- /dev/null +++ b/snippets/code-snippets/compressed-token/compress/action.mdx @@ -0,0 +1,39 @@ +```typescript +import "dotenv/config"; +import { Keypair } from "@solana/web3.js"; +import { createRpc } from "@lightprotocol/stateless.js"; +import { createMint, mintTo, decompress, compress } from "@lightprotocol/compressed-token"; +import { createAssociatedTokenAccount } from "@solana/spl-token"; +import { homedir } from "os"; +import { readFileSync } from "fs"; + +// devnet: +const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +// localnet: +// const RPC_URL = undefined; +const payer = Keypair.fromSecretKey( + new Uint8Array( + JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) + ) +); + +(async function () { + // devnet: + const rpc = createRpc(RPC_URL); + // localnet: + // const rpc = createRpc(); + + // Setup: Get SPL tokens (needed to compress) + const { mint } = await createMint(rpc, payer, payer.publicKey, 9); + const splAta = await createAssociatedTokenAccount(rpc, payer, mint, payer.publicKey); + await mintTo(rpc, payer, mint, payer.publicKey, payer, 1_000_000_000); + await decompress(rpc, payer, mint, 1_000_000_000, payer, splAta); + + // Compress SPL tokens + const recipient = Keypair.generate(); + const tx = await compress(rpc, payer, mint, 500_000_000, payer, splAta, recipient.publicKey); + + console.log("Mint:", mint.toBase58()); + console.log("Tx:", tx); +})(); +``` diff --git a/snippets/code-snippets/light-token/create-spl-mint/action.mdx b/snippets/code-snippets/compressed-token/create-mint/action.mdx similarity index 56% rename from snippets/code-snippets/light-token/create-spl-mint/action.mdx rename to snippets/code-snippets/compressed-token/create-mint/action.mdx index 0f0c2413..186789db 100644 --- a/snippets/code-snippets/light-token/create-spl-mint/action.mdx +++ b/snippets/code-snippets/compressed-token/create-mint/action.mdx @@ -2,17 +2,14 @@ import "dotenv/config"; import { Keypair } from "@solana/web3.js"; import { createRpc } from "@lightprotocol/stateless.js"; -import { createMintInterface } from "@lightprotocol/compressed-token"; -import { TOKEN_PROGRAM_ID } from "@solana/spl-token"; +import { createMint } from "@lightprotocol/compressed-token"; import { homedir } from "os"; import { readFileSync } from "fs"; // devnet: const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; -const rpc = createRpc(RPC_URL); // localnet: -// const rpc = createRpc(); - +// const RPC_URL = undefined; const payer = Keypair.fromSecretKey( new Uint8Array( JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) @@ -20,17 +17,16 @@ const payer = Keypair.fromSecretKey( ); (async function () { - // Creates SPL mint + SPL Interface PDA in one transaction - const mintKeypair = Keypair.generate(); - const { mint, transactionSignature } = await createMintInterface( + // devnet: + const rpc = createRpc(RPC_URL); + // localnet: + // const rpc = createRpc(); + + const { mint, transactionSignature } = await createMint( rpc, payer, - payer, - null, - 9, - mintKeypair, - undefined, - TOKEN_PROGRAM_ID + payer.publicKey, + 9 ); console.log("Mint:", mint.toBase58()); diff --git a/snippets/code-snippets/light-token/create-mint/instruction.mdx b/snippets/code-snippets/compressed-token/create-mint/instruction.mdx similarity index 79% rename from snippets/code-snippets/light-token/create-mint/instruction.mdx rename to snippets/code-snippets/compressed-token/create-mint/instruction.mdx index c6ec4b96..47be6211 100644 --- a/snippets/code-snippets/light-token/create-mint/instruction.mdx +++ b/snippets/code-snippets/compressed-token/create-mint/instruction.mdx @@ -13,10 +13,7 @@ import { selectStateTreeInfo, LIGHT_TOKEN_PROGRAM_ID, } from "@lightprotocol/stateless.js"; -import { - createMintInstruction, - createTokenMetadata, -} from "@lightprotocol/compressed-token"; +import { createMintInstruction } from "@lightprotocol/compressed-token"; import { homedir } from "os"; import { readFileSync } from "fs"; @@ -30,10 +27,10 @@ function findMintAddress(mintSigner: PublicKey): [PublicKey, number] { } // devnet: -// const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; -// const rpc = createRpc(RPC_URL); +const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +const rpc = createRpc(RPC_URL); // localnet: -const rpc = createRpc(); +// const rpc = createRpc(); const payer = Keypair.fromSecretKey( new Uint8Array( @@ -60,22 +57,14 @@ const payer = Keypair.fromSecretKey( payer.publicKey, validityProof, addressTreeInfo, - stateTreeInfo, - createTokenMetadata( - "Example Token", - "EXT", - "https://example.com/metadata.json" - ) + stateTreeInfo ); const tx = new Transaction().add( ComputeBudgetProgram.setComputeUnitLimit({ units: 1_000_000 }), ix ); - const signature = await sendAndConfirmTransaction(rpc, tx, [ - payer, - mintSigner, - ]); + const signature = await sendAndConfirmTransaction(rpc, tx, [payer, mintSigner]); console.log("Mint:", mintPda.toBase58()); console.log("Tx:", signature); diff --git a/snippets/code-snippets/compressed-token/create-token-pool/action.mdx b/snippets/code-snippets/compressed-token/create-token-pool/action.mdx new file mode 100644 index 00000000..636d558d --- /dev/null +++ b/snippets/code-snippets/compressed-token/create-token-pool/action.mdx @@ -0,0 +1,36 @@ +```typescript +import "dotenv/config"; +import { Keypair, PublicKey } from "@solana/web3.js"; +import { createRpc } from "@lightprotocol/stateless.js"; +import { createTokenPool } from "@lightprotocol/compressed-token"; +import { createMint as createSplMint, TOKEN_PROGRAM_ID } from "@solana/spl-token"; +import { homedir } from "os"; +import { readFileSync } from "fs"; + +// devnet: +const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +// localnet: +// const RPC_URL = undefined; +const payer = Keypair.fromSecretKey( + new Uint8Array( + JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) + ) +); + +(async function () { + // devnet: + const rpc = createRpc(RPC_URL); + // localnet: + // const rpc = createRpc(); + + // Setup: Create existing SPL mint + const mintKeypair = Keypair.generate(); + await createSplMint(rpc, payer, payer.publicKey, null, 9, mintKeypair, undefined, TOKEN_PROGRAM_ID); + + // Create interface PDA for existing mint + const tx = await createTokenPool(rpc, payer, mintKeypair.publicKey); + + console.log("Mint:", mintKeypair.publicKey.toBase58()); + console.log("Tx:", tx); +})(); +``` diff --git a/snippets/code-snippets/compressed-token/decompress/action.mdx b/snippets/code-snippets/compressed-token/decompress/action.mdx new file mode 100644 index 00000000..8bd72642 --- /dev/null +++ b/snippets/code-snippets/compressed-token/decompress/action.mdx @@ -0,0 +1,37 @@ +```typescript +import "dotenv/config"; +import { Keypair } from "@solana/web3.js"; +import { createRpc } from "@lightprotocol/stateless.js"; +import { createMint, mintTo, decompress } from "@lightprotocol/compressed-token"; +import { createAssociatedTokenAccount } from "@solana/spl-token"; +import { homedir } from "os"; +import { readFileSync } from "fs"; + +// devnet: +const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +// localnet: +// const RPC_URL = undefined; +const payer = Keypair.fromSecretKey( + new Uint8Array( + JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) + ) +); + +(async function () { + // devnet: + const rpc = createRpc(RPC_URL); + // localnet: + // const rpc = createRpc(); + + // Setup: Create mint and mint compressed tokens + const { mint } = await createMint(rpc, payer, payer.publicKey, 9); + await mintTo(rpc, payer, mint, payer.publicKey, payer, 1_000_000_000); + const splAta = await createAssociatedTokenAccount(rpc, payer, mint, payer.publicKey); + + // Decompress to SPL tokens + const tx = await decompress(rpc, payer, mint, 500_000_000, payer, splAta); + + console.log("Mint:", mint.toBase58()); + console.log("Tx:", tx); +})(); +``` diff --git a/snippets/code-snippets/compressed-token/merge-token-accounts/action.mdx b/snippets/code-snippets/compressed-token/merge-token-accounts/action.mdx new file mode 100644 index 00000000..eea48df8 --- /dev/null +++ b/snippets/code-snippets/compressed-token/merge-token-accounts/action.mdx @@ -0,0 +1,38 @@ +```typescript +import "dotenv/config"; +import { Keypair } from "@solana/web3.js"; +import { createRpc, bn } from "@lightprotocol/stateless.js"; +import { createMint, mintTo, mergeTokenAccounts } from "@lightprotocol/compressed-token"; +import { homedir } from "os"; +import { readFileSync } from "fs"; + +// devnet: +const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +// localnet: +// const RPC_URL = undefined; +const payer = Keypair.fromSecretKey( + new Uint8Array( + JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) + ) +); + +(async function () { + // devnet: + const rpc = createRpc(RPC_URL); + // localnet: + // const rpc = createRpc(); + + // Setup: Create mint and mint multiple times to create multiple accounts + const { mint } = await createMint(rpc, payer, payer.publicKey, 9); + const owner = Keypair.generate(); + await mintTo(rpc, payer, mint, owner.publicKey, payer, bn(100_000_000)); + await mintTo(rpc, payer, mint, owner.publicKey, payer, bn(200_000_000)); + await mintTo(rpc, payer, mint, owner.publicKey, payer, bn(300_000_000)); + + // Merge all accounts for owner + const tx = await mergeTokenAccounts(rpc, payer, mint, owner); + + console.log("Mint:", mint.toBase58()); + console.log("Tx:", tx); +})(); +``` diff --git a/snippets/code-snippets/compressed-token/mint-to/action.mdx b/snippets/code-snippets/compressed-token/mint-to/action.mdx new file mode 100644 index 00000000..be0a05b7 --- /dev/null +++ b/snippets/code-snippets/compressed-token/mint-to/action.mdx @@ -0,0 +1,36 @@ +```typescript +import "dotenv/config"; +import { Keypair } from "@solana/web3.js"; +import { createRpc } from "@lightprotocol/stateless.js"; +import { createMint, mintTo } from "@lightprotocol/compressed-token"; +import { homedir } from "os"; +import { readFileSync } from "fs"; + +// devnet: +const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +// localnet: +// const RPC_URL = undefined; +const payer = Keypair.fromSecretKey( + new Uint8Array( + JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) + ) +); + +(async function () { + // devnet: + const rpc = createRpc(RPC_URL); + // localnet: + // const rpc = createRpc(); + + // Setup: Create mint + const { mint } = await createMint(rpc, payer, payer.publicKey, 9); + + // Mint compressed tokens + const recipient = Keypair.generate(); + const tx = await mintTo(rpc, payer, mint, recipient.publicKey, payer, 1_000_000_000); + + console.log("Mint:", mint.toBase58()); + console.log("Recipient:", recipient.publicKey.toBase58()); + console.log("Tx:", tx); +})(); +``` diff --git a/snippets/code-snippets/light-token/mint-to/instruction.mdx b/snippets/code-snippets/compressed-token/mint-to/instruction.mdx similarity index 82% rename from snippets/code-snippets/light-token/mint-to/instruction.mdx rename to snippets/code-snippets/compressed-token/mint-to/instruction.mdx index 7a2ccc63..bad87881 100644 --- a/snippets/code-snippets/light-token/mint-to/instruction.mdx +++ b/snippets/code-snippets/compressed-token/mint-to/instruction.mdx @@ -1,11 +1,6 @@ ```typescript import "dotenv/config"; -import { - Keypair, - ComputeBudgetProgram, - Transaction, - sendAndConfirmTransaction, -} from "@solana/web3.js"; +import { Keypair, ComputeBudgetProgram, Transaction, sendAndConfirmTransaction } from "@solana/web3.js"; import { createRpc, bn, DerivationMode } from "@lightprotocol/stateless.js"; import { createMintInterface, @@ -18,10 +13,10 @@ import { homedir } from "os"; import { readFileSync } from "fs"; // devnet: -// const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; -// const rpc = createRpc(RPC_URL); +const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +const rpc = createRpc(RPC_URL); // localnet: -const rpc = createRpc(); +// const rpc = createRpc(); const payer = Keypair.fromSecretKey( new Uint8Array( @@ -34,10 +29,7 @@ const payer = Keypair.fromSecretKey( const recipient = Keypair.generate(); await createAtaInterface(rpc, payer, mint, recipient.publicKey); - const destination = getAssociatedTokenAddressInterface( - mint, - recipient.publicKey - ); + const destination = getAssociatedTokenAddressInterface(mint, recipient.publicKey); const mintInterface = await getMintInterface(rpc, mint); @@ -72,6 +64,7 @@ const payer = Keypair.fromSecretKey( ); const signature = await sendAndConfirmTransaction(rpc, tx, [payer]); + console.log("Mint:", mint.toBase58()); console.log("Tx:", signature); })(); ``` diff --git a/snippets/code-snippets/compressed-token/revoke/action.mdx b/snippets/code-snippets/compressed-token/revoke/action.mdx new file mode 100644 index 00000000..52dfef41 --- /dev/null +++ b/snippets/code-snippets/compressed-token/revoke/action.mdx @@ -0,0 +1,40 @@ +```typescript +import "dotenv/config"; +import { Keypair } from "@solana/web3.js"; +import { createRpc } from "@lightprotocol/stateless.js"; +import { createMint, mintTo, approve, revoke } from "@lightprotocol/compressed-token"; +import BN from "bn.js"; +import { homedir } from "os"; +import { readFileSync } from "fs"; + +// devnet: +const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +// localnet: +// const RPC_URL = undefined; +const payer = Keypair.fromSecretKey( + new Uint8Array( + JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) + ) +); + +(async function () { + // devnet: + const rpc = createRpc(RPC_URL); + // localnet: + // const rpc = createRpc(); + + // Setup: Create mint, mint tokens, and approve delegate + const { mint } = await createMint(rpc, payer, payer.publicKey, 9); + const owner = Keypair.generate(); + await mintTo(rpc, payer, mint, owner.publicKey, payer, 1_000_000_000); + const delegate = Keypair.generate(); + await approve(rpc, payer, mint, new BN(500_000_000), owner, delegate.publicKey); + + // Get delegated accounts and revoke + const delegatedAccounts = await rpc.getCompressedTokenAccountsByDelegate(delegate.publicKey, { mint }); + const tx = await revoke(rpc, payer, delegatedAccounts.items, owner); + + console.log("Mint:", mint.toBase58()); + console.log("Tx:", tx); +})(); +``` diff --git a/snippets/code-snippets/compressed-token/transfer/action.mdx b/snippets/code-snippets/compressed-token/transfer/action.mdx new file mode 100644 index 00000000..ff7ab410 --- /dev/null +++ b/snippets/code-snippets/compressed-token/transfer/action.mdx @@ -0,0 +1,38 @@ +```typescript +import "dotenv/config"; +import { Keypair } from "@solana/web3.js"; +import { createRpc } from "@lightprotocol/stateless.js"; +import { createMint, mintTo, transfer } from "@lightprotocol/compressed-token"; +import { homedir } from "os"; +import { readFileSync } from "fs"; + +// devnet: +const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +// localnet: +// const RPC_URL = undefined; +const payer = Keypair.fromSecretKey( + new Uint8Array( + JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) + ) +); + +(async function () { + // devnet: + const rpc = createRpc(RPC_URL); + // localnet: + // const rpc = createRpc(); + + // Setup: Create mint and mint tokens + const { mint } = await createMint(rpc, payer, payer.publicKey, 9); + const sender = Keypair.generate(); + await mintTo(rpc, payer, mint, sender.publicKey, payer, 1_000_000_000); + + // Transfer compressed tokens + const recipient = Keypair.generate(); + const tx = await transfer(rpc, payer, mint, 500_000_000, sender, recipient.publicKey); + + console.log("Mint:", mint.toBase58()); + console.log("Recipient:", recipient.publicKey.toBase58()); + console.log("Tx:", tx); +})(); +``` diff --git a/snippets/code-snippets/light-token/approve-revoke/approve-action.mdx b/snippets/code-snippets/light-token/approve-revoke/approve-action.mdx deleted file mode 100644 index 8efc7cad..00000000 --- a/snippets/code-snippets/light-token/approve-revoke/approve-action.mdx +++ /dev/null @@ -1,48 +0,0 @@ -```typescript -import "dotenv/config"; -import { Keypair } from "@solana/web3.js"; -import { createRpc } from "@lightprotocol/stateless.js"; -import { - createMintInterface, - mintToCompressed, - getAssociatedTokenAddressInterface, -} from "@lightprotocol/compressed-token"; -import { approveInterface } from "@lightprotocol/compressed-token/unified"; -import { homedir } from "os"; -import { readFileSync } from "fs"; - -// devnet: -// const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; -// const rpc = createRpc(RPC_URL); -// localnet: -const rpc = createRpc(); - -const payer = Keypair.fromSecretKey( - new Uint8Array( - JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) - ) -); - -(async function () { - const { mint } = await createMintInterface(rpc, payer, payer, null, 9); - await mintToCompressed(rpc, payer, mint, payer, [ - { recipient: payer.publicKey, amount: 1_000_000_000n }, - ]); - - const senderAta = getAssociatedTokenAddressInterface(mint, payer.publicKey); - const delegate = Keypair.generate(); - const tx = await approveInterface( - rpc, - payer, - senderAta, - mint, - delegate.publicKey, - 500_000_000, - payer - ); - - console.log("Approved delegate:", delegate.publicKey.toBase58()); - console.log("Allowance: 500,000,000 tokens"); - console.log("Tx:", tx); -})(); -``` diff --git a/snippets/code-snippets/light-token/approve-revoke/revoke-action.mdx b/snippets/code-snippets/light-token/approve-revoke/revoke-action.mdx deleted file mode 100644 index 4d5a53cb..00000000 --- a/snippets/code-snippets/light-token/approve-revoke/revoke-action.mdx +++ /dev/null @@ -1,53 +0,0 @@ -```typescript -import "dotenv/config"; -import { Keypair } from "@solana/web3.js"; -import { createRpc } from "@lightprotocol/stateless.js"; -import { - createMintInterface, - mintToCompressed, - getAssociatedTokenAddressInterface, -} from "@lightprotocol/compressed-token"; -import { - approveInterface, - revokeInterface, -} from "@lightprotocol/compressed-token/unified"; -import { homedir } from "os"; -import { readFileSync } from "fs"; - -// devnet: -// const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; -// const rpc = createRpc(RPC_URL); -// localnet: -const rpc = createRpc(); - -const payer = Keypair.fromSecretKey( - new Uint8Array( - JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) - ) -); - -(async function () { - const { mint } = await createMintInterface(rpc, payer, payer, null, 9); - await mintToCompressed(rpc, payer, mint, payer, [ - { recipient: payer.publicKey, amount: 1_000_000_000n }, - ]); - - const senderAta = getAssociatedTokenAddressInterface(mint, payer.publicKey); - const delegate = Keypair.generate(); - await approveInterface( - rpc, - payer, - senderAta, - mint, - delegate.publicKey, - 500_000_000, - payer - ); - console.log("Approved delegate:", delegate.publicKey.toBase58()); - - const tx = await revokeInterface(rpc, payer, senderAta, mint, payer); - - console.log("Revoked all delegate permissions"); - console.log("Tx:", tx); -})(); -``` diff --git a/snippets/code-snippets/light-token/approve-revoke/rust-client/approve-action.mdx b/snippets/code-snippets/light-token/approve-revoke/rust-client/approve-action.mdx deleted file mode 100644 index 26156d6c..00000000 --- a/snippets/code-snippets/light-token/approve-revoke/rust-client/approve-action.mdx +++ /dev/null @@ -1,35 +0,0 @@ -```rust -use borsh::BorshDeserialize; -use light_client::rpc::Rpc; -use light_token_client::actions::Approve; -use rust_client::{setup, SetupContext}; -use solana_sdk::{signature::Keypair, signer::Signer}; - -#[tokio::main] -async fn main() -> Result<(), Box> { - // Setup creates mint and associated token account with tokens - let SetupContext { - mut rpc, - payer, - associated_token_account, - .. - } = setup().await; - - let delegate = Keypair::new(); - - let sig = Approve { - token_account: associated_token_account, - delegate: delegate.pubkey(), - amount: 500_000, - owner: Some(payer.pubkey()), - } - .execute(&mut rpc, &payer) - .await?; - - let data = rpc.get_account(associated_token_account).await?.ok_or("Account not found")?; - let token = light_token_interface::state::Token::deserialize(&mut &data.data[..])?; - println!("Delegate: {:?} Tx: {sig}", token.delegate); - - Ok(()) -} -``` diff --git a/snippets/code-snippets/light-token/approve-revoke/rust-client/approve-full.mdx b/snippets/code-snippets/light-token/approve-revoke/rust-client/approve-full.mdx deleted file mode 100644 index 279cd822..00000000 --- a/snippets/code-snippets/light-token/approve-revoke/rust-client/approve-full.mdx +++ /dev/null @@ -1,35 +0,0 @@ -```rust -mod shared; - -use light_client::rpc::Rpc; -use light_token::instruction::Approve; -use shared::SetupContext; -use solana_sdk::{signature::Keypair, signer::Signer}; - -#[tokio::test(flavor = "multi_thread")] -async fn approve_delegate() { - // Setup creates mint and ATA with tokens - let SetupContext { - mut rpc, - payer, - ata, - .. - } = shared::setup().await; - - let delegate = Keypair::new(); - let delegate_amount = 500_000u64; - - let approve_ix = Approve { - token_account: ata, - delegate: delegate.pubkey(), - owner: payer.pubkey(), - amount: delegate_amount, - } - .instruction() - .unwrap(); - - rpc.create_and_send_transaction(&[approve_ix], &payer.pubkey(), &[&payer]) - .await - .unwrap(); -} -``` diff --git a/snippets/code-snippets/light-token/approve-revoke/rust-client/approve-instruction.mdx b/snippets/code-snippets/light-token/approve-revoke/rust-client/approve-instruction.mdx deleted file mode 100644 index d8a5c27f..00000000 --- a/snippets/code-snippets/light-token/approve-revoke/rust-client/approve-instruction.mdx +++ /dev/null @@ -1,40 +0,0 @@ -```rust -use borsh::BorshDeserialize; -use light_client::rpc::Rpc; -use light_token::instruction::Approve; -use rust_client::{setup, SetupContext}; -use solana_sdk::{signature::Keypair, signer::Signer}; - -#[tokio::main] -async fn main() -> Result<(), Box> { - // Setup creates mint and associated token account with tokens - let SetupContext { - mut rpc, - payer, - associated_token_account, - .. - } = setup().await; - - let delegate = Keypair::new(); - let delegate_amount = 500_000u64; - - let approve_instruction = Approve { - token_account: associated_token_account, - delegate: delegate.pubkey(), - owner: payer.pubkey(), - amount: delegate_amount, - fee_payer: payer.pubkey(), - } - .instruction()?; - - let sig = rpc - .create_and_send_transaction(&[approve_instruction], &payer.pubkey(), &[&payer]) - .await?; - - let data = rpc.get_account(associated_token_account).await?.ok_or("Account not found")?; - let token = light_token_interface::state::Token::deserialize(&mut &data.data[..])?; - println!("Delegate: {:?} Tx: {sig}", token.delegate); - - Ok(()) -} -``` diff --git a/snippets/code-snippets/light-token/approve-revoke/rust-client/revoke-action.mdx b/snippets/code-snippets/light-token/approve-revoke/rust-client/revoke-action.mdx deleted file mode 100644 index f1fe2d58..00000000 --- a/snippets/code-snippets/light-token/approve-revoke/rust-client/revoke-action.mdx +++ /dev/null @@ -1,31 +0,0 @@ -```rust -use borsh::BorshDeserialize; -use light_client::rpc::Rpc; -use light_token_client::actions::Revoke; -use rust_client::{setup, SetupContext}; -use solana_sdk::signer::Signer; - -#[tokio::main] -async fn main() -> Result<(), Box> { - // Setup creates mint and associated token account with approved delegate - let SetupContext { - mut rpc, - payer, - associated_token_account, - .. - } = setup().await; - - let sig = Revoke { - token_account: associated_token_account, - owner: Some(payer.pubkey()), - } - .execute(&mut rpc, &payer) - .await?; - - let data = rpc.get_account(associated_token_account).await?.ok_or("Account not found")?; - let token = light_token_interface::state::Token::deserialize(&mut &data.data[..])?; - println!("Delegate: {:?} Tx: {sig}", token.delegate); - - Ok(()) -} -``` diff --git a/snippets/code-snippets/light-token/approve-revoke/rust-client/revoke-full.mdx b/snippets/code-snippets/light-token/approve-revoke/rust-client/revoke-full.mdx deleted file mode 100644 index 8d29a44c..00000000 --- a/snippets/code-snippets/light-token/approve-revoke/rust-client/revoke-full.mdx +++ /dev/null @@ -1,30 +0,0 @@ -```rust -mod shared; - -use light_client::rpc::Rpc; -use light_token::instruction::Revoke; -use shared::SetupContext; -use solana_sdk::signer::Signer; - -#[tokio::test(flavor = "multi_thread")] -async fn revoke_delegation() { - // Setup creates mint, ATA with tokens, and approves delegate - let SetupContext { - mut rpc, - payer, - ata, - .. - } = shared::setup().await; - - let revoke_ix = Revoke { - token_account: ata, - owner: payer.pubkey(), - } - .instruction() - .unwrap(); - - rpc.create_and_send_transaction(&[revoke_ix], &payer.pubkey(), &[&payer]) - .await - .unwrap(); -} -``` diff --git a/snippets/code-snippets/light-token/approve-revoke/rust-client/revoke-instruction.mdx b/snippets/code-snippets/light-token/approve-revoke/rust-client/revoke-instruction.mdx deleted file mode 100644 index 8aabf3e4..00000000 --- a/snippets/code-snippets/light-token/approve-revoke/rust-client/revoke-instruction.mdx +++ /dev/null @@ -1,35 +0,0 @@ -```rust -use borsh::BorshDeserialize; -use light_client::rpc::Rpc; -use light_token::instruction::Revoke; -use rust_client::{setup, SetupContext}; -use solana_sdk::signer::Signer; - -#[tokio::main] -async fn main() -> Result<(), Box> { - // Setup creates mint, associated token account with tokens, and approves delegate - let SetupContext { - mut rpc, - payer, - associated_token_account, - .. - } = setup().await; - - let revoke_instruction = Revoke { - token_account: associated_token_account, - owner: payer.pubkey(), - fee_payer: payer.pubkey(), - } - .instruction()?; - - let sig = rpc - .create_and_send_transaction(&[revoke_instruction], &payer.pubkey(), &[&payer]) - .await?; - - let data = rpc.get_account(associated_token_account).await?.ok_or("Account not found")?; - let token = light_token_interface::state::Token::deserialize(&mut &data.data[..])?; - println!("Delegate: {:?} Tx: {sig}", token.delegate); - - Ok(()) -} -``` diff --git a/snippets/code-snippets/light-token/approve-revoke/token-interface-approve-instruction.mdx b/snippets/code-snippets/light-token/approve-revoke/token-interface-approve-instruction.mdx deleted file mode 100644 index fd30329f..00000000 --- a/snippets/code-snippets/light-token/approve-revoke/token-interface-approve-instruction.mdx +++ /dev/null @@ -1,29 +0,0 @@ -```typescript -import { Keypair, Transaction, sendAndConfirmTransaction } from "@solana/web3.js"; -import { createRpc } from "@lightprotocol/stateless.js"; -import { createApproveInstructions } from "@lightprotocol/token-interface"; - -const rpc = createRpc(); -const payer = Keypair.fromSecretKey(/* ... */); - -const mint = /* existing mint public key */; -const owner = Keypair.generate(); -const delegate = Keypair.generate(); - -const instructions = await createApproveInstructions({ - rpc, - payer: payer.publicKey, - owner: owner.publicKey, - mint, - delegate: delegate.publicKey, - amount: 500_000_000n, -}); - -const signature = await sendAndConfirmTransaction( - rpc, - new Transaction().add(...instructions), - [payer, owner] -); -console.log("Approved delegate:", delegate.publicKey.toBase58()); -console.log("Tx:", signature); -``` diff --git a/snippets/code-snippets/light-token/approve-revoke/token-interface-revoke-instruction.mdx b/snippets/code-snippets/light-token/approve-revoke/token-interface-revoke-instruction.mdx deleted file mode 100644 index f925e8a8..00000000 --- a/snippets/code-snippets/light-token/approve-revoke/token-interface-revoke-instruction.mdx +++ /dev/null @@ -1,26 +0,0 @@ -```typescript -import { Keypair, Transaction, sendAndConfirmTransaction } from "@solana/web3.js"; -import { createRpc } from "@lightprotocol/stateless.js"; -import { createRevokeInstructions } from "@lightprotocol/token-interface"; - -const rpc = createRpc(); -const payer = Keypair.fromSecretKey(/* ... */); - -const mint = /* existing mint public key */; -const owner = Keypair.generate(); - -const instructions = await createRevokeInstructions({ - rpc, - payer: payer.publicKey, - owner: owner.publicKey, - mint, -}); - -const signature = await sendAndConfirmTransaction( - rpc, - new Transaction().add(...instructions), - [payer, owner] -); -console.log("Revoked all delegate permissions"); -console.log("Tx:", signature); -``` diff --git a/snippets/code-snippets/light-token/approve/anchor-program/full-example.mdx b/snippets/code-snippets/light-token/approve/anchor-program/full-example.mdx deleted file mode 100644 index 91bb8562..00000000 --- a/snippets/code-snippets/light-token/approve/anchor-program/full-example.mdx +++ /dev/null @@ -1,88 +0,0 @@ - -```rust lib.rs -#![allow(unexpected_cfgs, deprecated)] - -use anchor_lang::prelude::*; -use light_token::instruction::ApproveCpi; - -declare_id!("37XmzKqSG2VD1ZBvzyfbt1HN1mT1bqVAmfzX2ziB3KT1"); - -#[program] -pub mod light_token_anchor_approve { - use super::*; - - pub fn approve(ctx: Context, amount: u64) -> Result<()> { - ApproveCpi { - token_account: ctx.accounts.token_account.to_account_info(), - delegate: ctx.accounts.delegate.to_account_info(), - owner: ctx.accounts.owner.to_account_info(), - system_program: ctx.accounts.system_program.to_account_info(), - amount, - fee_payer: ctx.accounts.fee_payer.to_account_info(), - } - .invoke()?; - Ok(()) - } -} - -#[derive(Accounts)] -pub struct ApproveAccounts<'info> { - /// CHECK: Light token program for CPI - pub light_token_program: AccountInfo<'info>, - /// CHECK: Validated by light-token CPI - #[account(mut)] - pub token_account: AccountInfo<'info>, - /// CHECK: Validated by light-token CPI - pub delegate: AccountInfo<'info>, - pub owner: Signer<'info>, - #[account(mut)] - pub fee_payer: Signer<'info>, - pub system_program: Program<'info, System>, -} -``` - -```rust test.rs -use anchor_lang::{InstructionData, ToAccountMetas}; -use light_program_test::Rpc; -use light_token::instruction::LIGHT_TOKEN_PROGRAM_ID; -use light_token_anchor_approve::{accounts, instruction::Approve, ID}; -use anchor_lang::system_program; -use solana_sdk::{instruction::Instruction, signature::Keypair, signer::Signer}; -use test_utils::{mint_tokens, setup_test_env}; - -#[tokio::test] -async fn test_approve() { - let mut env = setup_test_env("light_token_anchor_approve", ID).await; - - // Mint tokens first - let mint_amount = 1_000_000u64; - mint_tokens(&mut env.rpc, &env.payer, env.mint_pda, env.associated_token_account, mint_amount).await; - - // Call the anchor program to approve delegate - let delegate = Keypair::new(); - let approve_amount = 500_000u64; - - let ix = Instruction { - program_id: ID, - accounts: accounts::ApproveAccounts { - light_token_program: LIGHT_TOKEN_PROGRAM_ID, - token_account: env.associated_token_account, - delegate: delegate.pubkey(), - owner: env.payer.pubkey(), - fee_payer: env.payer.pubkey(), - system_program: system_program::ID, - } - .to_account_metas(Some(true)), - data: Approve { amount: approve_amount }.data(), - }; - - let sig = env - .rpc - .create_and_send_transaction(&[ix], &env.payer.pubkey(), &[&env.payer]) - .await - .unwrap(); - - println!("Tx: {}", sig); -} -``` - diff --git a/snippets/code-snippets/light-token/approve/native-program/full-example.mdx b/snippets/code-snippets/light-token/approve/native-program/full-example.mdx deleted file mode 100644 index b8da4239..00000000 --- a/snippets/code-snippets/light-token/approve/native-program/full-example.mdx +++ /dev/null @@ -1,137 +0,0 @@ - -```rust instruction.rs -use super::authority_seeds; -use light_token::instruction::ApproveCpi; -use solana_program::{ - account_info::AccountInfo, entrypoint::ProgramResult, - program_error::ProgramError, -}; - -pub fn approve_invoke(accounts: &[AccountInfo], data: &[u8]) -> ProgramResult { - let [token_account, delegate, owner, system_program, _token_program] = - accounts - else { - return Err(ProgramError::NotEnoughAccountKeys); - }; - - let amount = u64::from_le_bytes( - data.try_into() - .map_err(|_| ProgramError::InvalidInstructionData)?, - ); - - // Approve delegate to transfer tokens on behalf of owner - ApproveCpi { - token_account: token_account.clone(), - delegate: delegate.clone(), - owner: owner.clone(), - system_program: system_program.clone(), - amount, - } - .invoke() -} - -pub fn approve_invoke_signed( - accounts: &[AccountInfo], - data: &[u8], -) -> ProgramResult { - let [token_account, delegate, owner, system_program, _token_program] = - accounts - else { - return Err(ProgramError::NotEnoughAccountKeys); - }; - - if data.len() < 9 { - return Err(ProgramError::InvalidInstructionData); - } - - let amount = u64::from_le_bytes(data[0..8].try_into().unwrap()); - let bump = data[8]; - let signer_seeds = authority_seeds!(bump); - - ApproveCpi { - token_account: token_account.clone(), - delegate: delegate.clone(), - owner: owner.clone(), - system_program: system_program.clone(), - amount, - } - .invoke_signed(&[signer_seeds]) -} -``` - -```rust test.rs -mod shared; - -use borsh::BorshDeserialize; -use light_client::rpc::Rpc; -use light_token_interface::state::Token; -use shared::{ - build_approve_cpi_ix, build_approve_signed_cpi_ix, create_test_rpc, - get_authority_pda, setup, setup_pda_owned_ata, SetupContext, -}; -use solana_sdk::{signature::Keypair, signer::Signer}; - -#[tokio::test(flavor = "multi_thread")] -async fn approve_cpi() { - // Setup: create mint and ATA with tokens - let SetupContext { - mut rpc, - payer, - ata, - .. - } = setup().await; - - let delegate = Keypair::new(); - let delegate_amount = 500_000u64; - - let ix = build_approve_cpi_ix( - ata, - delegate.pubkey(), - payer.pubkey(), - delegate_amount, - ); - - rpc.create_and_send_transaction(&[ix], &payer.pubkey(), &[&payer]) - .await - .unwrap(); - - // Verify delegate is set - let account_data = rpc.get_account(ata).await.unwrap().unwrap(); - let token_state = Token::deserialize(&mut &account_data.data[..]).unwrap(); - assert_eq!(token_state.delegate, Some(delegate.pubkey().into())); - assert_eq!(token_state.delegated_amount, delegate_amount); -} - -#[tokio::test(flavor = "multi_thread")] -async fn approve_signed_cpi() { - let mut rpc = create_test_rpc().await; - let payer = rpc.get_payer().insecure_clone(); - - let (pda_owner, bump) = get_authority_pda(); - - let (_mint, ata) = - setup_pda_owned_ata(&mut rpc, &payer, pda_owner, 1_000_000).await; - - let delegate = Keypair::new(); - let delegate_amount = 500_000u64; - - let ix = build_approve_signed_cpi_ix( - ata, - delegate.pubkey(), - pda_owner, - delegate_amount, - bump, - ); - - rpc.create_and_send_transaction(&[ix], &payer.pubkey(), &[&payer]) - .await - .unwrap(); - - // Verify delegate is set - let account_data = rpc.get_account(ata).await.unwrap().unwrap(); - let token_state = Token::deserialize(&mut &account_data.data[..]).unwrap(); - assert_eq!(token_state.delegate, Some(delegate.pubkey().into())); - assert_eq!(token_state.delegated_amount, delegate_amount); -} -``` - diff --git a/snippets/code-snippets/light-token/burn-checked/rust-client/instruction.mdx b/snippets/code-snippets/light-token/burn-checked/rust-client/instruction.mdx deleted file mode 100644 index 9801f7e5..00000000 --- a/snippets/code-snippets/light-token/burn-checked/rust-client/instruction.mdx +++ /dev/null @@ -1,44 +0,0 @@ -```rust -use borsh::BorshDeserialize; -use light_client::rpc::Rpc; -use light_token::instruction::BurnChecked; -use rust_client::{setup, SetupContext}; -use solana_sdk::signer::Signer; - -#[tokio::main] -async fn main() -> Result<(), Box> { - // Setup creates mint and ATA with tokens - let SetupContext { - mut rpc, - payer, - mint, - ata, - decimals, - .. - } = setup().await; - - let burn_amount = 400_000u64; - - // BurnChecked validates that decimals match the mint - let burn_ix = BurnChecked { - source: ata, - mint, - amount: burn_amount, - decimals, - authority: payer.pubkey(), - max_top_up: None, - fee_payer: None, - } - .instruction()?; - - let sig = rpc - .create_and_send_transaction(&[burn_ix], &payer.pubkey(), &[&payer]) - .await?; - - let data = rpc.get_account(ata).await?.ok_or("Account not found")?; - let token = light_token_interface::state::Token::deserialize(&mut &data.data[..])?; - println!("Balance: {} Tx: {sig}", token.amount); - - Ok(()) -} -``` diff --git a/snippets/code-snippets/light-token/burn/anchor-program/full-example.mdx b/snippets/code-snippets/light-token/burn/anchor-program/full-example.mdx deleted file mode 100644 index 8c2a8c41..00000000 --- a/snippets/code-snippets/light-token/burn/anchor-program/full-example.mdx +++ /dev/null @@ -1,87 +0,0 @@ - -```rust lib.rs -#![allow(unexpected_cfgs, deprecated)] - -use anchor_lang::prelude::*; -use light_token::instruction::BurnCpi; - -declare_id!("2TXVn8AqjfyeJvmFBD3kHJmh6fWkC4HNB5T76BmLKV5c"); - -#[program] -pub mod light_token_anchor_burn { - use super::*; - - pub fn burn(ctx: Context, amount: u64) -> Result<()> { - BurnCpi { - source: ctx.accounts.source.to_account_info(), - mint: ctx.accounts.mint.to_account_info(), - amount, - authority: ctx.accounts.authority.to_account_info(), - system_program: ctx.accounts.system_program.to_account_info(), - fee_payer: ctx.accounts.fee_payer.to_account_info(), - } - .invoke()?; - Ok(()) - } -} - -#[derive(Accounts)] -pub struct BurnAccounts<'info> { - /// CHECK: Light token program for CPI - pub light_token_program: AccountInfo<'info>, - /// CHECK: Validated by light-token CPI - #[account(mut)] - pub source: AccountInfo<'info>, - /// CHECK: Validated by light-token CPI - #[account(mut)] - pub mint: AccountInfo<'info>, - pub authority: Signer<'info>, - #[account(mut)] - pub fee_payer: Signer<'info>, - pub system_program: Program<'info, System>, -} -``` - -```rust test.rs -use anchor_lang::{InstructionData, ToAccountMetas}; -use light_program_test::Rpc; -use light_token::instruction::LIGHT_TOKEN_PROGRAM_ID; -use light_token_anchor_burn::{accounts, instruction::Burn, ID}; -use anchor_lang::system_program; -use solana_sdk::{instruction::Instruction, signer::Signer}; -use test_utils::{mint_tokens, setup_test_env}; - -#[tokio::test] -async fn test_burn() { - let mut env = setup_test_env("light_token_anchor_burn", ID).await; - - // Mint tokens first - let mint_amount = 1_000_000u64; - mint_tokens(&mut env.rpc, &env.payer, env.mint_pda, env.associated_token_account, mint_amount).await; - - // Call the anchor program to burn tokens - let burn_amount = 250_000u64; - let ix = Instruction { - program_id: ID, - accounts: accounts::BurnAccounts { - light_token_program: LIGHT_TOKEN_PROGRAM_ID, - source: env.associated_token_account, - mint: env.mint_pda, - authority: env.payer.pubkey(), - fee_payer: env.payer.pubkey(), - system_program: system_program::ID, - } - .to_account_metas(Some(true)), - data: Burn { amount: burn_amount }.data(), - }; - - let sig = env - .rpc - .create_and_send_transaction(&[ix], &env.payer.pubkey(), &[&env.payer]) - .await - .unwrap(); - - println!("Tx: {}", sig); -} -``` - diff --git a/snippets/code-snippets/light-token/burn/native-program/full-example.mdx b/snippets/code-snippets/light-token/burn/native-program/full-example.mdx deleted file mode 100644 index d1103e81..00000000 --- a/snippets/code-snippets/light-token/burn/native-program/full-example.mdx +++ /dev/null @@ -1,170 +0,0 @@ - -```rust instruction.rs -use super::authority_seeds; -use light_token::instruction::BurnCpi; -use solana_program::{ - account_info::AccountInfo, entrypoint::ProgramResult, - program_error::ProgramError, -}; - -pub fn burn_invoke(accounts: &[AccountInfo], data: &[u8]) -> ProgramResult { - let [source, mint, authority, system_program, _token_program] = accounts - else { - return Err(ProgramError::NotEnoughAccountKeys); - }; - - let amount = u64::from_le_bytes( - data.try_into() - .map_err(|_| ProgramError::InvalidInstructionData)?, - ); - - // Burn tokens from source account, reducing total supply - BurnCpi { - source: source.clone(), - mint: mint.clone(), - amount, - authority: authority.clone(), - system_program: system_program.clone(), - fee_payer: None, - max_top_up: None, - } - .invoke() -} - -pub fn burn_invoke_signed( - accounts: &[AccountInfo], - data: &[u8], -) -> ProgramResult { - let [source, mint, authority, system_program, _token_program] = accounts - else { - return Err(ProgramError::NotEnoughAccountKeys); - }; - - if data.len() < 9 { - return Err(ProgramError::InvalidInstructionData); - } - - let amount = u64::from_le_bytes(data[0..8].try_into().unwrap()); - let bump = data[8]; - let signer_seeds = authority_seeds!(bump); - - BurnCpi { - source: source.clone(), - mint: mint.clone(), - amount, - authority: authority.clone(), - system_program: system_program.clone(), - fee_payer: None, - max_top_up: None, - } - .invoke_signed(&[signer_seeds]) -} -``` - -```rust test.rs -mod shared; - -use borsh::BorshDeserialize; -use light_client::rpc::Rpc; -use light_token_interface::state::Token; -use shared::{ - build_burn_cpi_ix, build_burn_signed_cpi_ix, create_test_rpc, - get_authority_pda, setup, setup_pda_owned_ata, SetupContext, -}; -use solana_sdk::signer::Signer; - -#[tokio::test(flavor = "multi_thread")] -async fn burn_cpi() { - // Setup: create mint and ATA with tokens - let SetupContext { - mut rpc, - payer, - mint, - ata, - .. - } = setup().await; - - let initial_amount = 1_000_000u64; - let burn_amount = 300_000u64; - - // Get balance before burn - let account_data = rpc.get_account(ata).await.unwrap().unwrap(); - let token_state = Token::deserialize(&mut &account_data.data[..]).unwrap(); - let balance_before = token_state.amount; - assert_eq!( - balance_before, initial_amount, - "Initial balance should match" - ); - - let ix = build_burn_cpi_ix(ata, mint, payer.pubkey(), burn_amount); - - rpc.create_and_send_transaction(&[ix], &payer.pubkey(), &[&payer]) - .await - .unwrap(); - - // Verify balance decreased - let account_data = rpc.get_account(ata).await.unwrap().unwrap(); - let token_state = Token::deserialize(&mut &account_data.data[..]).unwrap(); - let balance_after = token_state.amount; - assert_eq!( - balance_after, - initial_amount - burn_amount, - "Balance should decrease by burn amount" - ); -} - -#[tokio::test(flavor = "multi_thread")] -async fn burn_signed_cpi() { - let mut rpc = create_test_rpc().await; - let payer = rpc.get_payer().insecure_clone(); - - let (pda_owner, bump) = get_authority_pda(); - let initial_amount = 1_000_000u64; - let burn_amount = 300_000u64; - - let (mint, ata) = - setup_pda_owned_ata(&mut rpc, &payer, pda_owner, initial_amount).await; - - let ix = build_burn_signed_cpi_ix(ata, mint, pda_owner, burn_amount, bump); - - rpc.create_and_send_transaction(&[ix], &payer.pubkey(), &[&payer]) - .await - .unwrap(); - - // Verify balance decreased - let account_data = rpc.get_account(ata).await.unwrap().unwrap(); - let token_state = Token::deserialize(&mut &account_data.data[..]).unwrap(); - let balance_after = token_state.amount; - assert_eq!( - balance_after, - initial_amount - burn_amount, - "Balance should decrease by burn amount" - ); -} - -#[tokio::test(flavor = "multi_thread")] -async fn burn_fails_with_insufficient_balance() { - // Setup: create mint and ATA with tokens - let SetupContext { - mut rpc, - payer, - mint, - ata, - .. - } = setup().await; - - let initial_amount = 1_000_000u64; - let burn_amount = initial_amount + 1; // More than balance - - let ix = build_burn_cpi_ix(ata, mint, payer.pubkey(), burn_amount); - - let result = rpc - .create_and_send_transaction(&[ix], &payer.pubkey(), &[&payer]) - .await; - assert!( - result.is_err(), - "Burn with insufficient balance should fail" - ); -} -``` - diff --git a/snippets/code-snippets/light-token/burn/rust-client/instruction.mdx b/snippets/code-snippets/light-token/burn/rust-client/instruction.mdx deleted file mode 100644 index 68a7c587..00000000 --- a/snippets/code-snippets/light-token/burn/rust-client/instruction.mdx +++ /dev/null @@ -1,40 +0,0 @@ -```rust -use borsh::BorshDeserialize; -use light_client::rpc::Rpc; -use light_token::instruction::Burn; -use rust_client::{setup, SetupContext}; -use solana_sdk::signer::Signer; - -#[tokio::main] -async fn main() -> Result<(), Box> { - // Setup creates mint and associated token account with tokens - let SetupContext { - mut rpc, - payer, - mint, - associated_token_account, - .. - } = setup().await; - - let burn_amount = 400_000u64; - - let burn_instruction = Burn { - source: associated_token_account, - mint, - amount: burn_amount, - authority: payer.pubkey(), - fee_payer: payer.pubkey(), - } - .instruction()?; - - let sig = rpc - .create_and_send_transaction(&[burn_instruction], &payer.pubkey(), &[&payer]) - .await?; - - let data = rpc.get_account(associated_token_account).await?.ok_or("Account not found")?; - let token = light_token_interface::state::Token::deserialize(&mut &data.data[..])?; - println!("Balance: {} Tx: {sig}", token.amount); - - Ok(()) -} -``` diff --git a/snippets/code-snippets/light-token/close-token-account/anchor-program/full-example.mdx b/snippets/code-snippets/light-token/close-token-account/anchor-program/full-example.mdx deleted file mode 100644 index 434ac83a..00000000 --- a/snippets/code-snippets/light-token/close-token-account/anchor-program/full-example.mdx +++ /dev/null @@ -1,83 +0,0 @@ - -```rust lib.rs -#![allow(unexpected_cfgs, deprecated)] - -use anchor_lang::prelude::*; -use light_token::instruction::CloseAccountCpi; - -declare_id!("GXLCuNhnkRVp596eCdbNsZ9ua1ePbKbb344VKS7V3zQQ"); - -#[program] -pub mod light_token_anchor_close { - use super::*; - - pub fn close_account(ctx: Context) -> Result<()> { - CloseAccountCpi { - token_program: ctx.accounts.light_token_program.to_account_info(), - account: ctx.accounts.account.to_account_info(), - destination: ctx.accounts.destination.to_account_info(), - owner: ctx.accounts.owner.to_account_info(), - rent_sponsor: ctx.accounts.rent_sponsor.to_account_info(), - } - .invoke()?; - Ok(()) - } -} - -#[derive(Accounts)] -pub struct CloseAccountAccounts<'info> { - /// CHECK: Light token program for CPI - pub light_token_program: AccountInfo<'info>, - /// CHECK: Validated by light-token CPI - #[account(mut)] - pub account: AccountInfo<'info>, - /// CHECK: Validated by light-token CPI - #[account(mut)] - pub destination: AccountInfo<'info>, - pub owner: Signer<'info>, - /// CHECK: Validated by light-token CPI - #[account(mut)] - pub rent_sponsor: AccountInfo<'info>, -} -``` - -```rust test.rs -use anchor_lang::{InstructionData, ToAccountMetas}; -use light_program_test::Rpc; -use light_token::instruction::{rent_sponsor_pda, LIGHT_TOKEN_PROGRAM_ID}; -use light_token_anchor_close::{accounts, instruction::CloseAccount, ID}; -use solana_sdk::{instruction::Instruction, signer::Signer}; -use test_utils::setup_test_env; - -#[tokio::test] -async fn test_close() { - let mut env = setup_test_env("light_token_anchor_close", ID).await; - - // Associated token account must be empty to close (no mint_tokens call). - - // Call the anchor program to close account - let rent_sponsor = rent_sponsor_pda(); - - let ix = Instruction { - program_id: ID, - accounts: accounts::CloseAccountAccounts { - light_token_program: LIGHT_TOKEN_PROGRAM_ID, - account: env.associated_token_account, - destination: env.payer.pubkey(), - owner: env.payer.pubkey(), - rent_sponsor, - } - .to_account_metas(Some(true)), - data: CloseAccount {}.data(), - }; - - let sig = env - .rpc - .create_and_send_transaction(&[ix], &env.payer.pubkey(), &[&env.payer]) - .await - .unwrap(); - - println!("Tx: {}", sig); -} -``` - diff --git a/snippets/code-snippets/light-token/close-token-account/native-program/full-example.mdx b/snippets/code-snippets/light-token/close-token-account/native-program/full-example.mdx deleted file mode 100644 index e468009d..00000000 --- a/snippets/code-snippets/light-token/close-token-account/native-program/full-example.mdx +++ /dev/null @@ -1,116 +0,0 @@ - -```rust instruction.rs -use super::authority_seeds; -use light_token::instruction::CloseAccountCpi; -use solana_program::{ - account_info::AccountInfo, entrypoint::ProgramResult, - program_error::ProgramError, -}; - -pub fn close_invoke(accounts: &[AccountInfo], _data: &[u8]) -> ProgramResult { - let [account, destination, owner, rent_sponsor, token_program] = accounts - else { - return Err(ProgramError::NotEnoughAccountKeys); - }; - - // Close token account. Must be empty (balance == 0) - CloseAccountCpi { - token_program: token_program.clone(), - account: account.clone(), - destination: destination.clone(), - owner: owner.clone(), - rent_sponsor: rent_sponsor.clone(), - } - .invoke() -} - -pub fn close_invoke_signed( - accounts: &[AccountInfo], - data: &[u8], -) -> ProgramResult { - let [account, destination, owner, rent_sponsor, token_program] = accounts - else { - return Err(ProgramError::NotEnoughAccountKeys); - }; - - if data.is_empty() { - return Err(ProgramError::InvalidInstructionData); - } - - let bump = data[0]; - let signer_seeds = authority_seeds!(bump); - - CloseAccountCpi { - token_program: token_program.clone(), - account: account.clone(), - destination: destination.clone(), - owner: owner.clone(), - rent_sponsor: rent_sponsor.clone(), - } - .invoke_signed(&[signer_seeds]) -} -``` - -```rust test.rs -mod shared; - -use light_client::rpc::Rpc; -use light_token::instruction::rent_sponsor_pda; -use shared::{ - build_close_cpi_ix, build_close_signed_cpi_ix, create_test_rpc, - get_authority_pda, setup_empty_ata, setup_pda_owned_ata, SetupContext, -}; -use solana_sdk::signer::Signer; - -#[tokio::test(flavor = "multi_thread")] -async fn close_cpi() { - // Setup: create mint and empty ATA (must be empty to close) - let SetupContext { - mut rpc, - payer, - ata, - .. - } = setup_empty_ata().await; - - let ix = build_close_cpi_ix( - ata, - payer.pubkey(), - payer.pubkey(), - rent_sponsor_pda(), - ); - - rpc.create_and_send_transaction(&[ix], &payer.pubkey(), &[&payer]) - .await - .unwrap(); - - let account = rpc.get_account(ata).await.unwrap(); - assert!(account.is_none()); -} - -#[tokio::test(flavor = "multi_thread")] -async fn close_signed_cpi() { - let mut rpc = create_test_rpc().await; - let payer = rpc.get_payer().insecure_clone(); - - let (pda_owner, bump) = get_authority_pda(); - - let (_mint, ata) = - setup_pda_owned_ata(&mut rpc, &payer, pda_owner, 0).await; - - let ix = build_close_signed_cpi_ix( - ata, - payer.pubkey(), - pda_owner, - rent_sponsor_pda(), - bump, - ); - - rpc.create_and_send_transaction(&[ix], &payer.pubkey(), &[&payer]) - .await - .unwrap(); - - let account = rpc.get_account(ata).await.unwrap(); - assert!(account.is_none()); -} -``` - diff --git a/snippets/code-snippets/light-token/close-token-account/rust-client/instruction.mdx b/snippets/code-snippets/light-token/close-token-account/rust-client/instruction.mdx deleted file mode 100644 index 8a0f3e36..00000000 --- a/snippets/code-snippets/light-token/close-token-account/rust-client/instruction.mdx +++ /dev/null @@ -1,28 +0,0 @@ -```rust -use light_client::rpc::Rpc; -use light_token::instruction::{CloseAccount, LIGHT_TOKEN_PROGRAM_ID}; -use rust_client::{setup_empty_associated_token_account, SetupContext}; -use solana_sdk::signer::Signer; - -#[tokio::main] -async fn main() -> Result<(), Box> { - // Setup creates mint and empty associated token account (must be empty to close). - let SetupContext { - mut rpc, - payer, - associated_token_account, - .. - } = setup_empty_associated_token_account().await; - let close_instruction = CloseAccount::new(LIGHT_TOKEN_PROGRAM_ID, associated_token_account, payer.pubkey(), payer.pubkey()) - .instruction()?; - - let sig = rpc - .create_and_send_transaction(&[close_instruction], &payer.pubkey(), &[&payer]) - .await?; - - let account = rpc.get_account(associated_token_account).await?; - println!("Closed: {} Tx: {sig}", account.is_none()); - - Ok(()) -} -``` diff --git a/snippets/code-snippets/light-token/counter/anchor-macro/full-example.mdx b/snippets/code-snippets/light-token/counter/anchor-macro/full-example.mdx deleted file mode 100644 index dd4680f2..00000000 --- a/snippets/code-snippets/light-token/counter/anchor-macro/full-example.mdx +++ /dev/null @@ -1,266 +0,0 @@ - - - -```rust lib.rs expandable -use anchor_lang::prelude::*; -use light_account::{ - CompressionInfo, LightAccount, LightAccounts, CreateAccountsProof, - derive_light_cpi_signer, light_program, CpiSigner, -}; - -declare_id!("YourProgramId11111111111111111111111111111111"); - -pub const LIGHT_CPI_SIGNER: CpiSigner = - derive_light_cpi_signer!("YourProgramId11111111111111111111111111111111"); - -pub const COUNTER_SEED: &[u8] = b"counter"; - -#[derive(Default, Debug, InitSpace, LightAccount)] -#[account] -pub struct Counter { - pub compression_info: CompressionInfo, - pub owner: Pubkey, - pub count: u64, -} - -#[derive(AnchorSerialize, AnchorDeserialize, Clone)] -pub struct CreateCounterParams { - pub create_accounts_proof: CreateAccountsProof, - pub count: u64, -} - -#[light_program] -#[program] -pub mod counter { - use super::*; - - pub fn create_counter<'info>( - ctx: Context<'_, '_, '_, 'info, CreateCounter<'info>>, - params: CreateCounterParams, - ) -> Result<()> { - ctx.accounts.counter.owner = ctx.accounts.owner.key(); - ctx.accounts.counter.count = params.count; - Ok(()) - } - - /// Standard Anchor — no Light-specific changes. - pub fn increment(ctx: Context) -> Result<()> { - ctx.accounts.counter.count = ctx.accounts.counter.count.checked_add(1).unwrap(); - Ok(()) - } - - /// Standard Anchor — no Light-specific changes. - pub fn close_counter(_ctx: Context) -> Result<()> { - Ok(()) - } -} - -#[derive(Accounts, LightAccounts)] -#[instruction(params: CreateCounterParams)] -pub struct CreateCounter<'info> { - #[account(mut)] - pub fee_payer: Signer<'info>, - - /// CHECK: Read-only, used for PDA derivation. - pub owner: AccountInfo<'info>, - - /// CHECK: Validated by Light Protocol CPI. - pub compression_config: AccountInfo<'info>, - - /// CHECK: PDA rent sponsor for compression rent reimbursement. - #[account(mut)] - pub pda_rent_sponsor: AccountInfo<'info>, - - #[account( - init, - payer = fee_payer, - space = 8 + ::INIT_SPACE, - seeds = [COUNTER_SEED, owner.key().as_ref()], - bump, - )] - #[light_account(init)] - pub counter: Account<'info, Counter>, - - pub system_program: Program<'info, System>, -} - -/// Standard Anchor -#[derive(Accounts)] -pub struct Increment<'info> { - pub owner: Signer<'info>, - - #[account( - mut, - seeds = [COUNTER_SEED, owner.key().as_ref()], - bump, - has_one = owner, - )] - pub counter: Account<'info, Counter>, -} - -/// Standard Anchor close -#[derive(Accounts)] -pub struct CloseCounter<'info> { - #[account(mut)] - pub fee_payer: Signer<'info>, - - pub owner: Signer<'info>, - - #[account( - mut, - close = fee_payer, - seeds = [COUNTER_SEED, owner.key().as_ref()], - bump, - has_one = owner, - )] - pub counter: Account<'info, Counter>, -} -``` - - - - -```rust counter.rs expandable -//! Light-PDA lifecycle test: create → increment → close. - -use anchor_lang::{InstructionData, ToAccountMetas}; -use light_client::interface::{ - get_create_accounts_proof, CreateAccountsProofInput, InitializeRentFreeConfig, -}; -use light_program_test::{ - program_test::{setup_mock_program_data, LightProgramTest}, - ProgramTestConfig, Rpc, -}; -use light_token::instruction::RENT_SPONSOR; -use solana_instruction::Instruction; -use solana_keypair::Keypair; -use solana_pubkey::Pubkey; -use solana_signer::Signer; - -const PROGRAM_ID: Pubkey = counter::ID; - -/// Setup: create test RPC and initialize rent-free config for the counter program. -async fn setup() -> (LightProgramTest, Keypair, Pubkey) { - let config = ProgramTestConfig::new_v2(true, Some(vec![("counter", PROGRAM_ID)])); - let mut rpc = LightProgramTest::new(config).await.unwrap(); - let payer = rpc.get_payer().insecure_clone(); - - let program_data_pda = setup_mock_program_data(&mut rpc, &payer, &PROGRAM_ID); - - // Register this program for rent-free accounts. One-time setup per program. - let (init_config_ix, compression_config) = InitializeRentFreeConfig::new( - &PROGRAM_ID, - &payer.pubkey(), - &program_data_pda, - RENT_SPONSOR, - payer.pubkey(), - ) - .build(); - - rpc.create_and_send_transaction(&[init_config_ix], &payer.pubkey(), &[&payer]) - .await - .expect("initialize rent-free config"); - - (rpc, payer, compression_config) -} - -#[tokio::test] -async fn test_counter_lifecycle() { - let (mut rpc, payer, compression_config) = setup().await; - - // ── Create ─────────────────────────────────────────────────────────── - let (counter_pda, _) = Pubkey::find_program_address( - &[counter::COUNTER_SEED, payer.pubkey().as_ref()], - &PROGRAM_ID, - ); - - let proof_result = get_create_accounts_proof( - &rpc, - &PROGRAM_ID, - vec![CreateAccountsProofInput::pda(counter_pda)], - ) - .await - .unwrap(); - - let create_accounts = counter::accounts::CreateCounter { - fee_payer: payer.pubkey(), - owner: payer.pubkey(), - compression_config, - counter: counter_pda, - system_program: solana_sdk::system_program::ID, - }; - - let create_data = counter::instruction::CreateCounter { - params: counter::CreateCounterParams { - create_accounts_proof: proof_result.create_accounts_proof, - count: 0, - }, - }; - - let create_ix = Instruction { - program_id: PROGRAM_ID, - accounts: [ - create_accounts.to_account_metas(None), - proof_result.remaining_accounts, - ] - .concat(), - data: create_data.data(), - }; - - rpc.create_and_send_transaction(&[create_ix], &payer.pubkey(), &[&payer]) - .await - .expect("create_counter"); - - // Verify initial state. - let account = rpc.get_account(counter_pda).await.unwrap().unwrap(); - let ctr: counter::Counter = - anchor_lang::AccountDeserialize::try_deserialize(&mut account.data.as_slice()).unwrap(); - assert_eq!(ctr.count, 0); - assert_eq!(ctr.owner, payer.pubkey()); - - // ── Increment (standard Anchor) ──────────────────────────── - let inc_accounts = counter::accounts::Increment { - owner: payer.pubkey(), - counter: counter_pda, - }; - let inc_data = counter::instruction::Increment {}; - let inc_ix = Instruction { - program_id: PROGRAM_ID, - accounts: inc_accounts.to_account_metas(None), - data: inc_data.data(), - }; - - rpc.create_and_send_transaction(&[inc_ix], &payer.pubkey(), &[&payer]) - .await - .expect("increment"); - - let account = rpc.get_account(counter_pda).await.unwrap().unwrap(); - let ctr: counter::Counter = - anchor_lang::AccountDeserialize::try_deserialize(&mut account.data.as_slice()).unwrap(); - assert_eq!(ctr.count, 1); - - // ── Close (standard Anchor) ──────────────────────────────── - let close_accounts = counter::accounts::CloseCounter { - fee_payer: payer.pubkey(), - owner: payer.pubkey(), - counter: counter_pda, - }; - let close_data = counter::instruction::CloseCounter {}; - let close_ix = Instruction { - program_id: PROGRAM_ID, - accounts: close_accounts.to_account_metas(None), - data: close_data.data(), - }; - - rpc.create_and_send_transaction(&[close_ix], &payer.pubkey(), &[&payer]) - .await - .expect("close_counter"); - - // Account should no longer exist. - let account = rpc.get_account(counter_pda).await.unwrap(); - assert!(account.is_none(), "counter should be closed"); -} -``` - - - diff --git a/snippets/code-snippets/light-token/create-ata/action.mdx b/snippets/code-snippets/light-token/create-ata/action.mdx deleted file mode 100644 index 8bbe8231..00000000 --- a/snippets/code-snippets/light-token/create-ata/action.mdx +++ /dev/null @@ -1,32 +0,0 @@ -```typescript -import "dotenv/config"; -import { Keypair } from "@solana/web3.js"; -import { createRpc } from "@lightprotocol/stateless.js"; -import { - createMintInterface, - createAtaInterface, -} from "@lightprotocol/compressed-token"; -import { homedir } from "os"; -import { readFileSync } from "fs"; - -// devnet: -// const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; -// const rpc = createRpc(RPC_URL); -// localnet: -const rpc = createRpc(); - -const payer = Keypair.fromSecretKey( - new Uint8Array( - JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) - ) -); - -(async function () { - const { mint } = await createMintInterface(rpc, payer, payer, null, 9); - - const owner = Keypair.generate(); - const ata = await createAtaInterface(rpc, payer, mint, owner.publicKey); - - console.log("ATA:", ata.toBase58()); -})(); -``` diff --git a/snippets/code-snippets/light-token/create-ata/anchor-macro/full-example.mdx b/snippets/code-snippets/light-token/create-ata/anchor-macro/full-example.mdx deleted file mode 100644 index 89b73bc7..00000000 --- a/snippets/code-snippets/light-token/create-ata/anchor-macro/full-example.mdx +++ /dev/null @@ -1,179 +0,0 @@ - -```rust lib.rs -#![allow(deprecated)] - -use anchor_lang::prelude::*; -use light_account::{ - derive_light_cpi_signer, light_program, CreateAccountsProof, CpiSigner, LightAccounts, - LIGHT_TOKEN_PROGRAM_ID, -}; -use light_token::instruction::{LIGHT_TOKEN_CONFIG, LIGHT_TOKEN_RENT_SPONSOR}; - -declare_id!("CLsn9MTFv97oMTsujRoQAw1u2rSm2HnKtGuWUbbc8Jfn"); - -pub const LIGHT_CPI_SIGNER: CpiSigner = - derive_light_cpi_signer!("CLsn9MTFv97oMTsujRoQAw1u2rSm2HnKtGuWUbbc8Jfn"); - -#[light_program] -#[program] -pub mod light_token_macro_create_associated_token_account { - use super::*; - - #[allow(unused_variables)] - pub fn create_associated_token_account<'info>( - ctx: Context<'_, '_, '_, 'info, CreateAssociatedTokenAccount<'info>>, - params: CreateAssociatedTokenAccountParams, - ) -> Result<()> { - Ok(()) - } -} - -#[derive(AnchorSerialize, AnchorDeserialize, Clone)] -pub struct CreateAssociatedTokenAccountParams { - pub create_accounts_proof: CreateAccountsProof, -} - -#[derive(Accounts, LightAccounts)] -#[instruction(params: CreateAssociatedTokenAccountParams)] -pub struct CreateAssociatedTokenAccount<'info> { - #[account(mut)] - pub fee_payer: Signer<'info>, - - /// CHECK: Token mint for the associated token account - pub associated_token_account_mint: AccountInfo<'info>, - - /// CHECK: Owner of the associated token account - pub associated_token_account_owner: AccountInfo<'info>, - - /// CHECK: Validated by light_account macro - #[account(mut)] - #[light_account(init, associated_token::authority = associated_token_account_owner, associated_token::mint = associated_token_account_mint)] - pub associated_token_account: UncheckedAccount<'info>, - - /// CHECK: Validated by address constraint - #[account(address = LIGHT_TOKEN_CONFIG)] - pub light_token_config: AccountInfo<'info>, - - /// CHECK: Validated by address constraint - #[account(mut, address = LIGHT_TOKEN_RENT_SPONSOR)] - pub light_token_rent_sponsor: AccountInfo<'info>, - - /// CHECK: Light Token program for CPI - #[account(address = LIGHT_TOKEN_PROGRAM_ID.into())] - pub light_token_program: AccountInfo<'info>, - - pub system_program: Program<'info, System>, -} -``` - -```rust test.rs -use anchor_lang::{InstructionData, ToAccountMetas}; -use light_client::interface::{get_create_accounts_proof, InitializeRentFreeConfig}; -use light_program_test::{ - program_test::{setup_mock_program_data, LightProgramTest}, - ProgramTestConfig, Rpc, -}; -use light_account::{derive_rent_sponsor_pda, LIGHT_TOKEN_PROGRAM_ID}; -use light_token::instruction::{LIGHT_TOKEN_CONFIG, LIGHT_TOKEN_RENT_SPONSOR}; -use solana_instruction::Instruction; -use solana_signer::Signer; -use test_utils::create_mint; - -/// Test creating a Light Protocol associated token account using the macro. -#[tokio::test] -async fn test_create_associated_token_account() { - use light_token_macro_create_associated_token_account::CreateAssociatedTokenAccountParams; - - let program_id = light_token_macro_create_associated_token_account::ID; - let mut config = - ProgramTestConfig::new_v2(true, Some(vec![("light_token_macro_create_associated_token_account", program_id)])); - config = config.with_light_protocol_events(); - - let mut rpc = LightProgramTest::new(config).await.unwrap(); - let payer = rpc.get_payer().insecure_clone(); - - let program_data_pda = setup_mock_program_data(&mut rpc, &payer, &program_id); - - let (rent_sponsor, _) = derive_rent_sponsor_pda(&program_id); - - let (init_config_ix, _config_pda) = InitializeRentFreeConfig::new( - &program_id, - &payer.pubkey(), - &program_data_pda, - rent_sponsor, - payer.pubkey(), - ) - .build(); - - rpc.create_and_send_transaction(&[init_config_ix], &payer.pubkey(), &[&payer]) - .await - .expect("Initialize config should succeed"); - - let (mint, _mint_seed) = create_mint(&mut rpc, &payer, None).await; - - // The associated token account owner will be the payer - let associated_token_account_owner = payer.pubkey(); - - // Derive the associated token account address using Light Token SDK's derivation - let associated_token_account = light_token::instruction::derive_token_ata(&associated_token_account_owner, &mint); - - // Get proof (no PDA accounts for associated token account-only instruction) - let proof_result = get_create_accounts_proof(&rpc, &program_id, vec![]) - .await - .unwrap(); - - // Build instruction - let accounts = light_token_macro_create_associated_token_account::accounts::CreateAssociatedTokenAccount { - fee_payer: payer.pubkey(), - associated_token_account_mint: mint, - associated_token_account_owner, - associated_token_account, - light_token_config: LIGHT_TOKEN_CONFIG, - light_token_rent_sponsor: LIGHT_TOKEN_RENT_SPONSOR, - light_token_program: LIGHT_TOKEN_PROGRAM_ID.into(), - system_program: solana_sdk::system_program::ID, - }; - - let instruction_data = light_token_macro_create_associated_token_account::instruction::CreateAssociatedTokenAccount { - params: CreateAssociatedTokenAccountParams { - create_accounts_proof: proof_result.create_accounts_proof, - }, - }; - - let instruction = Instruction { - program_id, - accounts: [ - accounts.to_account_metas(None), - proof_result.remaining_accounts, - ] - .concat(), - data: instruction_data.data(), - }; - - rpc.create_and_send_transaction(&[instruction], &payer.pubkey(), &[&payer]) - .await - .expect("CreateAssociatedTokenAccount instruction should succeed"); - - // Verify associated token account exists on-chain - let associated_token_account_data = rpc - .get_account(associated_token_account) - .await - .unwrap() - .expect("Associated token account should exist on-chain"); - - // Parse and verify token data - use light_token_interface::state::Token; - let token: Token = borsh::BorshDeserialize::deserialize(&mut &associated_token_account_data.data[..]) - .expect("Failed to deserialize Token"); - - // Verify owner - assert_eq!(token.owner, associated_token_account_owner.to_bytes(), "Associated token account owner should match"); - - // Verify mint - assert_eq!(token.mint, mint.to_bytes(), "Associated token account mint should match"); - - // Verify initial amount is 0 - assert_eq!(token.amount, 0, "Associated token account amount should be 0 initially"); -} -``` - diff --git a/snippets/code-snippets/light-token/create-ata/anchor-program/full-example.mdx b/snippets/code-snippets/light-token/create-ata/anchor-program/full-example.mdx deleted file mode 100644 index 86019ec4..00000000 --- a/snippets/code-snippets/light-token/create-ata/anchor-program/full-example.mdx +++ /dev/null @@ -1,172 +0,0 @@ - -```rust lib.rs -#![allow(unexpected_cfgs, deprecated)] - -use anchor_lang::prelude::*; -use light_token::instruction::CreateAssociatedAccountCpi; - -declare_id!("35MukgdfpNUbPMhTmEk63ECV8vjgpNVFRH9nP8ovMN58"); - -#[program] -pub mod light_token_anchor_create_associated_token_account { - use super::*; - - pub fn create_associated_token_account(ctx: Context, idempotent: bool) -> Result<()> { - let cpi = CreateAssociatedAccountCpi { - payer: ctx.accounts.payer.to_account_info(), - owner: ctx.accounts.owner.to_account_info(), - mint: ctx.accounts.mint.to_account_info(), - ata: ctx.accounts.associated_token_account.to_account_info(), - }; - - if idempotent { - cpi.idempotent().rent_free( - ctx.accounts.compressible_config.to_account_info(), - ctx.accounts.rent_sponsor.to_account_info(), - ctx.accounts.system_program.to_account_info(), - ) - } else { - cpi.rent_free( - ctx.accounts.compressible_config.to_account_info(), - ctx.accounts.rent_sponsor.to_account_info(), - ctx.accounts.system_program.to_account_info(), - ) - } - .invoke()?; - Ok(()) - } -} - -#[derive(Accounts)] -pub struct CreateAssociatedTokenAccountAccounts<'info> { - /// CHECK: Light token program for CPI - pub light_token_program: AccountInfo<'info>, - /// CHECK: Validated by light-token CPI - pub owner: AccountInfo<'info>, - /// CHECK: Validated by light-token CPI - pub mint: AccountInfo<'info>, - #[account(mut)] - pub payer: Signer<'info>, - /// CHECK: Validated by light-token CPI - #[account(mut)] - pub associated_token_account: AccountInfo<'info>, - pub system_program: Program<'info, System>, - /// CHECK: Validated by light-token CPI - pub compressible_config: AccountInfo<'info>, - /// CHECK: Validated by light-token CPI - #[account(mut)] - pub rent_sponsor: AccountInfo<'info>, -} -``` - -```rust test.rs -use anchor_lang::{InstructionData, ToAccountMetas}; -use light_client::indexer::AddressWithTree; -use light_program_test::{Indexer, LightProgramTest, ProgramTestConfig, Rpc}; -use light_token_anchor_create_associated_token_account::{accounts, instruction::CreateAssociatedTokenAccount, ID}; -use light_token::instruction::{ - CreateMint, CreateMintParams, config_pda, derive_mint_compressed_address, derive_token_ata, - find_mint_address, rent_sponsor_pda, LIGHT_TOKEN_PROGRAM_ID, - DEFAULT_RENT_PAYMENT, DEFAULT_WRITE_TOP_UP, -}; -use anchor_lang::system_program; -use solana_sdk::{ - instruction::Instruction, - signature::Keypair, - signer::Signer, -}; - -#[tokio::test] -async fn test_create_associated_token_account() { - let config = - ProgramTestConfig::new_v2(true, Some(vec![("light_token_anchor_create_associated_token_account", ID)])); - let mut rpc = LightProgramTest::new(config).await.unwrap(); - let payer = rpc.get_payer().insecure_clone(); - - let mint_seed = Keypair::new(); - let mint_authority = payer.pubkey(); - let decimals = 9u8; - - let address_tree = rpc.get_address_tree_v2(); - let output_queue = rpc.get_random_state_tree_info().unwrap().queue; - - let compression_address = - derive_mint_compressed_address(&mint_seed.pubkey(), &address_tree.tree); - let (mint_pda, bump) = find_mint_address(&mint_seed.pubkey()); - - let rpc_result = rpc - .get_validity_proof( - vec![], - vec![AddressWithTree { - address: compression_address, - tree: address_tree.tree, - }], - None, - ) - .await - .unwrap() - .value; - - let params = CreateMintParams { - decimals, - address_merkle_tree_root_index: rpc_result.addresses[0].root_index, - mint_authority, - proof: rpc_result.proof.0.unwrap(), - compression_address, - mint: mint_pda, - bump, - freeze_authority: None, - extensions: None, - rent_payment: DEFAULT_RENT_PAYMENT, - write_top_up: DEFAULT_WRITE_TOP_UP, - }; - - let create_mint_ix = CreateMint::new( - params, - mint_seed.pubkey(), - payer.pubkey(), - address_tree.tree, - output_queue, - ) - .instruction() - .unwrap(); - - rpc.create_and_send_transaction(&[create_mint_ix], &payer.pubkey(), &[&payer, &mint_seed]) - .await - .unwrap(); - - // You can use light, spl, t22 mints to create a light token associated token account. - // Derive associated token account address and bump - let associated_token_account = derive_token_ata(&payer.pubkey(), &mint_pda); - - // Call the anchor program to create associated token account - let compressible_config = config_pda(); - let rent_sponsor = rent_sponsor_pda(); - - let ix = Instruction { - program_id: ID, - accounts: accounts::CreateAssociatedTokenAccountAccounts { - light_token_program: LIGHT_TOKEN_PROGRAM_ID, - owner: payer.pubkey(), - mint: mint_pda, - payer: payer.pubkey(), - associated_token_account: associated_token_account, - system_program: system_program::ID, - compressible_config, - rent_sponsor, - } - .to_account_metas(Some(true)), - data: CreateAssociatedTokenAccount { - idempotent: false, - } - .data(), - }; - - let sig = rpc.create_and_send_transaction(&[ix], &payer.pubkey(), &[&payer]) - .await - .unwrap(); - - println!("Tx: {}", sig); -} -``` - diff --git a/snippets/code-snippets/light-token/create-ata/instruction.mdx b/snippets/code-snippets/light-token/create-ata/instruction.mdx deleted file mode 100644 index 9398d191..00000000 --- a/snippets/code-snippets/light-token/create-ata/instruction.mdx +++ /dev/null @@ -1,52 +0,0 @@ -```typescript -import "dotenv/config"; -import { - Keypair, - Transaction, - sendAndConfirmTransaction, -} from "@solana/web3.js"; -import { createRpc, LIGHT_TOKEN_PROGRAM_ID } from "@lightprotocol/stateless.js"; -import { - createMintInterface, - createAssociatedTokenAccountInterfaceInstruction, - getAssociatedTokenAddressInterface, -} from "@lightprotocol/compressed-token"; -import { homedir } from "os"; -import { readFileSync } from "fs"; - -// devnet: -// const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; -// const rpc = createRpc(RPC_URL); -// localnet: -const rpc = createRpc(); - -const payer = Keypair.fromSecretKey( - new Uint8Array( - JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) - ) -); - -(async function () { - const { mint } = await createMintInterface(rpc, payer, payer, null, 9); - - const owner = Keypair.generate(); - const associatedToken = getAssociatedTokenAddressInterface( - mint, - owner.publicKey - ); - - const ix = createAssociatedTokenAccountInterfaceInstruction( - payer.publicKey, - associatedToken, - owner.publicKey, - mint, - LIGHT_TOKEN_PROGRAM_ID - ); - - const tx = new Transaction().add(ix); - const signature = await sendAndConfirmTransaction(rpc, tx, [payer]); - - console.log("ATA:", associatedToken.toBase58()); - console.log("Tx:", signature); -})(); -``` diff --git a/snippets/code-snippets/light-token/create-ata/native-program/full-example.mdx b/snippets/code-snippets/light-token/create-ata/native-program/full-example.mdx deleted file mode 100644 index 668c2657..00000000 --- a/snippets/code-snippets/light-token/create-ata/native-program/full-example.mdx +++ /dev/null @@ -1,172 +0,0 @@ - -```rust instruction.rs -use super::authority_seeds; -use light_token::instruction::CreateAssociatedAccountCpi; -use solana_program::{ - account_info::AccountInfo, entrypoint::ProgramResult, - program_error::ProgramError, -}; - -pub fn create_ata_invoke( - accounts: &[AccountInfo], - data: &[u8], -) -> ProgramResult { - let [owner, mint, payer, associated_token_account, system_program, compressible_config, rent_sponsor, _token_program] = - accounts - else { - return Err(ProgramError::NotEnoughAccountKeys); - }; - - if data.is_empty() { - return Err(ProgramError::InvalidInstructionData); - } - - let bump = data[0]; - let idempotent = data.get(1).copied().unwrap_or(0) != 0; - - // Create associated token account. Works with light, spl, t22 mints - let cpi = CreateAssociatedAccountCpi { - payer: payer.clone(), - owner: owner.clone(), - mint: mint.clone(), - ata: associated_token_account.clone(), - bump, - }; - - if idempotent { - cpi.idempotent().rent_free( - compressible_config.clone(), - rent_sponsor.clone(), - system_program.clone(), - ) - } else { - cpi.rent_free( - compressible_config.clone(), - rent_sponsor.clone(), - system_program.clone(), - ) - } - .invoke() -} - -pub fn create_ata_invoke_signed( - accounts: &[AccountInfo], - data: &[u8], -) -> ProgramResult { - let [owner, mint, payer, associated_token_account, system_program, compressible_config, rent_sponsor, _token_program] = - accounts - else { - return Err(ProgramError::NotEnoughAccountKeys); - }; - - if data.len() < 3 { - return Err(ProgramError::InvalidInstructionData); - } - - let bump = data[0]; - let idempotent = data[1] != 0; - let authority_bump = data[2]; - let signer_seeds = authority_seeds!(authority_bump); - - let cpi = CreateAssociatedAccountCpi { - payer: payer.clone(), - owner: owner.clone(), - mint: mint.clone(), - ata: associated_token_account.clone(), - bump, - }; - - if idempotent { - cpi.idempotent().rent_free( - compressible_config.clone(), - rent_sponsor.clone(), - system_program.clone(), - ) - } else { - cpi.rent_free( - compressible_config.clone(), - rent_sponsor.clone(), - system_program.clone(), - ) - } - .invoke_signed(&[signer_seeds]) -} -``` - -```rust test.rs -mod shared; - -use light_client::rpc::Rpc; -use light_token::instruction::derive_token_ata; -use shared::{ - build_create_ata_cpi_ix, build_create_ata_signed_cpi_ix, create_test_rpc, - get_authority_pda, setup_mint_with_tokens, -}; -use solana_sdk::signer::Signer; - -#[tokio::test(flavor = "multi_thread")] -async fn create_ata_cpi() { - // Works with light, spl, or t22 mints - let mut rpc = create_test_rpc().await; - let payer = rpc.get_payer().insecure_clone(); - - let (mint, _) = setup_mint_with_tokens( - &mut rpc, - &payer, - payer.pubkey(), - None, - 9, - vec![], - ) - .await; - - let owner = payer.pubkey(); - let (ata, bump) = derive_token_ata(&owner, &mint); - - let ix = build_create_ata_cpi_ix(owner, mint, payer.pubkey(), ata, bump); - - rpc.create_and_send_transaction(&[ix], &payer.pubkey(), &[&payer]) - .await - .unwrap(); - - let account = rpc.get_account(ata).await.unwrap(); - assert!(account.is_some()); -} - -#[tokio::test(flavor = "multi_thread")] -async fn create_ata_signed_cpi() { - let mut rpc = create_test_rpc().await; - let payer = rpc.get_payer().insecure_clone(); - - let (pda_owner, authority_bump) = get_authority_pda(); - - let (mint, _) = setup_mint_with_tokens( - &mut rpc, - &payer, - payer.pubkey(), - None, - 9, - vec![], - ) - .await; - - let (ata, ata_bump) = derive_token_ata(&pda_owner, &mint); - - let ix = build_create_ata_signed_cpi_ix( - pda_owner, - mint, - payer.pubkey(), - ata, - ata_bump, - authority_bump, - ); - - rpc.create_and_send_transaction(&[ix], &payer.pubkey(), &[&payer]) - .await - .unwrap(); - - let account = rpc.get_account(ata).await.unwrap(); - assert!(account.is_some()); -} -``` - diff --git a/snippets/code-snippets/light-token/create-ata/rust-client/action.mdx b/snippets/code-snippets/light-token/create-ata/rust-client/action.mdx deleted file mode 100644 index f78de568..00000000 --- a/snippets/code-snippets/light-token/create-ata/rust-client/action.mdx +++ /dev/null @@ -1,33 +0,0 @@ -```rust -use light_token_client::actions::{CreateAta, CreateMint}; -use rust_client::setup_rpc_and_payer; -use solana_sdk::signer::Signer; - -#[tokio::main] -async fn main() -> Result<(), Box> { - let (mut rpc, payer) = setup_rpc_and_payer().await; - - // Create mint - let (_signature, mint) = CreateMint { - decimals: 9, - freeze_authority: None, - token_metadata: None, - seed: None, - } - .execute(&mut rpc, &payer, &payer) - .await?; - - // Create associated token account - let (_signature, associated_token_account) = CreateAta { - mint, - owner: payer.pubkey(), - idempotent: true, - } - .execute(&mut rpc, &payer) - .await?; - - println!("Associated token account: {associated_token_account}"); - - Ok(()) -} -``` diff --git a/snippets/code-snippets/light-token/create-ata/rust-client/idempotent.mdx b/snippets/code-snippets/light-token/create-ata/rust-client/idempotent.mdx deleted file mode 100644 index 63014368..00000000 --- a/snippets/code-snippets/light-token/create-ata/rust-client/idempotent.mdx +++ /dev/null @@ -1,11 +0,0 @@ -```rust -use light_token::instruction::CreateAssociatedTokenAccount; - -let create_ata_ix = CreateAssociatedTokenAccount::new( - payer.pubkey(), - payer.pubkey(), - mint, -) -.idempotent() -.instruction()?; -``` diff --git a/snippets/code-snippets/light-token/create-ata/rust-client/instruction.mdx b/snippets/code-snippets/light-token/create-ata/rust-client/instruction.mdx deleted file mode 100644 index 0b8a1fcd..00000000 --- a/snippets/code-snippets/light-token/create-ata/rust-client/instruction.mdx +++ /dev/null @@ -1,31 +0,0 @@ -```rust -use light_client::rpc::Rpc; -use light_token::instruction::{get_associated_token_address, CreateAssociatedTokenAccount}; -use rust_client::{setup_spl_mint_context, SplMintContext}; -use solana_sdk::{signature::Keypair, signer::Signer}; - -#[tokio::main] -async fn main() -> Result<(), Box> { - // You can use Light, SPL, or Token-2022 mints to create a Light associated token account. - let SplMintContext { - mut rpc, - payer, - mint, - } = setup_spl_mint_context().await; - - let owner = Keypair::new(); - - let create_associated_token_account_instruction = - CreateAssociatedTokenAccount::new(payer.pubkey(), owner.pubkey(), mint).instruction()?; - - let sig = rpc - .create_and_send_transaction(&[create_associated_token_account_instruction], &payer.pubkey(), &[&payer]) - .await?; - - let associated_token_account = get_associated_token_address(&owner.pubkey(), &mint); - let data = rpc.get_account(associated_token_account).await?; - println!("Associated token account: {associated_token_account} exists: {} Tx: {sig}", data.is_some()); - - Ok(()) -} -``` diff --git a/snippets/code-snippets/light-token/create-ata/token-interface-instruction.mdx b/snippets/code-snippets/light-token/create-ata/token-interface-instruction.mdx deleted file mode 100644 index 9dce2f72..00000000 --- a/snippets/code-snippets/light-token/create-ata/token-interface-instruction.mdx +++ /dev/null @@ -1,24 +0,0 @@ -```typescript -import { Keypair, Transaction, sendAndConfirmTransaction } from "@solana/web3.js"; -import { createRpc, LIGHT_TOKEN_PROGRAM_ID } from "@lightprotocol/stateless.js"; -import { createAtaInstruction, getAtaAddress } from "@lightprotocol/token-interface"; - -const rpc = createRpc(); -const payer = Keypair.fromSecretKey(/* ... */); - -const mint = /* existing mint public key */; -const owner = Keypair.generate(); -const associatedToken = getAtaAddress({ mint, owner: owner.publicKey }); - -const ix = createAtaInstruction({ - payer: payer.publicKey, - owner: owner.publicKey, - mint, - programId: LIGHT_TOKEN_PROGRAM_ID, -}); - -const tx = new Transaction().add(ix); -const signature = await sendAndConfirmTransaction(rpc, tx, [payer]); -console.log("ATA:", associatedToken.toBase58()); -console.log("Tx:", signature); -``` diff --git a/snippets/code-snippets/light-token/create-mint/action.mdx b/snippets/code-snippets/light-token/create-mint/action.mdx deleted file mode 100644 index 2e10a440..00000000 --- a/snippets/code-snippets/light-token/create-mint/action.mdx +++ /dev/null @@ -1,44 +0,0 @@ -```typescript -import "dotenv/config"; -import { Keypair } from "@solana/web3.js"; -import { createRpc } from "@lightprotocol/stateless.js"; -import { - createMintInterface, - createTokenMetadata, -} from "@lightprotocol/compressed-token"; -import { homedir } from "os"; -import { readFileSync } from "fs"; - -// devnet: -// const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; -// const rpc = createRpc(RPC_URL); -// localnet: -const rpc = createRpc(); - -const payer = Keypair.fromSecretKey( - new Uint8Array( - JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) - ) -); - -(async function () { - const { mint, transactionSignature } = await createMintInterface( - rpc, - payer, - payer, - null, - 9, - undefined, // keypair - undefined, // confirmOptions (default) - undefined, // programId (LIGHT_TOKEN_PROGRAM_ID) - createTokenMetadata( - "Example Token", - "EXT", - "https://example.com/metadata.json" - ) - ); - - console.log("Mint:", mint.toBase58()); - console.log("Tx:", transactionSignature); -})(); -``` diff --git a/snippets/code-snippets/light-token/create-mint/anchor-macro/full-example.mdx b/snippets/code-snippets/light-token/create-mint/anchor-macro/full-example.mdx deleted file mode 100644 index cd4f5a0e..00000000 --- a/snippets/code-snippets/light-token/create-mint/anchor-macro/full-example.mdx +++ /dev/null @@ -1,343 +0,0 @@ - -```rust lib.rs -#![allow(deprecated)] - -use anchor_lang::prelude::*; -use light_account::{ - derive_light_cpi_signer, light_program, CreateAccountsProof, CpiSigner, LightAccounts, -}; - -declare_id!("HVmVqSJyMejBeUigePMSfX4aENJzCGHNxAJuT2PDMPRx"); - -pub const LIGHT_CPI_SIGNER: CpiSigner = - derive_light_cpi_signer!("HVmVqSJyMejBeUigePMSfX4aENJzCGHNxAJuT2PDMPRx"); - -pub const MINT_SIGNER_SEED: &[u8] = b"mint_signer"; - -#[derive(AnchorSerialize, AnchorDeserialize, Clone)] -pub struct CreateMintParams { - pub create_accounts_proof: CreateAccountsProof, - pub mint_signer_bump: u8, -} - -#[derive(AnchorSerialize, AnchorDeserialize, Clone)] -pub struct CreateMintWithMetadataParams { - pub create_accounts_proof: CreateAccountsProof, - pub mint_signer_bump: u8, - pub name: Vec, - pub symbol: Vec, - pub uri: Vec, -} - -#[derive(Accounts, LightAccounts)] -#[instruction(params: CreateMintParams)] -pub struct CreateMint<'info> { - #[account(mut)] - pub fee_payer: Signer<'info>, - - pub authority: Signer<'info>, - - /// CHECK: PDA derived from authority - #[account( - seeds = [MINT_SIGNER_SEED, authority.key().as_ref()], - bump, - )] - pub mint_signer: UncheckedAccount<'info>, - - /// CHECK: Initialized by light_mint CPI - #[account(mut)] - #[light_account(init, - mint::signer = mint_signer, - mint::authority = fee_payer, - mint::decimals = 9, - mint::seeds = &[MINT_SIGNER_SEED, self.authority.to_account_info().key.as_ref()], - mint::bump = params.mint_signer_bump - )] - pub mint: UncheckedAccount<'info>, - - /// CHECK: Compression config PDA - pub compression_config: AccountInfo<'info>, - - /// CHECK: Light Token config - pub light_token_config: AccountInfo<'info>, - - /// CHECK: Rent sponsor - #[account(mut)] - pub light_token_rent_sponsor: AccountInfo<'info>, - - /// CHECK: Light Token program - pub light_token_program: AccountInfo<'info>, - - /// CHECK: Light Token CPI authority - pub light_token_cpi_authority: AccountInfo<'info>, - - pub system_program: Program<'info, System>, -} - -#[derive(Accounts, LightAccounts)] -#[instruction(params: CreateMintWithMetadataParams)] -pub struct CreateMintWithMetadata<'info> { - #[account(mut)] - pub fee_payer: Signer<'info>, - - pub authority: Signer<'info>, - - /// CHECK: PDA derived from authority - #[account( - seeds = [MINT_SIGNER_SEED, authority.key().as_ref()], - bump, - )] - pub mint_signer: UncheckedAccount<'info>, - - /// CHECK: Initialized by light_mint CPI - #[account(mut)] - #[light_account(init, - mint::signer = mint_signer, - mint::authority = fee_payer, - mint::decimals = 9, - mint::seeds = &[MINT_SIGNER_SEED, self.authority.to_account_info().key.as_ref()], - mint::bump = params.mint_signer_bump, - mint::name = params.name.clone(), - mint::symbol = params.symbol.clone(), - mint::uri = params.uri.clone(), - mint::update_authority = authority - )] - pub mint: UncheckedAccount<'info>, - - /// CHECK: Compression config PDA - pub compression_config: AccountInfo<'info>, - - /// CHECK: Light Token config - pub light_token_config: AccountInfo<'info>, - - /// CHECK: Rent sponsor - #[account(mut)] - pub light_token_rent_sponsor: AccountInfo<'info>, - - /// CHECK: Light Token program - pub light_token_program: AccountInfo<'info>, - - /// CHECK: Light Token CPI authority - pub light_token_cpi_authority: AccountInfo<'info>, - - pub system_program: Program<'info, System>, -} - -#[light_program] -#[program] -pub mod light_token_macro_create_mint { - use super::*; - - #[allow(unused_variables)] - pub fn create_mint<'info>( - ctx: Context<'_, '_, '_, 'info, CreateMint<'info>>, - params: CreateMintParams, - ) -> Result<()> { - Ok(()) - } - - #[allow(unused_variables)] - pub fn create_mint_with_metadata<'info>( - ctx: Context<'_, '_, '_, 'info, CreateMintWithMetadata<'info>>, - params: CreateMintWithMetadataParams, - ) -> Result<()> { - Ok(()) - } -} -``` - -```rust test.rs -use anchor_lang::{prelude::borsh, InstructionData, ToAccountMetas}; -use light_client::interface::{ - get_create_accounts_proof, CreateAccountsProofInput, InitializeRentFreeConfig, -}; -use light_program_test::{ - program_test::{setup_mock_program_data, LightProgramTest}, - ProgramTestConfig, Rpc, -}; -use light_account::{derive_rent_sponsor_pda, LIGHT_TOKEN_PROGRAM_ID}; -use light_token::instruction::{find_mint_address, LIGHT_TOKEN_CONFIG, LIGHT_TOKEN_RENT_SPONSOR}; -use solana_instruction::Instruction; -use solana_keypair::Keypair; -use solana_pubkey::Pubkey; -use solana_signer::Signer; - -use light_token_macro_create_mint::MINT_SIGNER_SEED; - -async fn setup() -> (light_program_test::LightProgramTest, Keypair, Pubkey, Pubkey) { - let program_id = light_token_macro_create_mint::ID; - let mut config = - ProgramTestConfig::new_v2(true, Some(vec![("light_token_macro_create_mint", program_id)])); - config = config.with_light_protocol_events(); - - let mut rpc = LightProgramTest::new(config).await.unwrap(); - let payer = rpc.get_payer().insecure_clone(); - - let program_data_pda = setup_mock_program_data(&mut rpc, &payer, &program_id); - - let (rent_sponsor, _) = derive_rent_sponsor_pda(&program_id); - - let (init_config_ix, config_pda) = InitializeRentFreeConfig::new( - &program_id, - &payer.pubkey(), - &program_data_pda, - rent_sponsor, - payer.pubkey(), - ) - .build(); - - rpc.create_and_send_transaction(&[init_config_ix], &payer.pubkey(), &[&payer]) - .await - .expect("Initialize config should succeed"); - - (rpc, payer, config_pda, program_id) -} - -#[tokio::test] -async fn test_create_mint() { - use light_token_macro_create_mint::CreateMintParams; - - let (mut rpc, payer, config_pda, program_id) = setup().await; - - let authority = Keypair::new(); - let (mint_signer_pda, mint_signer_bump) = Pubkey::find_program_address( - &[MINT_SIGNER_SEED, authority.pubkey().as_ref()], - &program_id, - ); - let (mint_pda, _) = find_mint_address(&mint_signer_pda); - - let proof_result = get_create_accounts_proof( - &rpc, - &program_id, - vec![CreateAccountsProofInput::mint(mint_signer_pda)], - ) - .await - .unwrap(); - - let accounts = light_token_macro_create_mint::accounts::CreateMint { - fee_payer: payer.pubkey(), - authority: authority.pubkey(), - mint_signer: mint_signer_pda, - mint: mint_pda, - compression_config: config_pda, - light_token_config: LIGHT_TOKEN_CONFIG, - light_token_rent_sponsor: LIGHT_TOKEN_RENT_SPONSOR, - light_token_program: LIGHT_TOKEN_PROGRAM_ID.into(), - light_token_cpi_authority: light_token::constants::LIGHT_TOKEN_CPI_AUTHORITY, - system_program: solana_sdk::system_program::ID, - }; - - let instruction_data = light_token_macro_create_mint::instruction::CreateMint { - params: CreateMintParams { - create_accounts_proof: proof_result.create_accounts_proof, - mint_signer_bump, - }, - }; - - let instruction = Instruction { - program_id, - accounts: [ - accounts.to_account_metas(None), - proof_result.remaining_accounts, - ] - .concat(), - data: instruction_data.data(), - }; - - rpc.create_and_send_transaction(&[instruction], &payer.pubkey(), &[&payer, &authority]) - .await - .expect("CreateMint should succeed"); - - let mint_account = rpc - .get_account(mint_pda) - .await - .unwrap() - .expect("Mint should exist on-chain"); - - use light_token_interface::state::Mint; - let mint: Mint = borsh::BorshDeserialize::deserialize(&mut &mint_account.data[..]) - .expect("Failed to deserialize Mint"); - - assert_eq!(mint.base.decimals, 9); - assert_eq!( - mint.base.mint_authority, - Some(payer.pubkey().to_bytes().into()), - ); -} - -#[tokio::test] -async fn test_create_mint_with_metadata() { - use light_token_macro_create_mint::CreateMintWithMetadataParams; - - let (mut rpc, payer, config_pda, program_id) = setup().await; - - let authority = Keypair::new(); - let (mint_signer_pda, mint_signer_bump) = Pubkey::find_program_address( - &[MINT_SIGNER_SEED, authority.pubkey().as_ref()], - &program_id, - ); - let (mint_pda, _) = find_mint_address(&mint_signer_pda); - - let proof_result = get_create_accounts_proof( - &rpc, - &program_id, - vec![CreateAccountsProofInput::mint(mint_signer_pda)], - ) - .await - .unwrap(); - - let accounts = light_token_macro_create_mint::accounts::CreateMintWithMetadata { - fee_payer: payer.pubkey(), - authority: authority.pubkey(), - mint_signer: mint_signer_pda, - mint: mint_pda, - compression_config: config_pda, - light_token_config: LIGHT_TOKEN_CONFIG, - light_token_rent_sponsor: LIGHT_TOKEN_RENT_SPONSOR, - light_token_program: LIGHT_TOKEN_PROGRAM_ID.into(), - light_token_cpi_authority: light_token::constants::LIGHT_TOKEN_CPI_AUTHORITY, - system_program: solana_sdk::system_program::ID, - }; - - let instruction_data = light_token_macro_create_mint::instruction::CreateMintWithMetadata { - params: CreateMintWithMetadataParams { - create_accounts_proof: proof_result.create_accounts_proof, - mint_signer_bump, - name: b"Test Token".to_vec(), - symbol: b"TST".to_vec(), - uri: b"https://example.com/metadata.json".to_vec(), - }, - }; - - let instruction = Instruction { - program_id, - accounts: [ - accounts.to_account_metas(None), - proof_result.remaining_accounts, - ] - .concat(), - data: instruction_data.data(), - }; - - rpc.create_and_send_transaction(&[instruction], &payer.pubkey(), &[&payer, &authority]) - .await - .expect("CreateMintWithMetadata should succeed"); - - let mint_account = rpc - .get_account(mint_pda) - .await - .unwrap() - .expect("Mint should exist on-chain"); - - use light_token_interface::state::Mint; - let mint: Mint = borsh::BorshDeserialize::deserialize(&mut &mint_account.data[..]) - .expect("Failed to deserialize Mint"); - - assert_eq!(mint.base.decimals, 9); - assert_eq!( - mint.base.mint_authority, - Some(payer.pubkey().to_bytes().into()), - ); -} -``` - diff --git a/snippets/code-snippets/light-token/create-mint/anchor-program/full-example.mdx b/snippets/code-snippets/light-token/create-mint/anchor-program/full-example.mdx deleted file mode 100644 index e81a155d..00000000 --- a/snippets/code-snippets/light-token/create-mint/anchor-program/full-example.mdx +++ /dev/null @@ -1,232 +0,0 @@ - -```rust lib.rs -#![allow(unexpected_cfgs, deprecated)] - -use anchor_lang::prelude::*; -use light_token::instruction::{ - CreateMintCpi, CreateMintParams, SystemAccountInfos, DEFAULT_RENT_PAYMENT, DEFAULT_WRITE_TOP_UP, -}; -use light_token::{CompressedProof, ExtensionInstructionData, TokenMetadataInstructionData}; - -declare_id!("A1rJEoepgKYWZYZ8KVFpxgeeRGwBrU7xk8S39srjVkUX"); - -/// Token metadata parameters for creating a mint with metadata. -#[derive(AnchorSerialize, AnchorDeserialize, Clone)] -pub struct TokenMetadataParams { - pub name: Vec, - pub symbol: Vec, - pub uri: Vec, - pub update_authority: Option, -} - -#[program] -pub mod light_token_anchor_create_mint { - use super::*; - - pub fn create_mint( - ctx: Context, - decimals: u8, - address_merkle_tree_root_index: u16, - compression_address: [u8; 32], - proof: CompressedProof, - freeze_authority: Option, - bump: u8, - rent_payment: Option, - write_top_up: Option, - metadata: Option, - ) -> Result<()> { - let mint = light_token::instruction::find_mint_address(ctx.accounts.mint_seed.key).0; - - let extensions = metadata.map(|m| { - vec![ExtensionInstructionData::TokenMetadata( - TokenMetadataInstructionData { - update_authority: m - .update_authority - .map(|p| p.to_bytes().into()), - name: m.name, - symbol: m.symbol, - uri: m.uri, - additional_metadata: None, - }, - )] - }); - - let params = CreateMintParams { - decimals, - address_merkle_tree_root_index, - mint_authority: *ctx.accounts.authority.key, - proof, - compression_address, - mint, - bump, - freeze_authority, - extensions, - rent_payment: rent_payment.unwrap_or(DEFAULT_RENT_PAYMENT), - write_top_up: write_top_up.unwrap_or(DEFAULT_WRITE_TOP_UP), - }; - - let system_accounts = SystemAccountInfos { - light_system_program: ctx.accounts.light_system_program.to_account_info(), - cpi_authority_pda: ctx.accounts.cpi_authority_pda.to_account_info(), - registered_program_pda: ctx.accounts.registered_program_pda.to_account_info(), - account_compression_authority: ctx.accounts.account_compression_authority.to_account_info(), - account_compression_program: ctx.accounts.account_compression_program.to_account_info(), - system_program: ctx.accounts.system_program.to_account_info(), - }; - - CreateMintCpi { - mint_seed: ctx.accounts.mint_seed.to_account_info(), - authority: ctx.accounts.authority.to_account_info(), - payer: ctx.accounts.payer.to_account_info(), - address_tree: ctx.accounts.address_tree.to_account_info(), - output_queue: ctx.accounts.output_queue.to_account_info(), - compressible_config: ctx.accounts.compressible_config.to_account_info(), - mint: ctx.accounts.mint.to_account_info(), - rent_sponsor: ctx.accounts.rent_sponsor.to_account_info(), - system_accounts, - cpi_context: None, - cpi_context_account: None, - params, - } - .invoke()?; - Ok(()) - } -} - -#[derive(Accounts)] -pub struct CreateMintAccounts<'info> { - /// CHECK: Light token program for CPI - pub light_token_program: AccountInfo<'info>, - pub mint_seed: Signer<'info>, - /// CHECK: Validated by light-token CPI - pub authority: AccountInfo<'info>, - #[account(mut)] - pub payer: Signer<'info>, - /// CHECK: Validated by light-token CPI - #[account(mut)] - pub address_tree: AccountInfo<'info>, - /// CHECK: Validated by light-token CPI - #[account(mut)] - pub output_queue: AccountInfo<'info>, - /// CHECK: Validated by light-token CPI - pub light_system_program: AccountInfo<'info>, - /// CHECK: Validated by light-token CPI - pub cpi_authority_pda: AccountInfo<'info>, - /// CHECK: Validated by light-token CPI - pub registered_program_pda: AccountInfo<'info>, - /// CHECK: Validated by light-token CPI - pub account_compression_authority: AccountInfo<'info>, - /// CHECK: Validated by light-token CPI - pub account_compression_program: AccountInfo<'info>, - pub system_program: Program<'info, System>, - /// CHECK: Validated by light-token CPI - use light_token::token::config_pda() - pub compressible_config: AccountInfo<'info>, - /// CHECK: Validated by light-token CPI - derived from find_mint_address(mint_seed) - #[account(mut)] - pub mint: AccountInfo<'info>, - /// CHECK: Validated by light-token CPI - use light_token::token::rent_sponsor_pda() - #[account(mut)] - pub rent_sponsor: AccountInfo<'info>, -} -``` - -```rust test.rs -use anchor_lang::{InstructionData, ToAccountMetas}; -use light_program_test::{Indexer, LightProgramTest, ProgramTestConfig, Rpc}; -use light_token_anchor_create_mint::{accounts, instruction::CreateMint, ID}; -use light_token::instruction::{ - config_pda, derive_mint_compressed_address, find_mint_address, rent_sponsor_pda, - SystemAccounts, LIGHT_TOKEN_PROGRAM_ID, DEFAULT_RENT_PAYMENT, DEFAULT_WRITE_TOP_UP, -}; -use anchor_lang::system_program; -use solana_sdk::{ - instruction::Instruction, - signature::Keypair, - signer::Signer, -}; - -#[tokio::test] -async fn test_create_mint() { - let config = - ProgramTestConfig::new_v2(true, Some(vec![("light_token_anchor_create_mint", ID)])); - let mut rpc = LightProgramTest::new(config).await.unwrap(); - let payer = rpc.get_payer().insecure_clone(); - - let mint_seed = Keypair::new(); - let mint_authority = payer.pubkey(); - let decimals = 9u8; - - let address_tree = rpc.get_address_tree_v2(); - let output_queue = rpc.get_random_state_tree_info().unwrap().queue; - - let compression_address = - derive_mint_compressed_address(&mint_seed.pubkey(), &address_tree.tree); - - let (mint_pda, bump) = find_mint_address(&mint_seed.pubkey()); - - let rpc_result = rpc - .get_validity_proof( - vec![], - vec![light_client::indexer::AddressWithTree { - address: compression_address, - tree: address_tree.tree, - }], - None, - ) - .await - .unwrap() - .value; - - let system_accounts = SystemAccounts::default(); - - // Call the anchor program to create mint - let ix = Instruction { - program_id: ID, - accounts: accounts::CreateMintAccounts { - light_token_program: LIGHT_TOKEN_PROGRAM_ID, - mint_seed: mint_seed.pubkey(), - authority: mint_authority, - payer: payer.pubkey(), - address_tree: address_tree.tree, - output_queue, - light_system_program: system_accounts.light_system_program, - cpi_authority_pda: system_accounts.cpi_authority_pda, - registered_program_pda: system_accounts.registered_program_pda, - account_compression_authority: system_accounts.account_compression_authority, - account_compression_program: system_accounts.account_compression_program, - system_program: system_program::ID, - compressible_config: config_pda(), - mint: mint_pda, - rent_sponsor: rent_sponsor_pda(), - } - .to_account_metas(Some(true)), - data: CreateMint { - decimals, - address_merkle_tree_root_index: rpc_result.addresses[0].root_index, - compression_address: compression_address.into(), - proof: rpc_result.proof.0.unwrap(), - freeze_authority: None, - bump, - rent_payment: Some(DEFAULT_RENT_PAYMENT), - write_top_up: Some(DEFAULT_WRITE_TOP_UP), - metadata: None, - } - .data(), - }; - - let sig = rpc - .create_and_send_transaction(&[ix], &payer.pubkey(), &[&payer, &mint_seed]) - .await - .unwrap(); - - let compressed_account = rpc - .get_compressed_account(compression_address, None) - .await - .unwrap() - .value; - - assert!(compressed_account.is_some(), "Light-mint should exist"); - println!("Tx: {}", sig); -} -``` - diff --git a/snippets/code-snippets/light-token/create-mint/native-program/full-example.mdx b/snippets/code-snippets/light-token/create-mint/native-program/full-example.mdx deleted file mode 100644 index 25a3bfe7..00000000 --- a/snippets/code-snippets/light-token/create-mint/native-program/full-example.mdx +++ /dev/null @@ -1,483 +0,0 @@ - -```rust instruction.rs -use super::authority_seeds; -use borsh::BorshDeserialize; -use light_compressible::CreateAccountsProof; -use light_token::instruction::{ - CreateMintCpi, CreateMintParams, SystemAccountInfos, -}; -use light_token::instruction::{ - ExtensionInstructionData, TokenMetadataInstructionData, -}; -use solana_program::{ - account_info::AccountInfo, entrypoint::ProgramResult, - program_error::ProgramError, pubkey::Pubkey, -}; - -#[derive(BorshDeserialize)] -struct CreateMintData { - decimals: u8, - mint_authority: Pubkey, - create_accounts_proof: CreateAccountsProof, - compression_address: [u8; 32], - mint: Pubkey, - bump: u8, - freeze_authority: Option, - rent_payment: u8, - write_top_up: u32, - metadata_name: Option>, - metadata_symbol: Option>, - metadata_uri: Option>, -} - -pub fn create_mint_invoke( - accounts: &[AccountInfo], - data: &[u8], -) -> ProgramResult { - let [mint_seed, authority, payer, address_tree, output_queue, compressible_config, mint, rent_sponsor, light_system_program, cpi_authority_pda, registered_program_pda, account_compression_authority, account_compression_program, system_program, _token_program] = - accounts - else { - return Err(ProgramError::NotEnoughAccountKeys); - }; - - let ix_data = CreateMintData::deserialize(&mut &data[..]) - .map_err(|_| ProgramError::InvalidInstructionData)?; - - // Build token metadata extension if metadata fields are provided - let extensions = match ( - &ix_data.metadata_name, - &ix_data.metadata_symbol, - &ix_data.metadata_uri, - ) { - (Some(name), Some(symbol), Some(uri)) => { - Some(vec![ExtensionInstructionData::TokenMetadata( - TokenMetadataInstructionData { - update_authority: Some( - ix_data.mint_authority.to_bytes().into(), - ), - name: name.clone(), - symbol: symbol.clone(), - uri: uri.clone(), - additional_metadata: None, - }, - )]) - } - _ => None, - }; - - // Create mint. rent_payment: ~24h rent/unit, write_top_up: ~3h rent/write - let params = CreateMintParams { - decimals: ix_data.decimals, - address_merkle_tree_root_index: ix_data - .create_accounts_proof - .address_tree_info - .root_index, - mint_authority: ix_data.mint_authority, - proof: ix_data.create_accounts_proof.proof.0.unwrap_or_default(), - compression_address: ix_data.compression_address, - mint: ix_data.mint, - bump: ix_data.bump, - freeze_authority: ix_data.freeze_authority, - extensions, - rent_payment: ix_data.rent_payment, - write_top_up: ix_data.write_top_up, - }; - - let system_accounts = SystemAccountInfos { - light_system_program: light_system_program.clone(), - cpi_authority_pda: cpi_authority_pda.clone(), - registered_program_pda: registered_program_pda.clone(), - account_compression_authority: account_compression_authority.clone(), - account_compression_program: account_compression_program.clone(), - system_program: system_program.clone(), - }; - - CreateMintCpi::new( - mint_seed.clone(), - authority.clone(), - payer.clone(), - address_tree.clone(), - output_queue.clone(), - compressible_config.clone(), - mint.clone(), - rent_sponsor.clone(), - system_accounts, - params, - ) - .invoke() -} - -#[derive(BorshDeserialize)] -struct CreateMintSignedData { - decimals: u8, - create_accounts_proof: CreateAccountsProof, - compression_address: [u8; 32], - mint: Pubkey, - bump: u8, - freeze_authority: Option, - rent_payment: u8, - write_top_up: u32, - authority_bump: u8, - metadata_name: Option>, - metadata_symbol: Option>, - metadata_uri: Option>, -} - -pub fn create_mint_invoke_signed( - accounts: &[AccountInfo], - data: &[u8], -) -> ProgramResult { - let [mint_seed, authority, payer, address_tree, output_queue, compressible_config, mint, rent_sponsor, light_system_program, cpi_authority_pda, registered_program_pda, account_compression_authority, account_compression_program, system_program, _token_program] = - accounts - else { - return Err(ProgramError::NotEnoughAccountKeys); - }; - - let ix_data = CreateMintSignedData::deserialize(&mut &data[..]) - .map_err(|_| ProgramError::InvalidInstructionData)?; - - let signer_seeds = authority_seeds!(ix_data.authority_bump); - - // Build token metadata extension if metadata fields are provided - let extensions = match ( - &ix_data.metadata_name, - &ix_data.metadata_symbol, - &ix_data.metadata_uri, - ) { - (Some(name), Some(symbol), Some(uri)) => { - Some(vec![ExtensionInstructionData::TokenMetadata( - TokenMetadataInstructionData { - update_authority: Some(authority.key.to_bytes().into()), - name: name.clone(), - symbol: symbol.clone(), - uri: uri.clone(), - additional_metadata: None, - }, - )]) - } - _ => None, - }; - - let params = CreateMintParams { - decimals: ix_data.decimals, - address_merkle_tree_root_index: ix_data - .create_accounts_proof - .address_tree_info - .root_index, - mint_authority: *authority.key, - proof: ix_data.create_accounts_proof.proof.0.unwrap_or_default(), - compression_address: ix_data.compression_address, - mint: ix_data.mint, - bump: ix_data.bump, - freeze_authority: ix_data.freeze_authority, - extensions, - rent_payment: ix_data.rent_payment, - write_top_up: ix_data.write_top_up, - }; - - let system_accounts = SystemAccountInfos { - light_system_program: light_system_program.clone(), - cpi_authority_pda: cpi_authority_pda.clone(), - registered_program_pda: registered_program_pda.clone(), - account_compression_authority: account_compression_authority.clone(), - account_compression_program: account_compression_program.clone(), - system_program: system_program.clone(), - }; - - CreateMintCpi::new( - mint_seed.clone(), - authority.clone(), - payer.clone(), - address_tree.clone(), - output_queue.clone(), - compressible_config.clone(), - mint.clone(), - rent_sponsor.clone(), - system_accounts, - params, - ) - .invoke_signed(&[signer_seeds]) -} -``` - -```rust test.rs -mod shared; - -use borsh::BorshSerialize; -use light_client::{ - indexer::{AddressWithTree, Indexer}, - rpc::Rpc, -}; -use light_compressed_account::instruction_data::{ - compressed_proof::ValidityProof, data::PackedAddressTreeInfo, -}; -use light_compressible::CreateAccountsProof; -use light_token::instruction::{ - config_pda, derive_mint_compressed_address, find_mint_address, - rent_sponsor_pda, SystemAccounts, LIGHT_TOKEN_PROGRAM_ID, -}; -use shared::{create_test_rpc, get_authority_pda, PROGRAM_ID}; -use solana_sdk::{ - instruction::{AccountMeta, Instruction}, - pubkey::Pubkey, - signature::Keypair, - signer::Signer, -}; - -#[tokio::test(flavor = "multi_thread")] -async fn create_mint_cpi() { - let mut rpc = create_test_rpc().await; - - let payer = rpc.get_payer().insecure_clone(); - let mint_seed = Keypair::new(); - let decimals = 9u8; - - // Get address tree to store compressed address for when mint turns inactive - // We must create a compressed address at creation to ensure the mint does not exist yet - let address_tree = rpc.get_address_tree_v2(); - // Get state tree to store mint when inactive - let output_queue = rpc.get_random_state_tree_info().unwrap().queue; - - // Derive mint addresses - let compression_address = - derive_mint_compressed_address(&mint_seed.pubkey(), &address_tree.tree); - let (mint, bump) = find_mint_address(&mint_seed.pubkey()); - - let rpc_result = rpc - .get_validity_proof( - vec![], - vec![AddressWithTree { - address: compression_address, - tree: address_tree.tree, - }], - None, - ) - .await - .unwrap() - .value; - - // Build instruction data - #[derive(BorshSerialize)] - struct CreateMintDataTest { - decimals: u8, - mint_authority: Pubkey, - create_accounts_proof: CreateAccountsProof, - compression_address: [u8; 32], - mint: Pubkey, - bump: u8, - freeze_authority: Option, - rent_payment: u8, - write_top_up: u32, - metadata_name: Option>, - metadata_symbol: Option>, - metadata_uri: Option>, - } - - let create_accounts_proof = CreateAccountsProof { - proof: ValidityProof(rpc_result.proof.0), - address_tree_info: PackedAddressTreeInfo { - address_merkle_tree_pubkey_index: 0, - address_queue_pubkey_index: 0, - root_index: rpc_result.addresses[0].root_index, - }, - output_state_tree_index: 0, - state_tree_index: None, - }; - - let test_data = CreateMintDataTest { - decimals, - mint_authority: payer.pubkey(), - create_accounts_proof, - compression_address, - mint, - bump, - freeze_authority: None, - rent_payment: 16, - write_top_up: 766, - metadata_name: Some(b"Example Token".to_vec()), - metadata_symbol: Some(b"EXT".to_vec()), - metadata_uri: Some(b"https://example.com/metadata.json".to_vec()), - }; - - let mut data = vec![0u8]; - data.extend(test_data.try_to_vec().unwrap()); - - let system_accounts = SystemAccounts::default(); - - // Build and send instruction (mint_seed must sign) - let ix = Instruction { - program_id: PROGRAM_ID, - accounts: vec![ - AccountMeta::new(mint_seed.pubkey(), true), - AccountMeta::new_readonly(payer.pubkey(), true), - AccountMeta::new(payer.pubkey(), true), - AccountMeta::new(address_tree.tree, false), - AccountMeta::new(output_queue, false), - AccountMeta::new_readonly(config_pda(), false), - AccountMeta::new(mint, false), - AccountMeta::new(rent_sponsor_pda(), false), - AccountMeta::new_readonly( - system_accounts.light_system_program, - false, - ), - AccountMeta::new_readonly(system_accounts.cpi_authority_pda, false), - AccountMeta::new_readonly( - system_accounts.registered_program_pda, - false, - ), - AccountMeta::new_readonly( - system_accounts.account_compression_authority, - false, - ), - AccountMeta::new_readonly( - system_accounts.account_compression_program, - false, - ), - AccountMeta::new_readonly(system_accounts.system_program, false), - AccountMeta::new_readonly(LIGHT_TOKEN_PROGRAM_ID, false), - ], - data, - }; - - rpc.create_and_send_transaction( - &[ix], - &payer.pubkey(), - &[&payer, &mint_seed], - ) - .await - .unwrap(); - - let mint_account = rpc.get_account(mint).await.unwrap(); - assert!(mint_account.is_some()); -} - -#[tokio::test(flavor = "multi_thread")] -async fn create_mint_signed_cpi() { - let mut rpc = create_test_rpc().await; - - let payer = rpc.get_payer().insecure_clone(); - let mint_seed = Keypair::new(); - let decimals = 9u8; - - let (pda_authority, authority_bump) = get_authority_pda(); - - // Get address tree to store compressed address for when mint turns inactive - // We must create a compressed address at creation to ensure the mint does not exist yet - let address_tree = rpc.get_address_tree_v2(); - // Get state tree to store mint when inactive - let output_queue = rpc.get_random_state_tree_info().unwrap().queue; - - // Derive mint addresses - let compression_address = - derive_mint_compressed_address(&mint_seed.pubkey(), &address_tree.tree); - let (mint, bump) = find_mint_address(&mint_seed.pubkey()); - - let rpc_result = rpc - .get_validity_proof( - vec![], - vec![AddressWithTree { - address: compression_address, - tree: address_tree.tree, - }], - None, - ) - .await - .unwrap() - .value; - - // Build instruction data - #[derive(BorshSerialize)] - struct CreateMintSignedDataTest { - decimals: u8, - create_accounts_proof: CreateAccountsProof, - compression_address: [u8; 32], - mint: Pubkey, - bump: u8, - freeze_authority: Option, - rent_payment: u8, - write_top_up: u32, - authority_bump: u8, - metadata_name: Option>, - metadata_symbol: Option>, - metadata_uri: Option>, - } - - let create_accounts_proof = CreateAccountsProof { - proof: ValidityProof(rpc_result.proof.0), - address_tree_info: PackedAddressTreeInfo { - address_merkle_tree_pubkey_index: 0, - address_queue_pubkey_index: 0, - root_index: rpc_result.addresses[0].root_index, - }, - output_state_tree_index: 0, - state_tree_index: None, - }; - - let test_data = CreateMintSignedDataTest { - decimals, - create_accounts_proof, - compression_address, - mint, - bump, - freeze_authority: None, - rent_payment: 16, - write_top_up: 766, - authority_bump, - metadata_name: Some(b"Example Token".to_vec()), - metadata_symbol: Some(b"EXT".to_vec()), - metadata_uri: Some(b"https://example.com/metadata.json".to_vec()), - }; - - let mut data = vec![19u8]; - data.extend(test_data.try_to_vec().unwrap()); - - let system_accounts = SystemAccounts::default(); - - // Build and send instruction (mint_seed must sign) - let ix = Instruction { - program_id: PROGRAM_ID, - accounts: vec![ - AccountMeta::new(mint_seed.pubkey(), true), - AccountMeta::new(pda_authority, false), - AccountMeta::new(payer.pubkey(), true), - AccountMeta::new(address_tree.tree, false), - AccountMeta::new(output_queue, false), - AccountMeta::new_readonly(config_pda(), false), - AccountMeta::new(mint, false), - AccountMeta::new(rent_sponsor_pda(), false), - AccountMeta::new_readonly( - system_accounts.light_system_program, - false, - ), - AccountMeta::new_readonly(system_accounts.cpi_authority_pda, false), - AccountMeta::new_readonly( - system_accounts.registered_program_pda, - false, - ), - AccountMeta::new_readonly( - system_accounts.account_compression_authority, - false, - ), - AccountMeta::new_readonly( - system_accounts.account_compression_program, - false, - ), - AccountMeta::new_readonly(system_accounts.system_program, false), - AccountMeta::new_readonly(LIGHT_TOKEN_PROGRAM_ID, false), - ], - data, - }; - - rpc.create_and_send_transaction( - &[ix], - &payer.pubkey(), - &[&payer, &mint_seed], - ) - .await - .unwrap(); - - let mint_account = rpc.get_account(mint).await.unwrap(); - assert!(mint_account.is_some()); -} -``` - diff --git a/snippets/code-snippets/light-token/create-mint/rust-client/action.mdx b/snippets/code-snippets/light-token/create-mint/rust-client/action.mdx deleted file mode 100644 index 5432b8eb..00000000 --- a/snippets/code-snippets/light-token/create-mint/rust-client/action.mdx +++ /dev/null @@ -1,31 +0,0 @@ -```rust -use light_client::rpc::Rpc; -use light_token_client::actions::{CreateMint, TokenMetadata}; -use rust_client::setup_rpc_and_payer; -use solana_sdk::signer::Signer; - -#[tokio::main] -async fn main() -> Result<(), Box> { - let (mut rpc, payer) = setup_rpc_and_payer().await; - - let (signature, mint) = CreateMint { - decimals: 9, - freeze_authority: None, - token_metadata: Some(TokenMetadata { - name: "Example Token".to_string(), - symbol: "EXT".to_string(), - uri: "https://example.com/metadata.json".to_string(), - update_authority: Some(payer.pubkey()), - additional_metadata: Some(vec![("type".to_string(), "example".to_string())]), - }), - seed: None, - } - .execute(&mut rpc, &payer, &payer) - .await?; - - let data = rpc.get_account(mint).await?; - println!("Mint: {mint} exists: {} Tx: {signature}", data.is_some()); - - Ok(()) -} -``` diff --git a/snippets/code-snippets/light-token/create-mint/rust-client/instruction.mdx b/snippets/code-snippets/light-token/create-mint/rust-client/instruction.mdx deleted file mode 100644 index bce376d0..00000000 --- a/snippets/code-snippets/light-token/create-mint/rust-client/instruction.mdx +++ /dev/null @@ -1,97 +0,0 @@ -```rust -use light_client::{ - indexer::{AddressWithTree, Indexer}, - rpc::Rpc, -}; -use light_program_test::{LightProgramTest, ProgramTestConfig}; -use light_token::instruction::{ - derive_mint_compressed_address, find_mint_address, CreateMint, CreateMintParams, - DEFAULT_RENT_PAYMENT, DEFAULT_WRITE_TOP_UP, -}; -use light_token_interface::{ - instructions::extensions::{ - token_metadata::TokenMetadataInstructionData, ExtensionInstructionData, - }, - state::AdditionalMetadata, -}; -use solana_sdk::{signature::Keypair, signer::Signer}; - -#[tokio::main] -async fn main() -> Result<(), Box> { - let mut rpc = LightProgramTest::new(ProgramTestConfig::new(false, None)).await?; - - let payer = rpc.get_payer().insecure_clone(); - let mint_seed = Keypair::new(); - let decimals = 9u8; - - // Get address tree to store compressed address for when mint turns inactive - // We must create a compressed address at creation to ensure the mint does not exist yet - let address_tree = rpc.get_address_tree_v2(); - // Get state tree to store mint when inactive - let output_queue = rpc.get_random_state_tree_info().unwrap().queue; - - // Derive mint addresses - let compression_address = - derive_mint_compressed_address(&mint_seed.pubkey(), &address_tree.tree); - let mint = find_mint_address(&mint_seed.pubkey()).0; // on-chain Mint PDA - - // Fetch validity proof to proof address does not exist yet - let rpc_result = rpc - .get_validity_proof( - vec![], - vec![AddressWithTree { - address: compression_address, - tree: address_tree.tree, - }], - None, - ) - .await - .unwrap() - .value; - - // Build CreateMintParams with token metadata extension - let params = CreateMintParams { - decimals, - address_merkle_tree_root_index: rpc_result.addresses[0].root_index, // stores mint compressed address - mint_authority: payer.pubkey(), - proof: rpc_result.proof.0.unwrap(), - compression_address, // address for compression when mint turns inactive - mint, - bump: find_mint_address(&mint_seed.pubkey()).1, - freeze_authority: None, - extensions: Some(vec![ExtensionInstructionData::TokenMetadata( - TokenMetadataInstructionData { - update_authority: Some(payer.pubkey().to_bytes().into()), - name: b"Example Token".to_vec(), - symbol: b"EXT".to_vec(), - uri: b"https://example.com/metadata.json".to_vec(), - additional_metadata: Some(vec![AdditionalMetadata { - key: b"type".to_vec(), - value: b"example".to_vec(), - }]), - }, - )]), - rent_payment: DEFAULT_RENT_PAYMENT, // 24h of rent - write_top_up: DEFAULT_WRITE_TOP_UP, // 3h of rent - }; - - // Build and send instruction (mint_seed must sign) - let create_mint_instruction = CreateMint::new( - params, - mint_seed.pubkey(), - payer.pubkey(), - address_tree.tree, - output_queue, - ) - .instruction()?; - - let sig = rpc - .create_and_send_transaction(&[create_mint_instruction], &payer.pubkey(), &[&payer, &mint_seed]) - .await?; - - let data = rpc.get_account(mint).await?; - println!("Mint: {} exists: {} Tx: {sig}", mint, data.is_some()); - - Ok(()) -} -``` diff --git a/snippets/code-snippets/light-token/create-mint/token-interface-instruction.mdx b/snippets/code-snippets/light-token/create-mint/token-interface-instruction.mdx deleted file mode 100644 index 0b9324ae..00000000 --- a/snippets/code-snippets/light-token/create-mint/token-interface-instruction.mdx +++ /dev/null @@ -1,38 +0,0 @@ -```typescript -import { Buffer } from "buffer"; -import { - Keypair, - PublicKey, - Transaction, - sendAndConfirmTransaction, -} from "@solana/web3.js"; -import { createRpc, LIGHT_TOKEN_PROGRAM_ID } from "@lightprotocol/stateless.js"; -import { createMintInstructions } from "@lightprotocol/token-interface"; - -const COMPRESSED_MINT_SEED = Buffer.from("compressed_mint"); -const rpc = createRpc(); -const payer = Keypair.fromSecretKey(/* ... */); - -function findMintAddress(mintSigner: PublicKey): [PublicKey, number] { - return PublicKey.findProgramAddressSync( - [COMPRESSED_MINT_SEED, mintSigner.toBuffer()], - LIGHT_TOKEN_PROGRAM_ID - ); -} - -const mintSigner = Keypair.generate(); -const [mintPda] = findMintAddress(mintSigner.publicKey); -const instructions = await createMintInstructions({ - rpc, - payer: payer.publicKey, - keypair: mintSigner, - decimals: 9, - mintAuthority: payer.publicKey, - tokenProgramId: LIGHT_TOKEN_PROGRAM_ID, -}); - -const tx = new Transaction().add(...instructions); -const signature = await sendAndConfirmTransaction(rpc, tx, [payer, mintSigner]); -console.log("Mint:", mintPda.toBase58()); -console.log("Tx:", signature); -``` diff --git a/snippets/code-snippets/light-token/create-spl-mint/instruction.mdx b/snippets/code-snippets/light-token/create-spl-mint/instruction.mdx deleted file mode 100644 index 6c69e1e7..00000000 --- a/snippets/code-snippets/light-token/create-spl-mint/instruction.mdx +++ /dev/null @@ -1,77 +0,0 @@ -```typescript -import "dotenv/config"; -import { - Keypair, - SystemProgram, - Transaction, - sendAndConfirmTransaction, -} from "@solana/web3.js"; -import { createRpc } from "@lightprotocol/stateless.js"; -import { LightTokenProgram } from "@lightprotocol/compressed-token"; -import { - MINT_SIZE, - TOKEN_PROGRAM_ID, - createInitializeMint2Instruction, -} from "@solana/spl-token"; -import { homedir } from "os"; -import { readFileSync } from "fs"; - -// devnet: -const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; -const rpc = createRpc(RPC_URL); -// localnet: -// const rpc = createRpc(); - -const payer = Keypair.fromSecretKey( - new Uint8Array( - JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) - ) -); - -(async function () { - const mintKeypair = Keypair.generate(); - const decimals = 9; - - // Get rent for mint account - const rentExemptBalance = await rpc.getMinimumBalanceForRentExemption(MINT_SIZE); - - // Instruction 1: Create mint account - const createMintAccountIx = SystemProgram.createAccount({ - fromPubkey: payer.publicKey, - lamports: rentExemptBalance, - newAccountPubkey: mintKeypair.publicKey, - programId: TOKEN_PROGRAM_ID, - space: MINT_SIZE, - }); - - // Instruction 2: Initialize mint - const initializeMintIx = createInitializeMint2Instruction( - mintKeypair.publicKey, - decimals, - payer.publicKey, // mint authority - null, // freeze authority - TOKEN_PROGRAM_ID - ); - - // Instruction 3: Create SPL Interface PDA (enables compression for this mint) - const createSplInterfaceIx = await LightTokenProgram.createSplInterface({ - feePayer: payer.publicKey, - mint: mintKeypair.publicKey, - tokenProgramId: TOKEN_PROGRAM_ID, - }); - - const tx = new Transaction().add( - createMintAccountIx, - initializeMintIx, - createSplInterfaceIx - ); - - const signature = await sendAndConfirmTransaction(rpc, tx, [ - payer, - mintKeypair, - ]); - - console.log("Mint:", mintKeypair.publicKey.toBase58()); - console.log("Tx:", signature); -})(); -``` diff --git a/snippets/code-snippets/light-token/create-spl-mint/token-interface-instruction.mdx b/snippets/code-snippets/light-token/create-spl-mint/token-interface-instruction.mdx deleted file mode 100644 index 852ead36..00000000 --- a/snippets/code-snippets/light-token/create-spl-mint/token-interface-instruction.mdx +++ /dev/null @@ -1,24 +0,0 @@ -```typescript -import { Keypair, Transaction, sendAndConfirmTransaction } from "@solana/web3.js"; -import { createRpc } from "@lightprotocol/stateless.js"; -import { createMintInstructions } from "@lightprotocol/token-interface"; -import { TOKEN_PROGRAM_ID } from "@solana/spl-token"; - -const rpc = createRpc(); -const payer = Keypair.fromSecretKey(/* ... */); -const mintKeypair = Keypair.generate(); - -const instructions = await createMintInstructions({ - rpc, - payer: payer.publicKey, - keypair: mintKeypair, - decimals: 9, - mintAuthority: payer.publicKey, - tokenProgramId: TOKEN_PROGRAM_ID, -}); - -const tx = new Transaction().add(...instructions); -const signature = await sendAndConfirmTransaction(rpc, tx, [payer, mintKeypair]); -console.log("Mint:", mintKeypair.publicKey.toBase58()); -console.log("Tx:", signature); -``` diff --git a/snippets/code-snippets/light-token/create-t22-mint/action.mdx b/snippets/code-snippets/light-token/create-t22-mint/action.mdx deleted file mode 100644 index 253d8af7..00000000 --- a/snippets/code-snippets/light-token/create-t22-mint/action.mdx +++ /dev/null @@ -1,40 +0,0 @@ -```typescript -import "dotenv/config"; -import { Keypair } from "@solana/web3.js"; -import { createRpc } from "@lightprotocol/stateless.js"; -import { createMintInterface } from "@lightprotocol/compressed-token"; -import { TOKEN_2022_PROGRAM_ID } from "@solana/spl-token"; -import { homedir } from "os"; -import { readFileSync } from "fs"; - -// devnet: -const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; -const rpc = createRpc(RPC_URL); -// localnet: -// const rpc = createRpc(); - -const payer = Keypair.fromSecretKey( - new Uint8Array( - JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) - ) -); - -(async function () { - // Creates Token-2022 mint and SPL interface PDA in one transaction - // SPL interface PDA holds Token-2022 tokens when wrapped to light-token - const mintKeypair = Keypair.generate(); - const { mint, transactionSignature } = await createMintInterface( - rpc, - payer, - payer, - null, - 9, - mintKeypair, - undefined, - TOKEN_2022_PROGRAM_ID - ); - - console.log("Mint:", mint.toBase58()); - console.log("Tx:", transactionSignature); -})(); -``` diff --git a/snippets/code-snippets/light-token/create-t22-mint/instruction.mdx b/snippets/code-snippets/light-token/create-t22-mint/instruction.mdx deleted file mode 100644 index f61f4661..00000000 --- a/snippets/code-snippets/light-token/create-t22-mint/instruction.mdx +++ /dev/null @@ -1,79 +0,0 @@ -```typescript -import "dotenv/config"; -import { - Keypair, - SystemProgram, - Transaction, - sendAndConfirmTransaction, -} from "@solana/web3.js"; -import { createRpc } from "@lightprotocol/stateless.js"; -import { LightTokenProgram } from "@lightprotocol/compressed-token"; -import { - MINT_SIZE, - TOKEN_2022_PROGRAM_ID, - createInitializeMint2Instruction, -} from "@solana/spl-token"; -import { homedir } from "os"; -import { readFileSync } from "fs"; - -// devnet: -const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; -const rpc = createRpc(RPC_URL); -// localnet: -// const rpc = createRpc(); - -const payer = Keypair.fromSecretKey( - new Uint8Array( - JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) - ) -); - -(async function () { - const mintKeypair = Keypair.generate(); - const decimals = 9; - - // Get rent for mint account - const rentExemptBalance = - await rpc.getMinimumBalanceForRentExemption(MINT_SIZE); - - // Instruction 1: Create mint account - const createMintAccountIx = SystemProgram.createAccount({ - fromPubkey: payer.publicKey, - lamports: rentExemptBalance, - newAccountPubkey: mintKeypair.publicKey, - programId: TOKEN_2022_PROGRAM_ID, - space: MINT_SIZE, - }); - - // Instruction 2: Initialize mint - const initializeMintIx = createInitializeMint2Instruction( - mintKeypair.publicKey, - decimals, - payer.publicKey, // mint authority - null, // freeze authority - TOKEN_2022_PROGRAM_ID - ); - - // Instruction 3: Create SPL interface PDA - // Holds Token-2022 tokens when wrapped to light-token - const createSplInterfaceIx = await LightTokenProgram.createSplInterface({ - feePayer: payer.publicKey, - mint: mintKeypair.publicKey, - tokenProgramId: TOKEN_2022_PROGRAM_ID, - }); - - const tx = new Transaction().add( - createMintAccountIx, - initializeMintIx, - createSplInterfaceIx - ); - - const signature = await sendAndConfirmTransaction(rpc, tx, [ - payer, - mintKeypair, - ]); - - console.log("Mint:", mintKeypair.publicKey.toBase58()); - console.log("Tx:", signature); -})(); -``` diff --git a/snippets/code-snippets/light-token/create-t22-mint/token-interface-instruction.mdx b/snippets/code-snippets/light-token/create-t22-mint/token-interface-instruction.mdx deleted file mode 100644 index 381928aa..00000000 --- a/snippets/code-snippets/light-token/create-t22-mint/token-interface-instruction.mdx +++ /dev/null @@ -1,24 +0,0 @@ -```typescript -import { Keypair, Transaction, sendAndConfirmTransaction } from "@solana/web3.js"; -import { createRpc } from "@lightprotocol/stateless.js"; -import { createMintInstructions } from "@lightprotocol/token-interface"; -import { TOKEN_2022_PROGRAM_ID } from "@solana/spl-token"; - -const rpc = createRpc(); -const payer = Keypair.fromSecretKey(/* ... */); -const mintKeypair = Keypair.generate(); - -const instructions = await createMintInstructions({ - rpc, - payer: payer.publicKey, - keypair: mintKeypair, - decimals: 9, - mintAuthority: payer.publicKey, - tokenProgramId: TOKEN_2022_PROGRAM_ID, -}); - -const tx = new Transaction().add(...instructions); -const signature = await sendAndConfirmTransaction(rpc, tx, [payer, mintKeypair]); -console.log("Mint:", mintKeypair.publicKey.toBase58()); -console.log("Tx:", signature); -``` diff --git a/snippets/code-snippets/light-token/create-token-account/anchor-macro/full-example.mdx b/snippets/code-snippets/light-token/create-token-account/anchor-macro/full-example.mdx deleted file mode 100644 index 6287b236..00000000 --- a/snippets/code-snippets/light-token/create-token-account/anchor-macro/full-example.mdx +++ /dev/null @@ -1,178 +0,0 @@ - -```rust lib.rs -#![allow(deprecated)] - -use anchor_lang::prelude::*; -use light_account::{ - derive_light_cpi_signer, light_program, CreateAccountsProof, CpiSigner, LightAccounts, -}; -use light_token::instruction::{LIGHT_TOKEN_CONFIG, LIGHT_TOKEN_RENT_SPONSOR}; - -declare_id!("9p5BUDtVmRRJqp2sN73ZUZDbaYtYvEWuxzrHH3A2ni9y"); - -pub const LIGHT_CPI_SIGNER: CpiSigner = - derive_light_cpi_signer!("9p5BUDtVmRRJqp2sN73ZUZDbaYtYvEWuxzrHH3A2ni9y"); - -pub const VAULT_AUTH_SEED: &[u8] = b"vault_auth"; -pub const VAULT_SEED: &[u8] = b"vault"; - -#[derive(AnchorSerialize, AnchorDeserialize, Clone)] -pub struct CreateTokenVaultParams { - pub create_accounts_proof: CreateAccountsProof, - pub vault_bump: u8, -} - -#[derive(Accounts, LightAccounts)] -#[instruction(params: CreateTokenVaultParams)] -pub struct CreateTokenVault<'info> { - #[account(mut)] - pub fee_payer: Signer<'info>, - - /// CHECK: Token mint for the vault - pub mint: AccountInfo<'info>, - - /// CHECK: Validated by seeds constraint - #[account( - seeds = [VAULT_AUTH_SEED], - bump, - )] - pub vault_authority: UncheckedAccount<'info>, - - /// CHECK: Validated by seeds constraint and light_account macro - #[account( - mut, - seeds = [VAULT_SEED, mint.key().as_ref()], - bump, - )] - #[light_account( - init, - token::seeds = [VAULT_SEED, self.mint.key()], - token::mint = mint, - token::owner = vault_authority, - token::owner_seeds = [VAULT_AUTH_SEED], - token::bump = params.vault_bump - )] - pub vault: UncheckedAccount<'info>, - - /// CHECK: Validated by address constraint - #[account(address = LIGHT_TOKEN_CONFIG)] - pub light_token_config: AccountInfo<'info>, - - /// CHECK: Validated by address constraint - #[account(mut, address = LIGHT_TOKEN_RENT_SPONSOR)] - pub light_token_rent_sponsor: AccountInfo<'info>, - - /// CHECK: Light token CPI authority - pub light_token_cpi_authority: AccountInfo<'info>, - - /// CHECK: Light token program for CPI - pub light_token_program: AccountInfo<'info>, - - pub system_program: Program<'info, System>, -} - -#[light_program] -#[program] -pub mod light_token_macro_create_token_account { - use super::*; - - #[allow(unused_variables)] - pub fn create_token_vault<'info>( - ctx: Context<'_, '_, '_, 'info, CreateTokenVault<'info>>, - params: CreateTokenVaultParams, - ) -> Result<()> { - Ok(()) - } -} -``` - -```rust test.rs -use anchor_lang::{InstructionData, ToAccountMetas}; -use light_client::interface::get_create_accounts_proof; -use light_program_test::{LightProgramTest, ProgramTestConfig, Rpc}; -use light_token::instruction::LIGHT_TOKEN_PROGRAM_ID; -use solana_instruction::Instruction; -use solana_pubkey::Pubkey; -use solana_signer::Signer; -use test_utils::create_mint; - -/// Test creating a token vault using the `#[light_account(init, token, ...)]` macro. -/// -/// This test verifies: -/// 1. The macro-annotated program compiles correctly -/// 2. A token vault can be created via the generated CPI -/// 3. The vault has the correct owner and mint -#[tokio::test] -async fn test_create_token_vault() { - use light_token::instruction::{LIGHT_TOKEN_CONFIG, LIGHT_TOKEN_RENT_SPONSOR}; - use light_token_macro_create_token_account::{ - CreateTokenVaultParams, VAULT_AUTH_SEED, VAULT_SEED, - }; - use light_token::constants::LIGHT_TOKEN_CPI_AUTHORITY; - - let program_id = light_token_macro_create_token_account::ID; - let config = ProgramTestConfig::new_v2( - true, - Some(vec![("light_token_macro_create_token_account", program_id)]), - ); - - let mut rpc = LightProgramTest::new(config).await.unwrap(); - let payer = rpc.get_payer().insecure_clone(); - - let (mint, _mint_seed) = create_mint(&mut rpc, &payer, None).await; - - // Derive PDAs - let (vault_authority, _auth_bump) = - Pubkey::find_program_address(&[VAULT_AUTH_SEED], &program_id); - let (vault, vault_bump) = - Pubkey::find_program_address(&[VAULT_SEED, mint.as_ref()], &program_id); - - // Get proof for token-only instruction (empty inputs) - let proof_result = get_create_accounts_proof(&rpc, &program_id, vec![]) - .await - .unwrap(); - - // Build instruction accounts - let accounts = light_token_macro_create_token_account::accounts::CreateTokenVault { - fee_payer: payer.pubkey(), - mint, - vault_authority, - vault, - light_token_config: LIGHT_TOKEN_CONFIG, - light_token_rent_sponsor: LIGHT_TOKEN_RENT_SPONSOR, - light_token_cpi_authority: LIGHT_TOKEN_CPI_AUTHORITY, - light_token_program: LIGHT_TOKEN_PROGRAM_ID, - system_program: solana_sdk::system_program::ID, - }; - - // Build instruction data - let instruction_data = light_token_macro_create_token_account::instruction::CreateTokenVault { - params: CreateTokenVaultParams { - create_accounts_proof: proof_result.create_accounts_proof, - vault_bump, - }, - }; - - let instruction = Instruction { - program_id, - accounts: [ - accounts.to_account_metas(None), - proof_result.remaining_accounts, - ] - .concat(), - data: instruction_data.data(), - }; - - // Execute the instruction - // Note: This may fail without InitializeRentFreeConfig setup. - // The full test requires rent-free config initialization. - let result = rpc - .create_and_send_transaction(&[instruction], &payer.pubkey(), &[&payer]) - .await; - - // For now, we verify the instruction builds correctly. - // Full execution requires additional setup (InitializeRentFreeConfig, etc.) - println!("Transaction result: {:?}", result); -} -``` - diff --git a/snippets/code-snippets/light-token/create-token-account/anchor-program/full-example.mdx b/snippets/code-snippets/light-token/create-token-account/anchor-program/full-example.mdx deleted file mode 100644 index 5f32174d..00000000 --- a/snippets/code-snippets/light-token/create-token-account/anchor-program/full-example.mdx +++ /dev/null @@ -1,161 +0,0 @@ - -```rust lib.rs -#![allow(unexpected_cfgs, deprecated)] - -use anchor_lang::prelude::*; -use light_token::instruction::CreateTokenAccountCpi; - -declare_id!("zXK1CnWj4WFfFHCArxxr4sh3Qqx2p3oui8ahqpjArgS"); - -#[program] -pub mod light_token_anchor_create_token_account { - use super::*; - - pub fn create_token_account(ctx: Context, owner: Pubkey) -> Result<()> { - CreateTokenAccountCpi { - payer: ctx.accounts.payer.to_account_info(), - account: ctx.accounts.account.to_account_info(), - mint: ctx.accounts.mint.to_account_info(), - owner, - } - .rent_free( - ctx.accounts.compressible_config.to_account_info(), - ctx.accounts.rent_sponsor.to_account_info(), - ctx.accounts.system_program.to_account_info(), - &ctx.accounts.light_token_program.key(), - ) - .invoke()?; - Ok(()) - } -} - -#[derive(Accounts)] -pub struct CreateTokenAccountAccounts<'info> { - #[account(mut)] - pub payer: Signer<'info>, - /// CHECK: Validated by light-token CPI - #[account(mut)] - pub account: Signer<'info>, - /// CHECK: Validated by light-token CPI - pub mint: AccountInfo<'info>, - /// CHECK: Validated by light-token CPI - pub compressible_config: AccountInfo<'info>, - /// CHECK: Validated by light-token CPI - #[account(mut)] - pub rent_sponsor: AccountInfo<'info>, - pub system_program: Program<'info, System>, - /// CHECK: Light token program for CPI - pub light_token_program: AccountInfo<'info>, -} -``` - -```rust test.rs -use anchor_lang::{InstructionData, ToAccountMetas}; -use light_client::indexer::AddressWithTree; -use light_program_test::{Indexer, LightProgramTest, ProgramTestConfig, Rpc}; -use light_token_anchor_create_token_account::{accounts, instruction::CreateTokenAccount, ID}; -use light_token::instruction::{ - CreateMint, CreateMintParams, config_pda, derive_mint_compressed_address, - find_mint_address, rent_sponsor_pda, LIGHT_TOKEN_PROGRAM_ID, - DEFAULT_RENT_PAYMENT, DEFAULT_WRITE_TOP_UP, -}; -use anchor_lang::system_program; -use solana_sdk::{ - instruction::Instruction, - signature::Keypair, - signer::Signer, -}; - -#[tokio::test] -async fn test_create_token_account() { - let config = ProgramTestConfig::new_v2( - true, - Some(vec![("light_token_anchor_create_token_account", ID)]), - ); - let mut rpc = LightProgramTest::new(config).await.unwrap(); - let payer = rpc.get_payer().insecure_clone(); - - // Create a mint first - let mint_seed = Keypair::new(); - let mint_authority = payer.pubkey(); - let decimals = 9u8; - - let address_tree = rpc.get_address_tree_v2(); - let output_queue = rpc.get_random_state_tree_info().unwrap().queue; - - let compression_address = - derive_mint_compressed_address(&mint_seed.pubkey(), &address_tree.tree); - let (mint_pda, bump) = find_mint_address(&mint_seed.pubkey()); - - let rpc_result = rpc - .get_validity_proof( - vec![], - vec![AddressWithTree { - address: compression_address, - tree: address_tree.tree, - }], - None, - ) - .await - .unwrap() - .value; - - let params = CreateMintParams { - decimals, - address_merkle_tree_root_index: rpc_result.addresses[0].root_index, - mint_authority, - proof: rpc_result.proof.0.unwrap(), - compression_address, - mint: mint_pda, - bump, - freeze_authority: None, - extensions: None, - rent_payment: DEFAULT_RENT_PAYMENT, - write_top_up: DEFAULT_WRITE_TOP_UP, - }; - - let create_mint_ix = CreateMint::new( - params, - mint_seed.pubkey(), - payer.pubkey(), - address_tree.tree, - output_queue, - ) - .instruction() - .unwrap(); - - rpc.create_and_send_transaction(&[create_mint_ix], &payer.pubkey(), &[&payer, &mint_seed]) - .await - .unwrap(); - - // You can use light, spl, t22 mints to create a light token account. - // Create a token account - let token_account = Keypair::new(); - let owner = payer.pubkey(); - let compressible_config = config_pda(); - let rent_sponsor = rent_sponsor_pda(); - - let ix = Instruction { - program_id: ID, - accounts: accounts::CreateTokenAccountAccounts { - payer: payer.pubkey(), - account: token_account.pubkey(), - mint: mint_pda, - compressible_config, - rent_sponsor, - system_program: system_program::ID, - light_token_program: LIGHT_TOKEN_PROGRAM_ID, - } - .to_account_metas(Some(true)), - data: CreateTokenAccount { owner }.data(), - }; - - let sig = rpc - .create_and_send_transaction(&[ix], &payer.pubkey(), &[&payer, &token_account]) - .await - .unwrap(); - - println!("Tx: {}", sig); -} -``` - diff --git a/snippets/code-snippets/light-token/create-token-account/native-program/full-example.mdx b/snippets/code-snippets/light-token/create-token-account/native-program/full-example.mdx deleted file mode 100644 index fabd355f..00000000 --- a/snippets/code-snippets/light-token/create-token-account/native-program/full-example.mdx +++ /dev/null @@ -1,170 +0,0 @@ - -```rust instruction.rs -use super::authority_seeds; -use light_token::instruction::CreateTokenAccountCpi; -use solana_program::{ - account_info::AccountInfo, entrypoint::ProgramResult, - program_error::ProgramError, pubkey::Pubkey, -}; - -/// Account order: -/// - accounts[0]: payer (signer, mut) -/// - accounts[1]: account (signer for invoke, PDA for invoke_signed, mut) -/// - accounts[2]: mint (readonly) -/// - accounts[3]: compressible_config (readonly) -/// - accounts[4]: system_program (readonly) -/// - accounts[5]: rent_sponsor (mut) -/// - accounts[6]: light_token_program (readonly) -pub fn create_token_account_invoke( - accounts: &[AccountInfo], - data: &[u8], -) -> ProgramResult { - let [payer, account, mint, compressible_config, system_program, rent_sponsor, token_program] = - accounts - else { - return Err(ProgramError::NotEnoughAccountKeys); - }; - - if data.len() < 32 { - return Err(ProgramError::InvalidInstructionData); - } - - let owner = Pubkey::try_from(&data[0..32]) - .map_err(|_| ProgramError::InvalidInstructionData)?; - - // Create token account. Works with light, spl, t22 mints - CreateTokenAccountCpi { - payer: payer.clone(), - account: account.clone(), - mint: mint.clone(), - owner, - } - .rent_free( - compressible_config.clone(), - rent_sponsor.clone(), - system_program.clone(), - token_program.key, - ) - .invoke() -} - -pub fn create_token_account_invoke_signed( - program_id: &Pubkey, - accounts: &[AccountInfo], - data: &[u8], -) -> ProgramResult { - let [payer, account, mint, compressible_config, system_program, rent_sponsor, _token_program] = - accounts - else { - return Err(ProgramError::NotEnoughAccountKeys); - }; - - if data.len() < 33 { - return Err(ProgramError::InvalidInstructionData); - } - - let owner = Pubkey::try_from(&data[0..32]) - .map_err(|_| ProgramError::InvalidInstructionData)?; - let authority_bump = data[32]; - let signer_seeds = authority_seeds!(authority_bump); - - CreateTokenAccountCpi { - payer: payer.clone(), - account: account.clone(), - mint: mint.clone(), - owner, - } - .rent_free( - compressible_config.clone(), - rent_sponsor.clone(), - system_program.clone(), - program_id, - ) - .invoke_signed(signer_seeds) -} -``` - -```rust test.rs -mod shared; - -use light_client::rpc::Rpc; -use shared::{ - build_create_token_account_cpi_ix, - build_create_token_account_signed_cpi_ix, create_test_rpc, - get_authority_pda, setup_mint_with_tokens, -}; -use solana_sdk::{signature::Keypair, signer::Signer}; - -#[tokio::test(flavor = "multi_thread")] -async fn create_token_account_cpi() { - let mut rpc = create_test_rpc().await; - let payer = rpc.get_payer().insecure_clone(); - - let (mint, _) = setup_mint_with_tokens( - &mut rpc, - &payer, - payer.pubkey(), - None, - 9, - vec![], - ) - .await; - - let token_account = Keypair::new(); - let owner = payer.pubkey(); - - let ix = build_create_token_account_cpi_ix( - payer.pubkey(), - token_account.pubkey(), - mint, - owner, - ); - - rpc.create_and_send_transaction( - &[ix], - &payer.pubkey(), - &[&payer, &token_account], - ) - .await - .unwrap(); - - let account = rpc.get_account(token_account.pubkey()).await.unwrap(); - assert!(account.is_some()); -} - -#[tokio::test(flavor = "multi_thread")] -async fn create_token_account_signed_cpi() { - let mut rpc = create_test_rpc().await; - let payer = rpc.get_payer().insecure_clone(); - - let (pda_account, authority_bump) = get_authority_pda(); - - let (mint, _) = setup_mint_with_tokens( - &mut rpc, - &payer, - payer.pubkey(), - None, - 9, - vec![], - ) - .await; - - let owner = payer.pubkey(); - - let ix = build_create_token_account_signed_cpi_ix( - payer.pubkey(), - pda_account, - mint, - owner, - authority_bump, - ); - - rpc.create_and_send_transaction(&[ix], &payer.pubkey(), &[&payer]) - .await - .unwrap(); - - let account = rpc.get_account(pda_account).await.unwrap(); - assert!(account.is_some()); -} -``` - diff --git a/snippets/code-snippets/light-token/create-token-account/rust-client/instruction.mdx b/snippets/code-snippets/light-token/create-token-account/rust-client/instruction.mdx deleted file mode 100644 index 2795ac32..00000000 --- a/snippets/code-snippets/light-token/create-token-account/rust-client/instruction.mdx +++ /dev/null @@ -1,36 +0,0 @@ -```rust -use light_client::rpc::Rpc; -use light_token::instruction::CreateTokenAccount; -use rust_client::{setup_spl_mint_context, SplMintContext}; -use solana_sdk::{signature::Keypair, signer::Signer}; - -#[tokio::main] -async fn main() -> Result<(), Box> { - // Setup creates mint - // You can use Light, SPL, or Token-2022 mints to create a light token account. - let SplMintContext { - mut rpc, - payer, - mint, - } = setup_spl_mint_context().await; - - let account = Keypair::new(); - - let create_token_account_instruction = - CreateTokenAccount::new(payer.pubkey(), account.pubkey(), mint, payer.pubkey()) - .instruction()?; - - let sig = rpc - .create_and_send_transaction(&[create_token_account_instruction], &payer.pubkey(), &[&payer, &account]) - .await?; - - let data = rpc.get_account(account.pubkey()).await?; - println!( - "Account: {} exists: {} Tx: {sig}", - account.pubkey(), - data.is_some() - ); - - Ok(()) -} -``` diff --git a/snippets/code-snippets/light-token/create-token-pool/action.mdx b/snippets/code-snippets/light-token/create-token-pool/action.mdx deleted file mode 100644 index b7a61015..00000000 --- a/snippets/code-snippets/light-token/create-token-pool/action.mdx +++ /dev/null @@ -1,29 +0,0 @@ -```typescript -import "dotenv/config"; -import { Keypair, PublicKey } from "@solana/web3.js"; -import { createRpc } from "@lightprotocol/stateless.js"; -import { createSplInterface } from "@lightprotocol/compressed-token"; -import { homedir } from "os"; -import { readFileSync } from "fs"; - -// devnet: -const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; -const rpc = createRpc(RPC_URL); -// localnet: -// const rpc = createRpc(); - -const payer = Keypair.fromSecretKey( - new Uint8Array( - JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) - ) -); - -(async function () { - const existingMint = new PublicKey("YOUR_EXISTING_MINT_ADDRESS"); - - const tx = await createSplInterface(rpc, payer, existingMint); - - console.log("Mint:", existingMint.toBase58()); - console.log("Tx:", tx); -})(); -``` diff --git a/snippets/code-snippets/light-token/create-token-pool/instruction.mdx b/snippets/code-snippets/light-token/create-token-pool/instruction.mdx deleted file mode 100644 index 55385a00..00000000 --- a/snippets/code-snippets/light-token/create-token-pool/instruction.mdx +++ /dev/null @@ -1,42 +0,0 @@ -```typescript -import "dotenv/config"; -import { - Keypair, - PublicKey, - Transaction, - sendAndConfirmTransaction, -} from "@solana/web3.js"; -import { createRpc } from "@lightprotocol/stateless.js"; -import { LightTokenProgram } from "@lightprotocol/compressed-token"; -import { TOKEN_PROGRAM_ID } from "@solana/spl-token"; -import { homedir } from "os"; -import { readFileSync } from "fs"; - -// devnet: -const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; -const rpc = createRpc(RPC_URL); -// localnet: -// const rpc = createRpc(); - -const payer = Keypair.fromSecretKey( - new Uint8Array( - JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) - ) -); - -(async function () { - const existingMint = new PublicKey("YOUR_EXISTING_MINT_ADDRESS"); - - const ix = await LightTokenProgram.createSplInterface({ - feePayer: payer.publicKey, - mint: existingMint, - tokenProgramId: TOKEN_PROGRAM_ID, - }); - - const tx = new Transaction().add(ix); - const signature = await sendAndConfirmTransaction(rpc, tx, [payer]); - - console.log("Mint:", existingMint.toBase58()); - console.log("Tx:", signature); -})(); -``` diff --git a/snippets/code-snippets/light-token/create-token-pool/token-interface-instruction.mdx b/snippets/code-snippets/light-token/create-token-pool/token-interface-instruction.mdx deleted file mode 100644 index e1f9aa24..00000000 --- a/snippets/code-snippets/light-token/create-token-pool/token-interface-instruction.mdx +++ /dev/null @@ -1,22 +0,0 @@ -```typescript -import { Keypair, PublicKey, Transaction, sendAndConfirmTransaction } from "@solana/web3.js"; -import { createRpc } from "@lightprotocol/stateless.js"; -import { createSplInterfaceInstruction } from "@lightprotocol/token-interface"; -import { TOKEN_PROGRAM_ID } from "@solana/spl-token"; - -const rpc = createRpc(); -const payer = Keypair.fromSecretKey(/* ... */); -const existingMint = new PublicKey("YOUR_EXISTING_MINT_ADDRESS"); - -const ix = createSplInterfaceInstruction({ - feePayer: payer.publicKey, - mint: existingMint, - index: 0, - tokenProgramId: TOKEN_PROGRAM_ID, -}); - -const tx = new Transaction().add(ix); -const signature = await sendAndConfirmTransaction(rpc, tx, [payer]); -console.log("Mint:", existingMint.toBase58()); -console.log("Tx:", signature); -``` diff --git a/snippets/code-snippets/light-token/delegate-transfer/action.mdx b/snippets/code-snippets/light-token/delegate-transfer/action.mdx deleted file mode 100644 index a0c97eac..00000000 --- a/snippets/code-snippets/light-token/delegate-transfer/action.mdx +++ /dev/null @@ -1,65 +0,0 @@ -```typescript -import "dotenv/config"; -import { Keypair } from "@solana/web3.js"; -import { createRpc } from "@lightprotocol/stateless.js"; -import { - createMintInterface, - mintToCompressed, - getAssociatedTokenAddressInterface, -} from "@lightprotocol/compressed-token"; -import { - approveInterface, - transferInterface, -} from "@lightprotocol/compressed-token/unified"; -import { homedir } from "os"; -import { readFileSync } from "fs"; - -// devnet: -// const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; -// const rpc = createRpc(RPC_URL); -// localnet: -const rpc = createRpc(); - -const payer = Keypair.fromSecretKey( - new Uint8Array( - JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) - ) -); - -(async function () { - const { mint } = await createMintInterface(rpc, payer, payer, null, 9); - await mintToCompressed(rpc, payer, mint, payer, [ - { recipient: payer.publicKey, amount: 1000n }, - ]); - - const senderAta = getAssociatedTokenAddressInterface(mint, payer.publicKey); - const delegate = Keypair.generate(); - const recipient = Keypair.generate(); - - // Approve delegate - await approveInterface( - rpc, - payer, - senderAta, - mint, - delegate.publicKey, - 500_000, - payer - ); - console.log("Approved delegate:", delegate.publicKey.toBase58()); - - // Delegate transfers tokens on behalf of the owner - const tx = await transferInterface( - rpc, - payer, - senderAta, - mint, - recipient.publicKey, - payer.publicKey, - delegate, - 200_000 - ); - - console.log("Delegated transfer:", tx); -})(); -``` diff --git a/snippets/code-snippets/light-token/freeze-thaw/rust-client/freeze-full.mdx b/snippets/code-snippets/light-token/freeze-thaw/rust-client/freeze-full.mdx deleted file mode 100644 index 3badb1e4..00000000 --- a/snippets/code-snippets/light-token/freeze-thaw/rust-client/freeze-full.mdx +++ /dev/null @@ -1,32 +0,0 @@ -```rust -mod shared; - -use light_client::rpc::Rpc; -use light_token::instruction::Freeze; -use shared::SetupContext; -use solana_sdk::signer::Signer; - -#[tokio::test(flavor = "multi_thread")] -async fn test_freeze() { - // Setup creates mint, ATA with tokens, and approves delegate - let SetupContext { - mut rpc, - payer, - mint, - ata, - .. - } = shared::setup().await; - - let freeze_ix = Freeze { - token_account: ata, - mint, - freeze_authority: payer.pubkey(), - } - .instruction() - .unwrap(); - - rpc.create_and_send_transaction(&[freeze_ix], &payer.pubkey(), &[&payer]) - .await - .unwrap(); -} -``` diff --git a/snippets/code-snippets/light-token/freeze-thaw/rust-client/freeze-instruction.mdx b/snippets/code-snippets/light-token/freeze-thaw/rust-client/freeze-instruction.mdx deleted file mode 100644 index 4b17db45..00000000 --- a/snippets/code-snippets/light-token/freeze-thaw/rust-client/freeze-instruction.mdx +++ /dev/null @@ -1,37 +0,0 @@ -```rust -use borsh::BorshDeserialize; -use light_client::rpc::Rpc; -use light_token::instruction::Freeze; -use rust_client::{setup, SetupContext}; -use solana_sdk::signer::Signer; - -#[tokio::main] -async fn main() -> Result<(), Box> { - // Setup creates mint, associated token account with tokens, and approves delegate - let SetupContext { - mut rpc, - payer, - mint, - associated_token_account, - .. - } = setup().await; - - // freeze_authority must match what was set during mint creation. - let freeze_instruction = Freeze { - token_account: associated_token_account, - mint, - freeze_authority: payer.pubkey(), - } - .instruction()?; - - let sig = rpc - .create_and_send_transaction(&[freeze_instruction], &payer.pubkey(), &[&payer]) - .await?; - - let data = rpc.get_account(associated_token_account).await?.ok_or("Account not found")?; - let token = light_token_interface::state::Token::deserialize(&mut &data.data[..])?; - println!("State: {:?} Tx: {sig}", token.state); - - Ok(()) -} -``` diff --git a/snippets/code-snippets/light-token/freeze-thaw/rust-client/thaw-full.mdx b/snippets/code-snippets/light-token/freeze-thaw/rust-client/thaw-full.mdx deleted file mode 100644 index ab5b444e..00000000 --- a/snippets/code-snippets/light-token/freeze-thaw/rust-client/thaw-full.mdx +++ /dev/null @@ -1,32 +0,0 @@ -```rust -mod shared; - -use light_client::rpc::Rpc; -use light_token::instruction::Thaw; -use shared::SetupContext; -use solana_sdk::signer::Signer; - -#[tokio::test(flavor = "multi_thread")] -async fn thaw() { - // Setup creates mint, ATA with tokens, and freezes account - let SetupContext { - mut rpc, - payer, - mint, - ata, - .. - } = shared::setup_frozen().await; - - let thaw_ix = Thaw { - token_account: ata, - mint, - freeze_authority: payer.pubkey(), - } - .instruction() - .unwrap(); - - rpc.create_and_send_transaction(&[thaw_ix], &payer.pubkey(), &[&payer]) - .await - .unwrap(); -} -``` diff --git a/snippets/code-snippets/light-token/freeze-thaw/rust-client/thaw-instruction.mdx b/snippets/code-snippets/light-token/freeze-thaw/rust-client/thaw-instruction.mdx deleted file mode 100644 index 7d7eb8f9..00000000 --- a/snippets/code-snippets/light-token/freeze-thaw/rust-client/thaw-instruction.mdx +++ /dev/null @@ -1,36 +0,0 @@ -```rust -use borsh::BorshDeserialize; -use light_client::rpc::Rpc; -use light_token::instruction::Thaw; -use rust_client::{setup_frozen, SetupContext}; -use solana_sdk::signer::Signer; - -#[tokio::main] -async fn main() -> Result<(), Box> { - // Setup creates mint, associated token account with tokens, and freezes account - let SetupContext { - mut rpc, - payer, - mint, - associated_token_account, - .. - } = setup_frozen().await; - - let thaw_instruction = Thaw { - token_account: associated_token_account, - mint, - freeze_authority: payer.pubkey(), - } - .instruction()?; - - let sig = rpc - .create_and_send_transaction(&[thaw_instruction], &payer.pubkey(), &[&payer]) - .await?; - - let data = rpc.get_account(associated_token_account).await?.ok_or("Account not found")?; - let token = light_token_interface::state::Token::deserialize(&mut &data.data[..])?; - println!("State: {:?} Tx: {sig}", token.state); - - Ok(()) -} -``` diff --git a/snippets/code-snippets/light-token/freeze/anchor-program/full-example.mdx b/snippets/code-snippets/light-token/freeze/anchor-program/full-example.mdx deleted file mode 100644 index 74d9185c..00000000 --- a/snippets/code-snippets/light-token/freeze/anchor-program/full-example.mdx +++ /dev/null @@ -1,75 +0,0 @@ - -```rust lib.rs -#![allow(unexpected_cfgs, deprecated)] - -use anchor_lang::prelude::*; -use light_token::instruction::FreezeCpi; - -declare_id!("JBMzMJX4sqCQfNVbosP2oqP1KZ5ZDWiwYTrupk687qXZ"); - -#[program] -pub mod light_token_anchor_freeze { - use super::*; - - pub fn freeze(ctx: Context) -> Result<()> { - FreezeCpi { - token_account: ctx.accounts.token_account.to_account_info(), - mint: ctx.accounts.mint.to_account_info(), - freeze_authority: ctx.accounts.freeze_authority.to_account_info(), - } - .invoke()?; - Ok(()) - } -} - -#[derive(Accounts)] -pub struct FreezeAccounts<'info> { - /// CHECK: Light token program for CPI - pub light_token_program: AccountInfo<'info>, - /// CHECK: Validated by light-token CPI - #[account(mut)] - pub token_account: AccountInfo<'info>, - /// CHECK: Validated by light-token CPI - pub mint: AccountInfo<'info>, - pub freeze_authority: Signer<'info>, -} -``` - -```rust test.rs -use anchor_lang::{InstructionData, ToAccountMetas}; -use light_program_test::Rpc; -use light_token::instruction::LIGHT_TOKEN_PROGRAM_ID; -use light_token_anchor_freeze::{accounts, instruction::Freeze, ID}; -use solana_sdk::{instruction::Instruction, signer::Signer}; -use test_utils::{mint_tokens, setup_test_env_with_freeze}; - -#[tokio::test] -async fn test_freeze() { - let mut env = setup_test_env_with_freeze("light_token_anchor_freeze", ID).await; - - // Mint tokens first - mint_tokens(&mut env.rpc, &env.payer, env.mint_pda, env.associated_token_account, 1_000_000).await; - - // Call the anchor program to freeze account - let ix = Instruction { - program_id: ID, - accounts: accounts::FreezeAccounts { - light_token_program: LIGHT_TOKEN_PROGRAM_ID, - token_account: env.associated_token_account, - mint: env.mint_pda, - freeze_authority: env.freeze_authority, - } - .to_account_metas(Some(true)), - data: Freeze {}.data(), - }; - - let sig = env - .rpc - .create_and_send_transaction(&[ix], &env.payer.pubkey(), &[&env.payer]) - .await - .unwrap(); - - println!("Tx: {}", sig); -} -``` - diff --git a/snippets/code-snippets/light-token/freeze/native-program/full-example.mdx b/snippets/code-snippets/light-token/freeze/native-program/full-example.mdx deleted file mode 100644 index f0156b5b..00000000 --- a/snippets/code-snippets/light-token/freeze/native-program/full-example.mdx +++ /dev/null @@ -1,118 +0,0 @@ - -```rust instruction.rs -use super::authority_seeds; -use light_token::instruction::FreezeCpi; -use solana_program::{ - account_info::AccountInfo, entrypoint::ProgramResult, - program_error::ProgramError, -}; - -pub fn freeze_invoke(accounts: &[AccountInfo], _data: &[u8]) -> ProgramResult { - let [token_account, mint, freeze_authority, _token_program] = accounts - else { - return Err(ProgramError::NotEnoughAccountKeys); - }; - - // Freeze token account. freeze_authority must match mint creation - FreezeCpi { - token_account: token_account.clone(), - mint: mint.clone(), - freeze_authority: freeze_authority.clone(), - } - .invoke() -} - -pub fn freeze_invoke_signed( - accounts: &[AccountInfo], - data: &[u8], -) -> ProgramResult { - let [token_account, mint, freeze_authority, _token_program] = accounts - else { - return Err(ProgramError::NotEnoughAccountKeys); - }; - - if data.is_empty() { - return Err(ProgramError::InvalidInstructionData); - } - - let bump = data[0]; - let signer_seeds = authority_seeds!(bump); - - FreezeCpi { - token_account: token_account.clone(), - mint: mint.clone(), - freeze_authority: freeze_authority.clone(), - } - .invoke_signed(&[signer_seeds]) -} -``` - -```rust test.rs -mod shared; - -use borsh::BorshDeserialize; -use light_client::rpc::Rpc; -use light_token_interface::state::Token; -use shared::{ - build_freeze_cpi_ix, build_freeze_signed_cpi_ix, create_test_rpc, - get_authority_pda, setup, setup_mint_with_tokens, SetupContext, -}; -use solana_sdk::signer::Signer; - -#[tokio::test(flavor = "multi_thread")] -async fn freeze_cpi() { - // Setup: create mint and ATA with freeze authority - let SetupContext { - mut rpc, - payer, - mint, - ata, - .. - } = setup().await; - - let ix = build_freeze_cpi_ix(ata, mint, payer.pubkey()); - - rpc.create_and_send_transaction(&[ix], &payer.pubkey(), &[&payer]) - .await - .unwrap(); - - // Verify account is frozen - let account_data = rpc.get_account(ata).await.unwrap().unwrap(); - let token_state = Token::deserialize(&mut &account_data.data[..]).unwrap(); - assert!(token_state.is_frozen(), "Account should be frozen"); -} - -#[tokio::test(flavor = "multi_thread")] -async fn freeze_signed_cpi() { - let mut rpc = create_test_rpc().await; - let payer = rpc.get_payer().insecure_clone(); - - let (pda_authority, bump) = get_authority_pda(); - let initial_amount = 1_000_000u64; - - // Create mint with PDA as freeze authority and mint tokens to payer - let (mint, associated_token_accounts) = setup_mint_with_tokens( - &mut rpc, - &payer, - payer.pubkey(), - Some(pda_authority), - 9, - vec![(initial_amount, payer.pubkey())], - ) - .await; - - let ata = associated_token_accounts[0]; - - let ix = build_freeze_signed_cpi_ix(ata, mint, pda_authority, bump); - - rpc.create_and_send_transaction(&[ix], &payer.pubkey(), &[&payer]) - .await - .unwrap(); - - // Verify account is frozen - let account_data = rpc.get_account(ata).await.unwrap().unwrap(); - let token_state = Token::deserialize(&mut &account_data.data[..]).unwrap(); - assert!(token_state.is_frozen(), "Account should be frozen"); -} -``` - diff --git a/snippets/code-snippets/light-token/gasless-transactions/rust-instruction.mdx b/snippets/code-snippets/light-token/gasless-transactions/rust-instruction.mdx deleted file mode 100644 index 87d23e7e..00000000 --- a/snippets/code-snippets/light-token/gasless-transactions/rust-instruction.mdx +++ /dev/null @@ -1,53 +0,0 @@ -```rust -use light_client::rpc::Rpc; -use light_program_test::{LightProgramTest, ProgramTestConfig}; -use light_token::instruction::{ - get_associated_token_address, CreateAssociatedTokenAccount, - TransferInterface, LIGHT_TOKEN_PROGRAM_ID, -}; -use solana_sdk::{pubkey::Pubkey, signature::Keypair, signer::Signer}; - -#[tokio::main] -async fn main() -> Result<(), Box> { - let mut rpc = LightProgramTest::new(ProgramTestConfig::new_v2(true, None)).await?; - - // Top-Up Sponsor: your application server, pays SOL for rent top-ups - let sponsor = rpc.get_payer().insecure_clone(); - - // User: only signs to authorize the transfer - let sender: Keypair = /* user's keypair */; - let recipient: Pubkey = /* recipient address */; - let mint: Pubkey = /* e.g. USDC mint */; - let decimals = 6u8; - - let sender_ata = get_associated_token_address(&sender.pubkey(), &mint); - let recipient_ata = get_associated_token_address(&recipient, &mint); - - // Create recipient associated token account if it doesn't exist - let create_ata_ix = - CreateAssociatedTokenAccount::new(sponsor.pubkey(), recipient, mint).instruction()?; - rpc.create_and_send_transaction(&[create_ata_ix], &sponsor.pubkey(), &[&sponsor]) - .await?; - - let transfer_ix = TransferInterface { - source: sender_ata, - destination: recipient_ata, - amount: 500_000, - decimals, - authority: sender.pubkey(), - payer: sponsor.pubkey(), - spl_interface: None, - source_owner: LIGHT_TOKEN_PROGRAM_ID, - destination_owner: LIGHT_TOKEN_PROGRAM_ID, - } - .instruction()?; - - let sig = rpc - .create_and_send_transaction(&[transfer_ix], &sponsor.pubkey(), &[&sponsor, &sender]) - .await?; - - println!("Tx: {sig}"); - - Ok(()) -} -``` diff --git a/snippets/code-snippets/light-token/gasless-transactions/ts-instruction.mdx b/snippets/code-snippets/light-token/gasless-transactions/ts-instruction.mdx deleted file mode 100644 index fbdac4cd..00000000 --- a/snippets/code-snippets/light-token/gasless-transactions/ts-instruction.mdx +++ /dev/null @@ -1,104 +0,0 @@ -```typescript -import "dotenv/config"; -import { - Keypair, - Transaction, - sendAndConfirmTransaction, -} from "@solana/web3.js"; -import { createRpc } from "@lightprotocol/stateless.js"; -import { - getAssociatedTokenAddressInterface, - getAtaInterface, -} from "@lightprotocol/compressed-token"; -import { createTransferInterfaceInstructions } from "@lightprotocol/compressed-token/unified"; -import { homedir } from "os"; -import { readFileSync } from "fs"; -import { setup } from "./setup.js"; - -// devnet: -// const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; -// const rpc = createRpc(RPC_URL); -// localnet: -const rpc = createRpc(); - -const sponsor = Keypair.fromSecretKey( - new Uint8Array( - JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")), - ), -); -const sender = Keypair.generate(); -const recipient = Keypair.generate(); - -console.log("Sponsor Address (Fee Payer):", sponsor.publicKey.toBase58()); -console.log("Sender Address:", sender.publicKey.toBase58()); -console.log("Recipient Address:", recipient.publicKey.toBase58()); - -(async function () { - const { mint } = await setup(rpc, sponsor, sender, recipient); - - console.log("\nMint Address:", mint.toBase58()); - - // Derive ATAs - const senderAta = getAssociatedTokenAddressInterface(mint, sender.publicKey); - const recipientAta = getAssociatedTokenAddressInterface( - mint, - recipient.publicKey, - ); - - console.log("Sender Token Account:", senderAta.toBase58()); - console.log("Recipient Token Account:", recipientAta.toBase58()); - - // Create transfer instruction - const instructions = await createTransferInterfaceInstructions( - rpc, - sponsor.publicKey, - mint, - 500_000, - sender.publicKey, - recipient.publicKey, - ); - - // Send — sponsor pays fees, sender authorizes transfer - let signature: string; - for (const ixs of instructions) { - const tx = new Transaction().add(...ixs); - signature = await sendAndConfirmTransaction(rpc, tx, [sponsor, sender]); - } - - console.log("\n=== Sponsored Token Payment Complete ==="); - console.log("Transaction Signature:", signature!); - - // Verify balances - const { parsed: senderBalance } = await getAtaInterface( - rpc, - senderAta, - sender.publicKey, - mint, - ); - const { parsed: recipientBalance } = await getAtaInterface( - rpc, - recipientAta, - recipient.publicKey, - mint, - ); - - console.log( - "\nSender Token Account Balance:", - senderBalance.amount.toString(), - ); - console.log( - "Recipient Token Account Balance:", - recipientBalance.amount.toString(), - ); - - // Verify fee payer - const tx = await rpc.getTransaction(signature!, { - maxSupportedTransactionVersion: 0, - }); - const feePayer = tx?.transaction.message.accountKeys[0]; - console.log( - "\nNote: The first account in accountKeys is always the fee payer", - ); - console.log("Fee Payer Address:", feePayer?.toBase58()); -})(); -``` diff --git a/snippets/code-snippets/light-token/load-ata/action.mdx b/snippets/code-snippets/light-token/load-ata/action.mdx deleted file mode 100644 index 8f808495..00000000 --- a/snippets/code-snippets/light-token/load-ata/action.mdx +++ /dev/null @@ -1,44 +0,0 @@ -```typescript -import "dotenv/config"; -import { Keypair } from "@solana/web3.js"; -import { createRpc } from "@lightprotocol/stateless.js"; -import { - createMintInterface, - mintToCompressed, - loadAta, - getAssociatedTokenAddressInterface, -} from "@lightprotocol/compressed-token"; -import { homedir } from "os"; -import { readFileSync } from "fs"; - -// devnet: -// const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; -// const rpc = createRpc(RPC_URL); -// localnet: -const rpc = createRpc(); - -const payer = Keypair.fromSecretKey( - new Uint8Array( - JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) - ) -); - -(async function () { - // Inactive Light Tokens are cryptographically preserved on the Solana ledger - // as compressed tokens (cold storage) - // Setup: Get compressed tokens in light-token associated token account - const { mint } = await createMintInterface(rpc, payer, payer, null, 9); - await mintToCompressed(rpc, payer, mint, payer, [ - { recipient: payer.publicKey, amount: 1000n }, - ]); - - // Load compressed tokens to light associated token account (hot balance) - const lightTokenAta = getAssociatedTokenAddressInterface( - mint, - payer.publicKey - ); - const tx = await loadAta(rpc, lightTokenAta, payer, mint, payer); - - console.log("Tx:", tx); -})(); -``` diff --git a/snippets/code-snippets/light-token/load-ata/instruction.mdx b/snippets/code-snippets/light-token/load-ata/instruction.mdx deleted file mode 100644 index 50ce8bfb..00000000 --- a/snippets/code-snippets/light-token/load-ata/instruction.mdx +++ /dev/null @@ -1,61 +0,0 @@ -```typescript -import "dotenv/config"; -import { - Keypair, - Transaction, - sendAndConfirmTransaction, -} from "@solana/web3.js"; -import { createRpc } from "@lightprotocol/stateless.js"; -import { - createMintInterface, - mintToCompressed, - getAssociatedTokenAddressInterface, -} from "@lightprotocol/compressed-token"; -import { createLoadAtaInstructions } from "@lightprotocol/compressed-token/unified"; -import { homedir } from "os"; -import { readFileSync } from "fs"; - -// devnet: -// const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; -// const rpc = createRpc(RPC_URL); -// localnet: -const rpc = createRpc(); - -const payer = Keypair.fromSecretKey( - new Uint8Array( - JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) - ) -); - -(async function () { - // Inactive Light Tokens are cryptographically preserved on the Solana ledger - // as compressed tokens (cold storage) - // Setup: Get compressed tokens in light-token associated token account - const { mint } = await createMintInterface(rpc, payer, payer, null, 9); - await mintToCompressed(rpc, payer, mint, payer, [ - { recipient: payer.publicKey, amount: 1000n }, - ]); - - const lightTokenAta = getAssociatedTokenAddressInterface( - mint, - payer.publicKey - ); - - // Load compressed tokens to light associated token account (hot balance) - const instructions = await createLoadAtaInstructions( - rpc, - lightTokenAta, - payer.publicKey, - mint, - payer.publicKey - ); - - if (instructions.length === 0) return console.log("Nothing to load"); - - for (const ixs of instructions) { - const tx = new Transaction().add(...ixs); - const sig = await sendAndConfirmTransaction(rpc, tx, [payer]); - console.log("Tx:", sig); - } -})(); -``` diff --git a/snippets/code-snippets/light-token/load-ata/token-interface-instruction.mdx b/snippets/code-snippets/light-token/load-ata/token-interface-instruction.mdx deleted file mode 100644 index 1bbebc84..00000000 --- a/snippets/code-snippets/light-token/load-ata/token-interface-instruction.mdx +++ /dev/null @@ -1,25 +0,0 @@ -```typescript -import { Keypair, Transaction, sendAndConfirmTransaction } from "@solana/web3.js"; -import { createRpc } from "@lightprotocol/stateless.js"; -import { createLoadInstructions } from "@lightprotocol/token-interface"; - -const rpc = createRpc(); -const payer = Keypair.fromSecretKey(/* ... */); - -const mint = /* existing mint public key */; -const owner = payer.publicKey; - -const instructions = await createLoadInstructions({ - rpc, - payer: payer.publicKey, - owner, - mint, - authority: owner, -}); - -if (instructions.length > 0) { - const tx = new Transaction().add(...instructions); - const signature = await sendAndConfirmTransaction(rpc, tx, [payer]); - console.log("Tx:", signature); -} -``` diff --git a/snippets/code-snippets/light-token/mint-spl-and-wrap/action.mdx b/snippets/code-snippets/light-token/mint-spl-and-wrap/action.mdx deleted file mode 100644 index 88789faf..00000000 --- a/snippets/code-snippets/light-token/mint-spl-and-wrap/action.mdx +++ /dev/null @@ -1,96 +0,0 @@ -```typescript -import "dotenv/config"; -import { Keypair, PublicKey } from "@solana/web3.js"; -import { createRpc } from "@lightprotocol/stateless.js"; -import { - createMintInterface, - createAtaInterfaceIdempotent, - getAssociatedTokenAddressInterface, - wrap, - transferInterface, -} from "@lightprotocol/compressed-token"; -import { - TOKEN_2022_PROGRAM_ID, - createAssociatedTokenAccount, - mintTo, -} from "@solana/spl-token"; -import { homedir } from "os"; -import { readFileSync } from "fs"; - -// devnet: -const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; -const rpc = createRpc(RPC_URL); -// localnet: -// const rpc = createRpc(); - -const payer = Keypair.fromSecretKey( - new Uint8Array( - JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) - ) -); - -(async function () { - const decimals = 9; - const tokenAmount = BigInt(100 * Math.pow(10, decimals)); - const recipient = Keypair.generate(); - - // Creates on-chain SPL or Token-2022 mint and registers SPL interface PDA. - // SPL interface PDA enables wrap/unwrap between SPL/Token-2022 and Light Token. - const mintKeypair = Keypair.generate(); - const { mint } = await createMintInterface( - rpc, - payer, - payer, - null, - decimals, - mintKeypair, - undefined, - TOKEN_2022_PROGRAM_ID, - ); - - // 1. Mint SPL tokens to payer's associated token account - const payerSplAta = await createAssociatedTokenAccount( - rpc, - payer, - mint, - payer.publicKey, - undefined, - TOKEN_2022_PROGRAM_ID, - ); - await mintTo( - rpc, - payer, - mint, - payerSplAta, - payer, - tokenAmount, - [], - undefined, - TOKEN_2022_PROGRAM_ID, - ); - - // 2. Wrap SPL tokens into payer's light associated token account - await createAtaInterfaceIdempotent(rpc, payer, mint, payer.publicKey); - const payerLightAta = getAssociatedTokenAddressInterface(mint, payer.publicKey); - await wrap(rpc, payer, payerSplAta, payerLightAta, payer, mint, tokenAmount); - - // 3. Transfer to recipient's light associated token account - await createAtaInterfaceIdempotent(rpc, payer, mint, recipient.publicKey); - await transferInterface( - rpc, - payer, - payerLightAta, - mint, - recipient.publicKey, - payer.publicKey, - payer, - tokenAmount, - ); - - console.log("Transferred", 100, "tokens to", recipient.publicKey.toBase58()); -})(); -``` - - -Source: [mint-spl-and-wrap.ts](https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/sign-with-privy/scripts/src/mint-spl-and-wrap.ts) - diff --git a/snippets/code-snippets/light-token/mint-to-checked/anchor-program/full-example.mdx b/snippets/code-snippets/light-token/mint-to-checked/anchor-program/full-example.mdx deleted file mode 100644 index 5f85684c..00000000 --- a/snippets/code-snippets/light-token/mint-to-checked/anchor-program/full-example.mdx +++ /dev/null @@ -1,88 +0,0 @@ - -```rust lib.rs -#![allow(unexpected_cfgs, deprecated)] - -use anchor_lang::prelude::*; -use light_token::instruction::MintToCheckedCpi; - -declare_id!("DGu3ofzac2Zndn95z2q9gCp8zHgW22YpMeEWj2up3QDb"); - -#[program] -pub mod light_token_anchor_mint_to_checked { - use super::*; - - pub fn mint_to_checked( - ctx: Context, - amount: u64, - decimals: u8, - ) -> Result<()> { - MintToCheckedCpi { - mint: ctx.accounts.mint.to_account_info(), - destination: ctx.accounts.destination.to_account_info(), - amount, - decimals, - authority: ctx.accounts.authority.to_account_info(), - system_program: ctx.accounts.system_program.to_account_info(), - max_top_up: None, - fee_payer: None, - } - .invoke()?; - Ok(()) - } -} - -#[derive(Accounts)] -pub struct MintToCheckedAccounts<'info> { - /// CHECK: Light token program for CPI - pub light_token_program: AccountInfo<'info>, - /// CHECK: Validated by light-token CPI - #[account(mut)] - pub mint: AccountInfo<'info>, - /// CHECK: Validated by light-token CPI - #[account(mut)] - pub destination: AccountInfo<'info>, - pub authority: Signer<'info>, - pub system_program: Program<'info, System>, -} -``` - -```rust test.rs -use anchor_lang::{InstructionData, ToAccountMetas}; -use light_program_test::Rpc; -use light_token::instruction::LIGHT_TOKEN_PROGRAM_ID; -use light_token_anchor_mint_to_checked::{accounts, instruction::MintToChecked, ID}; -use solana_sdk::{instruction::Instruction, signer::Signer, system_program}; -use test_utils::setup_test_env; - -#[tokio::test(flavor = "multi_thread")] -async fn test_mint_to_checked() { - let mut env = setup_test_env("light_token_anchor_mint_to_checked", ID).await; - - // MintToChecked validates decimals match the mint's decimals. - // No mint_tokens call - the test IS minting tokens via CPI. - let amount = 1_000_000u64; - let decimals = 9u8; - let ix = Instruction { - program_id: ID, - accounts: accounts::MintToCheckedAccounts { - light_token_program: LIGHT_TOKEN_PROGRAM_ID, - mint: env.mint_pda, - destination: env.ata, - authority: env.payer.pubkey(), - system_program: system_program::ID, - } - .to_account_metas(Some(true)), - data: MintToChecked { amount, decimals }.data(), - }; - - env.rpc - .create_and_send_transaction(&[ix], &env.payer.pubkey(), &[&env.payer]) - .await - .unwrap(); - - // Verify the account exists and has data - let ata_data = env.rpc.get_account(env.ata).await.unwrap().unwrap(); - assert!(!ata_data.data.is_empty(), "ATA account should have data"); -} -``` - diff --git a/snippets/code-snippets/light-token/mint-to-checked/native-program/full-example.mdx b/snippets/code-snippets/light-token/mint-to-checked/native-program/full-example.mdx deleted file mode 100644 index 1803ba14..00000000 --- a/snippets/code-snippets/light-token/mint-to-checked/native-program/full-example.mdx +++ /dev/null @@ -1,145 +0,0 @@ - -```rust instruction.rs -use super::authority_seeds; -use light_token::instruction::MintToCheckedCpi; -use solana_program::{ - account_info::AccountInfo, entrypoint::ProgramResult, - program_error::ProgramError, -}; - -pub fn mint_to_checked_invoke( - accounts: &[AccountInfo], - data: &[u8], -) -> ProgramResult { - let [mint, destination, authority, system_program, _token_program] = - accounts - else { - return Err(ProgramError::NotEnoughAccountKeys); - }; - - if data.len() < 9 { - return Err(ProgramError::InvalidInstructionData); - } - - let amount = u64::from_le_bytes(data[0..8].try_into().unwrap()); - let decimals = data[8]; - - // MintToChecked validates decimals match the mint - MintToCheckedCpi { - mint: mint.clone(), - destination: destination.clone(), - amount, - decimals, - authority: authority.clone(), - system_program: system_program.clone(), - max_top_up: None, - fee_payer: None, - } - .invoke() -} - -pub fn mint_to_checked_invoke_signed( - accounts: &[AccountInfo], - data: &[u8], -) -> ProgramResult { - let [mint, destination, authority, system_program, _token_program] = - accounts - else { - return Err(ProgramError::NotEnoughAccountKeys); - }; - - if data.len() < 10 { - return Err(ProgramError::InvalidInstructionData); - } - - let amount = u64::from_le_bytes(data[0..8].try_into().unwrap()); - let decimals = data[8]; - let bump = data[9]; - let signer_seeds = authority_seeds!(bump); - - MintToCheckedCpi { - mint: mint.clone(), - destination: destination.clone(), - amount, - decimals, - authority: authority.clone(), - system_program: system_program.clone(), - max_top_up: None, - fee_payer: None, - } - .invoke_signed(&[signer_seeds]) -} -``` - -```rust test.rs -mod shared; - -use light_client::rpc::Rpc; -use shared::{ - build_mint_to_checked_cpi_ix, build_mint_to_checked_signed_cpi_ix, - create_ata, create_test_rpc, get_authority_pda, - setup_mint_with_pda_authority, setup_mint_with_tokens, -}; -use solana_sdk::{signature::Keypair, signer::Signer}; - -#[tokio::test(flavor = "multi_thread")] -async fn mint_to_checked_cpi() { - let mut rpc = create_test_rpc().await; - let payer = rpc.get_payer().insecure_clone(); - - let (mint, associated_token_accounts) = setup_mint_with_tokens( - &mut rpc, - &payer, - payer.pubkey(), - None, - 9, - vec![(0, payer.pubkey())], - ) - .await; - - let mint_amount = 1_000_000u64; - - let ix = build_mint_to_checked_cpi_ix( - mint, - associated_token_accounts[0], - payer.pubkey(), - mint_amount, - 9, - ); - - rpc.create_and_send_transaction(&[ix], &payer.pubkey(), &[&payer]) - .await - .unwrap(); -} - -#[tokio::test(flavor = "multi_thread")] -async fn mint_to_checked_signed_cpi() { - let mut rpc = create_test_rpc().await; - let payer = rpc.get_payer().insecure_clone(); - - let (pda_authority, bump) = get_authority_pda(); - - let mint = - setup_mint_with_pda_authority(&mut rpc, &payer, pda_authority, 9).await; - - let recipient = Keypair::new(); - let recipient_ata = - create_ata(&mut rpc, &payer, recipient.pubkey(), mint).await; - - let mint_amount = 1_000_000u64; - - let ix = build_mint_to_checked_signed_cpi_ix( - mint, - recipient_ata, - pda_authority, - mint_amount, - 9, - bump, - ); - - rpc.create_and_send_transaction(&[ix], &payer.pubkey(), &[&payer]) - .await - .unwrap(); -} -``` - diff --git a/snippets/code-snippets/light-token/mint-to/action.mdx b/snippets/code-snippets/light-token/mint-to/action.mdx deleted file mode 100644 index ec43e0f1..00000000 --- a/snippets/code-snippets/light-token/mint-to/action.mdx +++ /dev/null @@ -1,47 +0,0 @@ -```typescript -import "dotenv/config"; -import { Keypair } from "@solana/web3.js"; -import { createRpc } from "@lightprotocol/stateless.js"; -import { - createMintInterface, - createAtaInterface, - mintToInterface, - getAssociatedTokenAddressInterface, -} from "@lightprotocol/compressed-token"; -import { homedir } from "os"; -import { readFileSync } from "fs"; - -// devnet: -// const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; -// const rpc = createRpc(RPC_URL); -// localnet: -const rpc = createRpc(); - -const payer = Keypair.fromSecretKey( - new Uint8Array( - JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) - ) -); - -(async function () { - const { mint } = await createMintInterface(rpc, payer, payer, null, 9); - - const recipient = Keypair.generate(); - await createAtaInterface(rpc, payer, mint, recipient.publicKey); - - const destination = getAssociatedTokenAddressInterface( - mint, - recipient.publicKey - ); - const tx = await mintToInterface( - rpc, - payer, - mint, - destination, - payer, - 1_000_000_000 - ); - - console.log("Tx:", tx); -})(); -``` diff --git a/snippets/code-snippets/light-token/mint-to/anchor-program/full-example.mdx b/snippets/code-snippets/light-token/mint-to/anchor-program/full-example.mdx deleted file mode 100644 index 82f6509e..00000000 --- a/snippets/code-snippets/light-token/mint-to/anchor-program/full-example.mdx +++ /dev/null @@ -1,84 +0,0 @@ - -```rust lib.rs -#![allow(unexpected_cfgs, deprecated)] - -use anchor_lang::prelude::*; -use light_token::instruction::MintToCpi; - -declare_id!("8bXEVmHLtAVqDLJp1dYWAZ61WQmqQKoTQ8LpPbRoUDCp"); - -#[program] -pub mod light_token_anchor_mint_to { - use super::*; - - pub fn mint_to(ctx: Context, amount: u64) -> Result<()> { - MintToCpi { - mint: ctx.accounts.mint.to_account_info(), - destination: ctx.accounts.destination.to_account_info(), - amount, - authority: ctx.accounts.authority.to_account_info(), - system_program: ctx.accounts.system_program.to_account_info(), - fee_payer: ctx.accounts.fee_payer.to_account_info(), - } - .invoke()?; - Ok(()) - } -} - -#[derive(Accounts)] -pub struct MintToAccounts<'info> { - /// CHECK: Light token program for CPI - pub light_token_program: AccountInfo<'info>, - /// CHECK: Validated by light-token CPI - #[account(mut)] - pub mint: AccountInfo<'info>, - /// CHECK: Validated by light-token CPI - #[account(mut)] - pub destination: AccountInfo<'info>, - pub authority: Signer<'info>, - #[account(mut)] - pub fee_payer: Signer<'info>, - pub system_program: Program<'info, System>, -} -``` - -```rust test.rs -use anchor_lang::{InstructionData, ToAccountMetas}; -use light_program_test::Rpc; -use light_token::instruction::LIGHT_TOKEN_PROGRAM_ID; -use light_token_anchor_mint_to::{accounts, instruction::MintTo, ID}; -use anchor_lang::system_program; -use solana_sdk::{instruction::Instruction, signer::Signer}; -use test_utils::setup_test_env; - -#[tokio::test(flavor = "multi_thread")] -async fn test_mint_to() { - let mut env = setup_test_env("light_token_anchor_mint_to", ID).await; - - // No mint_tokens call - the test IS minting tokens via CPI. - let amount = 1_000_000u64; - let ix = Instruction { - program_id: ID, - accounts: accounts::MintToAccounts { - light_token_program: LIGHT_TOKEN_PROGRAM_ID, - mint: env.mint_pda, - destination: env.associated_token_account, - authority: env.payer.pubkey(), - fee_payer: env.payer.pubkey(), - system_program: system_program::ID, - } - .to_account_metas(Some(true)), - data: MintTo { amount }.data(), - }; - - env.rpc - .create_and_send_transaction(&[ix], &env.payer.pubkey(), &[&env.payer]) - .await - .unwrap(); - - // Verify the account exists and has data - let associated_token_account_data = env.rpc.get_account(env.associated_token_account).await.unwrap().unwrap(); - assert!(!associated_token_account_data.data.is_empty(), "Associated token account should have data"); -} -``` - diff --git a/snippets/code-snippets/light-token/mint-to/native-program/full-example.mdx b/snippets/code-snippets/light-token/mint-to/native-program/full-example.mdx deleted file mode 100644 index 53a52aa5..00000000 --- a/snippets/code-snippets/light-token/mint-to/native-program/full-example.mdx +++ /dev/null @@ -1,187 +0,0 @@ - -```rust instruction.rs -use super::authority_seeds; -use light_token::instruction::MintToCpi; -use solana_program::{ - account_info::AccountInfo, entrypoint::ProgramResult, - program_error::ProgramError, -}; - -pub fn mint_to_invoke(accounts: &[AccountInfo], data: &[u8]) -> ProgramResult { - let [mint, destination, authority, system_program, _token_program] = - accounts - else { - return Err(ProgramError::NotEnoughAccountKeys); - }; - - let amount = u64::from_le_bytes( - data.try_into() - .map_err(|_| ProgramError::InvalidInstructionData)?, - ); - - // Mint tokens to destination account - MintToCpi { - mint: mint.clone(), - destination: destination.clone(), - amount, - authority: authority.clone(), - system_program: system_program.clone(), - fee_payer: None, - max_top_up: None, - } - .invoke() -} - -pub fn mint_to_invoke_signed( - accounts: &[AccountInfo], - data: &[u8], -) -> ProgramResult { - let [mint, destination, authority, system_program, _token_program] = - accounts - else { - return Err(ProgramError::NotEnoughAccountKeys); - }; - - if data.len() < 9 { - return Err(ProgramError::InvalidInstructionData); - } - - let amount = u64::from_le_bytes(data[0..8].try_into().unwrap()); - let bump = data[8]; - let signer_seeds = authority_seeds!(bump); - - MintToCpi { - mint: mint.clone(), - destination: destination.clone(), - amount, - authority: authority.clone(), - system_program: system_program.clone(), - fee_payer: None, - max_top_up: None, - } - .invoke_signed(&[signer_seeds]) -} -``` - -```rust test.rs -mod shared; - -use light_client::rpc::Rpc; -use light_token::instruction::derive_token_ata; -use shared::{ - build_create_ata_signed_cpi_ix, build_mint_to_cpi_ix, - build_mint_to_signed_cpi_ix, create_ata, create_test_rpc, - get_authority_pda, setup_empty_ata, setup_mint_with_pda_authority, - SetupContext, -}; -use solana_sdk::signer::Signer; - -#[tokio::test(flavor = "multi_thread")] -async fn mint_to_cpi() { - // Setup: create mint and empty ATA - let SetupContext { - mut rpc, - payer, - mint, - ata, - .. - } = setup_empty_ata().await; - - let amount = 1_000_000u64; - - let ix = build_mint_to_cpi_ix(mint, ata, payer.pubkey(), amount); - - rpc.create_and_send_transaction(&[ix], &payer.pubkey(), &[&payer]) - .await - .unwrap(); -} - -/// Mints tokens via CPI with PDA authority. -#[tokio::test(flavor = "multi_thread")] -async fn mint_to_signed_cpi() { - let mut rpc = create_test_rpc().await; - let payer = rpc.get_payer().insecure_clone(); - - let (pda_authority, authority_bump) = get_authority_pda(); - let decimals = 9u8; - - // Create mint with PDA authority - let mint = setup_mint_with_pda_authority( - &mut rpc, - &payer, - pda_authority, - decimals, - ) - .await; - - // Create ATA for the payer - let ata = create_ata(&mut rpc, &payer, payer.pubkey(), mint).await; - - // Mint tokens using signed CPI - let amount = 1_000_000u64; - let mint_to_ix = build_mint_to_signed_cpi_ix( - mint, - ata, - pda_authority, - amount, - authority_bump, - ); - - rpc.create_and_send_transaction(&[mint_to_ix], &payer.pubkey(), &[&payer]) - .await - .unwrap(); -} - -/// Mints tokens using CPI-style ATA creation. -#[tokio::test(flavor = "multi_thread")] -async fn mint_to_signed_cpi_with_ata_cpi() { - let mut rpc = create_test_rpc().await; - let payer = rpc.get_payer().insecure_clone(); - - let (pda_authority, authority_bump) = get_authority_pda(); - let decimals = 9u8; - - // Create mint with PDA authority - let mint = setup_mint_with_pda_authority( - &mut rpc, - &payer, - pda_authority, - decimals, - ) - .await; - - // Create ATA using the signed CPI instruction - let (ata, ata_bump) = derive_token_ata(&payer.pubkey(), &mint); - let create_ata_ix = build_create_ata_signed_cpi_ix( - payer.pubkey(), - mint, - payer.pubkey(), - ata, - ata_bump, - authority_bump, - ); - - rpc.create_and_send_transaction( - &[create_ata_ix], - &payer.pubkey(), - &[&payer], - ) - .await - .unwrap(); - - // Mint tokens using signed CPI - let amount = 1_000_000u64; - let mint_to_ix = build_mint_to_signed_cpi_ix( - mint, - ata, - pda_authority, - amount, - authority_bump, - ); - - rpc.create_and_send_transaction(&[mint_to_ix], &payer.pubkey(), &[&payer]) - .await - .unwrap(); -} -``` - diff --git a/snippets/code-snippets/light-token/mint-to/rust-client/action.mdx b/snippets/code-snippets/light-token/mint-to/rust-client/action.mdx deleted file mode 100644 index 3a741321..00000000 --- a/snippets/code-snippets/light-token/mint-to/rust-client/action.mdx +++ /dev/null @@ -1,46 +0,0 @@ -```rust -use borsh::BorshDeserialize; -use light_client::rpc::Rpc; -use light_token_client::actions::{CreateAta, CreateMint, MintTo}; -use rust_client::setup_rpc_and_payer; -use solana_sdk::signer::Signer; - -#[tokio::main] -async fn main() -> Result<(), Box> { - let (mut rpc, payer) = setup_rpc_and_payer().await; - - // Create mint (payer is also mint authority) - let (_signature, mint) = CreateMint { - decimals: 9, - freeze_authority: None, - token_metadata: None, - seed: None, - } - .execute(&mut rpc, &payer, &payer) - .await?; - - // Create associated token account - let (_signature, associated_token_account) = CreateAta { - mint, - owner: payer.pubkey(), - idempotent: true, - } - .execute(&mut rpc, &payer) - .await?; - - // Mint tokens (payer is mint authority) - let sig = MintTo { - mint, - destination: associated_token_account, - amount: 1_000_000, - } - .execute(&mut rpc, &payer, &payer) - .await?; - - let data = rpc.get_account(associated_token_account).await?.ok_or("Account not found")?; - let token = light_token_interface::state::Token::deserialize(&mut &data.data[..])?; - println!("Balance: {} Tx: {sig}", token.amount); - - Ok(()) -} -``` diff --git a/snippets/code-snippets/light-token/mint-to/rust-client/instruction.mdx b/snippets/code-snippets/light-token/mint-to/rust-client/instruction.mdx deleted file mode 100644 index c3ddcf2f..00000000 --- a/snippets/code-snippets/light-token/mint-to/rust-client/instruction.mdx +++ /dev/null @@ -1,40 +0,0 @@ -```rust -use borsh::BorshDeserialize; -use light_client::rpc::Rpc; -use light_token::instruction::MintTo; -use rust_client::{setup_empty_associated_token_account, SetupContext}; -use solana_sdk::signer::Signer; - -#[tokio::main] -async fn main() -> Result<(), Box> { - // Setup creates mint and empty associated token account - let SetupContext { - mut rpc, - payer, - mint, - associated_token_account, - .. - } = setup_empty_associated_token_account().await; - - let mint_amount = 1_000_000_000u64; - - let mint_to_instruction = MintTo { - mint, - destination: associated_token_account, - amount: mint_amount, - authority: payer.pubkey(), - fee_payer: payer.pubkey(), - } - .instruction()?; - - let sig = rpc - .create_and_send_transaction(&[mint_to_instruction], &payer.pubkey(), &[&payer]) - .await?; - - let data = rpc.get_account(associated_token_account).await?.ok_or("Account not found")?; - let token = light_token_interface::state::Token::deserialize(&mut &data.data[..])?; - println!("Balance: {} Tx: {sig}", token.amount); - - Ok(()) -} -``` diff --git a/snippets/code-snippets/light-token/mint-to/token-interface-instruction.mdx b/snippets/code-snippets/light-token/mint-to/token-interface-instruction.mdx deleted file mode 100644 index 3bf301d3..00000000 --- a/snippets/code-snippets/light-token/mint-to/token-interface-instruction.mdx +++ /dev/null @@ -1,36 +0,0 @@ -```typescript -import { Keypair, Transaction, sendAndConfirmTransaction } from "@solana/web3.js"; -import { createRpc, LIGHT_TOKEN_PROGRAM_ID } from "@lightprotocol/stateless.js"; -import { - createAtaInstruction, - createMintToInstruction, - getAtaAddress, -} from "@lightprotocol/token-interface"; - -const rpc = createRpc(); -const payer = Keypair.fromSecretKey(/* ... */); - -const mint = /* existing mint public key */; -const recipient = Keypair.generate(); -const destination = getAtaAddress({ mint, owner: recipient.publicKey }); - -const createAtaIx = createAtaInstruction({ - payer: payer.publicKey, - owner: recipient.publicKey, - mint, - programId: LIGHT_TOKEN_PROGRAM_ID, -}); - -const mintToIx = createMintToInstruction({ - mint, - destination, - authority: payer.publicKey, - payer: payer.publicKey, - amount: 1_000_000_000n, - tokenProgramId: LIGHT_TOKEN_PROGRAM_ID, -}); - -const tx = new Transaction().add(createAtaIx, mintToIx); -const signature = await sendAndConfirmTransaction(rpc, tx, [payer]); -console.log("Tx:", signature); -``` diff --git a/snippets/code-snippets/light-token/revoke/anchor-program/full-example.mdx b/snippets/code-snippets/light-token/revoke/anchor-program/full-example.mdx deleted file mode 100644 index 5464969c..00000000 --- a/snippets/code-snippets/light-token/revoke/anchor-program/full-example.mdx +++ /dev/null @@ -1,97 +0,0 @@ - -```rust lib.rs -#![allow(unexpected_cfgs, deprecated)] - -use anchor_lang::prelude::*; -use light_token::instruction::RevokeCpi; - -declare_id!("G3ph4MK5qaSdxYnfxToETg31AHEMMqVhPuMRgBhk38tQ"); - -#[program] -pub mod light_token_anchor_revoke { - use super::*; - - pub fn revoke(ctx: Context) -> Result<()> { - RevokeCpi { - token_account: ctx.accounts.token_account.to_account_info(), - owner: ctx.accounts.owner.to_account_info(), - system_program: ctx.accounts.system_program.to_account_info(), - fee_payer: ctx.accounts.fee_payer.to_account_info(), - } - .invoke()?; - Ok(()) - } -} - -#[derive(Accounts)] -pub struct RevokeAccounts<'info> { - /// CHECK: Light token program for CPI - pub light_token_program: AccountInfo<'info>, - /// CHECK: Validated by light-token CPI - #[account(mut)] - pub token_account: AccountInfo<'info>, - pub owner: Signer<'info>, - #[account(mut)] - pub fee_payer: Signer<'info>, - pub system_program: Program<'info, System>, -} -``` - -```rust test.rs -use anchor_lang::{InstructionData, ToAccountMetas}; -use light_program_test::Rpc; -use light_token::instruction::{Approve, LIGHT_TOKEN_PROGRAM_ID}; -use light_token_anchor_revoke::{accounts, instruction::Revoke, ID}; -use anchor_lang::system_program; -use solana_sdk::{instruction::Instruction, signature::Keypair, signer::Signer}; -use test_utils::{mint_tokens, setup_test_env}; - -#[tokio::test] -async fn test_revoke() { - let mut env = setup_test_env("light_token_anchor_revoke", ID).await; - - // Mint tokens first - let mint_amount = 1_000_000u64; - mint_tokens(&mut env.rpc, &env.payer, env.mint_pda, env.associated_token_account, mint_amount).await; - - // Approve delegate first using SDK - let delegate = Keypair::new(); - let approve_ix = Approve { - token_account: env.associated_token_account, - delegate: delegate.pubkey(), - owner: env.payer.pubkey(), - amount: 500_000, - fee_payer: env.payer.pubkey(), - } - .instruction() - .unwrap(); - - env.rpc - .create_and_send_transaction(&[approve_ix], &env.payer.pubkey(), &[&env.payer]) - .await - .unwrap(); - - // Call the anchor program to revoke delegation - let ix = Instruction { - program_id: ID, - accounts: accounts::RevokeAccounts { - light_token_program: LIGHT_TOKEN_PROGRAM_ID, - token_account: env.associated_token_account, - owner: env.payer.pubkey(), - fee_payer: env.payer.pubkey(), - system_program: system_program::ID, - } - .to_account_metas(Some(true)), - data: Revoke {}.data(), - }; - - let sig = env - .rpc - .create_and_send_transaction(&[ix], &env.payer.pubkey(), &[&env.payer]) - .await - .unwrap(); - - println!("Tx: {}", sig); -} -``` - diff --git a/snippets/code-snippets/light-token/revoke/native-program/full-example.mdx b/snippets/code-snippets/light-token/revoke/native-program/full-example.mdx deleted file mode 100644 index 574e340d..00000000 --- a/snippets/code-snippets/light-token/revoke/native-program/full-example.mdx +++ /dev/null @@ -1,107 +0,0 @@ - -```rust instruction.rs -use super::authority_seeds; -use light_token::instruction::RevokeCpi; -use solana_program::{ - account_info::AccountInfo, entrypoint::ProgramResult, - program_error::ProgramError, -}; - -pub fn revoke_invoke(accounts: &[AccountInfo], _data: &[u8]) -> ProgramResult { - let [token_account, owner, system_program, _token_program] = accounts - else { - return Err(ProgramError::NotEnoughAccountKeys); - }; - - // Revoke delegate authority from token account - RevokeCpi { - token_account: token_account.clone(), - owner: owner.clone(), - system_program: system_program.clone(), - } - .invoke() -} - -pub fn revoke_invoke_signed( - accounts: &[AccountInfo], - data: &[u8], -) -> ProgramResult { - let [token_account, owner, system_program, _token_program] = accounts - else { - return Err(ProgramError::NotEnoughAccountKeys); - }; - - if data.is_empty() { - return Err(ProgramError::InvalidInstructionData); - } - - let bump = data[0]; - let signer_seeds = authority_seeds!(bump); - - RevokeCpi { - token_account: token_account.clone(), - owner: owner.clone(), - system_program: system_program.clone(), - } - .invoke_signed(&[signer_seeds]) -} -``` - -```rust test.rs -mod shared; - -use light_client::rpc::Rpc; -use shared::{ - build_revoke_cpi_ix, build_revoke_signed_cpi_ix, create_test_rpc, - get_authority_pda, setup, setup_pda_owned_ata, SetupContext, -}; -use solana_sdk::{signature::Keypair, signer::Signer}; - -#[tokio::test(flavor = "multi_thread")] -async fn revoke_cpi() { - // Setup: create mint, ATA with tokens, and approve delegate - let SetupContext { - mut rpc, - payer, - ata, - .. - } = setup().await; - - let ix = build_revoke_cpi_ix(ata, payer.pubkey()); - - rpc.create_and_send_transaction(&[ix], &payer.pubkey(), &[&payer]) - .await - .unwrap(); -} - -#[tokio::test(flavor = "multi_thread")] -async fn revoke_signed_cpi() { - let mut rpc = create_test_rpc().await; - let payer = rpc.get_payer().insecure_clone(); - - let (pda_owner, bump) = get_authority_pda(); - - let (_mint, ata) = - setup_pda_owned_ata(&mut rpc, &payer, pda_owner, 1_000_000).await; - - let delegate = Keypair::new(); - let approve_ix = shared::build_approve_signed_cpi_ix( - ata, - delegate.pubkey(), - pda_owner, - 500_000, - bump, - ); - - rpc.create_and_send_transaction(&[approve_ix], &payer.pubkey(), &[&payer]) - .await - .unwrap(); - - let ix = build_revoke_signed_cpi_ix(ata, pda_owner, bump); - - rpc.create_and_send_transaction(&[ix], &payer.pubkey(), &[&payer]) - .await - .unwrap(); -} -``` - diff --git a/snippets/code-snippets/light-token/thaw/anchor-program/full-example.mdx b/snippets/code-snippets/light-token/thaw/anchor-program/full-example.mdx deleted file mode 100644 index 6318dc12..00000000 --- a/snippets/code-snippets/light-token/thaw/anchor-program/full-example.mdx +++ /dev/null @@ -1,89 +0,0 @@ - -```rust lib.rs -#![allow(unexpected_cfgs, deprecated)] - -use anchor_lang::prelude::*; -use light_token::instruction::ThawCpi; - -declare_id!("7j94EF5hSkDLf7R26bjrd8Qc6s3oLAQpcKiF3re8JYw9"); - -#[program] -pub mod light_token_anchor_thaw { - use super::*; - - pub fn thaw(ctx: Context) -> Result<()> { - ThawCpi { - token_account: ctx.accounts.token_account.to_account_info(), - mint: ctx.accounts.mint.to_account_info(), - freeze_authority: ctx.accounts.freeze_authority.to_account_info(), - } - .invoke()?; - Ok(()) - } -} - -#[derive(Accounts)] -pub struct ThawAccounts<'info> { - /// CHECK: Light token program for CPI - pub light_token_program: AccountInfo<'info>, - /// CHECK: Validated by light-token CPI - #[account(mut)] - pub token_account: AccountInfo<'info>, - /// CHECK: Validated by light-token CPI - pub mint: AccountInfo<'info>, - pub freeze_authority: Signer<'info>, -} -``` - -```rust test.rs -use anchor_lang::{InstructionData, ToAccountMetas}; -use light_program_test::Rpc; -use light_token::instruction::{Freeze, LIGHT_TOKEN_PROGRAM_ID}; -use light_token_anchor_thaw::{accounts, instruction::Thaw, ID}; -use solana_sdk::{instruction::Instruction, signer::Signer}; -use test_utils::{mint_tokens, setup_test_env_with_freeze}; - -#[tokio::test] -async fn test_thaw() { - let mut env = setup_test_env_with_freeze("light_token_anchor_thaw", ID).await; - - // Mint tokens first - mint_tokens(&mut env.rpc, &env.payer, env.mint_pda, env.associated_token_account, 1_000_000).await; - - // Freeze account first using SDK - let freeze_ix = Freeze { - token_account: env.associated_token_account, - mint: env.mint_pda, - freeze_authority: env.freeze_authority, - } - .instruction() - .unwrap(); - - env.rpc - .create_and_send_transaction(&[freeze_ix], &env.payer.pubkey(), &[&env.payer]) - .await - .unwrap(); - - // Call the anchor program to thaw account - let ix = Instruction { - program_id: ID, - accounts: accounts::ThawAccounts { - light_token_program: LIGHT_TOKEN_PROGRAM_ID, - token_account: env.associated_token_account, - mint: env.mint_pda, - freeze_authority: env.freeze_authority, - } - .to_account_metas(Some(true)), - data: Thaw {}.data(), - }; - - let sig = env - .rpc - .create_and_send_transaction(&[ix], &env.payer.pubkey(), &[&env.payer]) - .await - .unwrap(); - - println!("Tx: {}", sig); -} -``` - diff --git a/snippets/code-snippets/light-token/thaw/native-program/full-example.mdx b/snippets/code-snippets/light-token/thaw/native-program/full-example.mdx deleted file mode 100644 index aa8cb23c..00000000 --- a/snippets/code-snippets/light-token/thaw/native-program/full-example.mdx +++ /dev/null @@ -1,111 +0,0 @@ - -```rust instruction.rs -use super::authority_seeds; -use light_token::instruction::ThawCpi; -use solana_program::{ - account_info::AccountInfo, entrypoint::ProgramResult, - program_error::ProgramError, -}; - -pub fn thaw_invoke(accounts: &[AccountInfo], _data: &[u8]) -> ProgramResult { - let [token_account, mint, freeze_authority, _token_program] = accounts - else { - return Err(ProgramError::NotEnoughAccountKeys); - }; - - // Thaw frozen token account. freeze_authority must match mint creation - ThawCpi { - token_account: token_account.clone(), - mint: mint.clone(), - freeze_authority: freeze_authority.clone(), - } - .invoke() -} - -pub fn thaw_invoke_signed( - accounts: &[AccountInfo], - data: &[u8], -) -> ProgramResult { - let [token_account, mint, freeze_authority, _token_program] = accounts - else { - return Err(ProgramError::NotEnoughAccountKeys); - }; - - if data.is_empty() { - return Err(ProgramError::InvalidInstructionData); - } - - let bump = data[0]; - let signer_seeds = authority_seeds!(bump); - - ThawCpi { - token_account: token_account.clone(), - mint: mint.clone(), - freeze_authority: freeze_authority.clone(), - } - .invoke_signed(&[signer_seeds]) -} -``` - -```rust test.rs -mod shared; - -use light_client::rpc::Rpc; -use shared::{ - build_freeze_signed_cpi_ix, build_thaw_cpi_ix, build_thaw_signed_cpi_ix, - create_ata, create_test_rpc, get_authority_pda, setup_frozen, - setup_mint_with_tokens, SetupContext, -}; -use solana_sdk::signer::Signer; - -#[tokio::test(flavor = "multi_thread")] -async fn thaw_cpi() { - // Setup: create mint, ATA, and freeze account - let SetupContext { - mut rpc, - payer, - mint, - ata, - .. - } = setup_frozen().await; - - let ix = build_thaw_cpi_ix(ata, mint, payer.pubkey()); - - rpc.create_and_send_transaction(&[ix], &payer.pubkey(), &[&payer]) - .await - .unwrap(); -} - -#[tokio::test(flavor = "multi_thread")] -async fn thaw_signed_cpi() { - let mut rpc = create_test_rpc().await; - let payer = rpc.get_payer().insecure_clone(); - - let (pda_authority, bump) = get_authority_pda(); - - let (mint, _) = setup_mint_with_tokens( - &mut rpc, - &payer, - payer.pubkey(), - Some(pda_authority), - 9, - vec![], - ) - .await; - - let ata = create_ata(&mut rpc, &payer, payer.pubkey(), mint).await; - - // Freeze first using PDA authority - let freeze_ix = build_freeze_signed_cpi_ix(ata, mint, pda_authority, bump); - rpc.create_and_send_transaction(&[freeze_ix], &payer.pubkey(), &[&payer]) - .await - .unwrap(); - - // Then thaw using PDA authority - let thaw_ix = build_thaw_signed_cpi_ix(ata, mint, pda_authority, bump); - rpc.create_and_send_transaction(&[thaw_ix], &payer.pubkey(), &[&payer]) - .await - .unwrap(); -} -``` - diff --git a/snippets/code-snippets/light-token/transfer-checked/anchor-program/full-example.mdx b/snippets/code-snippets/light-token/transfer-checked/anchor-program/full-example.mdx deleted file mode 100644 index d933e078..00000000 --- a/snippets/code-snippets/light-token/transfer-checked/anchor-program/full-example.mdx +++ /dev/null @@ -1,106 +0,0 @@ - -```rust lib.rs -#![allow(unexpected_cfgs, deprecated)] - -use anchor_lang::prelude::*; -use light_token::instruction::TransferCheckedCpi; - -declare_id!("HXmfewpozFdxhM8BayL9v5541gwoGMXTrUoip5KySs2f"); - -#[program] -pub mod light_token_anchor_transfer_checked { - use super::*; - - pub fn transfer_checked( - ctx: Context, - amount: u64, - decimals: u8, - ) -> Result<()> { - TransferCheckedCpi { - source: ctx.accounts.source.to_account_info(), - mint: ctx.accounts.mint.to_account_info(), - destination: ctx.accounts.destination.to_account_info(), - amount, - decimals, - authority: ctx.accounts.authority.to_account_info(), - system_program: ctx.accounts.system_program.to_account_info(), - fee_payer: ctx.accounts.fee_payer.to_account_info(), - } - .invoke()?; - Ok(()) - } -} - -#[derive(Accounts)] -pub struct TransferCheckedAccounts<'info> { - /// CHECK: Light token program for CPI - pub light_token_program: AccountInfo<'info>, - /// CHECK: Validated by light-token CPI - #[account(mut)] - pub source: AccountInfo<'info>, - /// CHECK: Validated by light-token CPI - pub mint: AccountInfo<'info>, - /// CHECK: Validated by light-token CPI - #[account(mut)] - pub destination: AccountInfo<'info>, - pub authority: Signer<'info>, - #[account(mut)] - pub fee_payer: Signer<'info>, - pub system_program: Program<'info, System>, -} -``` - -```rust test.rs -use anchor_lang::{InstructionData, ToAccountMetas}; -use light_program_test::Rpc; -use light_token::instruction::LIGHT_TOKEN_PROGRAM_ID; -use light_token_anchor_transfer_checked::{accounts, instruction::TransferChecked, ID}; -use anchor_lang::system_program; -use solana_sdk::{instruction::Instruction, signature::Keypair, signer::Signer}; -use test_utils::{create_associated_token_account_for_owner, mint_tokens, setup_test_env}; - -#[tokio::test] -async fn test_transfer_checked() { - let mut env = setup_test_env("light_token_anchor_transfer_checked", ID).await; - mint_tokens(&mut env.rpc, &env.payer, env.mint_pda, env.associated_token_account, 1_000_000).await; - - // Create destination associated token account for recipient - let recipient = Keypair::new(); - let dest_associated_token_account = - create_associated_token_account_for_owner(&mut env.rpc, &env.payer, &recipient.pubkey(), &env.mint_pda).await; - - // TransferChecked validates decimals match the mint's decimals. - // Only use for Light->Light transfers. - // Use TransferInterface for all other transfers (Light, SPL or Token-2022). - let transfer_amount = 100_000u64; - let decimals = 9u8; - - let ix = Instruction { - program_id: ID, - accounts: accounts::TransferCheckedAccounts { - light_token_program: LIGHT_TOKEN_PROGRAM_ID, - source: env.associated_token_account, - mint: env.mint_pda, - destination: dest_associated_token_account, - authority: env.payer.pubkey(), - fee_payer: env.payer.pubkey(), - system_program: system_program::ID, - } - .to_account_metas(Some(true)), - data: TransferChecked { - amount: transfer_amount, - decimals, - } - .data(), - }; - - let sig = env - .rpc - .create_and_send_transaction(&[ix], &env.payer.pubkey(), &[&env.payer]) - .await - .unwrap(); - - println!("Tx: {}", sig); -} -``` - diff --git a/snippets/code-snippets/light-token/transfer-checked/native-program/full-example.mdx b/snippets/code-snippets/light-token/transfer-checked/native-program/full-example.mdx deleted file mode 100644 index 97f8e5d9..00000000 --- a/snippets/code-snippets/light-token/transfer-checked/native-program/full-example.mdx +++ /dev/null @@ -1,180 +0,0 @@ - -```rust instruction.rs -use super::authority_seeds; -use light_token::instruction::TransferCheckedCpi; -use solana_program::{ - account_info::AccountInfo, entrypoint::ProgramResult, - program_error::ProgramError, -}; - -pub fn transfer_checked_invoke( - accounts: &[AccountInfo], - data: &[u8], -) -> ProgramResult { - let [source, mint, destination, authority, system_program, _token_program] = - accounts - else { - return Err(ProgramError::NotEnoughAccountKeys); - }; - - if data.len() < 9 { - return Err(ProgramError::InvalidInstructionData); - } - - let amount = u64::from_le_bytes(data[0..8].try_into().unwrap()); - let decimals = data[8]; - - // TransferChecked validates decimals. Only for Light->Light. Use TransferInterface for SPL/Token 2022 - TransferCheckedCpi { - source: source.clone(), - mint: mint.clone(), - destination: destination.clone(), - amount, - decimals, - authority: authority.clone(), - system_program: system_program.clone(), - max_top_up: None, - fee_payer: None, - } - .invoke() -} - -pub fn transfer_checked_invoke_signed( - accounts: &[AccountInfo], - data: &[u8], -) -> ProgramResult { - let [source, mint, destination, authority, system_program, _token_program] = - accounts - else { - return Err(ProgramError::NotEnoughAccountKeys); - }; - - if data.len() < 10 { - return Err(ProgramError::InvalidInstructionData); - } - - let amount = u64::from_le_bytes(data[0..8].try_into().unwrap()); - let decimals = data[8]; - let bump = data[9]; - let signer_seeds = authority_seeds!(bump); - - TransferCheckedCpi { - source: source.clone(), - mint: mint.clone(), - destination: destination.clone(), - amount, - decimals, - authority: authority.clone(), - system_program: system_program.clone(), - max_top_up: None, - fee_payer: None, - } - .invoke_signed(&[signer_seeds]) -} -``` - -```rust test.rs -mod shared; - -use light_client::rpc::Rpc; -use shared::{ - build_transfer_checked_cpi_ix, build_transfer_checked_signed_cpi_ix, - create_ata, create_test_rpc, get_authority_pda, setup, setup_pda_owned_ata, - SetupContext, -}; -use solana_sdk::{signature::Keypair, signer::Signer}; - -#[tokio::test(flavor = "multi_thread")] -async fn transfer_checked_cpi() { - let SetupContext { - mut rpc, - payer, - mint, - ata, - .. - } = setup().await; - - let transfer_amount = 500_000u64; - - let recipient = Keypair::new(); - let recipient_ata = - create_ata(&mut rpc, &payer, recipient.pubkey(), mint).await; - - let ix = build_transfer_checked_cpi_ix( - ata, - mint, - recipient_ata, - payer.pubkey(), - transfer_amount, - 9, - ); - - rpc.create_and_send_transaction(&[ix], &payer.pubkey(), &[&payer]) - .await - .unwrap(); -} - -#[tokio::test(flavor = "multi_thread")] -async fn transfer_checked_signed_cpi() { - let mut rpc = create_test_rpc().await; - let payer = rpc.get_payer().insecure_clone(); - - let (pda_authority, bump) = get_authority_pda(); - let initial_amount = 1_000_000u64; - - let (mint, pda_ata) = - setup_pda_owned_ata(&mut rpc, &payer, pda_authority, initial_amount) - .await; - - let recipient = Keypair::new(); - let recipient_ata = - create_ata(&mut rpc, &payer, recipient.pubkey(), mint).await; - - let transfer_amount = 500_000u64; - let ix = build_transfer_checked_signed_cpi_ix( - pda_ata, - mint, - recipient_ata, - pda_authority, - transfer_amount, - 9, - bump, - ); - - rpc.create_and_send_transaction(&[ix], &payer.pubkey(), &[&payer]) - .await - .unwrap(); -} - -/// Tests transferring the exact balance from a token account. -#[tokio::test(flavor = "multi_thread")] -async fn transfer_checked_exact_balance_cpi() { - let SetupContext { - mut rpc, - payer, - mint, - ata, - .. - } = setup().await; - - let exact_balance = 1_000_000u64; - - let recipient = Keypair::new(); - let recipient_ata = - create_ata(&mut rpc, &payer, recipient.pubkey(), mint).await; - - let ix = build_transfer_checked_cpi_ix( - ata, - mint, - recipient_ata, - payer.pubkey(), - exact_balance, - 9, - ); - - rpc.create_and_send_transaction(&[ix], &payer.pubkey(), &[&payer]) - .await - .unwrap(); -} -``` - diff --git a/snippets/code-snippets/light-token/transfer-checked/rust-client/action.mdx b/snippets/code-snippets/light-token/transfer-checked/rust-client/action.mdx deleted file mode 100644 index 165e0989..00000000 --- a/snippets/code-snippets/light-token/transfer-checked/rust-client/action.mdx +++ /dev/null @@ -1,51 +0,0 @@ -```rust -use borsh::BorshDeserialize; -use light_client::rpc::Rpc; -use light_token_client::actions::{CreateAta, TransferChecked}; -use rust_client::{setup, SetupContext}; -use solana_sdk::{signature::Keypair, signer::Signer}; - -#[tokio::main] -async fn main() -> Result<(), Box> { - let SetupContext { - mut rpc, - payer, - mint, - associated_token_account, - decimals, - .. - } = setup().await; - - // Create recipient associated token account - let recipient = Keypair::new(); - let (_signature, recipient_associated_token_account) = CreateAta { - mint, - owner: recipient.pubkey(), - idempotent: true, - } - .execute(&mut rpc, &payer) - .await?; - - // TransferChecked validates decimals match the mint's decimals. - // Only use for Light->Light transfers. - // Use TransferInterface for all other transfers (Light, SPL or Token-2022). - let sig = TransferChecked { - source: associated_token_account, - mint, - destination: recipient_associated_token_account, - amount: 1000, - decimals, - } - .execute(&mut rpc, &payer, &payer) - .await?; - - let data = rpc - .get_account(recipient_associated_token_account) - .await? - .ok_or("Account not found")?; - let token = light_token_interface::state::Token::deserialize(&mut &data.data[..])?; - println!("Balance: {} Tx: {sig}", token.amount); - - Ok(()) -} -``` diff --git a/snippets/code-snippets/light-token/transfer-checked/rust-client/instruction.mdx b/snippets/code-snippets/light-token/transfer-checked/rust-client/instruction.mdx deleted file mode 100644 index 621f93de..00000000 --- a/snippets/code-snippets/light-token/transfer-checked/rust-client/instruction.mdx +++ /dev/null @@ -1,62 +0,0 @@ -```rust -use borsh::BorshDeserialize; -use light_client::rpc::Rpc; -use light_token::instruction::{ - get_associated_token_address, CreateAssociatedTokenAccount, TransferChecked, -}; -use rust_client::{setup, SetupContext}; -use solana_sdk::{signature::Keypair, signer::Signer}; - -#[tokio::main] -async fn main() -> Result<(), Box> { - // Setup creates mint and associated token account with tokens - let SetupContext { - mut rpc, - payer, - mint, - associated_token_account, - decimals, - .. - } = setup().await; - - let transfer_amount = 400_000u64; - - // Create recipient associated token account - let recipient = Keypair::new(); - let recipient_associated_token_account = get_associated_token_address(&recipient.pubkey(), &mint); - - let create_associated_token_account_instruction = CreateAssociatedTokenAccount::new(payer.pubkey(), recipient.pubkey(), mint) - .instruction()?; - - rpc.create_and_send_transaction(&[create_associated_token_account_instruction], &payer.pubkey(), &[&payer]) - .await?; - - // TransferChecked validates decimals match the mint's decimals - // Only use for Light->Light transfers. - // Use TransferInterface for all other transfers (Light, SPL or Token-2022). - let transfer_instruction = TransferChecked { - source: associated_token_account, - mint, - destination: recipient_associated_token_account, - amount: transfer_amount, - decimals, - authority: payer.pubkey(), - max_top_up: None, - fee_payer: None, - } - .instruction()?; - - let sig = rpc - .create_and_send_transaction(&[transfer_instruction], &payer.pubkey(), &[&payer]) - .await?; - - let data = rpc - .get_account(recipient_associated_token_account) - .await? - .ok_or("Account not found")?; - let token = light_token_interface::state::Token::deserialize(&mut &data.data[..])?; - println!("Balance: {} Tx: {sig}", token.amount); - - Ok(()) -} -``` diff --git a/snippets/code-snippets/light-token/transfer-interface/action.mdx b/snippets/code-snippets/light-token/transfer-interface/action.mdx deleted file mode 100644 index 4b9af681..00000000 --- a/snippets/code-snippets/light-token/transfer-interface/action.mdx +++ /dev/null @@ -1,54 +0,0 @@ -```typescript -import "dotenv/config"; -import { Keypair } from "@solana/web3.js"; -import { createRpc } from "@lightprotocol/stateless.js"; -import { - createMintInterface, - createAtaInterface, - mintToInterface, - transferInterface, - getAssociatedTokenAddressInterface, -} from "@lightprotocol/compressed-token"; -import { homedir } from "os"; -import { readFileSync } from "fs"; - -// devnet: -// const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; -// const rpc = createRpc(RPC_URL); -// localnet: -const rpc = createRpc(); - -const payer = Keypair.fromSecretKey( - new Uint8Array( - JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) - ) -); - -(async function () { - const { mint } = await createMintInterface(rpc, payer, payer, null, 9); - - const sender = Keypair.generate(); - await createAtaInterface(rpc, payer, mint, sender.publicKey); - const senderAta = getAssociatedTokenAddressInterface( - mint, - sender.publicKey - ); - await mintToInterface(rpc, payer, mint, senderAta, payer, 1_000_000_000); - - const recipient = Keypair.generate(); - - // Recipient wallet; transferInterface creates recipient ATA idempotently - const tx = await transferInterface( - rpc, - payer, - senderAta, - mint, - recipient.publicKey, - sender.publicKey, - sender, - 500_000_000 - ); - - console.log("Tx:", tx); -})(); -``` diff --git a/snippets/code-snippets/light-token/transfer-interface/anchor-program/create-and-transfer-example.mdx b/snippets/code-snippets/light-token/transfer-interface/anchor-program/create-and-transfer-example.mdx deleted file mode 100644 index 868d48b6..00000000 --- a/snippets/code-snippets/light-token/transfer-interface/anchor-program/create-and-transfer-example.mdx +++ /dev/null @@ -1,249 +0,0 @@ - -```rust lib.rs -#![allow(unexpected_cfgs, deprecated)] - -use anchor_lang::prelude::*; -use light_sdk::interface::CreateAccountsProof; -use light_token::anchor::{derive_light_cpi_signer, light_program, CpiSigner, LightAccounts}; -use light_token::instruction::TransferInterfaceCpi; - -declare_id!("672fL1Nm191MbPoygNM9DRiG2psBELn97XUpGbU3jW7E"); - -pub const LIGHT_CPI_SIGNER: CpiSigner = - derive_light_cpi_signer!("672fL1Nm191MbPoygNM9DRiG2psBELn97XUpGbU3jW7E"); - -#[derive(AnchorSerialize, AnchorDeserialize, Clone)] -pub struct TransferParams { - pub create_accounts_proof: CreateAccountsProof, - pub dest_associated_token_account_bump: u8, - pub amount: u64, - pub decimals: u8, -} - -#[light_program] -#[program] -pub mod create_and_transfer { - use super::*; - - pub fn transfer<'info>( - ctx: Context<'_, '_, '_, 'info, Transfer<'info>>, - params: TransferParams, - ) -> Result<()> { - TransferInterfaceCpi::new( - params.amount, - params.decimals, - ctx.accounts.source.to_account_info(), - ctx.accounts.destination.to_account_info(), - ctx.accounts.authority.to_account_info(), - ctx.accounts.payer.to_account_info(), - ctx.accounts.light_token_cpi_authority.to_account_info(), - ctx.accounts.system_program.to_account_info(), - ) - .invoke() - .map_err(|e| anchor_lang::prelude::ProgramError::from(e))?; - Ok(()) - } -} - -#[derive(Accounts, LightAccounts)] -#[instruction(params: TransferParams)] -pub struct Transfer<'info> { - #[account(mut)] - pub payer: Signer<'info>, - - pub authority: Signer<'info>, - - /// CHECK: Validated by light-token CPI - pub mint: AccountInfo<'info>, - - /// CHECK: Validated by light-token CPI - #[account(mut)] - pub source: AccountInfo<'info>, - - /// CHECK: Validated by light-token CPI - pub recipient: AccountInfo<'info>, - - /// CHECK: Validated by light-token CPI - #[account(mut)] - #[light_account(init, - associated_token::authority = recipient, - associated_token::mint = mint, - associated_token::bump = params.dest_associated_token_account_bump - )] - pub destination: UncheckedAccount<'info>, - - /// CHECK: Validated by light-token CPI - pub light_token_program: AccountInfo<'info>, - - pub system_program: Program<'info, System>, - - /// CHECK: Validated by light-token CPI - pub light_token_compressible_config: AccountInfo<'info>, - - /// CHECK: Validated by light-token CPI - #[account(mut)] - pub rent_sponsor: AccountInfo<'info>, - - /// CHECK: Validated by light-token CPI - pub light_token_cpi_authority: AccountInfo<'info>, -} -``` - -```rust test.rs -use anchor_lang::{InstructionData, ToAccountMetas}; -use light_client::interface::{get_create_accounts_proof, InitializeRentFreeConfig}; -use light_program_test::{ - program_test::{setup_mock_program_data, LightProgramTest}, - Indexer, ProgramTestConfig, Rpc, -}; -use light_sdk_types::LIGHT_TOKEN_PROGRAM_ID; -use light_token::instruction::{ - derive_token_ata, find_mint_address, COMPRESSIBLE_CONFIG_V1, RENT_SPONSOR, -}; -use solana_instruction::Instruction; -use solana_keypair::Keypair; -use solana_signer::Signer; -use create_and_transfer::{TransferParams, ID}; - -#[tokio::test] -async fn test_transfer() { - let config = ProgramTestConfig::new_v2(true, Some(vec![("create_and_transfer", ID)])) - .with_light_protocol_events(); - - let mut rpc = LightProgramTest::new(config).await.unwrap(); - let payer = rpc.get_payer().insecure_clone(); - - let program_data_pda = setup_mock_program_data(&mut rpc, &payer, &ID); - - let (init_config_ix, _config_pda) = InitializeRentFreeConfig::new( - &ID, - &payer.pubkey(), - &program_data_pda, - RENT_SPONSOR, - payer.pubkey(), - ) - .build(); - - rpc.create_and_send_transaction(&[init_config_ix], &payer.pubkey(), &[&payer]) - .await - .unwrap(); - - let (mint_pda, _mint_seed) = setup_create_mint( - &mut rpc, - &payer, - payer.pubkey(), // mint_authority - 9, // decimals - ) - .await; - - println!("Mint created at: {}", mint_pda); - - let sender = Keypair::new(); - let (sender_associated_token_account, _sender_associated_token_account_bump) = - derive_token_ata(&sender.pubkey(), &mint_pda); - - let create_sender_associated_token_account_ix = - light_token::instruction::CreateAssociatedTokenAccount::new( - payer.pubkey(), - sender.pubkey(), - mint_pda, - ) - .instruction() - .unwrap(); - - rpc.create_and_send_transaction( - &[create_sender_associated_token_account_ix], - &payer.pubkey(), - &[&payer], - ) - .await - .unwrap(); - - let mint_amount: u64 = 1_000_000_000; - mint_tokens(&mut rpc, &payer, mint_pda, sender_associated_token_account, mint_amount).await; - - println!( - "Minted {} tokens to sender: {}", - mint_amount, sender_associated_token_account - ); - - let recipient = Keypair::new(); - let (recipient_associated_token_account, recipient_associated_token_account_bump) = - derive_token_ata(&recipient.pubkey(), &mint_pda); - - let transfer_proof_result = get_create_accounts_proof(&rpc, &ID, vec![]).await.unwrap(); - - let transfer_accounts = create_and_transfer::accounts::Transfer { - payer: payer.pubkey(), - authority: sender.pubkey(), - mint: mint_pda, - source: sender_associated_token_account, - recipient: recipient.pubkey(), - destination: recipient_associated_token_account, - light_token_program: LIGHT_TOKEN_PROGRAM_ID.into(), - system_program: solana_sdk::system_program::ID, - light_token_compressible_config: COMPRESSIBLE_CONFIG_V1, - rent_sponsor: RENT_SPONSOR, - light_token_cpi_authority: light_token_types::CPI_AUTHORITY_PDA.into(), - }; - - let transfer_amount: u64 = 500_000_000; // 0.5 tokens - let decimals: u8 = 9; - - let transfer_ix = Instruction { - program_id: ID, - accounts: [ - transfer_accounts.to_account_metas(None), - transfer_proof_result.remaining_accounts, - ] - .concat(), - data: create_and_transfer::instruction::Transfer { - params: TransferParams { - create_accounts_proof: transfer_proof_result.create_accounts_proof, - dest_associated_token_account_bump: recipient_associated_token_account_bump, - amount: transfer_amount, - decimals, - }, - } - .data(), - }; - - let sig = rpc - .create_and_send_transaction(&[transfer_ix], &payer.pubkey(), &[&payer, &sender]) - .await - .unwrap(); - - println!("Transfer Tx: {}", sig); - - use light_token_interface::state::Token; - - let recipient_account = rpc - .get_account(recipient_associated_token_account) - .await - .unwrap() - .unwrap(); - let recipient_token: Token = - borsh::BorshDeserialize::deserialize(&mut &recipient_account.data[..]).unwrap(); - - assert_eq!(recipient_token.amount, transfer_amount); - assert_eq!(recipient_token.owner, recipient.pubkey().to_bytes()); - - println!( - "Recipient balance: {}, owner: {}", - recipient_token.amount, - recipient.pubkey() - ); - - let sender_account = rpc - .get_account(sender_associated_token_account) - .await - .unwrap() - .unwrap(); - let sender_token: Token = - borsh::BorshDeserialize::deserialize(&mut &sender_account.data[..]).unwrap(); - - assert_eq!(sender_token.amount, mint_amount - transfer_amount); - println!("Sender remaining balance: {}", sender_token.amount); -} -``` - \ No newline at end of file diff --git a/snippets/code-snippets/light-token/transfer-interface/anchor-program/full-example.mdx b/snippets/code-snippets/light-token/transfer-interface/anchor-program/full-example.mdx deleted file mode 100644 index a315ed2e..00000000 --- a/snippets/code-snippets/light-token/transfer-interface/anchor-program/full-example.mdx +++ /dev/null @@ -1,297 +0,0 @@ - -```rust lib.rs -#![allow(unexpected_cfgs, deprecated)] - -use anchor_lang::prelude::*; -use light_token::instruction::TransferInterfaceCpi; - -declare_id!("3rb6sG4jiYNLZC8jo8kLsFHpxr2Ci8e8Hh8UmeCMZmUV"); - -#[program] -pub mod light_token_anchor_transfer_interface { - use super::*; - - pub fn transfer( - ctx: Context, - amount: u64, - decimals: u8, - spl_interface_pda_bump: Option, - ) -> Result<()> { - let mut transfer = TransferInterfaceCpi::new( - amount, - decimals, - ctx.accounts.source.to_account_info(), - ctx.accounts.destination.to_account_info(), - ctx.accounts.authority.to_account_info(), - ctx.accounts.payer.to_account_info(), - ctx.accounts.cpi_authority.to_account_info(), - ctx.accounts.mint.to_account_info(), - ctx.accounts.system_program.to_account_info(), - ); - - if let Some(bump) = spl_interface_pda_bump { - transfer = transfer - .with_spl_interface( - Some(ctx.accounts.mint.to_account_info()), - ctx.accounts - .spl_token_program - .as_ref() - .map(|a| a.to_account_info()), - ctx.accounts - .spl_interface_pda - .as_ref() - .map(|a| a.to_account_info()), - Some(bump), - ) - ?; - } - - transfer.invoke()?; - Ok(()) - } -} - -#[derive(Accounts)] -pub struct TransferAccounts<'info> { - /// CHECK: Light token program for CPI - pub light_token_program: AccountInfo<'info>, - /// CHECK: Validated by light-token CPI - #[account(mut)] - pub source: AccountInfo<'info>, - /// CHECK: Validated by light-token CPI - #[account(mut)] - pub destination: AccountInfo<'info>, - pub authority: Signer<'info>, - #[account(mut)] - pub payer: Signer<'info>, - /// CHECK: Validated by light-token CPI - pub cpi_authority: AccountInfo<'info>, - pub system_program: Program<'info, System>, - - /// CHECK: Validated by light-token CPI - token mint - pub mint: AccountInfo<'info>, - // SPL interface accounts (optional, for cross-type transfers) - /// CHECK: SPL Token or Token-2022 program - pub spl_token_program: Option>, - /// CHECK: Validated by light-token CPI - pool PDA - #[account(mut)] - pub spl_interface_pda: Option>, -} -``` - -```rust test.rs -use anchor_lang::system_program; -use anchor_lang::{InstructionData, ToAccountMetas}; -use anchor_spl::token::{spl_token, Mint}; -use light_program_test::Rpc; -use solana_sdk::program_pack::Pack as _; -use light_token::instruction::{ - derive_token_ata, CreateAssociatedTokenAccount, LIGHT_TOKEN_PROGRAM_ID, -}; -use light_token::spl_interface::{find_spl_interface_pda_with_index, CreateSplInterfacePda}; -use light_token_anchor_transfer_interface::{accounts, instruction::Transfer, ID}; -use light_token_types::CPI_AUTHORITY_PDA; -use solana_sdk::{ - instruction::Instruction, - pubkey::Pubkey, - signature::Keypair, - signer::Signer, -}; -use test_utils::{create_associated_token_account_for_owner, mint_tokens, setup_test_env}; - -#[tokio::test] -async fn test_transfer() { - let mut env = setup_test_env("light_token_anchor_transfer_interface", ID).await; - mint_tokens(&mut env.rpc, &env.payer, env.mint_pda, env.associated_token_account, 1_000_000).await; - - // Create destination associated token account for recipient - let recipient = Keypair::new(); - let dest_associated_token_account = - create_associated_token_account_for_owner(&mut env.rpc, &env.payer, &recipient.pubkey(), &env.mint_pda).await; - - // Transfers tokens between accounts (SPL, Token-2022, or Light) in a single call. - let transfer_amount = 100_000u64; - let decimals = 9u8; - let cpi_authority_pda = Pubkey::new_from_array(CPI_AUTHORITY_PDA); - - let ix = Instruction { - program_id: ID, - accounts: accounts::TransferAccounts { - light_token_program: LIGHT_TOKEN_PROGRAM_ID, - source: env.associated_token_account, - destination: dest_associated_token_account, - authority: env.payer.pubkey(), - payer: env.payer.pubkey(), - cpi_authority: cpi_authority_pda, - system_program: system_program::ID, - mint: env.mint_pda, - spl_token_program: None, - spl_interface_pda: None, - } - .to_account_metas(Some(true)), - data: Transfer { - amount: transfer_amount, - decimals, - spl_interface_pda_bump: None, - } - .data(), - }; - - let sig = env - .rpc - .create_and_send_transaction(&[ix], &env.payer.pubkey(), &[&env.payer]) - .await - .unwrap(); - - println!("Tx: {}", sig); -} - -#[tokio::test] -async fn test_transfer_spl_to_light() { - let mut env = setup_test_env("light_token_anchor_transfer_interface", ID).await; - - let payer = env.payer.insecure_clone(); - let cpi_authority_pda = Pubkey::new_from_array(CPI_AUTHORITY_PDA); - - // 1. Create SPL mint - let mint_keypair = Keypair::new(); - let mint = mint_keypair.pubkey(); - let decimals = 9u8; - - let mint_rent = env - .rpc - .get_minimum_balance_for_rent_exemption(Mint::LEN) - .await - .unwrap(); - - let create_mint_account_ix = solana_sdk::system_instruction::create_account( - &payer.pubkey(), - &mint, - mint_rent, - Mint::LEN as u64, - &spl_token::ID, - ); - - let initialize_mint_ix = spl_token::instruction::initialize_mint( - &spl_token::ID, - &mint, - &payer.pubkey(), - None, - decimals, - ) - .unwrap(); - - env.rpc - .create_and_send_transaction( - &[create_mint_account_ix, initialize_mint_ix], - &payer.pubkey(), - &[&payer, &mint_keypair], - ) - .await - .unwrap(); - - // 2. Create SPL token pool (spl_interface_pda) - let create_pool_ix = - CreateSplInterfacePda::new(payer.pubkey(), mint, spl_token::ID, false).instruction(); - - env.rpc - .create_and_send_transaction(&[create_pool_ix], &payer.pubkey(), &[&payer]) - .await - .unwrap(); - - // 3. Create SPL token account and mint tokens - let spl_account_keypair = Keypair::new(); - let spl_account = spl_account_keypair.pubkey(); - - let spl_account_rent = env - .rpc - .get_minimum_balance_for_rent_exemption(spl_token::state::Account::LEN) - .await - .unwrap(); - - let create_spl_account_ix = solana_sdk::system_instruction::create_account( - &payer.pubkey(), - &spl_account, - spl_account_rent, - spl_token::state::Account::LEN as u64, - &spl_token::ID, - ); - - let init_spl_account_ix = spl_token::instruction::initialize_account( - &spl_token::ID, - &spl_account, - &mint, - &payer.pubkey(), - ) - .unwrap(); - - let mint_amount = 1_000_000u64; - let mint_to_ix = spl_token::instruction::mint_to( - &spl_token::ID, - &mint, - &spl_account, - &payer.pubkey(), - &[], - mint_amount, - ) - .unwrap(); - - env.rpc - .create_and_send_transaction( - &[create_spl_account_ix, init_spl_account_ix, mint_to_ix], - &payer.pubkey(), - &[&payer, &spl_account_keypair], - ) - .await - .unwrap(); - - // 4. Create Light ATA for destination - let recipient = Keypair::new(); - let dest_ata = derive_token_ata(&recipient.pubkey(), &mint); - let create_ata_ix = CreateAssociatedTokenAccount::new(payer.pubkey(), recipient.pubkey(), mint) - .instruction() - .unwrap(); - - env.rpc - .create_and_send_transaction(&[create_ata_ix], &payer.pubkey(), &[&payer]) - .await - .unwrap(); - - // 5. Transfer SPL tokens to Light ATA via transfer-interface - let transfer_amount = 100_000u64; - let (spl_interface_pda, spl_interface_pda_bump) = - find_spl_interface_pda_with_index(&mint, 0, false); - - let ix = Instruction { - program_id: ID, - accounts: accounts::TransferAccounts { - light_token_program: LIGHT_TOKEN_PROGRAM_ID, - source: spl_account, - destination: dest_ata, - authority: payer.pubkey(), - payer: payer.pubkey(), - cpi_authority: cpi_authority_pda, - system_program: system_program::ID, - mint: mint, - spl_token_program: Some(spl_token::ID), - spl_interface_pda: Some(spl_interface_pda), - } - .to_account_metas(Some(true)), - data: Transfer { - amount: transfer_amount, - decimals, - spl_interface_pda_bump: Some(spl_interface_pda_bump), - } - .data(), - }; - - let sig = env - .rpc - .create_and_send_transaction(&[ix], &payer.pubkey(), &[&payer]) - .await - .unwrap(); - - println!("Tx: {}", sig); -} -``` - diff --git a/snippets/code-snippets/light-token/transfer-interface/instruction.mdx b/snippets/code-snippets/light-token/transfer-interface/instruction.mdx deleted file mode 100644 index 5e94b693..00000000 --- a/snippets/code-snippets/light-token/transfer-interface/instruction.mdx +++ /dev/null @@ -1,64 +0,0 @@ -```typescript -import "dotenv/config"; -import { - Keypair, - Transaction, - sendAndConfirmTransaction, -} from "@solana/web3.js"; -import { createRpc } from "@lightprotocol/stateless.js"; -import { - createMintInterface, - createAtaInterface, - mintToInterface, - createLightTokenTransferInstruction, - getAssociatedTokenAddressInterface, -} from "@lightprotocol/compressed-token"; -import { homedir } from "os"; -import { readFileSync } from "fs"; - -// devnet: -// const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; -// const rpc = createRpc(RPC_URL); -// localnet: -const rpc = createRpc(); - -const payer = Keypair.fromSecretKey( - new Uint8Array( - JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) - ) -); - -(async function () { - const { mint } = await createMintInterface(rpc, payer, payer, null, 9); - - const sender = Keypair.generate(); - await createAtaInterface(rpc, payer, mint, sender.publicKey); - const senderAta = getAssociatedTokenAddressInterface( - mint, - sender.publicKey - ); - await mintToInterface(rpc, payer, mint, senderAta, payer, 1_000_000_000); - - const recipient = Keypair.generate(); - await createAtaInterface(rpc, payer, mint, recipient.publicKey); - const recipientAta = getAssociatedTokenAddressInterface( - mint, - recipient.publicKey - ); - - // Transfer tokens. Optional feePayer lets an application cover top-ups - // so the sender only signs to authorize the transfer. - const ix = createLightTokenTransferInstruction( - senderAta, - recipientAta, - sender.publicKey, // owner (signs the transfer) - 500_000_000, - payer.publicKey // optional: separate feePayer covers top-up - ); - - const tx = new Transaction().add(ix); - const signature = await sendAndConfirmTransaction(rpc, tx, [payer, sender]); - - console.log("Tx:", signature); -})(); -``` diff --git a/snippets/code-snippets/light-token/transfer-interface/native-program/full-example.mdx b/snippets/code-snippets/light-token/transfer-interface/native-program/full-example.mdx deleted file mode 100644 index 53d51fa8..00000000 --- a/snippets/code-snippets/light-token/transfer-interface/native-program/full-example.mdx +++ /dev/null @@ -1,185 +0,0 @@ - -```rust instruction.rs -use super::authority_seeds; -use light_token::instruction::TransferInterfaceCpi; -use solana_program::{ - account_info::AccountInfo, entrypoint::ProgramResult, - program_error::ProgramError, -}; - -pub fn transfer_invoke(accounts: &[AccountInfo], data: &[u8]) -> ProgramResult { - let [source, destination, authority, payer, light_token_authority, system_program, _token_program] = - accounts - else { - return Err(ProgramError::NotEnoughAccountKeys); - }; - - if data.len() < 9 { - return Err(ProgramError::InvalidInstructionData); - } - - let amount = u64::from_le_bytes(data[0..8].try_into().unwrap()); - let decimals = data[8]; - - // Transfer tokens between accounts (SPL, Token-2022, or Light) - TransferInterfaceCpi::new( - amount, - decimals, - source.clone(), - destination.clone(), - authority.clone(), - payer.clone(), - light_token_authority.clone(), - system_program.clone(), - ) - .invoke() -} - -pub fn transfer_invoke_signed( - accounts: &[AccountInfo], - data: &[u8], -) -> ProgramResult { - let [source, destination, authority, payer, light_token_authority, system_program, _token_program] = - accounts - else { - return Err(ProgramError::NotEnoughAccountKeys); - }; - - if data.len() < 10 { - return Err(ProgramError::InvalidInstructionData); - } - - let amount = u64::from_le_bytes(data[0..8].try_into().unwrap()); - let decimals = data[8]; - let bump = data[9]; - let signer_seeds = authority_seeds!(bump); - - TransferInterfaceCpi::new( - amount, - decimals, - source.clone(), - destination.clone(), - authority.clone(), - payer.clone(), - light_token_authority.clone(), - system_program.clone(), - ) - .invoke_signed(&[signer_seeds]) -} -``` - -```rust test.rs -mod shared; - -use light_client::rpc::Rpc; -use light_token::instruction::cpi_authority; -use shared::{ - build_transfer_interface_cpi_ix, build_transfer_interface_signed_cpi_ix, - create_ata, create_test_rpc, get_authority_pda, setup, setup_pda_owned_ata, - SetupContext, -}; -use solana_sdk::{signature::Keypair, signer::Signer}; - -#[tokio::test(flavor = "multi_thread")] -async fn transfer_interface_cpi() { - let SetupContext { - mut rpc, - payer, - mint, - ata, - .. - } = setup().await; - - let transfer_amount = 500_000u64; - - // Setup: create mint and token accounts - let recipient = Keypair::new(); - let recipient_ata = - create_ata(&mut rpc, &payer, recipient.pubkey(), mint).await; - - // 1. Transfer from source to destination - let ix = build_transfer_interface_cpi_ix( - ata, - recipient_ata, - payer.pubkey(), - payer.pubkey(), - cpi_authority(), - transfer_amount, - 9, - ); - - rpc.create_and_send_transaction(&[ix], &payer.pubkey(), &[&payer]) - .await - .unwrap(); -} - -#[tokio::test(flavor = "multi_thread")] -async fn transfer_interface_signed_cpi() { - let mut rpc = create_test_rpc().await; - let payer = rpc.get_payer().insecure_clone(); - - let (pda_authority, bump) = get_authority_pda(); - let initial_amount = 1_000_000u64; - - // Setup: create mint and token accounts - let (mint, pda_ata) = - setup_pda_owned_ata(&mut rpc, &payer, pda_authority, initial_amount) - .await; - - let recipient = Keypair::new(); - let recipient_ata = - create_ata(&mut rpc, &payer, recipient.pubkey(), mint).await; - - let transfer_amount = 500_000u64; - // 1. Transfer from source to destination - let ix = build_transfer_interface_signed_cpi_ix( - pda_ata, - recipient_ata, - pda_authority, - payer.pubkey(), - cpi_authority(), - transfer_amount, - 9, - bump, - ); - - rpc.create_and_send_transaction(&[ix], &payer.pubkey(), &[&payer]) - .await - .unwrap(); -} - -/// Transfers exact balance from token account. -#[tokio::test(flavor = "multi_thread")] -async fn transfer_exact_balance_cpi() { - let SetupContext { - mut rpc, - payer, - mint, - ata, - .. - } = setup().await; - - // The setup() function creates an ATA with 1_000_000 tokens - let exact_balance = 1_000_000u64; - - let recipient = Keypair::new(); - let recipient_ata = - create_ata(&mut rpc, &payer, recipient.pubkey(), mint).await; - - // Transfer the exact balance, leaving source with 0 - let ix = build_transfer_interface_cpi_ix( - ata, - recipient_ata, - payer.pubkey(), - payer.pubkey(), - cpi_authority(), - exact_balance, - 9, - ); - - rpc.create_and_send_transaction(&[ix], &payer.pubkey(), &[&payer]) - .await - .unwrap(); -} -``` - diff --git a/snippets/code-snippets/light-token/transfer-interface/rust-client/action.mdx b/snippets/code-snippets/light-token/transfer-interface/rust-client/action.mdx deleted file mode 100644 index 61f2c9c5..00000000 --- a/snippets/code-snippets/light-token/transfer-interface/rust-client/action.mdx +++ /dev/null @@ -1,50 +0,0 @@ -```rust -use borsh::BorshDeserialize; -use light_client::rpc::Rpc; -use light_token_client::actions::{CreateAta, TransferInterface}; -use rust_client::{setup, SetupContext}; -use solana_sdk::{signature::Keypair, signer::Signer}; - -#[tokio::main] -async fn main() -> Result<(), Box> { - let SetupContext { - mut rpc, - payer, - mint, - associated_token_account, - decimals, - .. - } = setup().await; - - // Create recipient associated token account - let recipient = Keypair::new(); - let (_signature, recipient_associated_token_account) = CreateAta { - mint, - owner: recipient.pubkey(), - idempotent: true, - } - .execute(&mut rpc, &payer) - .await?; - - // Transfers tokens between token accounts (SPL, Token-2022, or Light) in a single call. - let sig = TransferInterface { - source: associated_token_account, - mint, - destination: recipient_associated_token_account, - amount: 1000, - decimals, - ..Default::default() - } - .execute(&mut rpc, &payer, &payer) - .await?; - - let data = rpc - .get_account(recipient_associated_token_account) - .await? - .ok_or("Account not found")?; - let token = light_token_interface::state::Token::deserialize(&mut &data.data[..])?; - println!("Balance: {} Tx: {sig}", token.amount); - - Ok(()) -} -``` diff --git a/snippets/code-snippets/light-token/transfer-interface/rust-client/instruction.mdx b/snippets/code-snippets/light-token/transfer-interface/rust-client/instruction.mdx deleted file mode 100644 index afce1ac0..00000000 --- a/snippets/code-snippets/light-token/transfer-interface/rust-client/instruction.mdx +++ /dev/null @@ -1,74 +0,0 @@ -```rust -use anchor_spl::token::spl_token; -use borsh::BorshDeserialize; -use light_client::rpc::Rpc; -use light_program_test::{LightProgramTest, ProgramTestConfig}; -use light_token::{ - instruction::{ - get_associated_token_address, CreateAssociatedTokenAccount, SplInterface, - TransferInterface, LIGHT_TOKEN_PROGRAM_ID, - }, - spl_interface::find_spl_interface_pda_with_index, -}; -use rust_client::{setup_spl_associated_token_account, setup_spl_mint}; -use solana_sdk::signer::Signer; - -#[tokio::main] -async fn main() -> Result<(), Box> { - let mut rpc = LightProgramTest::new(ProgramTestConfig::new(true, None)).await?; - - let payer = rpc.get_payer().insecure_clone(); - let decimals = 2u8; - let amount = 10_000u64; - - // Setup creates mint, mints tokens and creates SPL associated token account - let mint = setup_spl_mint(&mut rpc, &payer, decimals).await; - let spl_associated_token_account = setup_spl_associated_token_account(&mut rpc, &payer, &mint, &payer.pubkey(), amount).await; - let (interface_pda, interface_bump) = find_spl_interface_pda_with_index(&mint, 0, false); - - // Create Light associated token account - let light_associated_token_account = get_associated_token_address(&payer.pubkey(), &mint); - - let create_associated_token_account_instruction = - CreateAssociatedTokenAccount::new(payer.pubkey(), payer.pubkey(), mint).instruction()?; - - rpc.create_and_send_transaction(&[create_associated_token_account_instruction], &payer.pubkey(), &[&payer]) - .await?; - - // SPL interface PDA for Mint (holds SPL tokens when transferred to Light Token) - let spl_interface = SplInterface { - mint, - spl_token_program: spl_token::ID, - spl_interface_pda: interface_pda, - spl_interface_pda_bump: interface_bump, - }; - - // Transfers tokens between token accounts (SPL, Token-2022, or Light) in a single call. - let transfer_instruction = TransferInterface { - source: spl_associated_token_account, - destination: light_associated_token_account, - amount, - decimals, - authority: payer.pubkey(), - payer: payer.pubkey(), - mint, - spl_interface: Some(spl_interface), - source_owner: spl_token::ID, - destination_owner: LIGHT_TOKEN_PROGRAM_ID, - } - .instruction()?; - - let sig = rpc - .create_and_send_transaction(&[transfer_instruction], &payer.pubkey(), &[&payer]) - .await?; - - let data = rpc - .get_account(light_associated_token_account) - .await? - .ok_or("Account not found")?; - let token = light_token_interface::state::Token::deserialize(&mut &data.data[..])?; - println!("Balance: {} Tx: {sig}", token.amount); - - Ok(()) -} -``` diff --git a/snippets/code-snippets/light-token/transfer-interface/token-interface-instruction.mdx b/snippets/code-snippets/light-token/transfer-interface/token-interface-instruction.mdx deleted file mode 100644 index aac4622e..00000000 --- a/snippets/code-snippets/light-token/transfer-interface/token-interface-instruction.mdx +++ /dev/null @@ -1,30 +0,0 @@ -```typescript -import { Keypair, Transaction, sendAndConfirmTransaction } from "@solana/web3.js"; -import { createRpc } from "@lightprotocol/stateless.js"; -import { createTransferInstructions } from "@lightprotocol/token-interface"; - -const rpc = createRpc(); -const payer = Keypair.fromSecretKey(/* ... */); - -const mint = /* existing mint public key */; -const sourceOwner = Keypair.generate(); -const authority = sourceOwner; // delegate Keypair for delegated transfer -const recipient = Keypair.generate(); - -const transferIxs = await createTransferInstructions({ - rpc, - payer: payer.publicKey, - mint, - sourceOwner: sourceOwner.publicKey, - authority: authority.publicKey, - recipient: recipient.publicKey, - amount: 500_000_000n, -}); - -const signature = await sendAndConfirmTransaction( - rpc, - new Transaction().add(...transferIxs), - [payer, authority] -); -console.log("Tx:", signature); -``` diff --git a/snippets/code-snippets/light-token/unwrap/action.mdx b/snippets/code-snippets/light-token/unwrap/action.mdx deleted file mode 100644 index 1245adb3..00000000 --- a/snippets/code-snippets/light-token/unwrap/action.mdx +++ /dev/null @@ -1,65 +0,0 @@ -```typescript -import "dotenv/config"; -import { Keypair } from "@solana/web3.js"; -import { createRpc } from "@lightprotocol/stateless.js"; -import { - createMintInterface, - createAtaInterface, - getAssociatedTokenAddressInterface, -} from "@lightprotocol/compressed-token"; -import { wrap, unwrap } from "@lightprotocol/compressed-token/unified"; -import { - TOKEN_PROGRAM_ID, - createAssociatedTokenAccount, - mintTo, -} from "@solana/spl-token"; -import { homedir } from "os"; -import { readFileSync } from "fs"; - -// devnet: -// const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; -// const rpc = createRpc(RPC_URL); -// localnet: -const rpc = createRpc(); - -const payer = Keypair.fromSecretKey( - new Uint8Array( - JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) - ) -); - -(async function () { - // Setup: Create SPL mint, fund SPL ATA, wrap into Light ATA - const { mint } = await createMintInterface( - rpc, - payer, - payer, - null, - 9, - undefined, - undefined, - TOKEN_PROGRAM_ID - ); - const splAta = await createAssociatedTokenAccount( - rpc, - payer, - mint, - payer.publicKey, - undefined, - TOKEN_PROGRAM_ID - ); - await mintTo(rpc, payer, mint, splAta, payer, 1000); - - await createAtaInterface(rpc, payer, mint, payer.publicKey); - const lightTokenAta = getAssociatedTokenAddressInterface( - mint, - payer.publicKey - ); - await wrap(rpc, payer, splAta, lightTokenAta, payer, mint, BigInt(1000)); - - // Unwrap: move tokens back from light-token to SPL ATA - const tx = await unwrap(rpc, payer, splAta, payer, mint, 500); - - console.log("Tx:", tx); -})(); -``` diff --git a/snippets/code-snippets/light-token/unwrap/instruction.mdx b/snippets/code-snippets/light-token/unwrap/instruction.mdx deleted file mode 100644 index c5c68c2f..00000000 --- a/snippets/code-snippets/light-token/unwrap/instruction.mdx +++ /dev/null @@ -1,83 +0,0 @@ -```typescript -import "dotenv/config"; -import { - Keypair, - Transaction, - sendAndConfirmTransaction, -} from "@solana/web3.js"; -import { createRpc } from "@lightprotocol/stateless.js"; -import { - createMintInterface, - createAtaInterface, - getAssociatedTokenAddressInterface, -} from "@lightprotocol/compressed-token"; -import { - wrap, - createUnwrapInstructions, -} from "@lightprotocol/compressed-token/unified"; -import { - TOKEN_PROGRAM_ID, - createAssociatedTokenAccount, - mintTo, -} from "@solana/spl-token"; -import { homedir } from "os"; -import { readFileSync } from "fs"; - -// devnet: -// const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; -// const rpc = createRpc(RPC_URL); -// localnet: -const rpc = createRpc(); - -const payer = Keypair.fromSecretKey( - new Uint8Array( - JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) - ) -); - -(async function () { - // Setup: Create SPL mint, fund SPL ATA, wrap into Light ATA - const { mint } = await createMintInterface( - rpc, - payer, - payer, - null, - 9, - undefined, - undefined, - TOKEN_PROGRAM_ID - ); - const splAta = await createAssociatedTokenAccount( - rpc, - payer, - mint, - payer.publicKey, - undefined, - TOKEN_PROGRAM_ID - ); - await mintTo(rpc, payer, mint, splAta, payer, 1000); - - await createAtaInterface(rpc, payer, mint, payer.publicKey); - const lightTokenAta = getAssociatedTokenAddressInterface( - mint, - payer.publicKey - ); - await wrap(rpc, payer, splAta, lightTokenAta, payer, mint, BigInt(1000)); - - // Create unwrap instructions - const instructions = await createUnwrapInstructions( - rpc, - splAta, - payer.publicKey, - mint, - 500, - payer.publicKey - ); - - for (const ixs of instructions) { - const tx = new Transaction().add(...ixs); - const signature = await sendAndConfirmTransaction(rpc, tx, [payer]); - console.log("Tx:", signature); - } -})(); -``` diff --git a/snippets/code-snippets/light-token/unwrap/rust-client/action.mdx b/snippets/code-snippets/light-token/unwrap/rust-client/action.mdx deleted file mode 100644 index 79f3bf78..00000000 --- a/snippets/code-snippets/light-token/unwrap/rust-client/action.mdx +++ /dev/null @@ -1,40 +0,0 @@ -```rust -use anchor_spl::token::spl_token::state::Account as SplAccount; -use light_client::rpc::Rpc; -use light_token_client::actions::Unwrap; -use rust_client::{setup_for_unwrap, UnwrapContext}; -use solana_sdk::program_pack::Pack; - -#[tokio::main] -async fn main() -> Result<(), Box> { - // Setup creates Light associated token account with tokens and empty SPL associated token account - let UnwrapContext { - mut rpc, - payer, - mint, - destination_associated_token_account, - light_associated_token_account, - decimals, - } = setup_for_unwrap().await; - - // Unwrap tokens from Light Token associated token account to SPL associated token account - let sig = Unwrap { - source: light_associated_token_account, - destination_spl_ata: destination_associated_token_account, - mint, - amount: 500_000, - decimals, - } - .execute(&mut rpc, &payer, &payer) - .await?; - - let data = rpc - .get_account(destination_associated_token_account) - .await? - .ok_or("Account not found")?; - let token = SplAccount::unpack(&data.data)?; - println!("Balance: {} Tx: {sig}", token.amount); - - Ok(()) -} -``` diff --git a/snippets/code-snippets/light-token/unwrap/token-interface-instruction.mdx b/snippets/code-snippets/light-token/unwrap/token-interface-instruction.mdx deleted file mode 100644 index 5f0d14d0..00000000 --- a/snippets/code-snippets/light-token/unwrap/token-interface-instruction.mdx +++ /dev/null @@ -1,32 +0,0 @@ -```typescript -import { Keypair, Transaction, sendAndConfirmTransaction } from "@solana/web3.js"; -import { createRpc } from "@lightprotocol/stateless.js"; -import { createUnwrapInstruction, getSplInterfaces } from "@lightprotocol/token-interface"; - -const rpc = createRpc(); -const payer = Keypair.fromSecretKey(/* ... */); - -const mint = /* existing SPL/Token-2022 mint */; -const lightTokenAta = /* existing Light ATA */; -const splAta = /* destination SPL ATA */; - -const splInterfaces = await getSplInterfaces(rpc, mint); -const splInterface = - splInterfaces.find((info) => info.isInitialized) ?? splInterfaces[0]; -if (!splInterface) throw new Error("No SPL interface found"); - -const unwrapIx = createUnwrapInstruction({ - source: lightTokenAta, - destination: splAta, - owner: payer.publicKey, - mint, - amount: 500n, - splInterface, - decimals: 9, - payer: payer.publicKey, -}); - -const tx = new Transaction().add(unwrapIx); -const signature = await sendAndConfirmTransaction(rpc, tx, [payer]); -console.log("Tx:", signature); -``` diff --git a/snippets/code-snippets/light-token/wrap/action.mdx b/snippets/code-snippets/light-token/wrap/action.mdx deleted file mode 100644 index a7a42224..00000000 --- a/snippets/code-snippets/light-token/wrap/action.mdx +++ /dev/null @@ -1,64 +0,0 @@ -```typescript -import "dotenv/config"; -import { Keypair } from "@solana/web3.js"; -import { createRpc } from "@lightprotocol/stateless.js"; -import { - createMintInterface, - createAtaInterface, - getAssociatedTokenAddressInterface, -} from "@lightprotocol/compressed-token"; -import { wrap } from "@lightprotocol/compressed-token/unified"; -import { - TOKEN_PROGRAM_ID, - createAssociatedTokenAccount, - mintTo, -} from "@solana/spl-token"; -import { homedir } from "os"; -import { readFileSync } from "fs"; - -// devnet: -// const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; -// const rpc = createRpc(RPC_URL); -// localnet: -const rpc = createRpc(); - -const payer = Keypair.fromSecretKey( - new Uint8Array( - JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) - ) -); - -(async function () { - // Setup: Create SPL mint and fund an SPL ATA - const { mint } = await createMintInterface( - rpc, - payer, - payer, - null, - 9, - undefined, - undefined, - TOKEN_PROGRAM_ID - ); - const splAta = await createAssociatedTokenAccount( - rpc, - payer, - mint, - payer.publicKey, - undefined, - TOKEN_PROGRAM_ID - ); - await mintTo(rpc, payer, mint, splAta, payer, 1000); - - // Create light-token ATA and wrap SPL tokens into it - await createAtaInterface(rpc, payer, mint, payer.publicKey); - const lightTokenAta = getAssociatedTokenAddressInterface( - mint, - payer.publicKey - ); - - const tx = await wrap(rpc, payer, splAta, lightTokenAta, payer, mint, BigInt(500)); - - console.log("Tx:", tx); -})(); -``` diff --git a/snippets/code-snippets/light-token/wrap/instruction.mdx b/snippets/code-snippets/light-token/wrap/instruction.mdx deleted file mode 100644 index c89a711d..00000000 --- a/snippets/code-snippets/light-token/wrap/instruction.mdx +++ /dev/null @@ -1,92 +0,0 @@ -```typescript -import "dotenv/config"; -import { - Keypair, - ComputeBudgetProgram, - Transaction, - sendAndConfirmTransaction, -} from "@solana/web3.js"; -import { createRpc } from "@lightprotocol/stateless.js"; -import { - createMintInterface, - createAtaInterface, - createWrapInstruction, - getAssociatedTokenAddressInterface, - getSplInterfaceInfos, -} from "@lightprotocol/compressed-token"; -import { - TOKEN_PROGRAM_ID, - createAssociatedTokenAccount, - mintTo, -} from "@solana/spl-token"; -import { homedir } from "os"; -import { readFileSync } from "fs"; - -// devnet: -// const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; -// const rpc = createRpc(RPC_URL); -// localnet: -const rpc = createRpc(); - -const payer = Keypair.fromSecretKey( - new Uint8Array( - JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) - ) -); - -(async function () { - // Setup: Create SPL mint and fund an SPL ATA - const { mint } = await createMintInterface( - rpc, - payer, - payer, - null, - 9, - undefined, - undefined, - TOKEN_PROGRAM_ID - ); - const splAta = await createAssociatedTokenAccount( - rpc, - payer, - mint, - payer.publicKey, - undefined, - TOKEN_PROGRAM_ID - ); - await mintTo(rpc, payer, mint, splAta, payer, 1000); - - // Create wrap instruction - await createAtaInterface(rpc, payer, mint, payer.publicKey); - const lightTokenAta = getAssociatedTokenAddressInterface( - mint, - payer.publicKey - ); - - const splInterfaceInfos = await getSplInterfaceInfos(rpc, mint); - const splInterfaceInfo = splInterfaceInfos.find( - (info) => info.isInitialized - ); - - if (!splInterfaceInfo) throw new Error("No SPL interface found"); - - const ix = createWrapInstruction( - splAta, - lightTokenAta, - payer.publicKey, - mint, - 500, - splInterfaceInfo, - 9, - payer.publicKey - ); - - const tx = new Transaction().add( - ComputeBudgetProgram.setComputeUnitLimit({ units: 200_000 }), - ix - ); - const signature = await sendAndConfirmTransaction(rpc, tx, [payer]); - - console.log("Tx:", signature); -})(); -``` diff --git a/snippets/code-snippets/light-token/wrap/rust-client/action.mdx b/snippets/code-snippets/light-token/wrap/rust-client/action.mdx deleted file mode 100644 index 5b235784..00000000 --- a/snippets/code-snippets/light-token/wrap/rust-client/action.mdx +++ /dev/null @@ -1,39 +0,0 @@ -```rust -use borsh::BorshDeserialize; -use light_client::rpc::Rpc; -use light_token_client::actions::Wrap; -use rust_client::{setup_for_wrap, WrapContext}; - -#[tokio::main] -async fn main() -> Result<(), Box> { - // Setup creates SPL associated token account with tokens and empty Light associated token account - let WrapContext { - mut rpc, - payer, - mint, - source_associated_token_account, - light_associated_token_account, - decimals, - } = setup_for_wrap().await; - - // Wrap tokens from SPL associated token account to Light Token associated token account - let sig = Wrap { - source_spl_ata: source_associated_token_account, - destination: light_associated_token_account, - mint, - amount: 500_000, - decimals, - } - .execute(&mut rpc, &payer, &payer) - .await?; - - let data = rpc - .get_account(light_associated_token_account) - .await? - .ok_or("Account not found")?; - let token = light_token_interface::state::Token::deserialize(&mut &data.data[..])?; - println!("Balance: {} Tx: {sig}", token.amount); - - Ok(()) -} -``` diff --git a/snippets/code-snippets/light-token/wrap/token-interface-instruction.mdx b/snippets/code-snippets/light-token/wrap/token-interface-instruction.mdx deleted file mode 100644 index 20af94b8..00000000 --- a/snippets/code-snippets/light-token/wrap/token-interface-instruction.mdx +++ /dev/null @@ -1,47 +0,0 @@ -```typescript -import { ComputeBudgetProgram, Keypair, Transaction, sendAndConfirmTransaction } from "@solana/web3.js"; -import { createRpc } from "@lightprotocol/stateless.js"; -import { - createAtaInstruction, - createWrapInstruction, - getAtaAddress, - getSplInterfaces, -} from "@lightprotocol/token-interface"; - -const rpc = createRpc(); -const payer = Keypair.fromSecretKey(/* ... */); - -const mint = /* existing SPL/Token-2022 mint */; -const splAta = /* existing SPL ATA */; -const lightTokenAta = getAtaAddress({ mint, owner: payer.publicKey }); - -const createAtaIx = createAtaInstruction({ - payer: payer.publicKey, - owner: payer.publicKey, - mint, -}); - -const splInterfaces = await getSplInterfaces(rpc, mint); -const splInterface = - splInterfaces.find((info) => info.isInitialized) ?? splInterfaces[0]; -if (!splInterface) throw new Error("No SPL interface found"); - -const wrapIx = createWrapInstruction({ - source: splAta, - destination: lightTokenAta, - owner: payer.publicKey, - mint, - amount: 500n, - splInterface, - decimals: 9, - payer: payer.publicKey, -}); - -const tx = new Transaction().add( - ComputeBudgetProgram.setComputeUnitLimit({ units: 200_000 }), - createAtaIx, - wrapIx -); -const signature = await sendAndConfirmTransaction(rpc, tx, [payer]); -console.log("Tx:", signature); -``` diff --git a/snippets/code-snippets/payments/interop/register-spl-mint.mdx b/snippets/code-snippets/payments/interop/register-spl-mint.mdx index 3494b3c9..354d43d8 100644 --- a/snippets/code-snippets/payments/interop/register-spl-mint.mdx +++ b/snippets/code-snippets/payments/interop/register-spl-mint.mdx @@ -29,7 +29,7 @@ const payer = Keypair.fromSecretKey( const mint = new PublicKey("YOUR_EXISTING_MINT_ADDRESS"); // One-time: Register the SPL interface PDA for this mint. - // This creates the omnibus account that holds SPL tokens when wrapped to light-token. + // This creates the omnibus account that holds SPL tokens when wrapped to a compressed token account. // Note: createMintInterface(... TOKEN_PROGRAM_ID) does this automatically for new mints. const ix = await LightTokenProgram.createSplInterface({ feePayer: payer.publicKey, diff --git a/snippets/code-snippets/payments/interop/unwrap.mdx b/snippets/code-snippets/payments/interop/unwrap.mdx index 81f03420..1e29bd17 100644 --- a/snippets/code-snippets/payments/interop/unwrap.mdx +++ b/snippets/code-snippets/payments/interop/unwrap.mdx @@ -52,7 +52,7 @@ const payer = Keypair.fromSecretKey( ); await mintTo(rpc, payer, mint, splAta, payer, 1000); - // 3. Create light-token ATA and wrap all SPL tokens into it + // 3. Create compressed token ATA and wrap all SPL tokens into it await createAtaInterface(rpc, payer, mint, payer.publicKey); const senderAta = getAssociatedTokenAddressInterface( mint, @@ -60,7 +60,7 @@ const payer = Keypair.fromSecretKey( ); await wrap(rpc, payer, splAta, senderAta, payer, mint, BigInt(1000)); - // 4. Unwrap: move tokens back from light-token to SPL ATA + // 4. Unwrap: move tokens back from compressed token to SPL ATA const tx = await unwrap(rpc, payer, splAta, payer, mint, 500); console.log("Tx:", tx); diff --git a/snippets/code-snippets/payments/interop/wrap.mdx b/snippets/code-snippets/payments/interop/wrap.mdx index 1caafd90..ec6f7609 100644 --- a/snippets/code-snippets/payments/interop/wrap.mdx +++ b/snippets/code-snippets/payments/interop/wrap.mdx @@ -52,14 +52,14 @@ const payer = Keypair.fromSecretKey( ); await mintTo(rpc, payer, mint, splAta, payer, 1000); - // 3. Create light-token ATA + // 3. Create compressed token ATA await createAtaInterface(rpc, payer, mint, payer.publicKey); const senderAta = getAssociatedTokenAddressInterface( mint, payer.publicKey ); - // 4. Wrap: move SPL tokens into the light-token system + // 4. Wrap: move SPL tokens into the compressed token system const tx = await wrap( rpc, payer, diff --git a/snippets/code-snippets/privy/balances/nodejs.mdx b/snippets/code-snippets/privy/balances/nodejs.mdx index 929a0b91..ebf6e51d 100644 --- a/snippets/code-snippets/privy/balances/nodejs.mdx +++ b/snippets/code-snippets/privy/balances/nodejs.mdx @@ -1,158 +1,38 @@ ```typescript -import 'dotenv/config'; -import {PublicKey, LAMPORTS_PER_SOL} from '@solana/web3.js'; -import {TOKEN_PROGRAM_ID, TOKEN_2022_PROGRAM_ID, getMint} from '@solana/spl-token'; +import {PublicKey} from '@solana/web3.js'; import {createRpc} from '@lightprotocol/stateless.js'; -import { - getAtaInterface, - getAssociatedTokenAddressInterface, -} from '@lightprotocol/compressed-token/unified'; +import {HELIUS_RPC_URL} from './config.js'; -interface TokenBalance { - mint: string; - decimals: number; - hot: number; - cold: number; - spl: number; - t22: number; - unified: number; -} - -interface BalanceBreakdown { - sol: number; - tokens: TokenBalance[]; -} - -export async function getBalances( - ownerAddress: string, -): Promise { - const rpc = createRpc(process.env.HELIUS_RPC_URL!); +export async function getCompressedBalances(ownerAddress: string) { + const rpc = createRpc(HELIUS_RPC_URL); const owner = new PublicKey(ownerAddress); - // SOL balance - let solLamports = 0; - try { - solLamports = await rpc.getBalance(owner); - } catch (e) { - console.error('Failed to fetch SOL balance:', e); - } - - // Per-mint accumulator (raw values, converted at assembly) - const mintMap = new Map(); - - const getOrCreate = (mintStr: string) => { - let entry = mintMap.get(mintStr); - if (!entry) { - entry = {spl: 0n, t22: 0n, hot: 0n, cold: 0n, decimals: 9, tokenProgram: TOKEN_PROGRAM_ID}; - mintMap.set(mintStr, entry); + // Get compressed SOL balance + const compressedSol = await rpc.getCompressedBalanceByOwner(owner); + const compressedSolLamports = compressedSol.value ? BigInt(compressedSol.value.toString()) : 0n; + + // Get compressed token accounts (filter out null items from indexer) + const compressedAccounts = await rpc.getCompressedTokenAccountsByOwner(owner); + const validItems = (compressedAccounts.items || []).filter((item): item is NonNullable => item !== null); + + // Aggregate balances by mint + const balances = new Map(); + for (const account of validItems) { + if (account.parsed) { + const mint = account.parsed.mint.toBase58(); + const amount = BigInt(account.parsed.amount.toString()); + const current = balances.get(mint) || 0n; + balances.set(mint, current + amount); } - return entry; - }; - - // 1. SPL accounts - try { - const splAccounts = await rpc.getTokenAccountsByOwner(owner, { - programId: TOKEN_PROGRAM_ID, - }); - for (const {account} of splAccounts.value) { - const buf = toBuffer(account.data); - if (!buf || buf.length < 72) continue; - const mint = new PublicKey(buf.subarray(0, 32)); - const amount = buf.readBigUInt64LE(64); - const mintStr = mint.toBase58(); - getOrCreate(mintStr).spl += amount; - } - } catch { - // No SPL accounts } - // 2. Token 2022 accounts - try { - const t22Accounts = await rpc.getTokenAccountsByOwner(owner, { - programId: TOKEN_2022_PROGRAM_ID, - }); - for (const {account} of t22Accounts.value) { - const buf = toBuffer(account.data); - if (!buf || buf.length < 72) continue; - const mint = new PublicKey(buf.subarray(0, 32)); - const amount = buf.readBigUInt64LE(64); - const mintStr = mint.toBase58(); - const entry = getOrCreate(mintStr); - entry.t22 += amount; - entry.tokenProgram = TOKEN_2022_PROGRAM_ID; - } - } catch { - // No Token 2022 accounts - } - - // 3. Cold balance from compressed token accounts - try { - const compressed = await rpc.getCompressedTokenBalancesByOwnerV2(owner); - for (const item of compressed.value.items) { - const mintStr = item.mint.toBase58(); - getOrCreate(mintStr).cold += BigInt(item.balance.toString()); - } - } catch { - // No compressed accounts - } - - // 4. Fetch actual decimals for each mint - const mintKeys = [...mintMap.keys()]; - await Promise.allSettled( - mintKeys.map(async (mintStr) => { - try { - const mint = new PublicKey(mintStr); - const entry = getOrCreate(mintStr); - const mintInfo = await getMint(rpc, mint, undefined, entry.tokenProgram); - entry.decimals = mintInfo.decimals; - } catch { - // Keep default decimals if mint fetch fails - } - }), - ); - - // 5. Hot balance from Light Token associated token account - await Promise.allSettled( - mintKeys.map(async (mintStr) => { - try { - const mint = new PublicKey(mintStr); - const ata = getAssociatedTokenAddressInterface(mint, owner); - const {parsed} = await getAtaInterface(rpc, ata, owner, mint); - getOrCreate(mintStr).hot = BigInt(parsed.amount.toString()); - } catch { - // Associated token account does not exist for this mint - } - }), - ); - - // 6. Assemble result (convert raw → UI amounts here) - const tokens: TokenBalance[] = []; - for (const [mintStr, entry] of mintMap) { - const d = entry.decimals; - tokens.push({ - mint: mintStr, - decimals: d, - hot: toUiAmount(entry.hot, d), - cold: toUiAmount(entry.cold, d), - spl: toUiAmount(entry.spl, d), - t22: toUiAmount(entry.t22, d), - unified: toUiAmount(entry.hot + entry.cold, d), - }); - } - - return {sol: solLamports / LAMPORTS_PER_SOL, tokens}; -} - -function toBuffer(data: Buffer | Uint8Array | string | unknown): Buffer | null { - if (data instanceof Buffer) return data; - if (data instanceof Uint8Array) return Buffer.from(data); - return null; -} - -function toUiAmount(raw: bigint, decimals: number): number { - return Number(raw) / 10 ** decimals; + return { + sol: compressedSolLamports.toString(), + tokens: Array.from(balances.entries()).map(([mint, amount]) => ({ + mint, + amount: amount.toString(), + accounts: validItems.filter(a => a.parsed?.mint.toBase58() === mint).length + })) + }; } - -export default getBalances; - ``` diff --git a/snippets/code-snippets/privy/balances/react.mdx b/snippets/code-snippets/privy/balances/react.mdx deleted file mode 100644 index 0c9f60e8..00000000 --- a/snippets/code-snippets/privy/balances/react.mdx +++ /dev/null @@ -1,177 +0,0 @@ -```typescript -import { useState, useCallback } from 'react'; -import { PublicKey, LAMPORTS_PER_SOL } from '@solana/web3.js'; -import { TOKEN_PROGRAM_ID, TOKEN_2022_PROGRAM_ID, getMint } from '@solana/spl-token'; -import { createRpc } from '@lightprotocol/stateless.js'; -import { - getAssociatedTokenAddressInterface, - getAtaInterface, -} from '@lightprotocol/compressed-token/unified'; - -export interface TokenBalance { - mint: string; - decimals: number; - isNative: boolean; - hot: bigint; - cold: bigint; - spl: bigint; - t22: bigint; - unified: bigint; -} - -export function useUnifiedBalance() { - const [balances, setBalances] = useState([]); - const [isLoading, setIsLoading] = useState(false); - - const fetchBalances = useCallback(async (ownerAddress: string) => { - if (!ownerAddress) return; - - setIsLoading(true); - try { - const rpc = createRpc(import.meta.env.VITE_HELIUS_RPC_URL); - const owner = new PublicKey(ownerAddress); - - // Per-mint accumulator - const mintMap = new Map(); - - const getOrCreate = (mintStr: string) => { - let entry = mintMap.get(mintStr); - if (!entry) { - entry = { spl: 0n, t22: 0n, hot: 0n, cold: 0n, decimals: 9, tokenProgram: TOKEN_PROGRAM_ID }; - mintMap.set(mintStr, entry); - } - return entry; - }; - - // 1. SOL balance - let solLamports = 0; - try { - solLamports = await rpc.getBalance(owner); - } catch { - // Failed to fetch SOL balance - } - - // 2. SPL accounts - try { - const splAccounts = await rpc.getTokenAccountsByOwner(owner, { - programId: TOKEN_PROGRAM_ID, - }); - for (const { account } of splAccounts.value) { - const buf = toBuffer(account.data); - if (!buf || buf.length < 72) continue; - const mint = new PublicKey(buf.subarray(0, 32)); - const amount = buf.readBigUInt64LE(64); - const mintStr = mint.toBase58(); - getOrCreate(mintStr).spl += amount; - } - } catch { - // No SPL accounts - } - - // 3. Token 2022 accounts - try { - const t22Accounts = await rpc.getTokenAccountsByOwner(owner, { - programId: TOKEN_2022_PROGRAM_ID, - }); - for (const { account } of t22Accounts.value) { - const buf = toBuffer(account.data); - if (!buf || buf.length < 72) continue; - const mint = new PublicKey(buf.subarray(0, 32)); - const amount = buf.readBigUInt64LE(64); - const mintStr = mint.toBase58(); - const entry = getOrCreate(mintStr); - entry.t22 += amount; - entry.tokenProgram = TOKEN_2022_PROGRAM_ID; - } - } catch { - // No Token 2022 accounts - } - - // 4. Cold balance from compressed token accounts - try { - const compressed = await rpc.getCompressedTokenBalancesByOwnerV2(owner); - for (const item of compressed.value.items) { - const mintStr = item.mint.toBase58(); - getOrCreate(mintStr).cold += BigInt(item.balance.toString()); - } - } catch { - // No compressed accounts - } - - // 5. Fetch actual decimals for each mint - const mintKeys = [...mintMap.keys()]; - await Promise.allSettled( - mintKeys.map(async (mintStr) => { - try { - const mint = new PublicKey(mintStr); - const entry = getOrCreate(mintStr); - const mintInfo = await getMint(rpc, mint, undefined, entry.tokenProgram); - entry.decimals = mintInfo.decimals; - } catch { - // Keep default decimals if mint fetch fails - } - }), - ); - - // 6. Hot balance from Light Token associated token account - await Promise.allSettled( - mintKeys.map(async (mintStr) => { - try { - const mint = new PublicKey(mintStr); - const ata = getAssociatedTokenAddressInterface(mint, owner); - const { parsed } = await getAtaInterface(rpc, ata, owner, mint); - const entry = getOrCreate(mintStr); - entry.hot = BigInt(parsed.amount.toString()); - } catch { - // Associated token account does not exist for this mint — hot stays 0n - } - }), - ); - - // 7. Assemble TokenBalance[] - const result: TokenBalance[] = []; - - // SOL entry - result.push({ - mint: 'So11111111111111111111111111111111111111112', - decimals: 9, - isNative: true, - hot: 0n, - cold: 0n, - spl: BigInt(solLamports), - t22: 0n, - unified: 0n, - }); - - // Token entries - for (const [mintStr, entry] of mintMap) { - result.push({ - mint: mintStr, - decimals: entry.decimals, - isNative: false, - hot: entry.hot, - cold: entry.cold, - spl: entry.spl, - t22: entry.t22, - unified: entry.hot + entry.cold, - }); - } - - setBalances(result); - } catch (error) { - console.error('Failed to fetch balances:', error); - setBalances([]); - } finally { - setIsLoading(false); - } - }, []); - - return { balances, isLoading, fetchBalances }; -} - -function toBuffer(data: Buffer | Uint8Array | string | unknown): Buffer | null { - if (data instanceof Buffer) return data; - if (data instanceof Uint8Array) return Buffer.from(data); - return null; -} -``` diff --git a/snippets/code-snippets/privy/compress/nodejs.mdx b/snippets/code-snippets/privy/compress/nodejs.mdx new file mode 100644 index 00000000..978c51c4 --- /dev/null +++ b/snippets/code-snippets/privy/compress/nodejs.mdx @@ -0,0 +1,89 @@ +```typescript +import 'dotenv/config'; +import {PrivyClient} from '@privy-io/node'; +import {createRpc, bn, selectStateTreeInfo} from '@lightprotocol/stateless.js'; +import {PublicKey, Transaction, ComputeBudgetProgram} from '@solana/web3.js'; +import {getAssociatedTokenAddressSync, getAccount} from '@solana/spl-token'; +import {CompressedTokenProgram, getTokenPoolInfos, selectTokenPoolInfo} from '@lightprotocol/compressed-token'; + +const compressTokens = async ( + fromAddress: string, + toAddress: string, + tokenMintAddress: string, + amount: number, + decimals: number = 6 +) => { + const connection = createRpc(process.env.HELIUS_RPC_URL!); + + const privy = new PrivyClient({ + appId: process.env.PRIVY_APP_ID!, + appSecret: process.env.PRIVY_APP_SECRET!, + }); + + // Create public key objects + const fromPubkey = new PublicKey(fromAddress); + const toPubkey = new PublicKey(toAddress); + const mintPubkey = new PublicKey(tokenMintAddress); + const tokenAmount = bn(amount * Math.pow(10, decimals)); + + // Get source token account and verify balance + const ownerAta = getAssociatedTokenAddressSync(mintPubkey, fromPubkey); + const ataAccount = await getAccount(connection, ownerAta); + if (ataAccount.amount < BigInt(tokenAmount.toString())) { + throw new Error('Insufficient SPL balance'); + } + + // Get state tree to store compressed tokens + // Get token pool info. Stores SPL tokens in interface PDA when compressed. + const stateTreeInfos = await connection.getStateTreeInfos(); + const selectedTreeInfo = selectStateTreeInfo(stateTreeInfos); + const tokenPoolInfos = await getTokenPoolInfos(connection, mintPubkey); + const tokenPoolInfo = selectTokenPoolInfo(tokenPoolInfos); + + // Create compress instruction + const instruction = await CompressedTokenProgram.compress({ + payer: fromPubkey, + owner: fromPubkey, + source: ownerAta, + toAddress: toPubkey, + mint: mintPubkey, + amount: tokenAmount, + outputStateTreeInfo: selectedTreeInfo, + tokenPoolInfo, + }); + + // Create transaction + const transaction = new Transaction(); + transaction.add(ComputeBudgetProgram.setComputeUnitLimit({units: 300_000})); + transaction.add(instruction); + + // Get recent blockhash + const {blockhash} = await connection.getLatestBlockhash(); + transaction.recentBlockhash = blockhash; + transaction.feePayer = fromPubkey; + + // Sign with Privy + const signResult = await privy.wallets().solana().signTransaction(process.env.TREASURY_WALLET_ID!, { + transaction: transaction.serialize({requireAllSignatures: false}), + authorization_context: { + authorization_private_keys: [process.env.TREASURY_AUTHORIZATION_KEY!] + } + }); + const signedTx = (signResult as any).signed_transaction || signResult.signedTransaction; + if (!signedTx) { + throw new Error('Privy returned invalid response: ' + JSON.stringify(signResult)); + } + const signedTransaction = Buffer.from(signedTx, 'base64'); + + // Send transaction + const signature = await connection.sendRawTransaction(signedTransaction, { + skipPreflight: false, + preflightCommitment: 'confirmed' + }); + await connection.confirmTransaction(signature, 'confirmed'); + + return signature; +}; + +export default compressTokens; +``` diff --git a/snippets/code-snippets/privy/decompress/nodejs.mdx b/snippets/code-snippets/privy/decompress/nodejs.mdx new file mode 100644 index 00000000..6f722014 --- /dev/null +++ b/snippets/code-snippets/privy/decompress/nodejs.mdx @@ -0,0 +1,81 @@ +```typescript +import 'dotenv/config'; +import {PrivyClient} from '@privy-io/node'; +import {createRpc} from '@lightprotocol/stateless.js'; +import {Keypair, PublicKey, Transaction} from '@solana/web3.js'; +import {getAssociatedTokenAddressSync, createAssociatedTokenAccount} from '@solana/spl-token'; +import {decompress} from '@lightprotocol/compressed-token'; + +const decompressTokens = async ( + fromAddress: string, + tokenMintAddress: string, + amount: number, + decimals: number = 6 +) => { + const connection = createRpc(process.env.HELIUS_RPC_URL!); + + const privy = new PrivyClient({ + appId: process.env.PRIVY_APP_ID!, + appSecret: process.env.PRIVY_APP_SECRET!, + }); + + const fromPubkey = new PublicKey(fromAddress); + const mintPubkey = new PublicKey(tokenMintAddress); + const rawAmount = amount * Math.pow(10, decimals); + + // Get destination ATA + const ownerAta = getAssociatedTokenAddressSync(mintPubkey, fromPubkey); + + // Check ATA exists (decompress action will handle creation internally) + // But we need to be aware ATA creation requires a separate signer + + // Create fake keypair for decompress action (only publicKey is used) + const dummyPayer = { + publicKey: fromPubkey, + secretKey: new Uint8Array(64), + } as any; + + // Intercept sendAndConfirmTransaction to use Privy signing + const originalSendAndConfirm = (connection as any).sendAndConfirmTransaction; + (connection as any).sendAndConfirmTransaction = async (tx: Transaction, signers: any[]) => { + const signResult = await privy.wallets().solana().signTransaction(process.env.TREASURY_WALLET_ID!, { + transaction: tx.serialize({requireAllSignatures: false}), + authorization_context: { + authorization_private_keys: [process.env.TREASURY_AUTHORIZATION_KEY!] + } + }); + + const signedTx = (signResult as any).signed_transaction || signResult.signedTransaction; + if (!signedTx) { + throw new Error('Privy returned invalid response'); + } + + const signedTransaction = Buffer.from(signedTx, 'base64'); + const signature = await connection.sendRawTransaction(signedTransaction, { + skipPreflight: false, + preflightCommitment: 'confirmed' + }); + await connection.confirmTransaction(signature, 'confirmed'); + return signature; + }; + + try { + // Use high-level decompress action (handles account configuration correctly) + const signature = await decompress( + connection, + dummyPayer, + mintPubkey, + rawAmount, + dummyPayer, + ownerAta + ); + + return signature; + } finally { + // Restore original function + (connection as any).sendAndConfirmTransaction = originalSendAndConfirm; + } +}; + +export default decompressTokens; +``` diff --git a/snippets/code-snippets/privy/helpers/sign-and-send-batches.mdx b/snippets/code-snippets/privy/helpers/sign-and-send-batches.mdx deleted file mode 100644 index 082607d7..00000000 --- a/snippets/code-snippets/privy/helpers/sign-and-send-batches.mdx +++ /dev/null @@ -1,46 +0,0 @@ -```typescript -import { Transaction, TransactionInstruction, PublicKey } from '@solana/web3.js'; -import type { ConnectedStandardSolanaWallet } from '@privy-io/js-sdk-core'; -import { useSignTransaction } from '@privy-io/react-auth/solana'; - -type SignTransactionFn = ReturnType['signTransaction']; - -interface SignAndSendOptions { - rpc: any; - feePayer: PublicKey; - wallet: ConnectedStandardSolanaWallet; - signTransaction: SignTransactionFn; -} - -export async function signAndSendBatches( - instructionBatches: TransactionInstruction[][], - options: SignAndSendOptions, -): Promise { - const { rpc, feePayer, wallet, signTransaction } = options; - const signatures: string[] = []; - - for (const ixs of instructionBatches) { - const tx = new Transaction().add(...ixs); - const { blockhash } = await rpc.getLatestBlockhash(); - tx.recentBlockhash = blockhash; - tx.feePayer = feePayer; - - const unsignedTxBuffer = tx.serialize({ requireAllSignatures: false }); - const signedTx = await signTransaction({ - transaction: unsignedTxBuffer, - wallet, - chain: 'solana:devnet', - }); - - const signedTxBuffer = Buffer.from(signedTx.signedTransaction); - const sig = await rpc.sendRawTransaction(signedTxBuffer, { - skipPreflight: false, - preflightCommitment: 'confirmed', - }); - await rpc.confirmTransaction(sig, 'confirmed'); - signatures.push(sig); - } - - return signatures.length > 0 ? signatures[signatures.length - 1] : null; -} -``` diff --git a/snippets/code-snippets/privy/receive/nodejs.mdx b/snippets/code-snippets/privy/receive/nodejs.mdx deleted file mode 100644 index 4cfeb478..00000000 --- a/snippets/code-snippets/privy/receive/nodejs.mdx +++ /dev/null @@ -1,63 +0,0 @@ -```typescript -import 'dotenv/config'; -import {PrivyClient} from '@privy-io/node'; -import {createRpc} from '@lightprotocol/stateless.js'; -import {PublicKey, Transaction} from '@solana/web3.js'; -import { - createLoadAtaInstructions, - getAssociatedTokenAddressInterface, -} from '@lightprotocol/compressed-token/unified'; - -const receiveLightTokens = async ( - recipientAddress: string, - tokenMintAddress: string, -) => { - const connection = createRpc(process.env.HELIUS_RPC_URL!); - - const privy = new PrivyClient({ - appId: process.env.PRIVY_APP_ID!, - appSecret: process.env.PRIVY_APP_SECRET!, - }); - - const recipient = new PublicKey(recipientAddress); - const mintPubkey = new PublicKey(tokenMintAddress); - const ata = getAssociatedTokenAddressInterface(mintPubkey, recipient); - - // Creates the ATA if needed and loads any compressed state into it. - // Returns TransactionInstruction[][] — almost always just one. - const instructions = await createLoadAtaInstructions( - connection, ata, recipient, mintPubkey, recipient, - ); - - // Sign and send each batch via Privy - const walletId = process.env.TREASURY_WALLET_ID!; - const authorizationKey = process.env.TREASURY_AUTHORIZATION_KEY!; - const signatures: string[] = []; - - for (const ixs of instructions) { - const tx = new Transaction().add(...ixs); - const {blockhash} = await connection.getLatestBlockhash(); - tx.recentBlockhash = blockhash; - tx.feePayer = recipient; - - const {signed_transaction} = await privy.wallets().solana().signTransaction( - walletId, { - transaction: tx.serialize({requireAllSignatures: false}), - authorization_context: {authorization_private_keys: [authorizationKey]}, - }, - ) as any; - - const sig = await connection.sendRawTransaction( - Buffer.from(signed_transaction, 'base64'), - {skipPreflight: false, preflightCommitment: 'confirmed'}, - ); - await connection.confirmTransaction(sig, 'confirmed'); - signatures.push(sig); - } - - return signatures.length > 0 ? signatures[signatures.length - 1] : null; -}; - -export default receiveLightTokens; - -``` diff --git a/snippets/code-snippets/privy/receive/react.mdx b/snippets/code-snippets/privy/receive/react.mdx deleted file mode 100644 index f85e0fdd..00000000 --- a/snippets/code-snippets/privy/receive/react.mdx +++ /dev/null @@ -1,61 +0,0 @@ -```typescript -import { useState } from 'react'; -import { PublicKey } from '@solana/web3.js'; -import { - createLoadAtaInstructions, - getAssociatedTokenAddressInterface, -} from '@lightprotocol/compressed-token/unified'; -import { createRpc } from '@lightprotocol/stateless.js'; -import type { ConnectedStandardSolanaWallet } from '@privy-io/js-sdk-core'; -import { useSignTransaction } from '@privy-io/react-auth/solana'; -import { signAndSendBatches } from './signAndSendBatches'; - -type SignTransactionFn = ReturnType['signTransaction']; - -export interface ReceiveParams { - ownerPublicKey: string; - mint: string; -} - -export interface ReceiveArgs { - params: ReceiveParams; - wallet: ConnectedStandardSolanaWallet; - signTransaction: SignTransactionFn; -} - -export function useReceive() { - const [isLoading, setIsLoading] = useState(false); - - const receive = async (args: ReceiveArgs): Promise => { - setIsLoading(true); - - try { - const { params, wallet, signTransaction } = args; - - const rpc = createRpc(import.meta.env.VITE_HELIUS_RPC_URL); - - const owner = new PublicKey(params.ownerPublicKey); - const mintPubkey = new PublicKey(params.mint); - const ata = getAssociatedTokenAddressInterface(mintPubkey, owner); - - // Returns TransactionInstruction[][]. - // Each inner array is one transaction. - // Almost always returns just one. - const instructions = await createLoadAtaInstructions( - rpc, ata, owner, mintPubkey, owner, - ); - - return await signAndSendBatches(instructions, { - rpc, - feePayer: owner, - wallet, - signTransaction, - }); - } finally { - setIsLoading(false); - } - }; - - return { receive, isLoading }; -} -``` diff --git a/snippets/code-snippets/privy/transaction-history/nodejs.mdx b/snippets/code-snippets/privy/transaction-history/nodejs.mdx index 00fce8c1..9d58855f 100644 --- a/snippets/code-snippets/privy/transaction-history/nodejs.mdx +++ b/snippets/code-snippets/privy/transaction-history/nodejs.mdx @@ -6,36 +6,63 @@ import {PublicKey} from '@solana/web3.js'; const getTransactionHistory = async ( ownerAddress: string, limit: number = 10, + includeDetails: boolean = false ) => { const connection = createRpc(process.env.HELIUS_RPC_URL!); const owner = new PublicKey(ownerAddress); - // Get Light Token interface signatures - const result = await connection.getSignaturesForOwnerInterface(owner); + // Get compression signatures for token owner + const signatures = await connection.getCompressionSignaturesForTokenOwner(owner); - if (!result.signatures || result.signatures.length === 0) { + if (signatures.items.length === 0) { return { count: 0, transactions: [], }; } - const limitedSignatures = result.signatures.slice(0, limit); + // Limit results + const limitedSignatures = signatures.items.slice(0, limit); + // Get detailed info if requested + if (includeDetails && limitedSignatures.length > 0) { + const transactions = await Promise.all( + limitedSignatures.map(async (sig) => { + const txInfo = await connection.getTransactionWithCompressionInfo(sig.signature); + + return { + signature: sig.signature, + slot: sig.slot, + blockTime: sig.blockTime, + timestamp: new Date(sig.blockTime * 1000).toISOString(), + compressionInfo: txInfo?.compressionInfo ? { + closedAccounts: txInfo.compressionInfo.closedAccounts.length, + openedAccounts: txInfo.compressionInfo.openedAccounts.length, + } : null, + }; + }) + ); + + return { + count: signatures.items.length, + transactions, + }; + } + + // Return basic signature info const transactions = limitedSignatures.map((sig) => ({ signature: sig.signature, slot: sig.slot, - blockTime: sig.blockTime ?? 0, - timestamp: sig.blockTime ? new Date(sig.blockTime * 1000).toISOString() : '', + blockTime: sig.blockTime, + timestamp: new Date(sig.blockTime * 1000).toISOString(), })); return { - count: result.signatures.length, + count: signatures.items.length, transactions, }; }; export default getTransactionHistory; - ``` diff --git a/snippets/code-snippets/privy/transaction-history/react.mdx b/snippets/code-snippets/privy/transaction-history/react.mdx deleted file mode 100644 index 1c98218e..00000000 --- a/snippets/code-snippets/privy/transaction-history/react.mdx +++ /dev/null @@ -1,65 +0,0 @@ -```typescript -import { useState, useCallback } from 'react'; -import { PublicKey } from '@solana/web3.js'; -import { createRpc } from '@lightprotocol/stateless.js'; - -export interface Transaction { - signature: string; - slot: number; - blockTime: number; - timestamp: string; -} - -export function useTransactionHistory() { - const [transactions, setTransactions] = useState([]); - const [isLoading, setIsLoading] = useState(false); - const [error, setError] = useState(null); - - const fetchTransactionHistory = useCallback( - async ( - ownerAddress: string, - limit: number = 10, - ) => { - if (!ownerAddress) { - setTransactions([]); - return; - } - - setIsLoading(true); - setError(null); - - try { - const rpc = createRpc(import.meta.env.VITE_HELIUS_RPC_URL); - const owner = new PublicKey(ownerAddress); - - const result = await rpc.getSignaturesForOwnerInterface(owner); - - if (!result.signatures || result.signatures.length === 0) { - setTransactions([]); - return; - } - - const limitedSignatures = result.signatures.slice(0, limit); - - const basicTransactions = limitedSignatures.map((sig) => ({ - signature: sig.signature, - slot: sig.slot, - blockTime: sig.blockTime ?? 0, - timestamp: sig.blockTime ? new Date(sig.blockTime * 1000).toISOString() : '', - })); - - setTransactions(basicTransactions); - } catch (err) { - const message = err instanceof Error ? err.message : String(err); - setError(message); - setTransactions([]); - } finally { - setIsLoading(false); - } - }, - [] - ); - - return { transactions, isLoading, error, fetchTransactionHistory }; -} -``` diff --git a/snippets/code-snippets/privy/transfer/nodejs.mdx b/snippets/code-snippets/privy/transfer/nodejs.mdx index 4a0844e4..4f49e90b 100644 --- a/snippets/code-snippets/privy/transfer/nodejs.mdx +++ b/snippets/code-snippets/privy/transfer/nodejs.mdx @@ -1,18 +1,16 @@ ```typescript import 'dotenv/config'; import {PrivyClient} from '@privy-io/node'; -import {createRpc} from '@lightprotocol/stateless.js'; -import {PublicKey, Transaction} from '@solana/web3.js'; -import { - createTransferInterfaceInstructions, -} from '@lightprotocol/compressed-token/unified'; +import {createRpc, bn} from '@lightprotocol/stateless.js'; +import {PublicKey, Transaction, ComputeBudgetProgram} from '@solana/web3.js'; +import {CompressedTokenProgram, selectMinCompressedTokenAccountsForTransfer} from '@lightprotocol/compressed-token'; -const transferLightTokens = async ( +const transferCompressedTokens = async ( fromAddress: string, toAddress: string, tokenMintAddress: string, amount: number, - decimals: number = 9, + decimals: number = 6 ) => { const connection = createRpc(process.env.HELIUS_RPC_URL!); @@ -21,46 +19,70 @@ const transferLightTokens = async ( appSecret: process.env.PRIVY_APP_SECRET!, }); + // Create public key objects const fromPubkey = new PublicKey(fromAddress); const toPubkey = new PublicKey(toAddress); const mintPubkey = new PublicKey(tokenMintAddress); - const tokenAmount = Math.floor(amount * Math.pow(10, decimals)); + const tokenAmount = bn(amount * Math.pow(10, decimals)); - // Loads cold (compressed), SPL, and Token 2022 balances into the Light Token associated token account before transfer. - // Returns TransactionInstruction[][] — send [0..n-2] in parallel, then [n-1] last. - const instructions = await createTransferInterfaceInstructions( - connection, fromPubkey, mintPubkey, tokenAmount, fromPubkey, toPubkey, - ); + // Get compressed token accounts (filter out null items from indexer) + const accounts = await connection.getCompressedTokenAccountsByOwner(fromPubkey, {mint: mintPubkey}); + const validItems = (accounts.items || []).filter((item): item is NonNullable => item !== null); + if (validItems.length === 0) { + throw new Error('No compressed token accounts found'); + } + + // Select minimum accounts needed for transfer + const [inputAccounts] = selectMinCompressedTokenAccountsForTransfer(validItems, tokenAmount); + if (inputAccounts.length === 0) { + throw new Error('Insufficient balance'); + } - // Sign and send each batch via Privy - const walletId = process.env.TREASURY_WALLET_ID!; - const authorizationKey = process.env.TREASURY_AUTHORIZATION_KEY!; - const signatures: string[] = []; + // Get validity proof to prove compressed token accounts exist in state tree. + const proof = await connection.getValidityProof(inputAccounts.map(account => bn(account.compressedAccount.hash))); + + // Create transfer instruction + const instruction = await CompressedTokenProgram.transfer({ + payer: fromPubkey, + inputCompressedTokenAccounts: inputAccounts, + toAddress: toPubkey, + amount: tokenAmount, + recentInputStateRootIndices: proof.rootIndices, + recentValidityProof: proof.compressedProof, + }); - for (const ixs of instructions) { - const tx = new Transaction().add(...ixs); - const {blockhash} = await connection.getLatestBlockhash(); - tx.recentBlockhash = blockhash; - tx.feePayer = fromPubkey; + // Create transaction + const transaction = new Transaction(); + transaction.add(ComputeBudgetProgram.setComputeUnitLimit({units: 300_000})); + transaction.add(instruction); - const {signed_transaction} = await privy.wallets().solana().signTransaction( - walletId, { - transaction: tx.serialize({requireAllSignatures: false}), - authorization_context: {authorization_private_keys: [authorizationKey]}, - }, - ) as any; + // Get recent blockhash + const {blockhash} = await connection.getLatestBlockhash(); + transaction.recentBlockhash = blockhash; + transaction.feePayer = fromPubkey; - const sig = await connection.sendRawTransaction( - Buffer.from(signed_transaction, 'base64'), - {skipPreflight: false, preflightCommitment: 'confirmed'}, - ); - await connection.confirmTransaction(sig, 'confirmed'); - signatures.push(sig); + // Sign with Privy + const signResult = await privy.wallets().solana().signTransaction(process.env.TREASURY_WALLET_ID!, { + transaction: transaction.serialize({requireAllSignatures: false}), + authorization_context: { + authorization_private_keys: [process.env.TREASURY_AUTHORIZATION_KEY!] + } + }); + const signedTx = (signResult as any).signed_transaction || signResult.signedTransaction; + if (!signedTx) { + throw new Error('Privy returned invalid response: ' + JSON.stringify(signResult)); } + const signedTransaction = Buffer.from(signedTx, 'base64'); - return signatures[signatures.length - 1]; -}; + // Send transaction + const signature = await connection.sendRawTransaction(signedTransaction, { + skipPreflight: false, + preflightCommitment: 'confirmed' + }); + await connection.confirmTransaction(signature, 'confirmed'); -export default transferLightTokens; + return signature; +}; +export default transferCompressedTokens; ``` diff --git a/snippets/code-snippets/privy/transfer/react.mdx b/snippets/code-snippets/privy/transfer/react.mdx deleted file mode 100644 index e5a3e715..00000000 --- a/snippets/code-snippets/privy/transfer/react.mdx +++ /dev/null @@ -1,71 +0,0 @@ -```typescript -import { useState } from 'react'; -import { PublicKey } from '@solana/web3.js'; -import { - createTransferInterfaceInstructions, -} from '@lightprotocol/compressed-token/unified'; -import { createRpc } from '@lightprotocol/stateless.js'; -import type { ConnectedStandardSolanaWallet } from '@privy-io/js-sdk-core'; -import { useSignTransaction } from '@privy-io/react-auth/solana'; -import { signAndSendBatches } from './signAndSendBatches'; - -type SignTransactionFn = ReturnType['signTransaction']; - -export interface TransferParams { - ownerPublicKey: string; - mint: string; - toAddress: string; - amount: number; - decimals?: number; -} - -export interface TransferArgs { - params: TransferParams; - wallet: ConnectedStandardSolanaWallet; - signTransaction: SignTransactionFn; -} - -export function useTransfer() { - const [isLoading, setIsLoading] = useState(false); - - const transfer = async (args: TransferArgs): Promise => { - setIsLoading(true); - - try { - const { params, wallet, signTransaction } = args; - const { ownerPublicKey, mint, toAddress, amount, decimals = 9 } = params; - - const rpc = createRpc(import.meta.env.VITE_HELIUS_RPC_URL); - - const owner = new PublicKey(ownerPublicKey); - const mintPubkey = new PublicKey(mint); - const recipient = new PublicKey(toAddress); - const tokenAmount = Math.floor(amount * Math.pow(10, decimals)); - - // Returns TransactionInstruction[][]. - // Each inner array is one transaction. - // Almost always returns just one. - const instructions = await createTransferInterfaceInstructions( - rpc, owner, mintPubkey, tokenAmount, owner, recipient, - ); - - const signature = await signAndSendBatches(instructions, { - rpc, - feePayer: owner, - wallet, - signTransaction, - }); - - if (!signature) { - throw new Error('Transfer returned no instructions'); - } - - return signature; - } finally { - setIsLoading(false); - } - }; - - return { transfer, isLoading }; -} -``` diff --git a/snippets/code-snippets/privy/unwrap/nodejs.mdx b/snippets/code-snippets/privy/unwrap/nodejs.mdx deleted file mode 100644 index 1bc631e2..00000000 --- a/snippets/code-snippets/privy/unwrap/nodejs.mdx +++ /dev/null @@ -1,74 +0,0 @@ -```typescript -import 'dotenv/config'; -import {PrivyClient} from '@privy-io/node'; -import {createRpc} from '@lightprotocol/stateless.js'; -import {PublicKey, Transaction} from '@solana/web3.js'; -import {getAssociatedTokenAddressSync} from '@solana/spl-token'; -import { - createUnwrapInstructions, -} from '@lightprotocol/compressed-token/unified'; - -const unwrapTokens = async ( - fromAddress: string, - tokenMintAddress: string, - amount: number, - decimals: number = 9, -) => { - const connection = createRpc(process.env.HELIUS_RPC_URL!); - - const privy = new PrivyClient({ - appId: process.env.PRIVY_APP_ID!, - appSecret: process.env.PRIVY_APP_SECRET!, - }); - - const fromPubkey = new PublicKey(fromAddress); - const mintPubkey = new PublicKey(tokenMintAddress); - const tokenAmount = BigInt(Math.floor(amount * Math.pow(10, decimals))); - - // Auto-detect token program (SPL vs Token 2022) from mint account owner - const mintAccountInfo = await connection.getAccountInfo(mintPubkey); - if (!mintAccountInfo) throw new Error(`Mint account ${tokenMintAddress} not found`); - const tokenProgramId = mintAccountInfo.owner; - - // Destination: SPL/T22 associated token account - const splAta = getAssociatedTokenAddressSync(mintPubkey, fromPubkey, false, tokenProgramId); - - // Returns TransactionInstruction[][]. - // Each inner array is one transaction. - // Handles loading + unwrapping together. - const instructions = await createUnwrapInstructions( - connection, splAta, fromPubkey, mintPubkey, tokenAmount, fromPubkey, - ); - - // Sign and send each batch via Privy - const walletId = process.env.TREASURY_WALLET_ID!; - const authorizationKey = process.env.TREASURY_AUTHORIZATION_KEY!; - const signatures: string[] = []; - - for (const ixs of instructions) { - const tx = new Transaction().add(...ixs); - const {blockhash} = await connection.getLatestBlockhash(); - tx.recentBlockhash = blockhash; - tx.feePayer = fromPubkey; - - const {signed_transaction} = await privy.wallets().solana().signTransaction( - walletId, { - transaction: tx.serialize({requireAllSignatures: false}), - authorization_context: {authorization_private_keys: [authorizationKey]}, - }, - ) as any; - - const sig = await connection.sendRawTransaction( - Buffer.from(signed_transaction, 'base64'), - {skipPreflight: false, preflightCommitment: 'confirmed'}, - ); - await connection.confirmTransaction(sig, 'confirmed'); - signatures.push(sig); - } - - return signatures[signatures.length - 1]; -}; - -export default unwrapTokens; - -``` diff --git a/snippets/code-snippets/privy/unwrap/react.mdx b/snippets/code-snippets/privy/unwrap/react.mdx deleted file mode 100644 index cf5def70..00000000 --- a/snippets/code-snippets/privy/unwrap/react.mdx +++ /dev/null @@ -1,78 +0,0 @@ -```typescript -import { useState } from 'react'; -import { PublicKey } from '@solana/web3.js'; -import { getAssociatedTokenAddressSync } from '@solana/spl-token'; -import { - createUnwrapInstructions, -} from '@lightprotocol/compressed-token/unified'; -import { createRpc } from '@lightprotocol/stateless.js'; -import type { ConnectedStandardSolanaWallet } from '@privy-io/js-sdk-core'; -import { useSignTransaction } from '@privy-io/react-auth/solana'; -import { signAndSendBatches } from './signAndSendBatches'; - -type SignTransactionFn = ReturnType['signTransaction']; - -export interface UnwrapParams { - ownerPublicKey: string; - mint: string; - amount: number; - decimals?: number; -} - -export interface UnwrapArgs { - params: UnwrapParams; - wallet: ConnectedStandardSolanaWallet; - signTransaction: SignTransactionFn; -} - -export function useUnwrap() { - const [isLoading, setIsLoading] = useState(false); - - const unwrap = async (args: UnwrapArgs): Promise => { - setIsLoading(true); - - try { - const { params, wallet, signTransaction } = args; - const { ownerPublicKey, mint, amount, decimals = 9 } = params; - - const rpc = createRpc(import.meta.env.VITE_HELIUS_RPC_URL); - - const owner = new PublicKey(ownerPublicKey); - const mintPubkey = new PublicKey(mint); - const tokenAmount = BigInt(Math.floor(amount * Math.pow(10, decimals))); - - // Auto-detect token program (SPL vs T22) from mint account owner - const mintAccountInfo = await rpc.getAccountInfo(mintPubkey); - if (!mintAccountInfo) throw new Error(`Mint account ${mint} not found`); - const tokenProgramId = mintAccountInfo.owner; - - // Destination: SPL/T22 associated token account - const splAta = getAssociatedTokenAddressSync(mintPubkey, owner, false, tokenProgramId); - - // Returns TransactionInstruction[][]. - // Each inner array is one transaction. - // Handles loading + unwrapping together. - const instructions = await createUnwrapInstructions( - rpc, splAta, owner, mintPubkey, tokenAmount, owner, - ); - - const signature = await signAndSendBatches(instructions, { - rpc, - feePayer: owner, - wallet, - signTransaction, - }); - - if (!signature) { - throw new Error('Unwrap returned no instructions'); - } - - return signature; - } finally { - setIsLoading(false); - } - }; - - return { unwrap, isLoading }; -} -``` diff --git a/snippets/code-snippets/privy/wrap/nodejs.mdx b/snippets/code-snippets/privy/wrap/nodejs.mdx deleted file mode 100644 index 8d4627cf..00000000 --- a/snippets/code-snippets/privy/wrap/nodejs.mdx +++ /dev/null @@ -1,87 +0,0 @@ -```typescript -import 'dotenv/config'; -import {PrivyClient} from '@privy-io/node'; -import {createRpc, LIGHT_TOKEN_PROGRAM_ID} from '@lightprotocol/stateless.js'; -import {PublicKey, Transaction, ComputeBudgetProgram} from '@solana/web3.js'; -import {getAssociatedTokenAddressSync, getAccount} from '@solana/spl-token'; -import {getSplInterfaceInfos} from '@lightprotocol/compressed-token'; -import { - createWrapInstruction, - getAssociatedTokenAddressInterface, - createAssociatedTokenAccountInterfaceIdempotentInstruction, -} from '@lightprotocol/compressed-token/unified'; - -const wrapTokens = async ( - fromAddress: string, - tokenMintAddress: string, - amount: number, - decimals: number = 9, -) => { - const connection = createRpc(process.env.HELIUS_RPC_URL!); - - const privy = new PrivyClient({ - appId: process.env.PRIVY_APP_ID!, - appSecret: process.env.PRIVY_APP_SECRET!, - }); - - const fromPubkey = new PublicKey(fromAddress); - const mintPubkey = new PublicKey(tokenMintAddress); - const tokenAmount = BigInt(Math.floor(amount * Math.pow(10, decimals))); - - // Get SPL interface info — determines whether mint uses SPL or Token 2022 - const splInterfaceInfos = await getSplInterfaceInfos(connection, mintPubkey); - const splInterfaceInfo = splInterfaceInfos.find( - (info) => info.isInitialized, - ); - if (!splInterfaceInfo) throw new Error('No SPL interface found for this mint'); - - // Derive source associated token account using the mint's token program (SPL or Token 2022) - const {tokenProgram} = splInterfaceInfo; - const splAta = getAssociatedTokenAddressSync(mintPubkey, fromPubkey, false, tokenProgram); - const ataAccount = await getAccount(connection, splAta, undefined, tokenProgram); - if (ataAccount.amount < BigInt(tokenAmount)) { - throw new Error('Insufficient SPL balance'); - } - - // Derive Light Token associated token account - const lightTokenAta = getAssociatedTokenAddressInterface(mintPubkey, fromPubkey); - - // Build instructions - const tx = new Transaction().add( - ComputeBudgetProgram.setComputeUnitLimit({units: 200_000}), - createAssociatedTokenAccountInterfaceIdempotentInstruction( - fromPubkey, lightTokenAta, fromPubkey, mintPubkey, LIGHT_TOKEN_PROGRAM_ID, - ), - createWrapInstruction( - splAta, lightTokenAta, fromPubkey, mintPubkey, - tokenAmount, splInterfaceInfo, decimals, fromPubkey, - ), - ); - - // Sign and send via Privy - const {blockhash} = await connection.getLatestBlockhash(); - tx.recentBlockhash = blockhash; - tx.feePayer = fromPubkey; - - const walletId = process.env.TREASURY_WALLET_ID!; - const authorizationKey = process.env.TREASURY_AUTHORIZATION_KEY!; - - const {signed_transaction} = await privy.wallets().solana().signTransaction( - walletId, { - transaction: tx.serialize({requireAllSignatures: false}), - authorization_context: {authorization_private_keys: [authorizationKey]}, - }, - ) as any; - - const signature = await connection.sendRawTransaction( - Buffer.from(signed_transaction, 'base64'), - {skipPreflight: false, preflightCommitment: 'confirmed'}, - ); - await connection.confirmTransaction(signature, 'confirmed'); - - return signature; -}; - -export default wrapTokens; - -``` diff --git a/snippets/code-snippets/privy/wrap/react.mdx b/snippets/code-snippets/privy/wrap/react.mdx deleted file mode 100644 index 7988b9ef..00000000 --- a/snippets/code-snippets/privy/wrap/react.mdx +++ /dev/null @@ -1,99 +0,0 @@ -```typescript -import { useState } from 'react'; -import { PublicKey, Transaction, ComputeBudgetProgram } from '@solana/web3.js'; -import { getAssociatedTokenAddressSync, getAccount } from '@solana/spl-token'; -import { getSplInterfaceInfos } from '@lightprotocol/compressed-token'; -import { - createWrapInstruction, - getAssociatedTokenAddressInterface, - createAssociatedTokenAccountInterfaceIdempotentInstruction, -} from '@lightprotocol/compressed-token/unified'; -import { createRpc, LIGHT_TOKEN_PROGRAM_ID } from '@lightprotocol/stateless.js'; -import type { ConnectedStandardSolanaWallet } from '@privy-io/js-sdk-core'; -import { useSignTransaction } from '@privy-io/react-auth/solana'; - -type SignTransactionFn = ReturnType['signTransaction']; - -export interface WrapParams { - ownerPublicKey: string; - mint: string; - amount: number; - decimals?: number; -} - -export interface WrapArgs { - params: WrapParams; - wallet: ConnectedStandardSolanaWallet; - signTransaction: SignTransactionFn; -} - -export function useWrap() { - const [isLoading, setIsLoading] = useState(false); - - const wrap = async (args: WrapArgs): Promise => { - setIsLoading(true); - - try { - const { params, wallet, signTransaction } = args; - const { ownerPublicKey, mint, amount, decimals = 9 } = params; - - const rpc = createRpc(import.meta.env.VITE_HELIUS_RPC_URL); - - const owner = new PublicKey(ownerPublicKey); - const mintPubkey = new PublicKey(mint); - const tokenAmount = BigInt(Math.floor(amount * Math.pow(10, decimals))); - - // Get SPL interface info — determines whether mint uses SPL or T22 - const splInterfaceInfos = await getSplInterfaceInfos(rpc, mintPubkey); - const splInterfaceInfo = splInterfaceInfos.find( - (info) => info.isInitialized, - ); - if (!splInterfaceInfo) throw new Error('No SPL interface found for this mint'); - const { tokenProgram } = splInterfaceInfo; - - // Derive source associated token account using the mint's token program (SPL or T22) - const splAta = getAssociatedTokenAddressSync(mintPubkey, owner, false, tokenProgram); - const ataAccount = await getAccount(rpc, splAta, undefined, tokenProgram); - if (ataAccount.amount < BigInt(tokenAmount)) { - throw new Error('Insufficient SPL balance'); - } - - // Derive light-token associated token account - const lightTokenAta = getAssociatedTokenAddressInterface(mintPubkey, owner); - - // Build transaction - const tx = new Transaction().add( - ComputeBudgetProgram.setComputeUnitLimit({ units: 200_000 }), - createAssociatedTokenAccountInterfaceIdempotentInstruction( - owner, lightTokenAta, owner, mintPubkey, LIGHT_TOKEN_PROGRAM_ID, - ), - createWrapInstruction( - splAta, lightTokenAta, owner, mintPubkey, - tokenAmount, splInterfaceInfo, decimals, owner, - ), - ); - - const { blockhash } = await rpc.getLatestBlockhash(); - tx.recentBlockhash = blockhash; - tx.feePayer = owner; - - const unsignedTxBuffer = tx.serialize({ requireAllSignatures: false }); - const signedTx = await signTransaction({ - transaction: unsignedTxBuffer, - wallet, - chain: 'solana:devnet', - }); - - const signedTxBuffer = Buffer.from(signedTx.signedTransaction); - return rpc.sendRawTransaction(signedTxBuffer, { - skipPreflight: false, - preflightCommitment: 'confirmed', - }); - } finally { - setIsLoading(false); - } - }; - - return { wrap, isLoading }; -} -``` diff --git a/snippets/code-snippets/streaming/find-closed-accounts.mdx b/snippets/code-snippets/streaming/find-closed-accounts.mdx index 50140fd0..f1a24696 100644 --- a/snippets/code-snippets/streaming/find-closed-accounts.mdx +++ b/snippets/code-snippets/streaming/find-closed-accounts.mdx @@ -57,6 +57,3 @@ fn find_closed_accounts( `cache.remove` filters out unrelated closures in the same transaction. No discriminator check is needed -- `compress_and_close` always drains lamports to zero. - -To build transactions that decompress cold accounts, see -[Router Integration](/light-token/defi/routers). diff --git a/snippets/code-snippets/wallet-adapter/balances/react.mdx b/snippets/code-snippets/wallet-adapter/balances/react.mdx deleted file mode 100644 index 0c9f60e8..00000000 --- a/snippets/code-snippets/wallet-adapter/balances/react.mdx +++ /dev/null @@ -1,177 +0,0 @@ -```typescript -import { useState, useCallback } from 'react'; -import { PublicKey, LAMPORTS_PER_SOL } from '@solana/web3.js'; -import { TOKEN_PROGRAM_ID, TOKEN_2022_PROGRAM_ID, getMint } from '@solana/spl-token'; -import { createRpc } from '@lightprotocol/stateless.js'; -import { - getAssociatedTokenAddressInterface, - getAtaInterface, -} from '@lightprotocol/compressed-token/unified'; - -export interface TokenBalance { - mint: string; - decimals: number; - isNative: boolean; - hot: bigint; - cold: bigint; - spl: bigint; - t22: bigint; - unified: bigint; -} - -export function useUnifiedBalance() { - const [balances, setBalances] = useState([]); - const [isLoading, setIsLoading] = useState(false); - - const fetchBalances = useCallback(async (ownerAddress: string) => { - if (!ownerAddress) return; - - setIsLoading(true); - try { - const rpc = createRpc(import.meta.env.VITE_HELIUS_RPC_URL); - const owner = new PublicKey(ownerAddress); - - // Per-mint accumulator - const mintMap = new Map(); - - const getOrCreate = (mintStr: string) => { - let entry = mintMap.get(mintStr); - if (!entry) { - entry = { spl: 0n, t22: 0n, hot: 0n, cold: 0n, decimals: 9, tokenProgram: TOKEN_PROGRAM_ID }; - mintMap.set(mintStr, entry); - } - return entry; - }; - - // 1. SOL balance - let solLamports = 0; - try { - solLamports = await rpc.getBalance(owner); - } catch { - // Failed to fetch SOL balance - } - - // 2. SPL accounts - try { - const splAccounts = await rpc.getTokenAccountsByOwner(owner, { - programId: TOKEN_PROGRAM_ID, - }); - for (const { account } of splAccounts.value) { - const buf = toBuffer(account.data); - if (!buf || buf.length < 72) continue; - const mint = new PublicKey(buf.subarray(0, 32)); - const amount = buf.readBigUInt64LE(64); - const mintStr = mint.toBase58(); - getOrCreate(mintStr).spl += amount; - } - } catch { - // No SPL accounts - } - - // 3. Token 2022 accounts - try { - const t22Accounts = await rpc.getTokenAccountsByOwner(owner, { - programId: TOKEN_2022_PROGRAM_ID, - }); - for (const { account } of t22Accounts.value) { - const buf = toBuffer(account.data); - if (!buf || buf.length < 72) continue; - const mint = new PublicKey(buf.subarray(0, 32)); - const amount = buf.readBigUInt64LE(64); - const mintStr = mint.toBase58(); - const entry = getOrCreate(mintStr); - entry.t22 += amount; - entry.tokenProgram = TOKEN_2022_PROGRAM_ID; - } - } catch { - // No Token 2022 accounts - } - - // 4. Cold balance from compressed token accounts - try { - const compressed = await rpc.getCompressedTokenBalancesByOwnerV2(owner); - for (const item of compressed.value.items) { - const mintStr = item.mint.toBase58(); - getOrCreate(mintStr).cold += BigInt(item.balance.toString()); - } - } catch { - // No compressed accounts - } - - // 5. Fetch actual decimals for each mint - const mintKeys = [...mintMap.keys()]; - await Promise.allSettled( - mintKeys.map(async (mintStr) => { - try { - const mint = new PublicKey(mintStr); - const entry = getOrCreate(mintStr); - const mintInfo = await getMint(rpc, mint, undefined, entry.tokenProgram); - entry.decimals = mintInfo.decimals; - } catch { - // Keep default decimals if mint fetch fails - } - }), - ); - - // 6. Hot balance from Light Token associated token account - await Promise.allSettled( - mintKeys.map(async (mintStr) => { - try { - const mint = new PublicKey(mintStr); - const ata = getAssociatedTokenAddressInterface(mint, owner); - const { parsed } = await getAtaInterface(rpc, ata, owner, mint); - const entry = getOrCreate(mintStr); - entry.hot = BigInt(parsed.amount.toString()); - } catch { - // Associated token account does not exist for this mint — hot stays 0n - } - }), - ); - - // 7. Assemble TokenBalance[] - const result: TokenBalance[] = []; - - // SOL entry - result.push({ - mint: 'So11111111111111111111111111111111111111112', - decimals: 9, - isNative: true, - hot: 0n, - cold: 0n, - spl: BigInt(solLamports), - t22: 0n, - unified: 0n, - }); - - // Token entries - for (const [mintStr, entry] of mintMap) { - result.push({ - mint: mintStr, - decimals: entry.decimals, - isNative: false, - hot: entry.hot, - cold: entry.cold, - spl: entry.spl, - t22: entry.t22, - unified: entry.hot + entry.cold, - }); - } - - setBalances(result); - } catch (error) { - console.error('Failed to fetch balances:', error); - setBalances([]); - } finally { - setIsLoading(false); - } - }, []); - - return { balances, isLoading, fetchBalances }; -} - -function toBuffer(data: Buffer | Uint8Array | string | unknown): Buffer | null { - if (data instanceof Buffer) return data; - if (data instanceof Uint8Array) return Buffer.from(data); - return null; -} -``` diff --git a/snippets/code-snippets/wallet-adapter/helpers/sign-and-send-batches.mdx b/snippets/code-snippets/wallet-adapter/helpers/sign-and-send-batches.mdx deleted file mode 100644 index bbf45657..00000000 --- a/snippets/code-snippets/wallet-adapter/helpers/sign-and-send-batches.mdx +++ /dev/null @@ -1,36 +0,0 @@ -```typescript -import { Transaction, TransactionInstruction, PublicKey } from '@solana/web3.js'; - -export type SignTransactionFn = (transaction: Transaction) => Promise; - -interface SignAndSendOptions { - rpc: any; - feePayer: PublicKey; - signTransaction: SignTransactionFn; -} - -export async function signAndSendBatches( - instructionBatches: TransactionInstruction[][], - options: SignAndSendOptions, -): Promise { - const { rpc, feePayer, signTransaction } = options; - const signatures: string[] = []; - - for (const ixs of instructionBatches) { - const tx = new Transaction().add(...ixs); - const { blockhash } = await rpc.getLatestBlockhash(); - tx.recentBlockhash = blockhash; - tx.feePayer = feePayer; - - const signedTx = await signTransaction(tx); - const sig = await rpc.sendRawTransaction(signedTx.serialize(), { - skipPreflight: false, - preflightCommitment: 'confirmed', - }); - await rpc.confirmTransaction(sig, 'confirmed'); - signatures.push(sig); - } - - return signatures.length > 0 ? signatures[signatures.length - 1] : null; -} -``` diff --git a/snippets/code-snippets/wallet-adapter/receive/react.mdx b/snippets/code-snippets/wallet-adapter/receive/react.mdx deleted file mode 100644 index 1c3e9b7a..00000000 --- a/snippets/code-snippets/wallet-adapter/receive/react.mdx +++ /dev/null @@ -1,57 +0,0 @@ -```typescript -import { useState } from 'react'; -import { PublicKey } from '@solana/web3.js'; -import { - createLoadAtaInstructions, - getAssociatedTokenAddressInterface, -} from '@lightprotocol/compressed-token/unified'; -import { createRpc } from '@lightprotocol/stateless.js'; -import { signAndSendBatches, type SignTransactionFn } from './signAndSendBatches'; - -export interface ReceiveParams { - ownerPublicKey: string; - mint: string; -} - -export interface ReceiveArgs { - params: ReceiveParams; - signTransaction: SignTransactionFn; -} - -export function useReceive() { - const [isLoading, setIsLoading] = useState(false); - - const receive = async (args: ReceiveArgs): Promise => { - setIsLoading(true); - - try { - const { params, signTransaction } = args; - - const rpc = import.meta.env.VITE_LOCALNET === 'true' - ? createRpc() - : createRpc(import.meta.env.VITE_HELIUS_RPC_URL); - - const owner = new PublicKey(params.ownerPublicKey); - const mintPubkey = new PublicKey(params.mint); - const ata = getAssociatedTokenAddressInterface(mintPubkey, owner); - - // Returns TransactionInstruction[][]. - // Each inner array is one transaction. - // Almost always returns just one. - const instructions = await createLoadAtaInstructions( - rpc, ata, owner, mintPubkey, owner, - ); - - return await signAndSendBatches(instructions, { - rpc, - feePayer: owner, - signTransaction, - }); - } finally { - setIsLoading(false); - } - }; - - return { receive, isLoading }; -} -``` diff --git a/snippets/code-snippets/wallet-adapter/transaction-history/react.mdx b/snippets/code-snippets/wallet-adapter/transaction-history/react.mdx deleted file mode 100644 index 1c98218e..00000000 --- a/snippets/code-snippets/wallet-adapter/transaction-history/react.mdx +++ /dev/null @@ -1,65 +0,0 @@ -```typescript -import { useState, useCallback } from 'react'; -import { PublicKey } from '@solana/web3.js'; -import { createRpc } from '@lightprotocol/stateless.js'; - -export interface Transaction { - signature: string; - slot: number; - blockTime: number; - timestamp: string; -} - -export function useTransactionHistory() { - const [transactions, setTransactions] = useState([]); - const [isLoading, setIsLoading] = useState(false); - const [error, setError] = useState(null); - - const fetchTransactionHistory = useCallback( - async ( - ownerAddress: string, - limit: number = 10, - ) => { - if (!ownerAddress) { - setTransactions([]); - return; - } - - setIsLoading(true); - setError(null); - - try { - const rpc = createRpc(import.meta.env.VITE_HELIUS_RPC_URL); - const owner = new PublicKey(ownerAddress); - - const result = await rpc.getSignaturesForOwnerInterface(owner); - - if (!result.signatures || result.signatures.length === 0) { - setTransactions([]); - return; - } - - const limitedSignatures = result.signatures.slice(0, limit); - - const basicTransactions = limitedSignatures.map((sig) => ({ - signature: sig.signature, - slot: sig.slot, - blockTime: sig.blockTime ?? 0, - timestamp: sig.blockTime ? new Date(sig.blockTime * 1000).toISOString() : '', - })); - - setTransactions(basicTransactions); - } catch (err) { - const message = err instanceof Error ? err.message : String(err); - setError(message); - setTransactions([]); - } finally { - setIsLoading(false); - } - }, - [] - ); - - return { transactions, isLoading, error, fetchTransactionHistory }; -} -``` diff --git a/snippets/code-snippets/wallet-adapter/transfer/react.mdx b/snippets/code-snippets/wallet-adapter/transfer/react.mdx deleted file mode 100644 index 8b4deb42..00000000 --- a/snippets/code-snippets/wallet-adapter/transfer/react.mdx +++ /dev/null @@ -1,65 +0,0 @@ -```typescript -import { useState } from 'react'; -import { PublicKey } from '@solana/web3.js'; -import { - createTransferInterfaceInstructions, -} from '@lightprotocol/compressed-token/unified'; -import { createRpc } from '@lightprotocol/stateless.js'; -import { signAndSendBatches, type SignTransactionFn } from './signAndSendBatches'; - -export interface TransferParams { - ownerPublicKey: string; - mint: string; - toAddress: string; - amount: number; - decimals?: number; -} - -export interface TransferArgs { - params: TransferParams; - signTransaction: SignTransactionFn; -} - -export function useTransfer() { - const [isLoading, setIsLoading] = useState(false); - - const transfer = async (args: TransferArgs): Promise => { - setIsLoading(true); - - try { - const { params, signTransaction } = args; - const { ownerPublicKey, mint, toAddress, amount, decimals = 9 } = params; - - const rpc = createRpc(import.meta.env.VITE_HELIUS_RPC_URL); - - const owner = new PublicKey(ownerPublicKey); - const mintPubkey = new PublicKey(mint); - const recipient = new PublicKey(toAddress); - const tokenAmount = Math.floor(amount * Math.pow(10, decimals)); - - // Returns TransactionInstruction[][]. - // Each inner array is one transaction. - // Almost always returns just one. - const instructions = await createTransferInterfaceInstructions( - rpc, owner, mintPubkey, tokenAmount, owner, recipient, - ); - - const signature = await signAndSendBatches(instructions, { - rpc, - feePayer: owner, - signTransaction, - }); - - if (!signature) { - throw new Error('Transfer returned no instructions'); - } - - return signature; - } finally { - setIsLoading(false); - } - }; - - return { transfer, isLoading }; -} -``` diff --git a/snippets/code-snippets/wallet-adapter/unwrap/react.mdx b/snippets/code-snippets/wallet-adapter/unwrap/react.mdx deleted file mode 100644 index 6ffead4c..00000000 --- a/snippets/code-snippets/wallet-adapter/unwrap/react.mdx +++ /dev/null @@ -1,72 +0,0 @@ -```typescript -import { useState } from 'react'; -import { PublicKey } from '@solana/web3.js'; -import { getAssociatedTokenAddressSync } from '@solana/spl-token'; -import { - createUnwrapInstructions, -} from '@lightprotocol/compressed-token/unified'; -import { createRpc } from '@lightprotocol/stateless.js'; -import { signAndSendBatches, type SignTransactionFn } from './signAndSendBatches'; - -export interface UnwrapParams { - ownerPublicKey: string; - mint: string; - amount: number; - decimals?: number; -} - -export interface UnwrapArgs { - params: UnwrapParams; - signTransaction: SignTransactionFn; -} - -export function useUnwrap() { - const [isLoading, setIsLoading] = useState(false); - - const unwrap = async (args: UnwrapArgs): Promise => { - setIsLoading(true); - - try { - const { params, signTransaction } = args; - const { ownerPublicKey, mint, amount, decimals = 9 } = params; - - const rpc = createRpc(import.meta.env.VITE_HELIUS_RPC_URL); - - const owner = new PublicKey(ownerPublicKey); - const mintPubkey = new PublicKey(mint); - const tokenAmount = BigInt(Math.floor(amount * Math.pow(10, decimals))); - - // Auto-detect token program (SPL vs T22) from mint account owner - const mintAccountInfo = await rpc.getAccountInfo(mintPubkey); - if (!mintAccountInfo) throw new Error(`Mint account ${mint} not found`); - const tokenProgramId = mintAccountInfo.owner; - - // Destination: SPL/T22 associated token account - const splAta = getAssociatedTokenAddressSync(mintPubkey, owner, false, tokenProgramId); - - // Returns TransactionInstruction[][]. - // Each inner array is one transaction. - // Handles loading + unwrapping together. - const instructions = await createUnwrapInstructions( - rpc, splAta, owner, mintPubkey, tokenAmount, owner, - ); - - const signature = await signAndSendBatches(instructions, { - rpc, - feePayer: owner, - signTransaction, - }); - - if (!signature) { - throw new Error('Unwrap returned no instructions'); - } - - return signature; - } finally { - setIsLoading(false); - } - }; - - return { unwrap, isLoading }; -} -``` diff --git a/snippets/code-snippets/wallet-adapter/wrap/react.mdx b/snippets/code-snippets/wallet-adapter/wrap/react.mdx deleted file mode 100644 index 3531d1d1..00000000 --- a/snippets/code-snippets/wallet-adapter/wrap/react.mdx +++ /dev/null @@ -1,90 +0,0 @@ -```typescript -import { useState } from 'react'; -import { PublicKey, Transaction, ComputeBudgetProgram } from '@solana/web3.js'; -import { getAssociatedTokenAddressSync, getAccount } from '@solana/spl-token'; -import { getSplInterfaceInfos } from '@lightprotocol/compressed-token'; -import { - createWrapInstruction, - getAssociatedTokenAddressInterface, - createAssociatedTokenAccountInterfaceIdempotentInstruction, -} from '@lightprotocol/compressed-token/unified'; -import { createRpc, LIGHT_TOKEN_PROGRAM_ID } from '@lightprotocol/stateless.js'; -import type { SignTransactionFn } from './signAndSendBatches'; - -export interface WrapParams { - ownerPublicKey: string; - mint: string; - amount: number; - decimals?: number; -} - -export interface WrapArgs { - params: WrapParams; - signTransaction: SignTransactionFn; -} - -export function useWrap() { - const [isLoading, setIsLoading] = useState(false); - - const wrap = async (args: WrapArgs): Promise => { - setIsLoading(true); - - try { - const { params, signTransaction } = args; - const { ownerPublicKey, mint, amount, decimals = 9 } = params; - - const rpc = createRpc(import.meta.env.VITE_HELIUS_RPC_URL); - - const owner = new PublicKey(ownerPublicKey); - const mintPubkey = new PublicKey(mint); - const tokenAmount = BigInt(Math.floor(amount * Math.pow(10, decimals))); - - // Get SPL interface info — determines whether mint uses SPL or T22 - const splInterfaceInfos = await getSplInterfaceInfos(rpc, mintPubkey); - const splInterfaceInfo = splInterfaceInfos.find( - (info) => info.isInitialized, - ); - if (!splInterfaceInfo) throw new Error('No SPL interface found for this mint'); - const { tokenProgram } = splInterfaceInfo; - - // Derive source associated token account using the mint's token program (SPL or T22) - const splAta = getAssociatedTokenAddressSync(mintPubkey, owner, false, tokenProgram); - const ataAccount = await getAccount(rpc, splAta, undefined, tokenProgram); - if (ataAccount.amount < BigInt(tokenAmount)) { - throw new Error('Insufficient SPL balance'); - } - - // Derive light-token associated token account - const lightTokenAta = getAssociatedTokenAddressInterface(mintPubkey, owner); - - // Build transaction - const tx = new Transaction().add( - ComputeBudgetProgram.setComputeUnitLimit({ units: 200_000 }), - createAssociatedTokenAccountInterfaceIdempotentInstruction( - owner, lightTokenAta, owner, mintPubkey, LIGHT_TOKEN_PROGRAM_ID, - ), - createWrapInstruction( - splAta, lightTokenAta, owner, mintPubkey, - tokenAmount, splInterfaceInfo, decimals, owner, - ), - ); - - const { blockhash } = await rpc.getLatestBlockhash(); - tx.recentBlockhash = blockhash; - tx.feePayer = owner; - - const signedTx = await signTransaction(tx); - const sig = await rpc.sendRawTransaction(signedTx.serialize(), { - skipPreflight: false, - preflightCommitment: 'confirmed', - }); - await rpc.confirmTransaction(sig, 'confirmed'); - return sig; - } finally { - setIsLoading(false); - } - }; - - return { wrap, isLoading }; -} -``` diff --git a/snippets/compressible-vs-solana-rent.mdx b/snippets/compressible-vs-solana-rent.mdx index 81e6ea47..9bf52b5c 100644 --- a/snippets/compressible-vs-solana-rent.mdx +++ b/snippets/compressible-vs-solana-rent.mdx @@ -3,7 +3,7 @@ The **creator of compressible accounts** tops-up the account with **rent for at ``` rust rent_per_epoch = base_rent + (data_len * lamports_per_byte_per_epoch) -// For 260-byte light-token account: +// For 260-byte compressed token account: // 128 + (260 * 1) = 388 lamports per epoch ``` diff --git a/snippets/cost-tables/cu-performance.mdx b/snippets/cost-tables/cu-performance.mdx deleted file mode 100644 index 9446fa42..00000000 --- a/snippets/cost-tables/cu-performance.mdx +++ /dev/null @@ -1,5 +0,0 @@ -| CU Performance | Light Token | SPL-Token | -|:---|---:|---:| -| **ATA Creation** | **4,348** | 14,194 | -| **Transfer** | **312** | 4,645 | -| **Transfer** (rent-free) | **1,885** | 4,645 | diff --git a/snippets/cost-tables/light-pda-cost.mdx b/snippets/cost-tables/light-pda-cost.mdx deleted file mode 100644 index dd21f63a..00000000 --- a/snippets/cost-tables/light-pda-cost.mdx +++ /dev/null @@ -1,3 +0,0 @@ -| Creation Cost | Regular PDA | Light-PDA | -|:---|---:|---:| -| **100-byte account** | ~0.0016 SOL | ~0.000012 SOL | diff --git a/snippets/cost-tables/mint-account-cost.mdx b/snippets/cost-tables/mint-account-cost.mdx deleted file mode 100644 index 6f694538..00000000 --- a/snippets/cost-tables/mint-account-cost.mdx +++ /dev/null @@ -1,3 +0,0 @@ -| Creation Cost | Light Token | SPL-Token | -|:---|---:|---:| -| **Mint Account** | **0.000091 SOL** | 0.0015 SOL | diff --git a/snippets/cost-tables/token-account-cost.mdx b/snippets/cost-tables/token-account-cost.mdx deleted file mode 100644 index 22d465fb..00000000 --- a/snippets/cost-tables/token-account-cost.mdx +++ /dev/null @@ -1,3 +0,0 @@ -| Creation Cost | Light Token | SPL-Token | -|:---|---:|---:| -| **Token Account** | **0.000017 SOL** | 0.0029 SOL | diff --git a/snippets/cost-tables/token-creation-cost.mdx b/snippets/cost-tables/token-creation-cost.mdx index 05ea393e..dca5012b 100644 --- a/snippets/cost-tables/token-creation-cost.mdx +++ b/snippets/cost-tables/token-creation-cost.mdx @@ -1,4 +1,3 @@ -| Creation Cost | Light Token | SPL / Token 2022 | +| Creation | Solana | Compressed | |:---|---:|---:| -| **Mint Account** | **0.000091 SOL** | 0.0015 SOL | -| **Token Account** | **0.000017 SOL** | 0.0029 SOL | +| **Token Account** | ~2,000,000 lamports | **5,000** lamports | diff --git a/snippets/jsx/light-token-vs-spl-calculator.jsx b/snippets/jsx/light-token-vs-spl-calculator.jsx deleted file mode 100644 index 0a4bf67b..00000000 --- a/snippets/jsx/light-token-vs-spl-calculator.jsx +++ /dev/null @@ -1,156 +0,0 @@ -export const LightTokenVsSplCalculator = () => { - const [numAccounts, setNumAccounts] = useState(100000); - const [showCustomAccounts, setShowCustomAccounts] = useState(false); - - const ACCOUNT_STORAGE_OVERHEAD = 128; - const LAMPORTS_PER_BYTE = 6960; - const DATA_LEN = 165; // SPL token account size - const LIGHT_TOKEN_DEFAULT_CREATION_COST = 17400; // Default rent config: 6,400 prepaid rent (24h) + 11,000 compression cost - const LAMPORTS_PER_SOL = 1_000_000_000; - - const ACCOUNTS_MAX = 1000000; - - const splCost = numAccounts * (ACCOUNT_STORAGE_OVERHEAD + DATA_LEN) * LAMPORTS_PER_BYTE; - const tokenCost = numAccounts * LIGHT_TOKEN_DEFAULT_CREATION_COST; - const savings = splCost - tokenCost; - const savingsPercent = ((savings / splCost) * 100).toFixed(1); - - const handleAccountsChange = (value) => { - const num = Math.max(1, Math.min(1000000, Number.parseInt(value) || 1)); - setNumAccounts(num); - }; - - const formatSOL = (lamports) => { - const sol = lamports / LAMPORTS_PER_SOL; - if (sol >= 1000) { - return sol.toLocaleString(undefined, { maximumFractionDigits: 2 }); - } else if (sol >= 1) { - return sol.toFixed(4); - } - return sol.toFixed(6); - }; - - const accountsPresets = [10000, 100000, 500000]; - - const SliderMarkers = ({ max, step }) => { - const marks = []; - for (let i = step; i < max; i += step) { - const percent = (i / max) * 100; - marks.push( -
- ); - } - return <>{marks}; - }; - - return ( -
-
- {/* Number of Accounts */} -
-
- - Number of Token Accounts - -
- {accountsPresets.map((a) => ( - - ))} - {showCustomAccounts ? ( - handleAccountsChange(e.target.value)} - className="w-24 px-2 py-1 text-right text-xs font-mono font-medium bg-blue-500/10 dark:bg-blue-500/20 border border-blue-500/50 rounded-lg backdrop-blur-sm focus:outline-none focus:ring-2 focus:ring-blue-500/50" - autoFocus - /> - ) : ( - - )} -
-
-
- - {numAccounts.toLocaleString()} accounts - -
- - { - setNumAccounts(Number.parseInt(e.target.value)); - setShowCustomAccounts(false); - }} - className="relative w-full h-1.5 bg-black/[0.03] dark:bg-white/20 rounded-full appearance-none cursor-pointer backdrop-blur-sm z-10" - /> -
-
-
- - {/* Result Cards */} -
-
-
- SPL Token -
-
- {formatSOL(splCost)} -
-
SOL
-
- -
-
- Light Token -
-
- {formatSOL(tokenCost)} -
-
SOL
-
- -
-
- Savings -
-
- {savingsPercent}% -
-
{formatSOL(savings)} SOL
-
-
-
-
- ); -}; diff --git a/snippets/light-token-configure-rent.mdx b/snippets/light-token-configure-rent.mdx deleted file mode 100644 index 92088710..00000000 --- a/snippets/light-token-configure-rent.mdx +++ /dev/null @@ -1,61 +0,0 @@ -```rust -use light_token::instruction::CompressibleParamsCpi; - -let compressible_params = CompressibleParamsCpi::new( - compressible_config.clone(), - rent_sponsor.clone(), - system_program.clone(), -); -``` - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - Compressible Config - - - Protocol PDA that stores account rent config.
- - - Rent Sponsor - - - - - light token program PDA that fronts rent exemption at creation. -
- Claims rent when account compresses. -
- - - System Program - - - Solana System Program to create the on-chain account.
diff --git a/snippets/light-token-guides/cata-intro.mdx b/snippets/light-token-guides/cata-intro.mdx deleted file mode 100644 index 7bb47701..00000000 --- a/snippets/light-token-guides/cata-intro.mdx +++ /dev/null @@ -1,11 +0,0 @@ -import CompressibleRentExplained from "/snippets/compressible-rent-explained.mdx"; -import CompressibleDefaultRentConfig from "/snippets/compressible-default-rent-config.mdx"; - -1. Associated light-token accounts (light-ATA) are Solana accounts that hold token balances of light-mints, SPL mints, or Token 2022 mints. -2. The address for light-ATAs is deterministically derived with the owner's address, _light token program ID_, and mint address. -3. light-ATAs accounts are compressible with a default rent config. - - - - - diff --git a/snippets/light-token-guides/client-custom-rent-config.mdx b/snippets/light-token-guides/client-custom-rent-config.mdx deleted file mode 100644 index 0fa31e53..00000000 --- a/snippets/light-token-guides/client-custom-rent-config.mdx +++ /dev/null @@ -1,67 +0,0 @@ -import { CompressibleRentCalculator } from '/snippets/jsx/compressible-rent-calculator.jsx'; - - -We recommend to use default values, but you can customize the rent config based on the expected account activity. - - -1. Set the hours to determine the amount of prepaid rent -2. Set the lamports per write a transaction payer will pay for top ups - -```rust -use light_token::instruction::{CompressibleParams, CreateTokenAccount}; -use light_compressible::config::CompressibleConfig; -use light_token_types::state::TokenDataVersion; - -let compressible_params = CompressibleParams { - compressible_config: CompressibleConfig::light_token_v1_config_pda(), - rent_sponsor: CompressibleConfig::light_token_v1_rent_sponsor_pda(), - pre_pay_num_epochs: 35, // ~52h - lamports_per_write: Some(788), - compress_to_account_pubkey: None, - token_account_version: TokenDataVersion::ShaFlat, -}; - -let instruction = CreateTokenAccount::new( - payer.pubkey(), - account.pubkey(), - mint, - owner, - compressible_params, -).instruction()?; -``` - - - - - - - - - - - - - - - - - - - - - - - - - - -
Compressible Config - Protocol PDA that stores account rent config. -
Rent Sponsor - - Light Token program PDA that fronts rent exemption at creation.
- - Claims rent when account compresses. -
System ProgramSolana System Program to create the on-chain account.
- - - - diff --git a/snippets/light-token-guides/close-intro.mdx b/snippets/light-token-guides/close-intro.mdx deleted file mode 100644 index c799d6e0..00000000 --- a/snippets/light-token-guides/close-intro.mdx +++ /dev/null @@ -1,5 +0,0 @@ -1. Closing a light-token account transfers remaining lamports to a destination account and the rent sponsor can reclaim sponsored rent. -2. light-token accounts can be closed - * by the account owner at any time. - * by the `compression_authority` - when the account becomes compressible. The account is compressed and closed - it can be loaded with the same state (decompressed). diff --git a/snippets/light-token-guides/light-token-client-prerequisites.mdx b/snippets/light-token-guides/light-token-client-prerequisites.mdx deleted file mode 100644 index 187bbcd3..00000000 --- a/snippets/light-token-guides/light-token-client-prerequisites.mdx +++ /dev/null @@ -1,12 +0,0 @@ -import RustInstallDependencies from '/snippets/setup/rust-install-dependencies.mdx'; -import RustSetupEnvironment from '/snippets/setup/rust-setup-environment-tabs.mdx'; - - - - - - - - - - diff --git a/snippets/light-token-guides/light-token-intro.mdx b/snippets/light-token-guides/light-token-intro.mdx deleted file mode 100644 index 383a3f39..00000000 --- a/snippets/light-token-guides/light-token-intro.mdx +++ /dev/null @@ -1,10 +0,0 @@ -import CompressibleRentExplained from '/snippets/compressible-rent-explained.mdx'; -import CompressibleDefaultRentConfig from '/snippets/compressible-default-rent-config.mdx'; - -1. light-token accounts are Solana accounts that hold token balances of light-mints, SPL mints, or Token 2022 mints. -2. light-token accounts are compressible with a default rent config. - - - - - diff --git a/snippets/light-token-guides/light-token-program-prerequisites.mdx b/snippets/light-token-guides/light-token-program-prerequisites.mdx deleted file mode 100644 index efc151c3..00000000 --- a/snippets/light-token-guides/light-token-program-prerequisites.mdx +++ /dev/null @@ -1,99 +0,0 @@ - - - -```toml Anchor Cargo.toml -[dependencies] -light-token = "0.23.0" -light-token-types = "0.23.0" -anchor-lang = "0.31.1" - -[dev-dependencies] -light-program-test = { version = "0.23.0", features = ["v2"] } -light-client = { version = "0.23.0", features = ["v2"] } -solana-sdk = "2" -tokio = { version = "1", features = ["full"] } -``` - -```toml Native Rust Cargo.toml -[dependencies] -light-token = "0.23.0" -light-compressible = "0.6.0" -light-token-interface = "0.5.0" -light-compressed-account = "0.11.0" -borsh = "0.10.4" -solana-program = "2.2" - -[dev-dependencies] -light-program-test = { version = "0.23.0", features = ["v2"] } -light-client = { version = "0.23.0", features = ["v2"] } -solana-sdk = "2" -tokio = { version = "1", features = ["full"] } -``` - - - - - - - - - -Test with LiteSVM: - -```bash -# Initialize project -cargo init my-light-project -cd my-light-project - -# Build -cargo build-sbf - -# Run tests -cargo test-sbf -``` - -```rust -use light_program_test::{LightProgramTest, ProgramTestConfig}; -use solana_sdk::signer::Signer; - -#[tokio::test] -async fn test_example() { - let mut rpc = LightProgramTest::new(ProgramTestConfig::default()) - .await - .unwrap(); - - let payer = rpc.get_payer().insecure_clone(); - println!("Payer: {}", payer.pubkey()); -} -``` - - - - -```bash -npm install -g @lightprotocol/zk-compression-cli -``` - -```bash -# Start local test validator (in separate terminal) -light test-validator -``` - - - - -Replace `` with your actual API key. [Get your API key here](https://www.helius.dev/zk-compression). - -```rust -use light_client::rpc::{LightClient, LightClientConfig, Rpc}; - -let rpc_url = "https://devnet.helius-rpc.com?api-key="; -let rpc = LightClient::new( - LightClientConfig::new(rpc_url.to_string(), None, None) -).await?; -``` - - - - - \ No newline at end of file diff --git a/snippets/light-token-guides/light-token-ts-client-prerequisites.mdx b/snippets/light-token-guides/light-token-ts-client-prerequisites.mdx deleted file mode 100644 index 6c73dd51..00000000 --- a/snippets/light-token-guides/light-token-ts-client-prerequisites.mdx +++ /dev/null @@ -1,14 +0,0 @@ -import InstallDependencies from '/snippets/setup/install-dependencies-codegroup.mdx'; -import SetupEnvironment from '/snippets/setup/setup-environment-tabs.mdx'; - - - - - - - - - - - - diff --git a/snippets/light-token-guides/token-interface-sdk2-callout.mdx b/snippets/light-token-guides/token-interface-sdk2-callout.mdx deleted file mode 100644 index 34c33f10..00000000 --- a/snippets/light-token-guides/token-interface-sdk2-callout.mdx +++ /dev/null @@ -1,5 +0,0 @@ - - **SDK 2.0 (`@lightprotocol/token-interface`)** is the latest JavaScript SDK. - It has better API ergonomics, guarantees single-instruction loading, and is - compatible with KIT (the new Solana SDKs). - diff --git a/snippets/light-token-guides/transfer-interface-intro.mdx b/snippets/light-token-guides/transfer-interface-intro.mdx deleted file mode 100644 index a79a483b..00000000 --- a/snippets/light-token-guides/transfer-interface-intro.mdx +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - -
**light-token → light-token Account** -
    -
  • Transfers light-tokens between light-token accounts
  • -
-
**SPL token → light-token Account** -
    -
  • Transfers SPL tokens to light-token accounts
  • -
  • SPL tokens are locked in interface PDA
  • -
  • light-tokens are minted to light-token account
  • -
-
**light-token → SPL Account** -
    -
  • Releases SPL tokens from interface PDA to SPL account
  • -
  • Burns light-tokens in source light-token account
  • -
-
- - - For example, **SPL → light-token** can be used for transfers from Alice's SPL token account to her own light-token account. You can use this to **convert existing SPL tokens to light-tokens** with **sponsored rent-exemption**. Learn more in the [core concepts to the light token program](/light-token/welcome). - diff --git a/snippets/migration-reference/macros/light-pda.mdx b/snippets/migration-reference/macros/light-pda.mdx deleted file mode 100644 index 93480170..00000000 --- a/snippets/migration-reference/macros/light-pda.mdx +++ /dev/null @@ -1,29 +0,0 @@ -```rust -use light_account::{ - CompressionInfo, LightAccount, LightAccounts, - CreateAccountsProof, derive_light_cpi_signer, - light_program, CpiSigner, LightDiscriminator, -}; - -#[light_program] -#[program] -pub mod my_program { - // instruction logic unchanged -} - -#[derive(LightAccount, LightDiscriminator)] -pub struct MyState { - pub compression_info: CompressionInfo, - pub authority: Pubkey, - pub data: u64, -} - -#[derive(LightAccounts)] -pub struct Initialize<'info> { - #[light_account(init)] - pub state: UncheckedAccount<'info>, - #[account(mut)] - pub pda_rent_sponsor: AccountInfo<'info>, - // ... -} -``` diff --git a/snippets/overview-tables/compressed-pdas-guides-table.mdx b/snippets/overview-tables/compressed-pdas-guides-table.mdx index 32066e3c..6a6a28c0 100644 --- a/snippets/overview-tables/compressed-pdas-guides-table.mdx +++ b/snippets/overview-tables/compressed-pdas-guides-table.mdx @@ -12,37 +12,37 @@ - Create + Create Initialize compressed PDAs in your program - Update + Update Modify state in compressed accounts - Close + Close Reclaim lamports from compressed accounts - Reinitialize + Reinitialize Reset and reuse compressed accounts - Burn + Burn Permanently delete compressed accounts - Nullifier PDAs + Nullifier PDAs Prevent replay attacks with one-time use accounts diff --git a/snippets/overview-tables/compressed-tokens-advanced-guides-table.mdx b/snippets/overview-tables/compressed-tokens-advanced-guides-table.mdx index 9f752f9d..5d43fac2 100644 --- a/snippets/overview-tables/compressed-tokens-advanced-guides-table.mdx +++ b/snippets/overview-tables/compressed-tokens-advanced-guides-table.mdx @@ -1,4 +1,4 @@ | Guide | Description | | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------ | -| [Create an Airdrop without Claim](/token-distribution) | ZK Compression is the most efficient way to distribute SPL tokens. Distribute via Webapp or customize with claim. | -| [Privy Guide](/light-token/wallets/privy) | Integrate light-tokens with Privy embedded wallets for rent-free token accounts | +| [Create an Airdrop without Claim](/compressed-tokens/token-distribution) | ZK Compression is the most efficient way to distribute SPL tokens. Distribute via Webapp or customize with claim. | +| [Privy Guide](/compressed-tokens/privy) | Integrate compressed tokens with Privy embedded wallets for rent-free token accounts | diff --git a/snippets/overview-tables/cookbook-guides-table.mdx b/snippets/overview-tables/cookbook-guides-table.mdx deleted file mode 100644 index a855886c..00000000 --- a/snippets/overview-tables/cookbook-guides-table.mdx +++ /dev/null @@ -1,98 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Create Mint - Create a Light mint with token metadata, or create SPL and Token 2022 mints with interface PDA for interoperability
- Add Interface PDA - Add an interface PDA to an existing SPL or Token 2022 mint for interoperability with Light Token
- Create ATA - Create associated light-token accounts
- Create Token Account - Create light-token accounts
- Mint To - Mint tokens to light-token accounts
- Transfer - Transfer between Light Token, SPL and Token 2022 accounts
- Transfer Checked - Transfer between Light Token accounts with decimals verification
- Approve & Revoke - Delegate and revoke token authority
- Transfer Delegated - Transfer tokens as an approved delegate
- Freeze & Thaw - Freeze and thaw light-token accounts
- Wrap & Unwrap - Convert between SPL/Token 2022 and light-token
- Load ATA - Load cold light-token accounts to hot balance for transfers in one instruction
- Close Token Account - Close token account to reclaim remaining lamports
- Burn - Burn tokens from light-token accounts
diff --git a/snippets/overview-tables/examples-guides-table.mdx b/snippets/overview-tables/examples-guides-table.mdx deleted file mode 100644 index d0d9dbb3..00000000 --- a/snippets/overview-tables/examples-guides-table.mdx +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - -
- Client - TypeScript and Rust client examples for light-token SDK
- Program - Anchor program examples for light-token CPI, Macros and more
\ No newline at end of file diff --git a/snippets/overview-tables/integrate-light-token-guides-table.mdx b/snippets/overview-tables/integrate-light-token-guides-table.mdx deleted file mode 100644 index 33c764d6..00000000 --- a/snippets/overview-tables/integrate-light-token-guides-table.mdx +++ /dev/null @@ -1,6 +0,0 @@ -| | | -| :---- | :---------- | -| [for Stablecoin Payments](/light-token/payments/overview) | Process payments and transfers using light-token | -| [for Wallets](/light-token/wallets/overview) | Allow your users to store and swap tokens more efficiently | -| [for Streaming Mints](/light-token/streaming/mints) | Stream light-mint accounts | -| [for Indexing Tokens](/light-token/streaming/tokens) | Index light-token accounts | diff --git a/snippets/overview-tables/light-mint-guides-table.mdx b/snippets/overview-tables/light-mint-guides-table.mdx deleted file mode 100644 index 52088e41..00000000 --- a/snippets/overview-tables/light-mint-guides-table.mdx +++ /dev/null @@ -1,4 +0,0 @@ -| | | -| :---- | :---------- | -| [Create Mint Account](/light-token/cookbook/create-mint) | Program and client guide to create light-mints with token metadata | -| [Mint Tokens](/light-token/cookbook/mint-to) | Mint tokens to light-token accounts | diff --git a/snippets/overview-tables/light-token-client-examples-table.mdx b/snippets/overview-tables/light-token-client-examples-table.mdx deleted file mode 100644 index 8044fc04..00000000 --- a/snippets/overview-tables/light-token-client-examples-table.mdx +++ /dev/null @@ -1,66 +0,0 @@ -### Toolkits - -| | | | -|---------|-------------|-------------| -| **payments** | All you need for wallet integrations and payment flows. Minimal API differences to SPL. | [Example](https://github.com/Lightprotocol/examples-light-token/tree/main/toolkits/payments) \| [Docs](/light-token/payments/overview) | -| **sign-with-privy** | Light-token operations signed with Privy wallets (Node.js + React) | [Example](https://github.com/Lightprotocol/examples-light-token/tree/main/toolkits/sign-with-privy) \| [Docs](/light-token/wallets/privy) | -| **sign-with-wallet-adapter** | Light-token operations signed with Wallet Adapter (React) | [Example](https://github.com/Lightprotocol/examples-light-token/tree/main/toolkits/sign-with-wallet-adapter) \| [Docs](/light-token/wallets/wallet-adapter) | -| **gasless-transactions** | Abstract SOL fees so users never hold SOL. Sponsor rent top-ups and transaction fees. | [Example](https://github.com/Lightprotocol/examples-light-token/tree/main/toolkits/gasless-transactions) \| [Docs](/light-token/wallets/gasless-transactions) | -| **spl-to-light** | Transfer from SPL to Light via TransferInterface | [Example](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/instructions/spl_to_light_transfer.rs) | - -### TypeScript - -| | | | | -|---------|--------|-------------|------| -| **approve** | [Action](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/actions/delegate-approve.ts) | [Instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/instructions/delegate-approve.ts) | [Docs](/light-token/cookbook/approve-revoke) | -| **create-ata** | [Action](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/actions/create-ata.ts) | [Instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/instructions/create-ata.ts) | [Docs](/light-token/cookbook/create-ata) | -| **create-ata-explicit-rent-sponsor** | [Action](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/actions/create-ata-explicit-rent-sponsor.ts) | — | [Docs](/light-token/cookbook/create-ata) | -| **create-mint** | [Action](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/actions/create-mint.ts) | [Instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/instructions/create-mint.ts) | [Docs](/light-token/cookbook/create-mint) | -| **create-spl-interface** | [Action](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/actions/create-spl-interface.ts) | [Instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/instructions/create-spl-interface.ts) | [Docs](light-token/cookbook/add-interface-pda) | -| **create-spl-mint** | [Action](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/actions/create-spl-mint.ts) | [Instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/instructions/create-spl-mint.ts) | [Docs](/light-token/cookbook/create-mint#create-spl-mint-with-interface-pda) | -| **create-t22-mint** | [Action](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/actions/create-t22-mint.ts) | [Instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/instructions/create-t22-mint.ts) | [Docs](/light-token/cookbook/create-mint#create-token-2022-mint-with-interface-pda) | -| **delegate-transfer** | [Action](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/actions/delegate-transfer.ts) | — | [Docs](/light-token/cookbook/transfer-delegated) | -| **load-ata** | [Action](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/actions/load-ata.ts) | [Instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/instructions/load-ata.ts) | [Docs](/light-token/cookbook/load-ata) | -| **mint-to** | [Action](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/actions/mint-to.ts) | [Instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/instructions/mint-to.ts) | [Docs](/light-token/cookbook/mint-to) | -| **revoke** | [Action](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/actions/delegate-revoke.ts) | [Instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/instructions/delegate-revoke.ts) | [Docs](/light-token/cookbook/approve-revoke) | -| **transfer-interface** | [Action](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/actions/transfer-interface.ts) | [Instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/instructions/transfer-interface.ts) | [Docs](/light-token/cookbook/transfer-interface) | -| **unwrap** | [Action](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/actions/unwrap.ts) | [Instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/instructions/unwrap.ts) | [Docs](/light-token/cookbook/wrap-unwrap) | -| **wrap** | [Action](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/actions/wrap.ts) | [Instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/typescript-client/instructions/wrap.ts) | [Docs](/light-token/cookbook/wrap-unwrap) | - -### Rust - -| | | | | -|---------|--------|-------------|------| -| **approve** | [Action](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/actions/approve.rs) | [Instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/instructions/approve.rs) | [Docs](/light-token/cookbook/approve-revoke) | -| **burn** | — | [Instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/instructions/burn.rs) | [Docs](/light-token/cookbook/burn) | -| **burn-checked** | — | [Instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/instructions/burn_checked.rs) | [Docs](/light-token/cookbook/burn) | -| **close** | — | [Instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/instructions/close.rs) | [Docs](/light-token/cookbook/close-token-account) | -| **create-ata** | [Action](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/actions/create_associated_token_account.rs) | [Instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/instructions/create_associated_token_account.rs) | [Docs](/light-token/cookbook/create-ata) | -| **create-mint** | [Action](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/actions/create_mint.rs) | [Instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/instructions/create_mint.rs) | [Docs](/light-token/cookbook/create-mint) | -| **create-token-account** | — | [Instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/instructions/create_token_account.rs) | [Docs](/light-token/cookbook/create-token-account) | -| **freeze** | — | [Instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/instructions/freeze.rs) | [Docs](/light-token/cookbook/freeze-thaw) | -| **mint-to** | [Action](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/actions/mint_to.rs) | [Instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/instructions/mint_to.rs) | [Docs](/light-token/cookbook/mint-to) | -| **mint-to-checked** | — | [Instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/instructions/mint_to_checked.rs) | [Docs](/light-token/cookbook/mint-to) | -| **revoke** | [Action](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/actions/revoke.rs) | [Instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/instructions/revoke.rs) | [Docs](/light-token/cookbook/approve-revoke) | -| **thaw** | — | [Instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/instructions/thaw.rs) | [Docs](/light-token/cookbook/freeze-thaw) | -| **transfer-checked** | [Action](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/actions/transfer_checked.rs) | [Instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/instructions/transfer_checked.rs) | [Docs](/light-token/cookbook/transfer-checked) | -| **transfer-interface** | [Action](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/actions/transfer_interface.rs) | [Instruction](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/instructions/transfer_interface.rs) | [Docs](/light-token/cookbook/transfer-interface) | -| **unwrap** | [Action](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/actions/unwrap.rs) | — | [Docs](/light-token/cookbook/wrap-unwrap) | -| **wrap** | [Action](https://github.com/Lightprotocol/examples-light-token/blob/main/rust-client/actions/wrap.rs) | — | [Docs](/light-token/cookbook/wrap-unwrap) | - -### Extensions - -See how [Light Token works with Token 2022 extensions](/light-token/extensions/overview). - -| | | -|---------|-------------| -| **close-mint** | [Example](https://github.com/Lightprotocol/examples-light-token/blob/main/extensions/close-mint.ts) | -| **confidential-transfer** | [Example](https://github.com/Lightprotocol/examples-light-token/blob/main/extensions/confidential-transfer.ts) | -| **default-account-state** | [Example](https://github.com/Lightprotocol/examples-light-token/blob/main/extensions/default-account-state.ts) | -| **interest-bearing-tokens** | [Example](https://github.com/Lightprotocol/examples-light-token/blob/main/extensions/interest-bearing-tokens.ts) | -| **metadata-and-metadata-pointer** | [Example](https://github.com/Lightprotocol/examples-light-token/blob/main/extensions/metadata-and-metadata-pointer.ts) | -| **pausable-mint** | [Example](https://github.com/Lightprotocol/examples-light-token/blob/main/extensions/pausable-mint.ts) | -| **permanent-delegate** | [Example](https://github.com/Lightprotocol/examples-light-token/blob/main/extensions/permanent-delegate.ts) | -| **token-groups-and-members** | [Example](https://github.com/Lightprotocol/examples-light-token/blob/main/extensions/token-groups-and-members.ts) | -| **transfer-fees** | [Example](https://github.com/Lightprotocol/examples-light-token/blob/main/extensions/transfer-fees.ts) | -| **transfer-hook** | [Example](https://github.com/Lightprotocol/examples-light-token/blob/main/extensions/transfer-hook.ts) | diff --git a/snippets/overview-tables/light-token-guides-table.mdx b/snippets/overview-tables/light-token-guides-table.mdx deleted file mode 100644 index 6c8218cc..00000000 --- a/snippets/overview-tables/light-token-guides-table.mdx +++ /dev/null @@ -1,6 +0,0 @@ -| | | -| :---- | :---------- | -| [Create Token Accounts](/light-token/cookbook/create-token-account) | | -| [Create Associated light-token Accounts](/light-token/cookbook/create-ata) | | -| [Transfer Interface](/light-token/cookbook/transfer-interface) | For transfers between light-token and SPL token accounts. | -| [Close Token Accounts](/light-token/cookbook/close-token-account) | | diff --git a/snippets/overview-tables/light-token-program-examples-table.mdx b/snippets/overview-tables/light-token-program-examples-table.mdx deleted file mode 100644 index d59e6a54..00000000 --- a/snippets/overview-tables/light-token-program-examples-table.mdx +++ /dev/null @@ -1,40 +0,0 @@ -### Examples - -| | Description | | -|---------|-------------|------| -| **cp-swap-reference** | Fork of Raydium AMM that creates markets without paying rent-exemption | [Example](https://github.com/Lightprotocol/cp-swap-reference) \| [Docs](/light-token/defi/programs) | -| **create-and-transfer** | Create account via macro and transfer via CPI | [Example](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/create-and-transfer) | -| **escrow** | Peer-to-peer light-token swap with offer/accept flow | [Example](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/escrow) | -| **fundraiser** | Token fundraiser with target, deadline, and refunds | [Example](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/fundraiser) | -| **light-token-minter** | Create light-mints with metadata, mint tokens | [Example](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/light-token-minter) | -| **pinocchio-swap** | Light Token swap reference implementation | [Example](https://github.com/Lightprotocol/examples-light-token/tree/main/pinocchio/swap) \| [Docs](/light-token/defi/programs-pinocchio) | -| **token-swap** | AMM with liquidity pools and swaps | [Example](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/token-swap) | - -### Macros - -| | Description | | -|---------|-------------|------| -| **counter** | Create PDA with sponsored rent-exemption | [Example](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-macros/counter) \| [Docs](/pda/light-pda/overview) | -| **create-associated-token-account** | Create associated light-token account | [Example](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-macros/create-associated-token-account) \| [Docs](/light-token/cookbook/create-ata) | -| **create-mint** | Create light-token mint | [Example](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-macros/create-mint) \| [Docs](/light-token/cookbook/create-mint) | -| **create-token-account** | Create light-token account | [Example](https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-macros/create-token-account) \| [Docs](/light-token/cookbook/create-token-account) | - -### Instructions - -The instructions use pure CPI calls which you can combine with existing and / or light macros. -For existing programs, you can replace spl_token with light_token instructions as you need. The API is a superset of SPL-token so switching is straightforward. - -| | Description | | -|---------|-------------|------| -| **approve** | Approve delegate via CPI | [Example](https://github.com/Lightprotocol/examples-light-token/blob/main/programs/anchor/basic-instructions/approve/src/lib.rs) \| [Docs](/light-token/cookbook/approve-revoke) | -| **burn** | Burn tokens via CPI | [Example](https://github.com/Lightprotocol/examples-light-token/blob/main/programs/anchor/basic-instructions/burn/src/lib.rs) \| [Docs](/light-token/cookbook/burn) | -| **close** | Close token account via CPI | [Example](https://github.com/Lightprotocol/examples-light-token/blob/main/programs/anchor/basic-instructions/close/src/lib.rs) \| [Docs](/light-token/cookbook/close-token-account) | -| **create-associated-token-account** | Create associated light-token account via CPI | [Example](https://github.com/Lightprotocol/examples-light-token/blob/main/programs/anchor/basic-instructions/create-associated-token-account/src/lib.rs) \| [Docs](/light-token/cookbook/create-ata) | -| **create-mint** | Create light-token mint via CPI | [Example](https://github.com/Lightprotocol/examples-light-token/blob/main/programs/anchor/basic-instructions/create-mint/src/lib.rs) \| [Docs](/light-token/cookbook/create-mint) | -| **create-token-account** | Create light-token account via CPI | [Example](https://github.com/Lightprotocol/examples-light-token/blob/main/programs/anchor/basic-instructions/create-token-account/src/lib.rs) \| [Docs](/light-token/cookbook/create-token-account) | -| **freeze** | Freeze token account via CPI | [Example](https://github.com/Lightprotocol/examples-light-token/blob/main/programs/anchor/basic-instructions/freeze/src/lib.rs) \| [Docs](/light-token/cookbook/freeze-thaw) | -| **mint-to** | Mint tokens via CPI | [Example](https://github.com/Lightprotocol/examples-light-token/blob/main/programs/anchor/basic-instructions/mint-to/src/lib.rs) \| [Docs](/light-token/cookbook/mint-to) | -| **revoke** | Revoke delegate via CPI | [Example](https://github.com/Lightprotocol/examples-light-token/blob/main/programs/anchor/basic-instructions/revoke/src/lib.rs) \| [Docs](/light-token/cookbook/approve-revoke) | -| **thaw** | Thaw token account via CPI | [Example](https://github.com/Lightprotocol/examples-light-token/blob/main/programs/anchor/basic-instructions/thaw/src/lib.rs) \| [Docs](/light-token/cookbook/freeze-thaw) | -| **transfer-checked** | Transfer with mint validation via CPI | [Example](https://github.com/Lightprotocol/examples-light-token/blob/main/programs/anchor/basic-instructions/transfer-checked/src/lib.rs) \| [Docs](/light-token/cookbook/transfer-checked) | -| **transfer-interface** | Transfer between light-token, Token 2022, and SPL accounts via CPI | [Example](https://github.com/Lightprotocol/examples-light-token/blob/main/programs/anchor/basic-instructions/transfer-interface/src/lib.rs) \| [Docs](/light-token/cookbook/transfer-interface) | diff --git a/snippets/overview-tables/sdk-reference.mdx b/snippets/overview-tables/sdk-reference.mdx index ced6b237..f68e65ac 100644 --- a/snippets/overview-tables/sdk-reference.mdx +++ b/snippets/overview-tables/sdk-reference.mdx @@ -6,20 +6,17 @@ icon="js" href="https://lightprotocol.github.io/light-protocol/stateless.js/index.html" > - TypeScript RPC client for Light Token and Compressed Accounts. + TypeScript RPC client for ZK Compression and compressed accounts. - Rust RPC client for Light Token and ZK Compression. + Rust RPC client for ZK Compression. - TypeScript token operations for Light Token and Compressed Tokens. - - - Rust token operations for Light Token. + TypeScript token operations for compressed tokens. @@ -32,9 +29,6 @@ Procedural macros for Light accounts. - - CPI instructions for Light Token program. - -Use the [payments](https://github.com/Lightprotocol/skills/tree/main/skills/payments) agent skill to add light-token payment support to your project: +Use the [payments](https://github.com/Lightprotocol/skills/tree/main/skills/payments) agent skill to add compressed token payment support to your project: diff --git a/snippets/setup/payments-setup-helper.mdx b/snippets/setup/payments-setup-helper.mdx index b4308034..2c4acf1a 100644 --- a/snippets/setup/payments-setup-helper.mdx +++ b/snippets/setup/payments-setup-helper.mdx @@ -30,7 +30,7 @@ export const payer = Keypair.fromSecretKey( ) ); -/** Create SPL mint, fund payer, wrap into light-token ATA. */ +/** Create SPL mint, fund payer, wrap into compressed token ATA. */ export async function setup(amount = 1_000_000_000) { const { mint } = await createMintInterface( rpc, diff --git a/snippets/setup/register-spl-mint.mdx b/snippets/setup/register-spl-mint.mdx index 0e3688a6..830314ad 100644 --- a/snippets/setup/register-spl-mint.mdx +++ b/snippets/setup/register-spl-mint.mdx @@ -1,6 +1,6 @@ ## One-time: Create interface PDA to existing SPL Mint -For existing SPL mints (e.g. USDC), register the SPL interface once. This creates the omnibus PDA that holds SPL tokens when wrapped to light-token. +For existing SPL mints (e.g. USDC), register the SPL interface once. This creates the omnibus PDA that holds SPL tokens when wrapped to a compressed token account. Find a full code example [here](https://github.com/Lightprotocol/examples-light-token/blob/main/toolkits/payments/interop/register-spl-mint.ts). diff --git a/support.mdx b/support.mdx index 9ee746aa..b1f1a023 100644 --- a/support.mdx +++ b/support.mdx @@ -1,6 +1,6 @@ --- title: Support -description: Get expert help with Light-Token and ZK Compression. Discord community, Telegram, and Email support available. +description: Get expert help with Compressed Tokens and ZK Compression. Discord community, Telegram, and Email support available. --- diff --git a/zk/overview.mdx b/zk/overview.mdx index 41488c4c..57069a34 100644 --- a/zk/overview.mdx +++ b/zk/overview.mdx @@ -122,7 +122,7 @@ ZK applications on Solana can use existing state Merkle trees to store state in -Your circuit must include compressed accounts. Find [guides to compressed accounts in the documentation](/pda/compressed-pdas/overview) and the [full example with zk implementation here](https://github.com/Lightprotocol/program-examples/blob/99d260f9f356743b8fe3501c684f7926930d6079/zk-id/circuits/compressed_account.circom). +Your circuit must include compressed accounts. Find [guides to compressed accounts in the documentation](/compressed-pdas/overview) and the [full example with zk implementation here](https://github.com/Lightprotocol/program-examples/blob/99d260f9f356743b8fe3501c684f7926930d6079/zk-id/circuits/compressed_account.circom). ## Get Started & Examples From bdf7e6dbd4af62c9a35aed1e232b5e3aad723b9f Mon Sep 17 00:00:00 2001 From: Tilo Palfner Date: Tue, 9 Jun 2026 02:31:56 +0100 Subject: [PATCH 2/2] fix broken link in delegate guide --- compressed-tokens/guides/delegate.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compressed-tokens/guides/delegate.mdx b/compressed-tokens/guides/delegate.mdx index 1a507f08..7894b193 100644 --- a/compressed-tokens/guides/delegate.mdx +++ b/compressed-tokens/guides/delegate.mdx @@ -158,9 +158,9 @@ for (const delegate of delegates) { # Next Steps