MintPass pkc-js challenge implementation
npm install @mintpass/challengeThis directory contains the MintPass challenge implementation for plebbit-js that verifies users own a MintPass NFT.
- NFT Ownership Verification: Checks if users own a MintPass NFT of the required type
- Transfer Cooldown Protection: Prevents quick NFT transfers between accounts to bypass verification
- Chain Flexibility: Supports different chains where MintPass contracts are deployed
- ENS Support: Works with ENS addresses and wallet addresses
- Type-specific Requirements: Can require specific token types (SMS=0, Email=1, etc.)
For use in plebbit-js projects, clone the mintpass repo alongside your plebbit-js project:
``bashClone mintpass repo
git clone https://github.com/your-username/mintpass.git
Usage
$3
`javascript
// Import via file path (not package import)
const challengeSettings = {
path: '../mintpass/challenge/dist/mintpass.js', // Relative path to built challenge
options: {
chainTicker: 'base',
contractAddress: '0x13d41d6B8EA5C86096bb7a94C3557FCF184491b9',
requiredTokenType: '0', // 0 = SMS verification
transferCooldownSeconds: '604800', // 1 week
error: 'You need a MintPass NFT to post. Visit https://mintpass.org/request/{authorAddress}'
}
};// Set on subplebbit
subplebbit.settings.challenges = [challengeSettings];
`$3
Your project should look like:
`
your-project/
├── plebbit-js/ # Your plebbit-js fork
└── mintpass/ # Cloned mintpass repo
└── challenge/
└── dist/
└── mintpass.js # Built challenge file
`$3
| Option | Type | Default | Description |
|--------|------|---------|-------------|
|
chainTicker | string | "base" | Chain where MintPass contract is deployed |
| contractAddress | string | Optional on supported chains | If omitted and chainTicker is supported, defaults to the known MintPass deployment for that chain (e.g., Base Sepolia) |
| requiredTokenType | string | "0" | Required token type (0=SMS, 1=Email, etc.) |
| transferCooldownSeconds | string | "604800" | Cooldown period after NFT transfer (1 week) |
| error | string | Default message | Custom error message for users without NFT |$3
- Type 0: SMS verification
- Type 1: Email verification
- Type 2+: Future verification methods
$3
$3
- When
chainTicker is "base" or "eth", the challenge first looks for author.wallets[chainTicker].
- If that specific wallet is missing, it automatically falls back between base and eth (e.g., base → eth or eth → base).
- This makes EVM wallet usage robust when clients store a single EVM wallet entry.$3
- If
contractAddress is omitted and chainTicker is supported, the challenge uses a known default for that chain (e.g., Base Sepolia reference deployment).
- You can still override contractAddress explicitly in settings.The challenge tracks when NFTs are used by different plebbit accounts and enforces a cooldown period to prevent:
- Quick transfers to bypass bans
- NFT sharing between multiple accounts
- Sybil attacks via NFT circulation
Development
$3
`bash
cd challenges
yarn install
yarn build
`$3
The challenge includes comprehensive automated testing that covers both the challenge logic and complete user publishing flow.
#### Quick Start
`bash
cd challenges
yarn test
`This command automatically:
- Starts a local Hardhat blockchain node
- Deploys the MintPass contract
- Runs the full integration test suite
- Cleans up all processes when complete
#### Manual Testing
For situations where you need to manage the test infrastructure manually:
`bash
Terminal 1: Start the Hardhat node
cd contracts && npx hardhat nodeTerminal 2: Run tests against the running node
cd challenges && yarn test:manual
`#### Test Coverage
The automated test suite includes:
- NFT Ownership Verification: Tests both success and failure scenarios
- Complete Publishing Flow: Simulates real user posting experience
- Local IPFS Integration: Tests with isolated local IPFS daemon
- Challenge/Verification Exchange: Validates complete challenge workflow
For detailed testing information, see AUTOMATED_TESTING.md.
$3
The challenge exports a
ChallengeFileFactory function compatible with plebbit-js:`javascript
// In your plebbit-js fork
import mintpass from '@mintpass/challenge';// Register the challenge
Plebbit.challenges.mintpass = mintpass;
// Use in subplebbit settings
const subplebbit = await plebbit.createSubplebbit({
settings: {
challenges: [{
name: 'mintpass',
options: {
contractAddress: '0x...',
requiredTokenType: '0'
}
}]
}
});
`Architecture
The challenge follows the plebbit-js challenge pattern:
1. Wallet Verification: Validates author's wallet signature
2. NFT Ownership Check: Calls
ownsTokenType()` on MintPass contract| Scenario | Error Message |
|----------|---------------|
| No wallet set | "Author wallet address is not defined" |
| Invalid signature | "The signature of the wallet is invalid" |
| No NFT owned | Custom error with link to verification site |
| NFT in cooldown | "Your MintPass NFT is in cooldown period" |
| Contract call fails | "Failed to check MintPass NFT ownership" |
MIT License - Same as the MintPass project.