This project demonstrates how to efficiently fetch all PKPs (Programmable Key Pairs) owned by an Ethereum address using Multicall3 to minimize RPC calls.
The example script fetches all PKP NFTs owned by a given Ethereum address on the Lit Protocol testnet (Chronicle Yellowstone) and retrieves their metadata including:
- Token IDs
- Public keys
- Derived Ethereum addresses
The script uses only 3 RPC calls to fetch all PKP data, regardless of how many PKPs are owned:
- First call:
balanceOf()
to get the count of PKPs owned - Second call: Multicall3 to batch all
tokenOfOwnerByIndex()
calls to get all token IDs - Third call: Multicall3 to batch all
getPubkey()
calls to get the public key for each PKP
This is a significant optimization compared to making individual RPC calls for each PKP, which would require 2N+1 calls (1 for balance, N for token IDs, N for public keys).
- Install dependencies:
npm install
- Copy the example environment file and configure it:
cp .env.example .env
- Ensure your
.env
file contains:
YELLOWSTONE_RPC_URL
: RPC endpoint for Chronicle Yellowstone testnetPKP_NFT_CONTRACT_ADDRESS
: Address of the PKP NFT contractMULTICALL3_ADDRESS
: Address of the Multicall3 contractEXAMPLE_WALLET_WITH_PKPS
: An Ethereum address that owns PKPs
Run the example:
npm run example
getPKPsWithMulticall.ts
: Main example script that demonstrates the multicall approachabis/PKPNFTDiamond.json
: ABI for the PKP NFT contractabis/Multicall3.json
: ABI for the Multicall3 contract
balanceOf(address)
: Get the number of PKPs owned by an addresstokenOfOwnerByIndex(address, index)
: Get the token ID at a specific index for an ownergetPubkey(tokenId)
: Get the public key for a specific PKP
aggregate3(calls)
: Execute multiple contract calls in a single RPC request
The PKP NFT contract also provides getPkpInfoFromTokenIds(tokenIds[])
which could fetch all metadata in a single call. However, this function may have issues with large arrays on some networks. The example uses individual getPubkey()
calls batched through Multicall3 for better reliability.
- Efficiency: Only 3 RPC calls regardless of PKP count
- Cost-effective: Reduces RPC usage and associated costs
- Fast: Parallel execution of all data fetching
- Reliable: Handles any number of PKPs owned by an address
- Node.js 14+
- TypeScript
- Ethers.js v5