Mastra Integration

Import w3stor tools and use them in Mastra agents and workflows. The SDK handles x402 payment signing automatically.

Install

Terminal
npm install @w3stor/sdk @mastra/core zod @x402/fetch @x402/evm viem

Setup

Pass a private key and the SDK creates an x402 payment signer for paid operations on Base Sepolia USDC.

import { createTools } from "@w3stor/sdk/mastra";
const { uploadTool, listTool, statusTool, attestTool } = await createTools({  privateKey: process.env.PRIVATE_KEY, // x402 payments handled automatically});

Using a viem Account

Pass a viem account directly if you already have one.

import { createTools } from "@w3stor/sdk/mastra";import { privateKeyToAccount } from "viem/accounts";
const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
const { uploadTool, listTool, statusTool, attestTool } = await createTools({  account,});

Agent Configuration

Create a Mastra agent with all four w3stor tools.

import { Agent } from "@mastra/core";import { createTools } from "@w3stor/sdk/mastra";
const { uploadTool, listTool, statusTool, attestTool } = await createTools({  privateKey: process.env.PRIVATE_KEY,});
export const storageAgent = new Agent({  name: "w3stor-agent",  instructions: "You are a decentralized storage agent. Help users upload files to IPFS and Filecoin, check replication status, and create attestations.",  model: { provider: "OPEN_AI", name: "gpt-4o" },  tools: {    upload: uploadTool,    list: listTool,    status: statusTool,    attest: attestTool,  },});

Workflow: Upload, Verify, Attest

Chain storage operations into an automated pipeline that uploads, waits for replication, then creates an on-chain attestation.

import { Workflow, Step } from "@mastra/core";import { z } from "zod";import { createTools } from "@w3stor/sdk/mastra";
const { uploadTool, statusTool, attestTool } = await createTools({  privateKey: process.env.PRIVATE_KEY,});
const uploadAndVerify = new Workflow({  name: "upload-verify-attest",  triggerSchema: z.object({    filePath: z.string(),    tags: z.string().optional(),  }),});
const uploadStep = new Step({  id: "upload",  execute: async ({ context }) => {    const result = await uploadTool.execute({      context: {        filePath: context.triggerData.filePath,        tags: context.triggerData.tags,        replicationTarget: 3,      },    });    return { cid: result.cid, size: result.size };  },});
const verifyStep = new Step({  id: "verify",  execute: async ({ context }) => {    const { cid } = context.getStepResult<{ cid: string }>("upload");    let status;    let attempts = 0;    do {      await new Promise((r) => setTimeout(r, 10000));      status = await statusTool.execute({ context: { cid } });      attempts++;    } while (status.status !== "stored" && attempts < 30);    return { cid, status: status.status, replicationCount: status.replicationCount };  },});
const attestStep = new Step({  id: "attest",  execute: async ({ context }) => {    const { cid, status } = context.getStepResult<{ cid: string; status: string }>("verify");    if (status !== "stored") return { error: "Not fully replicated" };    return attestTool.execute({ context: { cid } });  },});
uploadAndVerify.step(uploadStep).then(verifyStep).then(attestStep).commit();
const run = await uploadAndVerify.execute({  triggerData: { filePath: "/data/research-paper.pdf", tags: "paper,2026" },});console.log("Result:", run.results);