Each example below is a self-contained Lit Action. Pass the code string to theDocumentation Index
Fetch the complete documentation index at: https://docs.dev.litprotocol.com/llms.txt
Use this file to discover all available pages before exploring further.
/core/v1/lit_action endpoint with any required js_params. The pkpId parameter is the wallet address of the PKP you want to use, passed in via js_params.
For examples that need more than one file to run — a Solidity contract, a deploy script, an off-chain client — see the examples/ folder in the repo.
1. Sign a Message
The simplest pattern: retrieve a PKP’s private key and sign an arbitrary message with it. The signature proves the message was attested by a specific, on-chain-registered key.2. Encrypt a Secret
Encrypt a sensitive string so that only the holder of the PKP can later decrypt it. Useful for storing API keys, passwords, or personal data on-chain or in IPFS without exposing the plaintext.ciphertext anywhere — IPFS, a smart contract, a database — and retrieve the plaintext only when needed using the Decrypt action below.
3. Decrypt a Secret
Decrypt a ciphertext that was previously produced byLit.Actions.Encrypt using the same PKP. Only an action that is permitted to use the PKP (enforced on-chain) can decrypt it.
4. Fetch a Crypto Price and Sign It
Fetch the current price of ETH from a public API and sign the result. The caller receives both the price and a signature — a verifiable price proof that can be submitted to a smart contract as a trusted oracle update.ecrecover on the signature to confirm the price was signed by a specific, known PKP address — without trusting any off-chain intermediary.
5. Gate a Signature on Live Weather Data
Fetch live weather for a city using a decrypted API key and only sign a message if the temperature exceeds a threshold. Demonstrates combining decryption, an authenticated HTTP request, and conditional signing in one action.6. Read from a Smart Contract
Call a view function on an EVM smart contract and return the result. Useful for reading on-chain state (balances, governance votes, NFT ownership) inside an action, or for gating downstream logic on chain data.7. Send ETH to an Address
Construct, sign, and broadcast an ETH transfer transaction from a PKP wallet. The PKP pays the gas and the transfer amount, so ensure the PKP wallet holds sufficient ETH on the target chain before running this action.8. Gate an ERC-20 Transfer on On-Chain Sanctions Data (Cross-Chain)
Screen the recipient of every transfer against the Chainalysis on-chain sanctions oracle and only sign a transfer authorization when the recipient is clear. The Chainalysis oracle is free and keyless — it’s just a smart contract at0x40C57923924B5c5c5455c48D93317139ADDaC8fb you can staticcall. But it is only deployed on a handful of mainnets (Ethereum, Arbitrum, Polygon, BSC, Avalanche, Optimism, Celo). On Base, Linea, Scroll, any L3, any testnet, or any non-EVM chain, a contract can’t reach it. The Lit Action bridges that gap: it eth_calls the oracle on Ethereum mainnet, then signs an authorization that the CompliantToken contract — deployed wherever you want — verifies with ecrecover.
The signature uses Lit.Actions.getLitActionPrivateKey() — an identity derived from the action’s IPFS CID. See Action-Identity Signing.
The trust anchor is a hardcoded hostname whitelist. Anyone calling the action supplies screeningRpcUrl via js_params, so a caller-supplied chainId check would just be theater (pair a malicious RPC with a matching chain id, gate passes). Instead the action checks the URL’s hostname against eth-mainnet.g.alchemy.com — TLS guarantees we’re actually talking to Alchemy. Trust shifts to “Alchemy is honest about Ethereum mainnet.”
Lit.Actions.getLitActionWalletAddress({ ipfsId }) from inside any helper action, then pass that address to the CompliantToken constructor.
Swapping providers (Infura, QuickNode, your own node) means editing the regex — which produces a new action CID and signer address, requiring a redeploy. That’s by design: the trust anchor is content-addressed. For richer screening — hacker wallets, mixer interactions, fresh threat intel — swap the on-chain lookup for a paid API like Chainalysis KYT, TRM Labs, or GetBlock. The pattern becomes: encrypt the API key to a PKP, decrypt inside the TEE, call the API, sign on pass.
The matching contract signs nothing itself — it just verifies that the digest recovers to a hard-coded PKP address:
transfer and transferFrom overrides revert, so every movement of tokens must go through this gate.
The full runnable example — token contract, hardhat deploy script, and an end-to-end transfer runner — lives at
examples/compliance-transfer-gate/ in the repo. The example is keyless: the action reads the Chainalysis oracle via an Alchemy RPC and signs with its own CID-derived key, so no PKP or encrypted secrets are required.9. Median Price Oracle Across Three Exchanges
Fetch a spot price from three independent exchanges (Coinbase, Kraken, Bitstamp), take the median, and sign it for any EVM chain. This is the practical “I need a Chainlink-shaped feed without Chainlink” pattern. Median (rather than strict byte-equality) is the right aggregation for live market prices — exchanges disagree by a few cents at every moment, so byte-equality would never pass. A median naturally rejects one outlier; combined with aMAX_SPREAD_BPS check (refuse to sign if min/max differ by more than the threshold) it catches both single-source manipulation and any-source-market-state-broken situations.
The safety thresholds (MAX_SPREAD_BPS, MIN_SOURCES, DECIMALS) are hardcoded constants in the action source rather than caller-supplied js_params. Otherwise anyone holding the usage key could request a signature with MIN_SOURCES: 1 and a huge spread cap, bypassing the median-of-three story. Editing a constant mints a new action CID — and therefore a new signer address — which forces a redeploy of the registry. The trust anchor is content-addressed.
All three sources here are keyless public HTTP endpoints — no API keys, no PKP, no encryption.
The full runnable example —
PriceOracle registry contract, deploy script, end-to-end submission runner, and a zero-dep npm run test-medianizer harness that exercises the fetch logic without touching any chain — lives at examples/multi-source-price-oracle/ in the repo.10. Resolve a Prediction Market by AI Consensus
Poll multiple LLM providers in parallel with the same yes/no question and only sign the resolution when every model agrees. Same multi-source idea as example 9, but the parallel sources are AI models instead of price feeds — and the aggregation is strict agreement rather than a median, because the output is categorical YES/NO/UNCLEAR. Perplexity Sonar is required because its built-in web search lets it answer questions about events that happened after a frontier model’s training cutoff. OpenAI and Anthropic are optional second opinions — independent training corpora mean a confident-but-wrong frontier answer is unlikely to be confirmed by another frontier model. Configuring all three gives you 3-of-3 agreement before anything reaches the chain.The full runnable example —
PredictionMarket contract, deploy script, key-encryption helper, propose/resolve runners, and a heavily-commented setup pipeline — lives at examples/prediction-market-oracle/ in the repo.11. Cross-Chain Burn/Mint Bridge
Deploy the sameBridgeToken contract on two chains. The holder calls burn on chain A, which destroys the local supply and emits BurnInitiated(from, recipient, amount, destChainId, nonce). A Lit Action reads that event via eth_getTransactionReceipt against a hostname-whitelisted RPC, validates it, and signs a mint authorization for chain B. Anyone can submit the mint — the signature is the authorization, not the caller.
Same content-addressed trust property as the compliance gate: the signer key comes from Lit.Actions.getLitActionPrivateKey(), which derives the key from the action’s IPFS CID. Edit the action by a byte and the signer changes, and every deployed BridgeToken refuses the modified action. The trust collapses from “trust this federation of relayers” to “trust this exact piece of code.”
BridgeToken.mint re-derives the same digest, recovers the signer, and checks it matches the pinned bridgeOracle. It also checks an independent bridgePartner[srcChainId] mapping — wired during setup to point at the sibling deployment — so a forged burn from a copycat contract with the same event shape can’t mint here. Each (srcChainId, burnTxHash, logIndex) is recorded in usedBurnIds to prevent replays.
This is the permissionless half: any wallet can submit the mint tx (sponsored by a relayer, the recipient themselves, or whoever wants the gas burden). The mint goes through only because the signature is valid — there’s no on-chain allowlist of submitters.
The full runnable example —
BridgeToken contract, two-chain deploy script, setBridgePartner wiring, and an end-to-end npm run bridge runner that burns on one chain and mints on the other — lives at examples/cross-chain-token/ in the repo. Defaults to Base Sepolia ↔ Arbitrum Sepolia; the RPC_HOSTS table is the only thing you’d touch to add more chains.