Documentation Index
Fetch the complete documentation index at: https://docs.zkterm.io/llms.txt
Use this file to discover all available pages before exploring further.
Overview
Pinata provides IPFS pinning services that zkStorage uses to store encrypted files. Files are encrypted client-side before upload, then pinned to IPFS via Pinata’s API.
How It Works
- Encrypt: Files encrypted client-side with AES-256-GCM
- Upload: Encrypted blob uploaded to Pinata API
- Pin: Pinata pins the file to IPFS network
- CID: Returns Content Identifier (CID) for retrieval
- Download: Fetch via Pinata gateway, decrypt client-side
Features
- Fast Uploads - Direct upload to Pinata with retry logic
- Gateway Access - Downloads via gateway.pinata.cloud
- Metadata Storage - Separate CID for file metadata
- Multi-Gateway Fallback - Cloudflare and ipfs.io as backup
Integration with zkStorage
zkStorage uses Pinata for all IPFS operations:
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Client │ │ zkTerm │ │ Pinata │
│ (Browser) │ │ Server │ │ IPFS │
├─────────────┤ ├─────────────┤ ├─────────────┤
│ 1. Encrypt │ ───> │ 2. Upload │ ───> │ 3. Pin │
│ file │ │ to API │ │ to IPFS │
│ │ <─── │ 4. Return │ <─── │ 5. Return │
│ │ │ CID │ │ CID │
└─────────────┘ └─────────────┘ └─────────────┘
Terminal Commands
zkStorage commands that use Pinata:
zk storage upload # Upload → Pinata → IPFS
zk storage download <file-id> # Pinata Gateway → Decrypt
zk storage list # List files (metadata from DB)
API Details
Upload to Pinata
zkTerm uploads encrypted files using Pinata’s pinFileToIPFS endpoint:
const response = await fetch('https://api.pinata.cloud/pinning/pinFileToIPFS', {
method: 'POST',
headers: {
'Authorization': `Bearer ${PINATA_JWT}`,
},
body: formData,
});
const { IpfsHash } = await response.json();
// IpfsHash is the CID, e.g., "QmXyz123..."
Download from Gateway
Downloads use the Pinata gateway with fallbacks:
const gateways = [
'https://gateway.pinata.cloud/ipfs',
'https://cloudflare-ipfs.com/ipfs',
'https://ipfs.io/ipfs',
];
const response = await fetch(`${gateway}/${cid}`);
File Structure
Each zkStorage upload creates two IPFS objects:
| Object | Content | CID Example |
|---|
| Encrypted File | AES-256-GCM encrypted data | QmXyz123... |
| Metadata | IV, salt, original name/size | QmAbc456... |
Metadata JSON:
{
"originalName": "document.pdf",
"originalSize": 1234567,
"iv": "base64...",
"salt": "base64...",
"iterations": 100000,
"zkEnabled": true,
"commitment": "poseidon-hash..."
}
Error Handling
| Error | Cause | Solution |
|---|
PINATA_JWT not configured | Missing API key | Set PINATA_JWT env var |
Upload failed: 401 | Invalid JWT | Regenerate Pinata API key |
Gateway timeout | IPFS propagation delay | Retry or use fallback gateway |
CID not found | File unpinned | Re-upload the file |
Retry Logic
Uploads include automatic retry with exponential backoff:
for (let attempt = 1; attempt <= 3; attempt++) {
try {
return await uploadToPinata(buffer, filename);
} catch (error) {
await sleep(1000 * attempt); // 1s, 2s, 3s
}
}
Timeouts
| Operation | Timeout |
|---|
| File upload | 60 seconds |
| Gateway fetch | 30 seconds |
| Metadata fetch | 30 seconds |
Environment Variables
| Variable | Description |
|---|
PINATA_JWT | Pinata API JWT token (required) |
Getting a Pinata API Key
- Create account at pinata.cloud
- Go to API Keys section
- Create new key with
pinFileToIPFS permission
- Copy JWT token to
PINATA_JWT environment variable
Pricing
Pinata offers:
- Free tier: 1GB storage, 100 pins
- Starter: $20/month, 25GB storage
- Professional: Custom pricing
zkStorage uses minimal storage since only encrypted blobs are stored.
Migration Notes
zkStorage previously used NFT.Storage (deprecated June 2024). Migration to Pinata provides:
- Better upload reliability
- Faster gateway access
- Active maintenance and support