Creates a rent-free PDA derived from id. If the id has been used before, the PDA already exists, causing the instruction to fail.
- Rust 1.79+
- Solana CLI 2.2+
- Anchor CLI 0.31.1
- Node.js 18+
anchor build
npm run buildcargo test-sbf -p light-nullifier-programRequires local validator.
npm install -g @lightprotocol/zk-compression-cli@0.28.0-beta.5light test-validator
npm testBoth examples load your Solana keypair at ~/.config/solana/id.json.
Devnet(default):
Set up the .env file with a Helius API key (get one here):
cp .env.example .env
# edit .env and add your API_KEYLocalnet: For localnet, install the CLI, start the test-validator with the program, and swap the RPC comments in the example files:
npm install -g @lightprotocol/zk-compression-cli@0.28.0-beta.5light test-validator --sbf-program NFLx5WGPrTHHvdRNsidcrNcLxRruMC92E4yv7zhZBoT target/deploy/light_nullifier_program.soFind and run example here: rust/src/main.rs.
cd examples/rust && cargo runFind and run example here: action-create-nullifier.ts.
npm installnpm run ts:create-nullifierWorks with LightClient (production) or LightProgramTest (testing).
use light_nullifier_program::sdk::{create_nullifier_ix,PROGRAM_ID};use light_client::{LightClient,LightClientConfig};let rpc_url = "https://devnet.helius-rpc.com/?api-key=...".to_string();let config = LightClientConfig::new(rpc_url,None,None);letmut rpc = LightClient::new(config).await?;let ix = create_nullifier_ix(&mut rpc, payer.pubkey(), id).await?;Or step-by-step:
use light_nullifier_program::sdk::{fetch_proof, build_instruction};let proof_result = fetch_proof(&mut rpc,&id).await?;let ix = build_instruction(payer.pubkey(), id, proof_result);Works with any Rpc from @lightprotocol/stateless.js.
import{createNullifierIx,PROGRAM_ID,}from"@lightprotocol/nullifier-program";import{createRpc}from"@lightprotocol/stateless.js";constrpc=createRpc("https://devnet.helius-rpc.com/?api-key=...");constix=awaitcreateNullifierIx(rpc,payer.publicKey,id);Or step-by-step:
import{fetchProof,buildInstruction}from"@lightprotocol/nullifier-program";constproofResult=awaitfetchProof(rpc,id);constix=buildInstruction(payer.publicKey,id,proofResult);Check if nullifier exists:
import{deriveNullifierAddress}from"@lightprotocol/nullifier-program";import{bn}from"@lightprotocol/stateless.js";constaddress=deriveNullifierAddress(id);constaccount=awaitrpc.getCompressedAccount(bn(address.toBytes()));constexists=account!==null;- Derive a compressed account address from
["nullifier", id]seeds. E.g. hash payment inputs. - Creates the empty rentfree PDA account, "spending the nullifier"
- If the address already exists, the instruction fails
- prepend or append this instruction to your regular transaction (eg. payment)
Find more documentation here: https://www.zkcompression.com/compressed-pdas/guides/how-to-create-nullifier-pdas.
The nullifier program code is unaudited, use at your own risk.