skills-templates/arweave-bridge/SKILL.md
ZigZag Exchange Arweave Bridge - Pay with zkSync stablecoins (USDC/USDT/DAI) for permanent Arweave storage. Use for building dApps needing decentralized file storage, NFT metadata permanence, or Layer 2 storage solutions.
npx skillsauth add enuno/claude-command-and-control arweave-bridgeInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
The Arweave Bridge is a service built by ZigZag Exchange that enables zkSync transactions to access permanent storage on Arweave. It provides a seamless way for Layer 2 users to store data permanently without needing to acquire AR tokens directly.
Core Value Proposition: Access Arweave permanent storage at $1/MB by paying directly on zkSync with stablecoins.
This skill should be triggered when:
https://zigzag-arweave-bridge.herokuapp.com/
0xcb7aca0cdea76c5bd5946714083c559e34627607
1 MB per $1 of stablecoin deposited
Query remaining storage bytes for an address.
Endpoint:
GET /allocation/zksync?address={wallet_address}
Response:
{
"remaining_bytes": 1048576
}
Example:
curl "https://zigzag-arweave-bridge.herokuapp.com/allocation/zksync?address=0xYourWalletAddress"
Get current server timestamp for signature generation.
Endpoint:
GET /time
Response:
{
"timestamp": 1640000000000
}
Example:
curl "https://zigzag-arweave-bridge.herokuapp.com/time"
Upload a file to Arweave permanent storage.
Endpoint:
POST /arweave/upload
Content-Type: multipart/form-data
Required Fields:
| Field | Type | Description |
|-------|------|-------------|
| sender | string | Ethereum wallet address |
| file | file | The file to upload |
| timestamp | number | Current server timestamp (ms) |
| signature | string | ECDSA signature of {sender}:{timestamp} |
Response:
{
"arweave_tx_id": "abc123...",
"remaining_bytes": 1000000
}
All uploads require cryptographic signature verification:
/time{sender_address}:{timestamp}Message Format:
0xYourAddress:1640000000000
import { FormData, fileFromPath } from "formdata-node";
import fetch from "node-fetch";
import { ethers } from "ethers";
import dotenv from "dotenv";
dotenv.config();
const BASE_URL = "https://zigzag-arweave-bridge.herokuapp.com";
async function uploadToArweave(filePath) {
// 1. Get current server time
const timeResponse = await fetch(`${BASE_URL}/time`);
const { timestamp } = await timeResponse.json();
// 2. Create wallet and sign message
const wallet = new ethers.Wallet(process.env.ETH_PRIVKEY);
const sender = wallet.address;
const message = `${sender}:${timestamp}`;
const signature = await wallet.signMessage(message);
// 3. Prepare form data
const formData = new FormData();
formData.append("sender", sender);
formData.append("timestamp", timestamp.toString());
formData.append("signature", signature);
formData.append("file", await fileFromPath(filePath));
// 4. Upload file
const response = await fetch(`${BASE_URL}/arweave/upload`, {
method: "POST",
body: formData,
});
const result = await response.json();
console.log("Arweave TX ID:", result.arweave_tx_id);
console.log("Remaining bytes:", result.remaining_bytes);
return result;
}
// Usage
uploadToArweave("./my-file.json");
{
"dependencies": {
"formdata-node": "^4.0.0",
"node-fetch": "^3.0.0",
"ethers": "^5.0.0",
"dotenv": "^10.0.0"
}
}
# Required for signing uploads
ETH_PRIVKEY=your_private_key_here
Send stablecoins on zkSync to the bridge address:
Address: 0xcb7aca0cdea76c5bd5946714083c559e34627607
Network: zkSync
Tokens: USDC, USDT, or DAI
Rate: $1 = 1 MB storage
Credits typically appear within 1-2 minutes.
const response = await fetch(
`${BASE_URL}/allocation/zksync?address=${yourAddress}`
);
const { remaining_bytes } = await response.json();
console.log(`Available storage: ${remaining_bytes / 1024 / 1024} MB`);
Use the complete upload example above, ensuring:
Once uploaded, your file is permanently stored on Arweave:
https://arweave.net/{arweave_tx_id}
// Store NFT metadata permanently
const metadata = {
name: "My NFT",
description: "A permanent NFT",
image: "https://arweave.net/previous_image_tx_id",
attributes: [...]
};
// Write to temp file and upload
fs.writeFileSync("/tmp/metadata.json", JSON.stringify(metadata));
const result = await uploadToArweave("/tmp/metadata.json");
// Use Arweave URL as NFT tokenURI
const tokenURI = `https://arweave.net/${result.arweave_tx_id}`;
// Store token pair metadata for DEX listing
const pairMetadata = {
baseToken: "0x...",
quoteToken: "0x...",
icon: "base64_image_data",
description: "Trading pair info"
};
const result = await uploadToArweave(pairMetadataPath);
// Metadata now permanently accessible and verifiable
// Archive important documents permanently
const documents = ["contract.pdf", "agreement.pdf", "records.json"];
for (const doc of documents) {
const result = await uploadToArweave(doc);
console.log(`${doc} archived: https://arweave.net/${result.arweave_tx_id}`);
}
| Error | Cause | Solution |
|-------|-------|----------|
| Invalid signature | Wrong private key or message format | Verify {sender}:{timestamp} format |
| Timestamp expired | Request took too long | Get fresh timestamp and retry |
| Insufficient allocation | Not enough storage credits | Send more stablecoins to bridge |
| Invalid sender | Address doesn't match signature | Ensure sender matches signing wallet |
{
"error": "Invalid signature",
"message": "The provided signature does not match the sender address"
}
ETH_PRIVKEY in client-side code┌─────────────┐ ┌─────────────────────┐ ┌─────────────┐
│ User │────▶│ Arweave Bridge │────▶│ Arweave │
│ (zkSync) │ │ (Heroku Server) │ │ (Storage) │
└─────────────┘ └─────────────────────┘ └─────────────┘
│ │
│ USDC/USDT/DAI │ Manages allocations
▼ │ Validates signatures
┌─────────────┐ │ Uploads to Arweave
│ Bridge │◀─────────────┘
│ Address │
└─────────────┘
tools
MemPalace local-first AI memory system. Use when setting up persistent memory for Claude Code sessions, mining project files or conversation transcripts, querying past context, configuring MCP tools, managing the knowledge graph, or troubleshooting palace operations.
tools
LangSmith Python SDK — trace, evaluate, and monitor LLM applications. Covers @traceable decorator, trace context manager, Client API, evaluate() / aevaluate(), comparative evaluation, custom evaluators, dataset management, prompt caching, ASGI middleware, and pytest plugin.
development
LangGraph (Python) — build stateful, controllable agent graphs with checkpointing, streaming, persistence, interrupts, fault tolerance, and durable execution. Covers both Graph API (StateGraph) and Functional API (@entrypoint/@task).
development
LangGraph Graph API (Python) — build explicit DAG agent workflows with StateGraph, typed state, nodes, edges, Command routing, Send fan-out, checkpointers, interrupts, and streaming. Use when you need explicit control flow and graph topology.