Payment docs: restructure, add guides, production readiness#31
Payment docs: restructure, add guides, production readiness#31
Conversation
10 new pages mirroring Solana payments structure: - Send: basic payment, memo, verify address, batch, fee abstraction - Accept: receive payments, verify payments - Advanced: spend permissions, deferred execution - Interop: wrap/unwrap for CEX on/off-ramp - Production readiness checklist Update docs.json navigation and overview.mdx cards.
Delegation (approve/revoke) not yet supported on Light Token associated token accounts. Remove from nav and cross-links until SDK exposes interface functions for hot accounts.
Rename page, snippets, nav entries, redirects, and all cross-references. Add redirect from old URL. Update descriptions to "Abstract SOL fees so users never hold SOL. Sponsor rent top-ups and transaction fees."
|
Important Review skippedToo many files! This PR contains 166 files, which is 16 over the limit of 150. ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (166)
You can disable this status message by setting the Use the checkbox below for a quick retry:
WalkthroughThis PR significantly expands Light Token payment documentation by introducing nine new comprehensive guides covering transfer types, verification, and spend permissions; restructures wallet guidance from "rent top-ups" to "gasless transactions"; reorganizes navigation and redirects; adds numerous TypeScript code snippets and examples; and removes beta disclaimers from DeFi program documentation. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
📝 Coding Plan
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
| <Card title="Basic payment" icon="arrow-right" href="/light-token/payments/basic-payment"> | ||
| Send a single token transfer. | ||
| </Card> | ||
| <Card title="Verify address" icon="shield-check" href="/light-token/payments/verify-address"> |
There was a problem hiding this comment.
🔴 Broken internal link to non-existent page /light-token/payments/verify-address
In the newly added verify-payments.mdx, the "Verify address" card links to /light-token/payments/verify-address, but the actual page file is light-token/payments/verify-recipient-address.mdx and is registered in docs.json:73 as "light-token/payments/verify-recipient-address". There is no redirect defined for /light-token/payments/verify-address either. Clicking this card will result in a 404.
| <Card title="Verify address" icon="shield-check" href="/light-token/payments/verify-address"> | |
| <Card title="Verify address" icon="shield-check" href="/light-token/payments/verify-recipient-address"> |
Was this helpful? React with 👍 or 👎 to provide feedback.
| EXAMPLES="/home/tilo/Workspace/examples-light-token-main/toolkits/payments" | ||
| SNIPPETS_DIR="/home/tilo/Workspace/docs-main/snippets/code-snippets/payments" |
There was a problem hiding this comment.
🟡 Hardcoded absolute local paths in copy-payments-snippets.sh
The new script scripts/copy-payments-snippets.sh has hardcoded absolute paths referencing /home/tilo/Workspace/... (lines 6-7). This script will fail for any developer other than the original author since these paths are machine-specific. The script should use relative paths or environment variables.
Prompt for agents
In scripts/copy-payments-snippets.sh lines 6-7, replace the hardcoded absolute paths with relative paths or environment variables. For example, use SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd) to derive the docs snippets directory relative to the script location, and accept the examples-light-token repo path as a command-line argument or environment variable (e.g. EXAMPLES=${1:-../examples-light-token/toolkits/payments}).
Was this helpful? React with 👍 or 👎 to provide feedback.
There was a problem hiding this comment.
Actionable comments posted: 13
🧹 Nitpick comments (6)
snippets/code-snippets/payments/interop/wrap.mdx (1)
20-20: Non-null assertion onprocess.env.API_KEYmay fail silently.Same issue as in
register-spl-mint.mdx— ifAPI_KEYis not set, the URL will containundefined, causing cryptic RPC errors. Consider adding validation for consistency across snippets.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@snippets/code-snippets/payments/interop/wrap.mdx` at line 20, The RPC_URL constant is built using a non-null assertion on process.env.API_KEY which can produce a URL with "undefined" if the env var is missing; update the initialization of RPC_URL to validate process.env.API_KEY first (e.g., check API_KEY presence at startup or throw/log a clear error) and only interpolate when present, ensuring code that uses RPC_URL (the RPC_URL constant) will never receive an invalid URL; include a clear error message that mentions API_KEY when it is absent.snippets/code-snippets/payments/interop/register-spl-mint.mdx (2)
29-29: Placeholder address will cause a runtimePublicKeyerror.The string
"YOUR_EXISTING_MINT_ADDRESS"is not a valid base58 public key, sonew PublicKey(...)will throw immediately if users run this snippet without modification. Consider adding a validation check or a clearer early-exit pattern.💡 Suggested improvement
- const mint = new PublicKey("YOUR_EXISTING_MINT_ADDRESS"); + const MINT_ADDRESS = "YOUR_EXISTING_MINT_ADDRESS"; // Replace with actual mint + if (MINT_ADDRESS.startsWith("YOUR_")) { + throw new Error("Replace MINT_ADDRESS with your actual SPL mint public key"); + } + const mint = new PublicKey(MINT_ADDRESS);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@snippets/code-snippets/payments/interop/register-spl-mint.mdx` at line 29, The snippet creates a PublicKey from the literal "YOUR_EXISTING_MINT_ADDRESS" which will throw at runtime; update the mint creation to validate the input before calling new PublicKey and handle errors gracefully: check that the provided mint string is not the placeholder/empty and matches expected base58 length/format, then construct PublicKey(mintString) inside a try/catch (or explicit validation function) and if invalid log/throw a clear message and early-exit; refer to the PublicKey constructor and the mint variable when making these changes.
16-16: Non-null assertion onprocess.env.API_KEYmay fail silently.If
API_KEYis not set, the URL will containundefined, causing cryptic RPC errors rather than a clear failure. Adding an early check improves DX.💡 Suggested improvement
+if (!process.env.API_KEY) { + throw new Error("API_KEY environment variable is required"); +} const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@snippets/code-snippets/payments/interop/register-spl-mint.mdx` at line 16, The RPC_URL constant uses a non-null assertion on process.env.API_KEY which can produce an invalid URL if the env var is missing; update the top-level initialization around RPC_URL to explicitly validate process.env.API_KEY (the API_KEY env) before building RPC_URL (the RPC_URL constant) and fail fast with a clear error/exception or process exit when the key is absent so you never construct a URL containing "undefined".snippets/code-snippets/payments/send/payment-with-memo.mdx (1)
65-69: Memo log filtering captures program invocation logs, not the memo content itself.The filter matches log lines containing the Memo program ID, which includes the program invocation entry. To extract the actual memo text, you may also want to look for the subsequent log line or parse the data more specifically. Current approach works for demonstration but users may expect to see
"INV-2024-001"directly.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@snippets/code-snippets/payments/send/payment-with-memo.mdx` around lines 65 - 69, The current filter (logs.filter(...) using the Memo program ID) only captures the program invocation line, not the memo text; update the extraction so after finding lines that include "Program MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr" (or the variable holding that program id) you also read the subsequent log line(s) (or the "Program log:" entry) to capture the actual memo string (e.g., "INV-2024-001"); change the memoLogs derivation (where txDetails, logs, and memoLogs are used) to locate the invocation index and pull the next log entry or parse the "Program log:" entries instead of only filtering by program id.snippets/code-snippets/payments/verify/verify-address.mdx (1)
42-46: Emptycatchblocks swallow all errors, not just "account not found".The catch blocks assume any error means the account doesn't exist, but this could mask network failures, RPC rate limits, or other unexpected errors. For production-quality examples, consider checking the error type.
💡 Suggested improvement
} catch (e) { + // In production, check if error indicates "account not found" vs other failures console.log( "Account does not exist yet — will be created on first transfer" ); }Also applies to: 52-59
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@snippets/code-snippets/payments/verify/verify-address.mdx` around lines 42 - 46, Empty catch blocks swallow errors when checking account existence; update the two catch blocks (the one handling "Account does not exist yet — will be created on first transfer" and the second catch at 52-59) to inspect the thrown error and only treat it as "account not found" when it matches a specific error code/message; otherwise log the full error (e.g., console.error) and rethrow or surface it so network/RPC/permission errors aren’t silently ignored.snippets/code-snippets/payments/interop/unwrap.mdx (1)
20-21: Fail fast whenAPI_KEYis missing.Using
process.env.API_KEY!here can produce a broken URL silently. Add an explicit guard so the snippet fails with a clear message.Suggested patch
-const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +const apiKey = process.env.API_KEY; +if (!apiKey) { + throw new Error("Missing API_KEY. Set API_KEY in your environment."); +} +const RPC_URL = `https://devnet.helius-rpc.com?api-key=${apiKey}`;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@snippets/code-snippets/payments/interop/unwrap.mdx` around lines 20 - 21, The snippet builds RPC_URL using process.env.API_KEY! which can produce a broken URL silently; add an explicit guard before constructing RPC_URL to check process.env.API_KEY (or a const like API_KEY) and throw or console.error+process.exit with a clear message if missing, then use that validated API_KEY when creating RPC_URL and calling createRpc (reference symbols: RPC_URL, createRpc, process.env.API_KEY); ensure the guard runs early so the example fails fast with a clear error instead of producing an invalid URL.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@light-token/payments/batch-payments.mdx`:
- Around line 96-104: The loop currently iterates only over ixs[0], dropping
additional batches returned by createTransferInterfaceInstructions; change the
loop to iterate over each batch in ixs (e.g., for (const batch of ixs)) and then
iterate each TransactionInstruction in the batch, applying the same duplicate
ComputeBudget filter (using COMPUTE_BUDGET_ID) and pushing valid instructions
into allTransferIxs while preserving the isFirst check; update references around
the ixs variable, the inner iterator, and the duplicate filter logic so all
transaction batches are processed.
In `@light-token/payments/overview.mdx`:
- Line 105: Update the Card component's title prop to use the correct
singular/possessive form: locate the Card with title="Verify Recipients Address"
(the Card element in the diff) and change the title string to either "Verify
Recipient Address" or "Verify Recipient's Address" so the grammar is correct.
In `@light-token/payments/payment-with-memo.mdx`:
- Around line 46-50: The docs advertise installing `@solana/spl-memo` but the
examples still manually build a memo instruction; either remove the npm install
line or update the examples to import and use createMemoInstruction from that
package (replace the manual TransactionInstruction construction with
createMemoInstruction(memo, signers?) and add the import statement for
createMemoInstruction from "@solana/spl-memo"); update all examples that
manually construct a memo to use the createMemoInstruction helper so the
installation instruction is actually used.
In `@light-token/payments/receive-payments.mdx`:
- Around line 14-15: Reword the sentence that currently reads “We recommend to
prepend a load instruction before.” to a clear, grammatical instruction:
explicitly state that users should prepend a "load" instruction (or call) to
create the associated token account if needed and to load any cold balance into
it — e.g., "Prepend a 'load' instruction to create the associated token account
if needed and to load any cold balance into it." Ensure the term Load (or "load"
instruction) is used consistently.
- Around line 106-123: Import Transaction from "@solana/web3.js" and avoid
redeclaring the ata const: in the example that builds an instruction using
createAssociatedTokenAccountInstruction, add Transaction to the imports and
either reuse the existing ata variable or rename the result of
getOrCreateAssociatedTokenAccount (e.g., ataAccount) instead of re-declaring
const ata; update references so getAssociatedTokenAddressSync(mint, recipient)
-> ata is used for the instruction and the await
getOrCreateAssociatedTokenAccount(connection, payer, mint, recipient) result is
stored in a distinct identifier (or assigned to the same variable without a new
const).
In `@light-token/payments/spend-permissions.mdx`:
- Around line 76-84: The delegate approval snippets pass the wrong signer:
update each approveInterface(...) call to use the token owner as the signing
argument (owner) instead of payer so the token-owner actually signs the
approval; specifically, change the final argument in approveInterface
invocations in delegate-approve.mdx, delegate-full-flow.mdx, delegate-check.mdx,
and delegate-revoke.mdx to pass owner (matching the documented behavior) while
keeping delegate.publicKey, amount cap, and other args unchanged.
In `@light-token/payments/verify-recipient-address.mdx`:
- Around line 3-4: Frontmatter contains typos: fix the navigation metadata by
correcting the keys' values — change sidebarTitle from "Verify Recipients
Address" to "Verify Recipient Address" and update description from "VVerify
recipient addresses before sending payments. Address validation prevents sending
tokens to invalid or unexpected account types." to "Verify recipient addresses
before sending payments. Address validation prevents sending tokens to invalid
or unexpected account types." so the sidebarTitle and description strings are
spelled and capitalized correctly.
In `@light-token/payments/wrap-unwrap.mdx`:
- Around line 14-16: Update the compound modifiers for readability by
hyphenating them where they describe an associated token account: replace
occurrences of "Light Token associated token account" with "Light
Token-associated token account" and "SPL or Token 2022 account" usages that
describe the account target with "SPL-associated token account" and "Token
2022-associated token account" (also update the occurrences around the same
phrasing at lines ~118-119). Ensure all similar phrases in wrap-unwrap.mdx use
the hyphenated form for consistency.
In `@light-token/wallets/gasless-transactions.mdx`:
- Around line 21-22: Fix the grammar in the paragraph beginning "Rent
sponsorship is a built-in feature..." by replacing the incorrect possessive
"Light SDK’s that sponsors" with a correct plural/verb agreement and clearer
wording: refer to the phrase "Light SDKs" (no apostrophe) and use "sponsor" or
rephrase to "The Light SDKs sponsor rent-exemption for all account types..." and
ensure the second sentence references "under the hood" and "SPL-token"
consistently (e.g., "This is handled under the hood in a way that doesn’t
disrupt the UX your users expect from SPL Token.") so subject-verb agreement and
punctuation are corrected while preserving original meaning.
In `@light-token/wallets/smart-wallets.mdx`:
- Line 11: Remove the stray horizontal rule marker '---' that appears
immediately after the imports in smart-wallets.mdx; locate the standalone line
containing only '---' (top of file after the import block) and delete it so the
page no longer renders an unintended separator.
In `@scripts/copy-payments-snippets.sh`:
- Around line 6-7: The script uses hardcoded absolute paths in the EXAMPLES and
SNIPPETS_DIR variables which will fail on other machines/CI; update
scripts/copy-payments-snippets.sh to read EXAMPLES and SNIPPETS_DIR from
environment variables (e.g., ${EXAMPLES:-...} style) or require them and exit
with an error if unset, mirroring the pattern used in
copy-sponsor-top-ups-snippets.sh; ensure you reference and replace the EXAMPLES
and SNIPPETS_DIR variable assignments in the file and add a guard that prints a
helpful message and exits nonzero when either variable is not provided.
In `@snippets/ai-prompts/wallets/smart-wallets.mdx`:
- Line 32: Whitelist the token "sqds" for cspell so CI stops failing: add "sqds"
to the repository cspell dictionary (cspell.json/cspell.yaml) or add an inline
cspell directive at the top of the file smart-wallets.mdx to ignore/allow `sqds`
(the occurrences are the `@sqds` package token mentioned around the
smartAccount/createLightTokenTransferInstruction lines). Ensure the change only
whitelists the token (do not alter the package name) and apply the same fix for
both occurrences mentioned (lines near 32 and 60).
In `@snippets/code-snippets/payments/send/batch-send.mdx`:
- Around line 53-57: The loop only consumes ixs[0], dropping any preceding
“load” batches returned by createTransferInterfaceInstructions; fix by either
pre-loading ATAs with createLoadAtaInstructions before creating transfers, or
iterate all instruction batches in ixs (for each batch in ixs) and append their
instructions to allTransferIxs (still skipping COMPUTE_BUDGET_ID entries as done
now), ensuring createTransferInterfaceInstructions' multi-batch output is fully
processed.
---
Nitpick comments:
In `@snippets/code-snippets/payments/interop/register-spl-mint.mdx`:
- Line 29: The snippet creates a PublicKey from the literal
"YOUR_EXISTING_MINT_ADDRESS" which will throw at runtime; update the mint
creation to validate the input before calling new PublicKey and handle errors
gracefully: check that the provided mint string is not the placeholder/empty and
matches expected base58 length/format, then construct PublicKey(mintString)
inside a try/catch (or explicit validation function) and if invalid log/throw a
clear message and early-exit; refer to the PublicKey constructor and the mint
variable when making these changes.
- Line 16: The RPC_URL constant uses a non-null assertion on process.env.API_KEY
which can produce an invalid URL if the env var is missing; update the top-level
initialization around RPC_URL to explicitly validate process.env.API_KEY (the
API_KEY env) before building RPC_URL (the RPC_URL constant) and fail fast with a
clear error/exception or process exit when the key is absent so you never
construct a URL containing "undefined".
In `@snippets/code-snippets/payments/interop/unwrap.mdx`:
- Around line 20-21: The snippet builds RPC_URL using process.env.API_KEY! which
can produce a broken URL silently; add an explicit guard before constructing
RPC_URL to check process.env.API_KEY (or a const like API_KEY) and throw or
console.error+process.exit with a clear message if missing, then use that
validated API_KEY when creating RPC_URL and calling createRpc (reference
symbols: RPC_URL, createRpc, process.env.API_KEY); ensure the guard runs early
so the example fails fast with a clear error instead of producing an invalid
URL.
In `@snippets/code-snippets/payments/interop/wrap.mdx`:
- Line 20: The RPC_URL constant is built using a non-null assertion on
process.env.API_KEY which can produce a URL with "undefined" if the env var is
missing; update the initialization of RPC_URL to validate process.env.API_KEY
first (e.g., check API_KEY presence at startup or throw/log a clear error) and
only interpolate when present, ensuring code that uses RPC_URL (the RPC_URL
constant) will never receive an invalid URL; include a clear error message that
mentions API_KEY when it is absent.
In `@snippets/code-snippets/payments/send/payment-with-memo.mdx`:
- Around line 65-69: The current filter (logs.filter(...) using the Memo program
ID) only captures the program invocation line, not the memo text; update the
extraction so after finding lines that include "Program
MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr" (or the variable holding that
program id) you also read the subsequent log line(s) (or the "Program log:"
entry) to capture the actual memo string (e.g., "INV-2024-001"); change the
memoLogs derivation (where txDetails, logs, and memoLogs are used) to locate the
invocation index and pull the next log entry or parse the "Program log:" entries
instead of only filtering by program id.
In `@snippets/code-snippets/payments/verify/verify-address.mdx`:
- Around line 42-46: Empty catch blocks swallow errors when checking account
existence; update the two catch blocks (the one handling "Account does not exist
yet — will be created on first transfer" and the second catch at 52-59) to
inspect the thrown error and only treat it as "account not found" when it
matches a specific error code/message; otherwise log the full error (e.g.,
console.error) and rethrow or surface it so network/RPC/permission errors aren’t
silently ignored.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 0915083e-9e5a-40a4-bb3c-9a5cdf8d12eb
📒 Files selected for processing (47)
README.mddocs.jsonfaq.mdxlight-token/defi/programs-pinocchio.mdxlight-token/defi/programs.mdxlight-token/defi/routers.mdxlight-token/payments/basic-payment.mdxlight-token/payments/batch-payments.mdxlight-token/payments/integration-guide.mdxlight-token/payments/overview.mdxlight-token/payments/payment-with-memo.mdxlight-token/payments/production-readiness.mdxlight-token/payments/receive-payments.mdxlight-token/payments/spend-permissions.mdxlight-token/payments/verify-payments.mdxlight-token/payments/verify-recipient-address.mdxlight-token/payments/wrap-unwrap.mdxlight-token/wallets/gasless-transactions.mdxlight-token/wallets/overview.mdxlight-token/wallets/smart-wallets.mdxlight-token/wallets/sponsor-top-ups.mdxlight-token/welcome.mdxpda/compressed-pdas/nullifier-pda.mdxscripts/copy-payments-snippets.shskill.mdsnippets/ai-prompts/all-prompts.mdxsnippets/ai-prompts/wallets/gasless-transactions.mdxsnippets/ai-prompts/wallets/smart-wallets.mdxsnippets/code-snippets/light-token/gasless-transactions/rust-instruction.mdxsnippets/code-snippets/light-token/gasless-transactions/ts-instruction.mdxsnippets/code-snippets/payments/interop/register-spl-mint.mdxsnippets/code-snippets/payments/interop/unwrap.mdxsnippets/code-snippets/payments/interop/wrap.mdxsnippets/code-snippets/payments/receive/receive.mdxsnippets/code-snippets/payments/send/batch-send.mdxsnippets/code-snippets/payments/send/payment-with-memo.mdxsnippets/code-snippets/payments/send/send-action.mdxsnippets/code-snippets/payments/send/send-instruction.mdxsnippets/code-snippets/payments/send/sign-all-transactions.mdxsnippets/code-snippets/payments/spend-permissions/delegate-approve.mdxsnippets/code-snippets/payments/spend-permissions/delegate-check.mdxsnippets/code-snippets/payments/spend-permissions/delegate-full-flow.mdxsnippets/code-snippets/payments/spend-permissions/delegate-revoke.mdxsnippets/code-snippets/payments/verify/get-balance.mdxsnippets/code-snippets/payments/verify/get-history.mdxsnippets/code-snippets/payments/verify/verify-address.mdxsnippets/overview-tables/light-token-client-examples-table.mdx
💤 Files with no reviewable changes (4)
- light-token/defi/programs.mdx
- light-token/defi/routers.mdx
- light-token/defi/programs-pinocchio.mdx
- light-token/wallets/sponsor-top-ups.mdx
| for (const { address, amount } of recipients) { | ||
| const ixs = await createTransferInterfaceInstructions( | ||
| rpc, payer.publicKey, mint, amount, owner.publicKey, address | ||
| ); | ||
| // Filter duplicate ComputeBudget instructions from subsequent calls | ||
| for (const ix of ixs[0]) { | ||
| if (!isFirst && ix.programId.toBase58() === COMPUTE_BUDGET_ID) continue; | ||
| allTransferIxs.push(ix); | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify single-batch indexing usage on createTransferInterfaceInstructions output.
rg -n 'createTransferInterfaceInstructions|ixs\[0\]' light-token/payments/batch-payments.mdxRepository: Lightprotocol/docs-v2
Length of output: 461
🏁 Script executed:
# Read the batch-payments.mdx file to understand context and other usages
wc -l light-token/payments/batch-payments.mdxRepository: Lightprotocol/docs-v2
Length of output: 108
🏁 Script executed:
# Get context around the problematic lines and other usages
head -175 light-token/payments/batch-payments.mdx | tail -80Repository: Lightprotocol/docs-v2
Length of output: 2419
🏁 Script executed:
# Check how other usages handle the return value (lines 125, 150, 170)
sed -n '120,180p' light-token/payments/batch-payments.mdxRepository: Lightprotocol/docs-v2
Length of output: 1804
Use for (const batch of ixs) instead of for (const ix of ixs[0]) to process all transaction batches.
The code only accesses ixs[0], but createTransferInterfaceInstructions() returns TransactionInstruction[][] and can return multiple batches (e.g., for cold account loading). Accessing only the first batch silently drops instructions that may be required. The documentation in this same file explicitly states: "The loop pattern handles the rare multi-transaction case (cold account loading) automatically" and shows the correct pattern in the "TransactionInstruction[][] pattern" section.
Proposed fix
for (const { address, amount } of recipients) {
const ixs = await createTransferInterfaceInstructions(
rpc, payer.publicKey, mint, amount, owner.publicKey, address
);
// Filter duplicate ComputeBudget instructions from subsequent calls
- for (const ix of ixs[0]) {
+ for (const batch of ixs) {
+ for (const ix of batch) {
if (!isFirst && ix.programId.toBase58() === COMPUTE_BUDGET_ID) continue;
allTransferIxs.push(ix);
- }
+ isFirst = false;
+ }
- isFirst = false;
}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@light-token/payments/batch-payments.mdx` around lines 96 - 104, The loop
currently iterates only over ixs[0], dropping additional batches returned by
createTransferInterfaceInstructions; change the loop to iterate over each batch
in ixs (e.g., for (const batch of ixs)) and then iterate each
TransactionInstruction in the batch, applying the same duplicate ComputeBudget
filter (using COMPUTE_BUDGET_ID) and pushing valid instructions into
allTransferIxs while preserving the isFirst check; update references around the
ixs variable, the inner iterator, and the duplicate filter logic so all
transaction batches are processed.
| <Card title="Receive payments" icon="arrow-down" href="/light-token/payments/receive-payments" horizontal /> | ||
| <Card title="Payment with memo" icon="memo" href="/light-token/payments/payment-with-memo" horizontal /> | ||
| <Card title="Get Balance and Transaction History" icon="magnifying-glass" href="/light-token/payments/verify-payments" horizontal /> | ||
| <Card title="Verify Recipients Address" icon="shield-check" href="/light-token/payments/verify-recipient-address" horizontal /> |
There was a problem hiding this comment.
Fix grammar in the card title.
“Verify Recipients Address” should be singular/possessive (e.g., “Verify Recipient Address” or “Verify Recipient’s Address”).
✏️ Suggested text fix
-<Card title="Verify Recipients Address" icon="shield-check" href="/light-token/payments/verify-recipient-address" horizontal />
+<Card title="Verify Recipient Address" icon="shield-check" href="/light-token/payments/verify-recipient-address" horizontal />📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <Card title="Verify Recipients Address" icon="shield-check" href="/light-token/payments/verify-recipient-address" horizontal /> | |
| <Card title="Verify Recipient Address" icon="shield-check" href="/light-token/payments/verify-recipient-address" horizontal /> |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@light-token/payments/overview.mdx` at line 105, Update the Card component's
title prop to use the correct singular/possessive form: locate the Card with
title="Verify Recipients Address" (the Card element in the diff) and change the
title string to either "Verify Recipient Address" or "Verify Recipient's
Address" so the grammar is correct.
| Additionally install the memo program package: | ||
|
|
||
| ```bash | ||
| npm install @solana/spl-memo | ||
| ``` |
There was a problem hiding this comment.
Package installation suggested but not used in code examples.
The documentation instructs users to install @solana/spl-memo, but the code examples manually construct the memo instruction instead of using createMemoInstruction from that package. Either remove the install instruction or update the code to use the library.
Option A: Use the installed package
+import { createMemo } from "@solana/spl-memo";
+
// Add memo to the transfer transaction
-const memoIx = new TransactionInstruction({
- keys: [],
- programId: MEMO_PROGRAM_ID,
- data: Buffer.from("INV-2024-001"),
-});
+const memoIx = createMemo({ memo: "INV-2024-001" }, []);Option B: Remove the unused package instruction
-Additionally install the memo program package:
-
-```bash
-npm install `@solana/spl-memo`
-```📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| Additionally install the memo program package: | |
| ```bash | |
| npm install @solana/spl-memo | |
| ``` |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@light-token/payments/payment-with-memo.mdx` around lines 46 - 50, The docs
advertise installing `@solana/spl-memo` but the examples still manually build a
memo instruction; either remove the npm install line or update the examples to
import and use createMemoInstruction from that package (replace the manual
TransactionInstruction construction with createMemoInstruction(memo, signers?)
and add the import statement for createMemoInstruction from "@solana/spl-memo");
update all examples that manually construct a memo to use the
createMemoInstruction helper so the installation instruction is actually used.
| 2. We recommend to prepend a load instruction before. | ||
| Load creates the associated token account if needed and loads any cold balance into it. |
There was a problem hiding this comment.
Tighten the load-step instruction wording.
Current phrasing is hard to parse (“prepend a load instruction before”). Suggest making this explicit and grammatical for first-time readers.
✏️ Suggested wording
-2. We recommend to prepend a load instruction before.
-Load creates the associated token account if needed and loads any cold balance into it.
+2. We recommend prepending a load step before sending.
+ This creates the associated token account if needed and loads any cold balance into it.📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| 2. We recommend to prepend a load instruction before. | |
| Load creates the associated token account if needed and loads any cold balance into it. | |
| 2. We recommend prepending a load step before sending. | |
| This creates the associated token account if needed and loads any cold balance into it. |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@light-token/payments/receive-payments.mdx` around lines 14 - 15, Reword the
sentence that currently reads “We recommend to prepend a load instruction
before.” to a clear, grammatical instruction: explicitly state that users should
prepend a "load" instruction (or call) to create the associated token account if
needed and to load any cold balance into it — e.g., "Prepend a 'load'
instruction to create the associated token account if needed and to load any
cold balance into it." Ensure the term Load (or "load" instruction) is used
consistently.
| ```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 | ||
| ); |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify duplicate declaration and missing Transaction import in this snippet block.
rg -n 'const ata =|new Transaction\(' light-token/payments/receive-payments.mdxRepository: Lightprotocol/docs-v2
Length of output: 474
🏁 Script executed:
sed -n '100,130p' light-token/payments/receive-payments.mdx | cat -nRepository: Lightprotocol/docs-v2
Length of output: 872
Fix non-compiling SPL comparison snippet (const redeclaration + missing import).
Line 116 uses Transaction without importing it from @solana/web3.js, and line 121 redeclares const ata already declared on line 113. This snippet won't compile as-is when copied.
💡 Proposed fix
+import { Transaction } from "@solana/web3.js";
import {
createAssociatedTokenAccountInstruction,
getAssociatedTokenAddressSync,
getOrCreateAssociatedTokenAccount,
} from "@solana/spl-token";
-const ata = getAssociatedTokenAddressSync(mint, recipient);
+const destinationAta = getAssociatedTokenAddressSync(mint, recipient);
// Instruction:
const tx = new Transaction().add(
- createAssociatedTokenAccountInstruction(payer.publicKey, ata, recipient, mint)
+ createAssociatedTokenAccountInstruction(
+ payer.publicKey,
+ destinationAta,
+ recipient,
+ mint
+ )
);
// Action:
-const ata = await getOrCreateAssociatedTokenAccount(
+const destinationAccount = await getOrCreateAssociatedTokenAccount(
connection, payer, mint, recipient
);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| ```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 | |
| ); | |
| import { Transaction } from "@solana/web3.js"; | |
| import { | |
| createAssociatedTokenAccountInstruction, | |
| getAssociatedTokenAddressSync, | |
| getOrCreateAssociatedTokenAccount, | |
| } from "@solana/spl-token"; | |
| const destinationAta = getAssociatedTokenAddressSync(mint, recipient); | |
| // Instruction: | |
| const tx = new Transaction().add( | |
| createAssociatedTokenAccountInstruction( | |
| payer.publicKey, | |
| destinationAta, | |
| recipient, | |
| mint | |
| ) | |
| ); | |
| // Action: | |
| const destinationAccount = await getOrCreateAssociatedTokenAccount( | |
| connection, payer, mint, recipient | |
| ); |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@light-token/payments/receive-payments.mdx` around lines 106 - 123, Import
Transaction from "@solana/web3.js" and avoid redeclaring the ata const: in the
example that builds an instruction using
createAssociatedTokenAccountInstruction, add Transaction to the imports and
either reuse the existing ata variable or rename the result of
getOrCreateAssociatedTokenAccount (e.g., ataAccount) instead of re-declaring
const ata; update references so getAssociatedTokenAddressSync(mint, recipient)
-> ata is used for the instruction and the await
getOrCreateAssociatedTokenAccount(connection, payer, mint, recipient) result is
stored in a distinct identifier (or assigned to the same variable without a new
const).
| Rent sponsorship is a built-in feature of the Light SDK’s that sponsors rent-exemption for all account types to reduce creation cost. | ||
| 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. |
There was a problem hiding this comment.
Fix grammar in rent sponsorship explanation.
“Light SDK’s that sponsors…” reads incorrectly and may reduce trust in a core concept section.
✏️ Suggested wording
-Rent sponsorship is a built-in feature of the Light SDK’s that sponsors rent-exemption for all account types to reduce creation cost.
+Rent sponsorship is a built-in feature of the Light SDK that sponsors rent-exemption for all account types to reduce account-creation cost.📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| Rent sponsorship is a built-in feature of the Light SDK’s that sponsors rent-exemption for all account types to reduce creation cost. | |
| 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. | |
| Rent sponsorship is a built-in feature of the Light SDK that sponsors rent-exemption for all account types to reduce account-creation cost. | |
| 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. |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@light-token/wallets/gasless-transactions.mdx` around lines 21 - 22, Fix the
grammar in the paragraph beginning "Rent sponsorship is a built-in feature..."
by replacing the incorrect possessive "Light SDK’s that sponsors" with a correct
plural/verb agreement and clearer wording: refer to the phrase "Light SDKs" (no
apostrophe) and use "sponsor" or rephrase to "The Light SDKs sponsor
rent-exemption for all account types..." and ensure the second sentence
references "under the hood" and "SPL-token" consistently (e.g., "This is handled
under the hood in a way that doesn’t disrupt the UX your users expect from SPL
Token.") so subject-verb agreement and punctuation are corrected while
preserving original meaning.
| import SmartWalletsAiPrompt from "/snippets/ai-prompts/wallets/smart-wallets.mdx"; | ||
| import SupportFooter from "/snippets/support-footer.mdx"; | ||
|
|
||
| --- |
There was a problem hiding this comment.
Remove the stray horizontal rule marker.
The standalone --- after imports is likely accidental and introduces an unnecessary top-of-page separator.
🧹 Proposed fix
----🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@light-token/wallets/smart-wallets.mdx` at line 11, Remove the stray
horizontal rule marker '---' that appears immediately after the imports in
smart-wallets.mdx; locate the standalone line containing only '---' (top of file
after the import block) and delete it so the page no longer renders an
unintended separator.
| EXAMPLES="/home/tilo/Workspace/examples-light-token-main/toolkits/payments" | ||
| SNIPPETS_DIR="/home/tilo/Workspace/docs-main/snippets/code-snippets/payments" |
There was a problem hiding this comment.
Hardcoded absolute paths will break on other machines and CI.
The paths /home/tilo/Workspace/... are user-specific and won't work for other contributors or CI environments. The existing copy-sponsor-top-ups-snippets.sh script demonstrates the recommended pattern using environment variables with a required check.
🔧 Suggested fix using environment variables
-EXAMPLES="/home/tilo/Workspace/examples-light-token-main/toolkits/payments"
-SNIPPETS_DIR="/home/tilo/Workspace/docs-main/snippets/code-snippets/payments"
+SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
+EXAMPLES="${EXAMPLES_LIGHT_TOKEN:?Set EXAMPLES_LIGHT_TOKEN to examples-light-token repo root}/toolkits/payments"
+SNIPPETS_DIR="$SCRIPT_DIR/../snippets/code-snippets/payments"📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| EXAMPLES="/home/tilo/Workspace/examples-light-token-main/toolkits/payments" | |
| SNIPPETS_DIR="/home/tilo/Workspace/docs-main/snippets/code-snippets/payments" | |
| SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" | |
| EXAMPLES="${EXAMPLES_LIGHT_TOKEN:?Set EXAMPLES_LIGHT_TOKEN to examples-light-token repo root}/toolkits/payments" | |
| SNIPPETS_DIR="$SCRIPT_DIR/../snippets/code-snippets/payments" |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/copy-payments-snippets.sh` around lines 6 - 7, The script uses
hardcoded absolute paths in the EXAMPLES and SNIPPETS_DIR variables which will
fail on other machines/CI; update scripts/copy-payments-snippets.sh to read
EXAMPLES and SNIPPETS_DIR from environment variables (e.g., ${EXAMPLES:-...}
style) or require them and exit with an error if unset, mirroring the pattern
used in copy-sponsor-top-ups-snippets.sh; ensure you reference and replace the
EXAMPLES and SNIPPETS_DIR variable assignments in the file and add a guard that
prints a helpful message and exits nonzero when either variable is not provided.
| for (const ix of ixs[0]) { | ||
| if (!isFirst && ix.programId.toBase58() === COMPUTE_BUDGET_ID) | ||
| continue; | ||
| allTransferIxs.push(ix); | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Searching for createTransferInterfaceInstructions usage and handling..."
rg -n -C3 'createTransferInterfaceInstructions\(|sliceLast\(|TransactionInstruction\[\]\[\]'Repository: Lightprotocol/docs-v2
Length of output: 50379
🏁 Script executed:
cat -n snippets/code-snippets/payments/send/batch-send.mdx | sed -n '40,70p'Repository: Lightprotocol/docs-v2
Length of output: 1383
🏁 Script executed:
cat -n light-token/payments/batch-payments.mdx | sed -n '90,110p'Repository: Lightprotocol/docs-v2
Length of output: 931
🏁 Script executed:
cat -n snippets/code-snippets/payments/send/batch-send.mdx | sed -n '1,50p'Repository: Lightprotocol/docs-v2
Length of output: 2098
🏁 Script executed:
cat -n light-token/payments/batch-payments.mdx | sed -n '60,95p'Repository: Lightprotocol/docs-v2
Length of output: 1562
🏁 Script executed:
cat -n snippets/code-snippets/payments/send/batch-send.mdx | sed -n '24,40p'Repository: Lightprotocol/docs-v2
Length of output: 873
🏁 Script executed:
grep -n "createAtaInterfaceIdempotent\|Idempotent" light-token/payments/batch-payments.mdxRepository: Lightprotocol/docs-v2
Length of output: 47
🏁 Script executed:
cat -n light-token/payments/batch-payments.mdx | sed -n '140,180p'Repository: Lightprotocol/docs-v2
Length of output: 1648
Pre-load accounts or loop all instruction batches instead of only processing ixs[0].
The batch-send example creates ATAs idempotently but does not pre-load accounts like the batch-payments guide does. If accounts remain cold/compressed, createTransferInterfaceInstructions will return multiple instruction batches (load + transfer), but this code only processes ixs[0] and silently drops the load instructions in ixs[1..n].
Compare against the batch-payments guide, which explicitly pre-loads all accounts with createLoadAtaInstructions before the batch transfer. Alternatively, follow the documented TransactionInstruction[][] pattern (shown at batch-payments.mdx:145–158) and loop through all batches.
Suggested fix: Pre-load accounts
// Step 2: Create ATAs idempotently for sender + all recipients
await createAtaInterfaceIdempotent(rpc, payer, mint, payer.publicKey);
for (const { address } of recipients) {
await createAtaInterfaceIdempotent(rpc, payer, mint, address);
}
+// Step 2b: Pre-load sender + recipient accounts to ensure they are hot
+const senderAta = getAssociatedTokenAddressInterface(mint, payer.publicKey);
+const loadSenderIxs = await createLoadAtaInstructions(
+ rpc, senderAta, payer.publicKey, mint, payer.publicKey
+);
+for (const ixs of loadSenderIxs) {
+ await sendAndConfirmTransaction(rpc, new Transaction().add(...ixs), [payer]);
+}
+
+for (const { address } of recipients) {
+ const recipientAta = getAssociatedTokenAddressInterface(mint, address);
+ const loadIxs = await createLoadAtaInstructions(
+ rpc, recipientAta, address, mint, payer.publicKey
+ );
+ for (const ixs of loadIxs) {
+ await sendAndConfirmTransaction(rpc, new Transaction().add(...ixs), [payer]);
+ }
+}
// Step 3: Derive ATA addresses🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@snippets/code-snippets/payments/send/batch-send.mdx` around lines 53 - 57,
The loop only consumes ixs[0], dropping any preceding “load” batches returned by
createTransferInterfaceInstructions; fix by either pre-loading ATAs with
createLoadAtaInstructions before creating transfers, or iterate all instruction
batches in ixs (for each batch in ixs) and append their instructions to
allTransferIxs (still skipping COMPUTE_BUDGET_ID entries as done now), ensuring
createTransferInterfaceInstructions' multi-batch output is fully processed.
| { | ||
| "source": "/pda/compressed-pdas/nullifier-pda", | ||
| "destination": "https://zkcompression.com/pda/compressed-pdas/nullifier-pda" | ||
| }, |
There was a problem hiding this comment.
🔴 Self-referential redirect creates infinite loop for nullifier-pda page
The PR adds a redirect from /pda/compressed-pdas/nullifier-pda to https://zkcompression.com/pda/compressed-pdas/nullifier-pda at docs.json:372-375. Since the site is hosted at zkcompression.com, this redirects the page to itself. The page pda/compressed-pdas/nullifier-pda.mdx exists as an actual file and is listed in the navigation at docs.json:109, so this redirect is both unnecessary and potentially creates an infinite redirect loop depending on how Mintlify prioritizes redirects vs. navigation pages.
| { | |
| "source": "/pda/compressed-pdas/nullifier-pda", | |
| "destination": "https://zkcompression.com/pda/compressed-pdas/nullifier-pda" | |
| }, |
Was this helpful? React with 👍 or 👎 to provide feedback.
Summary
Test plan
mint devand verify all payment pages renderSummary by CodeRabbit
Release Notes
New Features
Documentation