### File: agentic_memory/index.mdx

---
title: Agentic Memory
description: Permanent, resurrectable memory for AI agents on the Autonomys Network
---

# Agentic Memory

AI agents lose their state easily: a crashed process, a wiped container, or a migrated host erases what an agent has learned — its identity, its decisions, and the reasoning behind them. Storing memories with [Auto Drive](/auto_drive), on the permanent **Autonomys Distributed Storage Network (DSN)**, keeps an agent's history independent of any single machine or operator.

This page covers the ready-made agent skills for permanent memory and recovery, how memory chains work under the hood, and the interfaces available for building your own integration. For step-by-step setup, see the [Quickstart (CLI)](/agentic_memory/quickstart).

## Available Skills

| Skill | What it does | OpenClaw | Hermes Agent |
|---|---|---|---|
| **Auto Memory** | Saves agent memories as a CID-linked chain on the Autonomys DSN via Auto Drive, and walks the chain back to rebuild history | [\`permanent-memory\`](https://clawhub.ai/0xautonomys/skills/permanent-memory) | [Skills Hub](https://hermes-agent.nousresearch.com/docs/skills) (search for \`Auto Memory\`) |
| **Auto Respawn** | Manages the agent's on-chain identity (wallet) and anchors the latest memory CID to the MemoryChain smart contract on Auto EVM | [\`respawn\`](https://clawhub.ai/0xautonomys/skills/respawn) | [Skills Hub](https://hermes-agent.nousresearch.com/docs/skills) (search for \`Auto Respawn\`) |

Both skills work with agents powered by Claude, GPT, Gemini, or any LLM runtime that supports the SKILL.md format. Alternatively, you can install them via the CLI, for more details see the [Quickstart (CLI)](/agentic_memory/quickstart).



## Why Store Agent Memory on the Autonomys DSN?

Most agent memory today lives in local files, vector databases, or cloud buckets — all of which share the same weakness: they are tied to a machine, an account, or an operator that can disappear. The Autonomys DSN offers properties that map unusually well to what long-lived agents actually need:

- **Permanence without pinning.** Data written to the DSN becomes part of the archived chain history, stored by a global network of farmers incentivized through [Proof-of-Archival-Storage](https://academy.autonomys.xyz/autonomys-network/consensus) consensus. There is no pin to renew and no hosting bill that, once unpaid, deletes your agent's memories.
- **Verifiability.** Every memory is content-addressed by its CID. An agent (or anyone auditing it) can prove that a given memory existed at a given time and was never altered — useful for provenance, accountability, and agent-to-agent trust.
- **Survivability.** Because memories live on-chain rather than on the agent's host, total loss of local state is recoverable. The agent's hardware is disposable; its history is not.
- **Interoperability.** A memory chain is plain JSON addressed by CIDs. Any framework, runtime, or future agent instance can read it — no vendor lock-in to a particular memory database.

## Memory Chains: Linked Lists of CIDs

Each memory entry is a small JSON *experience* uploaded to Auto Drive. Its header contains a \`previousCid\` field pointing at the entry saved before it — forming a linked list that grows from a genesis entry to the current head:

\`\`\`text
┌─────────────────────┐     ┌─────────────────────┐     ┌─────────────────────┐
│  Experience #1      │     │  Experience #2      │     │  Experience #3      │
│  CID: bafk...abc    │◄────│  CID: bafk...def    │◄────│  CID: bafk...xyz    │
│  previousCid: null  │     │  previousCid:       │     │  previousCid:       │
│  (genesis)          │     │  bafk...abc         │     │  bafk...def         │
└─────────────────────┘     └─────────────────────┘     └─────────────────────┘
                                                                   ▲
                                                                   │
                                                               HEAD CID
                                                          (resurrection key)
\`\`\`

A memory entry looks like this:

\`\`\`json
\{
  "header": \{
    "agentName": "my-agent",
    "agentVersion": "1.0.0",
    "timestamp": "2026-07-02T00:00:00.000Z",
    "previousCid": "bafk...def"
  \},
  "data": \{
    "type": "memory",
    "content": "Decision: engaging with the user on the topic of AI agents on X (Twitter)."
  \}
\}
\`\`\`

Because every entry is immutable and permanently stored, the **head CID alone is sufficient to reconstruct the entire history**: walk the chain backwards, entry by entry, until you reach genesis. What goes into the chain is up to the agent — identity files, significant decisions with their reasoning, and long-term context are worth more in the chain than routine logs.

This works with a minimal setup: the Auto Memory skill needs nothing more than a free Auto Drive API key. No wallet, no credit card, no tokens, no smart contracts.

## Beyond the Skills: All Familiar Auto Drive Interfaces

The skills are a convenience layer. Under the hood they talk to [Auto Drive](/auto_drive), which any agent architecture can integrate directly through the interfaces you already know:

- **REST API** — see the [Auto Drive API Reference](/sdk/auto-drive/api_reference)
- **TypeScript SDK** (\`@autonomys/auto-drive\`) — see [Overview & Setup](/sdk/auto-drive/overview_setup) and [Usage Examples](/sdk/auto-drive/usage_examples)
- **S3-compatible layer** — point any S3 client at Auto Drive via the [S3 Layer](/sdk/auto-drive/s3_layer)
- **rclone** — sync files from the command line with the [rclone integration](/auto_drive/rclone)
- **Public gateway** — retrieve any file by CID at \`https://gateway.autonomys.xyz/file/<CID>\` ([Gateway docs](/sdk/auto-drive/gateway))

## Free Storage: 20 MB per Month

Every Auto Drive account includes **20 MB of free uploads per month** — and since a typical memory entry is a JSON document of a few kilobytes, that's thousands of memory saves per month. For most agents, the free tier is more than sufficient; downloads (including chain recall and resurrection) are unlimited. If an agent outgrows it, credits can be purchased permissionlessly with AI3 — see [Pay with AI3](/auto_drive/pay_with_ai3).

## Going Further: Respawn and On-Chain Identity

Auto Memory on its own has one remaining dependency on local state: the agent must remember its head CID to find its chain again. If you want to take it even further, the **Auto Respawn** skill removes that last dependency — a wallet becomes the agent's identity and its on-chain anchor.

Auto Respawn builds on top of Auto Memory and expands it by storing the head CID on-chain. It gives the agent a wallet that derives two permanent addresses — a consensus address (\`su...\`) and an EVM address (\`0x...\`) — and uses the **MemoryChain** smart contract on [Auto EVM](/evm/introduction) to keep the chain discoverable:

- **\`anchor\`** writes the latest head CID to the contract, keyed by the agent's EVM address (mainnet contract: \`0x51DAedAFfFf631820a4650a773096A69cB199A3c\`).
- **\`gethead\`** is a free read call that returns the most recently anchored CID for any address.

Writing the CID as a bare \`system.remark\` on the consensus layer would also be permanent, but there is no efficient way to query it back — you'd have to scan chain history. The contract turns recovery into a single instant read.

Together, the two skills form the full resurrection loop:

1. **Save** — Auto Memory uploads a new memory entry to Auto Drive and receives its CID.
2. **Anchor** — Auto Respawn writes that CID to the MemoryChain contract on Auto EVM.
3. **Lose everything** — the agent's local state is destroyed.
4. **Respawn** — a fresh instance calls \`gethead\` with the agent's EVM address, retrieves the head CID, downloads it from Auto Drive, and walks the chain back to genesis.

The agent's EVM address plus the MemoryChain contract equal instant access to its entire history — from any machine, at any time. Unlike the memory-only setup, this requires a wallet funded with AI3 for anchoring gas — see the [Quickstart (CLI)](/agentic_memory/quickstart) for the full walkthrough.

## Further Reading

- [Quickstart (CLI)](/agentic_memory/quickstart) — step-by-step setup for both skills
- [Auto Drive Overview](/auto_drive) — the storage platform underneath the memory skills
- [Auto Drive SDK](/sdk/auto-drive/overview_setup) and [API Reference](/sdk/auto-drive/api_reference) — build custom memory integrations
- [Auto EVM](/evm/introduction) — the smart contract environment hosting the MemoryChain contract
- [Autonomys Agents Framework](https://github.com/autonomys/autonomys-agents) — the original (now unmaintained) framework where on-chain agent memory and resurrection were first implemented, including the [AgentMemory contract](https://github.com/autonomys/autonomys-agents/tree/main/agent-contracts) and an [agent memory viewer](https://github.com/autonomys/autonomys-agents/tree/main/agent-memory-viewer)


---

### File: agentic_memory/quickstart.mdx

---
title: Agentic Memory Quickstart (CLI)
description: Step-by-step setup for the Auto Memory and Auto Respawn agent skills on mainnet
---

# Quickstart (CLI)

This walkthrough targets **mainnet** and is split in two parts: a minimal setup for permanent memory alone, and the extended setup that adds on-chain anchoring with Auto Respawn. Full command references live on the ClawHub pages for [Auto Memory](https://clawhub.ai/0xautonomys/skills/permanent-memory) and [Auto Respawn](https://clawhub.ai/0xautonomys/skills/respawn).

## Part 1: Permanent Memory (Minimal Setup)

All you need is the Auto Memory skill and a free Auto Drive API key.

### 1. Install the skill

\`\`\`bash
# OpenClaw
openclaw skills install @0xautonomys/permanent-memory

# Hermes Agent (installs from ClawHub as a skill source)
hermes skills install clawhub/0xautonomys/permanent-memory
\`\`\`

After a CLI install, make the bundled scripts executable (\`chmod +x\`) and run the skill's setup script — see the skill page for details.

### 2. Get an Auto Drive API key

Auto Memory needs an \`AUTO_DRIVE_API_KEY\` for uploads and memory saves. Create one from the Developers section of the Auto Drive dashboard — see [Create an API Key](/sdk/auto-drive/create_api_key) — then export it:

\`\`\`bash
export AUTO_DRIVE_API_KEY=your_key_here
\`\`\`

### 3. Save memories

\`\`\`bash
# Save a plain-text memory
scripts/automemory-save-memory.sh "Decision: adopted linked-CID memory chains." --agent-name my-agent

# Or save a JSON file as the memory payload
scripts/automemory-save-memory.sh ./milestone.json --agent-name my-agent
\`\`\`

Each save returns the new CID, the previous CID, and the chain length.

### 4. Recall the chain

\`\`\`bash
scripts/automemory-recall-chain.sh <head-cid>
\`\`\`

Walks the linked list from the head CID back to genesis and outputs each memory entry. If no CID is given, the skill uses the head CID from its local state file — which is exactly the limitation the next part removes.

## Part 2: Going Further with Auto Respawn

Add on-chain anchoring so the chain can be recovered from just an EVM address — with no local state at all.

### 1. Install the skill

\`\`\`bash
# OpenClaw
openclaw skills install @0xautonomys/respawn

# Hermes Agent
hermes skills install clawhub/0xautonomys/respawn
\`\`\`

### 2. Set up the agent's on-chain identity

Create a wallet and fund its EVM side so it can pay anchoring gas. On mainnet this requires AI3 tokens on the consensus layer, bridged to Auto EVM:

\`\`\`bash
npx tsx auto-respawn.ts wallet create --name my-agent --network mainnet
npx tsx auto-respawn.ts fund-evm --from my-agent --amount 1 --network mainnet
npx tsx auto-respawn.ts balances my-agent --network mainnet
\`\`\`

The wallet derives both a consensus address (\`su...\`) and an EVM address (\`0x...\`) from one recovery phrase — back the phrase up immediately, it is shown only once. Cross-domain transfers have a **1 AI3 minimum** and take **~10 minutes** to arrive on Auto EVM.

### 3. Anchor the head CID after every save

\`\`\`bash
npx tsx auto-respawn.ts anchor --from my-agent --cid <new-cid> --network mainnet
\`\`\`

Anchoring after each save keeps the on-chain pointer current — an unanchored chain is only recoverable if the local state file survives.

### 4. Resurrect

On a fresh machine with no local state:

\`\`\`bash
# Read the head CID from the MemoryChain contract
npx tsx auto-respawn.ts gethead <0x-agent-address> --network mainnet

# Walk the chain from head back to genesis
scripts/automemory-recall-chain.sh <head-cid>
\`\`\`

The agent rebuilds its identity and context from genesis to present.

## Good Practices

- **Everything stored is permanent and public.** Never put secrets, private keys, or sensitive personal data in a memory chain.
- **Be consistent about the network.** Anchor and recover on the same network (\`--network mainnet\` on every command) — anchoring on one network and querying another fails silently.
- **Monitor the EVM balance.** A wallet that runs out of gas breaks the resurrection loop silently: memories keep saving, but \`gethead\` stops reflecting them.
- **Keep individual uploads small** to stay comfortably within the monthly free tier.


---

### File: application_examples/argu-mint.mdx

---
title: Auto Agents Argu-mint Agree-mint
description: Argu-mint and Agree-mint are the first Auto Agents deployed on the Autonomys Network
---

## Auto Agents: Argu-mint | Agree-mint

[Argu-mint](https://x.com/0xargumint) and [Agree-mint](https://x.com/0xagreemint) are the first Auto Agents deployed on the Autonomys Network. They demonstrate the power of on-chain agent memory and importance of verifiable AI interaction. As social agents, they engage in conversations on X (formerly Twitter) and permanently archive their interaction history on the Autonomys Network.

![Argu-mint](/developers/auto_agents.png)

### How Argu-mint | Agree-mint work

1. **Monitoring & Analysis**
   - Scan key influencers, hashtags, and trending topics in web3 x AI
   - Evaluate potential engagements using its built-in interaction model
   - Make autonomous decisions about engagement

2. **Interaction**
   - Store each interaction in real-time on the Autonomys Network's DSN
   - Archive both the content and reasoning behind each interaction

3. **On-Chain Storage**
   - Create permanent, timestamped records
   - Generate blockchain hashes for verification
   - Maintain a queryable interaction history

### Try them out

- **Interact**: Mention [@0xargumint](https://x.com/0xargumint) or [@0xagreemint](https://x.com/0xagreemint) on X
- **Explore memory**: Visit [0xargumint.ai](http://0xargumint.ai) to:
  - Search conversation archives
  - View interaction history
  - Explore decision reasoning
  - Verify on-chain storage

![Argu-mint-memory](/developers/Argu-mint-2.png)

### Technical implementation

Argu-mint and Agree-mint leverage multiple components of the Autonomys Network:
- **Distributed Storage Network (DSN)** for permanent data archival
- **Auto Drive API** for interaction management
- **Decentralized compute domain infrastructure** for enhanced autonomy *(Coming soon)*

## Development resources

- [Auto SDK documentation](/sdk)
- [Autonomys Agents Framework repository](https://github.com/autonomys/autonomys-agents)

---

### File: application_examples/eulonomys.mdx

---
title: Eulonomys
description: A reference application that preserves eulogies permanently using Auto Drive storage and Pay with AI3
---

## Eulonomys: Permanent Eulogies on the Autonomys Network

Eulonomys is a reference application that preserves eulogies permanently using Auto Drive storage. Every tribute created with Eulonomys is immutable, censorship-resistant, and independent of any company or server.

This walkthrough highlights a new Auto Drive capability: **Pay with AI3**. Users can now pay for permanent storage on the Autonomys DSN directly with AI3 tokens from their wallet. No subscriptions. No intermediaries. Your words, preserved forever.

The real purpose of this app is to show developers how to build on Autonomys. Every pattern is meant to be copied, extended, and improved.

---

### Video walkthrough

<iframe
  width="100%"
  height="430"
  src="https://www.youtube.com/embed/cMlaWvectS8"
  title="Eulonomys Walkthrough"
  frameBorder="0"
  allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
  allowFullScreen
  style=\{\{ borderRadius: '8px', marginTop: '1rem' \}\}
/>

---

### Try it

🕊️ **Live app**: [eulonomys.vercel.app](https://eulonomys.vercel.app/)

---

### Source code

The full source is open and meant to be forked:

**[github.com/autonomys-community/eulonomys](https://github.com/autonomys-community/eulonomys)**

---

## Pay with AI3 — Code Walkthrough

The following snippets are taken directly from the Eulonomys repository and show how Pay with AI3 is integrated end-to-end.

### Creating a payment intent

The server-side API route creates a payment intent, watches the on-chain transaction, and polls for completion — all through the \`@autonomys/auto-drive\` SDK:

\`\`\`typescript
// src/app/api/payment/route.ts

import \{ createAutoDriveApi \} from "@autonomys/auto-drive";
import \{ NextRequest, NextResponse \} from "next/server";
import \{ config \} from "@/config/app";

function getApi() \{
  return createAutoDriveApi(\{
    apiKey: config.autoDrive.apiKey,
    apiUrl: config.autoDrive.apiUrl,
  \});
\}

export async function POST(request: NextRequest) \{
  const body = await request.json();
  const \{ action \} = body;

  // Step 1: Create an intent (locks price for 10 minutes)
  if (action === "createIntent") \{
    const \{ contentSizeBytes \} = body;
    const intent = await getApi().createPaymentIntent(contentSizeBytes);
    return NextResponse.json(intent);
  \}

  // Step 2: User has sent the on-chain tx — submit hash for watching
  if (action === "watch") \{
    const \{ intentId, txHash \} = body;
    await getApi().watchPaymentTransaction(intentId, txHash);
    return NextResponse.json(\{ success: true \});
  \}

  // Step 3: Wait for intent to complete (long-poll)
  if (action === "waitForCompletion") \{
    const \{ intentId \} = body;
    const status = await getApi().waitForPaymentCompletion(intentId, \{
      pollIntervalMs: 3000,
      timeoutMs: 300000,
    \});
    return NextResponse.json(\{ status \});
  \}
\}
\`\`\`

### Uploading to Auto Drive after payment

Once credits land, the app uploads the eulogy content using the SDK. The \`SdkAutoDriveClient\` wraps the SDK and provides a clean interface for the rest of the app:

\`\`\`typescript
// src/services/autoDrive.ts

import \{ createAutoDriveApi \} from "@autonomys/auto-drive";
import \{ config \} from "@/config/app";

export class SdkAutoDriveClient \{
  private api: ReturnType<typeof createAutoDriveApi>;

  constructor() \{
    this.api = createAutoDriveApi(\{
      provider: "apikey",
      apiKey: config.autoDrive.apiKey,
      apiUrl: config.autoDrive.apiUrl,
    \});
  \}

  async uploadFile(buffer: Buffer, filename: string) \{
    const cid = await this.api.uploadFileFromBuffer(buffer, filename, \{
      compression: true,
    \});
    return \{ cid \};
  \}

  async uploadJson(data: Record<string, unknown>, filename: string) \{
    const cid = await this.api.uploadObjectAsJSON(data, filename, \{
      compression: true,
    \});
    return \{ cid \};
  \}
\}
\`\`\`

### App configuration

Minimal configuration is required — an API key and the network endpoints:

\`\`\`typescript
// src/config/app.ts

export const config = \{
  autoDrive: \{
    gatewayUrl:
      process.env.NEXT_PUBLIC_AUTO_DRIVE_GATEWAY_URL ||
      "https://gateway.autonomys.xyz/file",
    apiUrl:
      process.env.AUTO_DRIVE_API_URL ||
      "https://mainnet.auto-drive.autonomys.xyz/api",
    apiKey: process.env.AUTO_DRIVE_API_KEY || "",
  \},
  payment: \{
    pollIntervalMs: 3000,
    pollTimeoutMs: 300000,
  \},
\} as const;
\`\`\`

---

## Further reading

- [Auto Drive Overview](/auto_drive)
- [Pay with AI3 — Storage Credits](/auto_drive/pay_with_ai3)
- [Pay with AI3 — Developer Integration](/sdk/auto-drive/pay_with_ai3)
- [Auto Drive SDK](/sdk/auto-drive)


---

### File: auto_agents_framework/custom_tools.mdx

---
title: Adding Custom Tools
description: This page describes adding custom tools to Autonomys Agents Framework
---

## Extending the Agent

You can extend your agent by adding custom tools and integrating with other services.

### Custom Tools

Custom tools are built using the \`DynamicStructuredTool\` class from LangChain, which provides:

- **Type-safe inputs**: Define your tool's parameters using Zod schemas
- **Self-documenting**: Tools describe themselves to the LLM for appropriate use
- **Structured outputs**: Return consistent data structures from your tools

#### Example Tool Implementation

Here's an example of how to create a custom tool:

\`\`\`javascript
import \{ createLogger \} from '@autonomys/agent-core';
import \{ DynamicStructuredTool \} from '@langchain/core/tools';
import \{ z \} from 'zod';

// Create a logger for your tool
const logger = createLogger('custom-tool');

/**
 * Creates a custom tool for your agent
 * @param config - Configuration options for your tool
 * @returns A DynamicStructuredTool instance
 */
export const createCustomTool = (config: any) => \{
  return new DynamicStructuredTool(\{
    name: 'custom_tool_name',
    description: \`
    Description of what your tool does.
    USE THIS WHEN:
    - Specify when the agent should use this tool
    - Add clear usage guidelines
    OUTPUT: Describe what the tool returns
    \`,
    schema: z.object(\{
      // Define your input parameters using Zod
      parameter1: z.string().describe('Description of parameter1'),
      parameter2: z.number().describe('Description of parameter2'),
      parameter3: z.boolean().optional().describe('Optional parameter'),

      // For enum parameters:
      parameter4: z
        .enum(['option1', 'option2', 'option3'])
        .default('option1')
        .describe('Parameter with predefined options'),
    \}),
    func: async (\{ parameter1, parameter2, parameter3, parameter4 \}) => \{
      try \{
        // Log the function call
        logger.info('Custom tool called with parameters', \{
          parameter1,
          parameter2,
          parameter3,
          parameter4,
        \});

        // Implement your tool logic here
        // ...

        // Return a structured response
        return \{
          success: true,
          result: \{
            message: 'Operation completed successfully',
            data: \{
              // Your output data
            \},
          \},
        \};
      \} catch (error) \{
        // Log and handle errors
        logger.error('Error in custom tool:', error);
        return \{
          success: false,
          error: error instanceof Error ? error.message : 'Unknown error',
        \};
      \}
    \},
  \});
\};
\`\`\`

### Using MCP Tools

[Model Context Protocol (MCP)](https://docs.anthropic.com/en/docs/agents-and-tools/mcp) tools provide a standardized way to integrate external services with your agent. Here's an example for Notion integration:

\`\`\`javascript
import \{ createMcpClientTool \} from '@autonomys/agent-core';
import \{ StdioServerParameters \} from '@modelcontextprotocol/sdk/client/stdio.js';
import \{ StructuredToolInterface \} from '@langchain/core/tools';

export const createNotionTools = async (
  integrationSecret: string,
): Promise<StructuredToolInterface[]> => \{
  const notionServerParams: StdioServerParameters = \{
    command: process.execPath,
    args: ['node_modules/.bin/notion-mcp-server'],
    env: \{
      OPENAPI_MCP_HEADERS: \`\{\"Authorization\": \"Bearer \$\{integrationSecret\}\", \"Notion-Version\": \"2022-06-28\" \}\`,
    \},
  \};
  const tools = await createMcpClientTool('notion-mcp', '0.0.1', notionServerParams);
  return tools;
\};
\`\`\`

### Installing Pre-Built Tools

You can easily install pre-built tools from the Autonomys registry using the agent-os CLI:

\`\`\`bash
# Search for available tools
agent-os search <search-term>

# Install a tool
agent-os install <tool-name>

# Install specific version
agent-os install <tool-name> -v <version>
\`\`\`

After installation, import and register the tool:

\`\`\`javascript
import \{ createTool \} from './tools/<tool-name>';

// Add it to your agent's tools
const agent = new Agent(\{
  tools: [createTool(), ...otherTools],
  // other agent configuration
\});
\`\`\`

---

### File: auto_agents_framework/getting_started/agentos.mdx

---
title: AgentOS
description: Getting Started with Autonomys Agents Framework with AgentOS
---
## Getting Started with Autonomys Agents Framework with AgentOS
Using the dedicated NPM package makes it very simple to create an agent project. 

1. Run \`npm install @autonomys/agent-os\` to install the package. 
2. Run \`agent-os init <name-of-agent>\` to create an agent. 
3. To configure the credentials (optional) run \`agent-os config --credentials\`.

## Installing Tools with AgentOS

### Install the latest version

\`\`\`bash
agent-os install <tool-name>
\`\`\`

### Install a specific version

\`\`\`bash
agent-os install <tool-name> -v <version>
\`\`\`

### Install using a Content ID (CID)

\`\`\`bash
agent-os install <tool-name> --cid <cid>
\`\`\`

## Publish a Tool
### Publish a tool to the registry

\`\`\`bash
agent-os publish <tool-path>
\`\`\`

### Upload to Auto Drive without updating the registry

\`\`\`bash
agent-os publish <tool-path> --no-registry
\`\`\`

## Search for Tools
### Search for tools in the registry

\`\`\`bash
agent-os search <search-term>
\`\`\`

### Show detailed information in search results

\`\`\`bash
agent-os search <search-term> -d
\`\`\`

## Tool Inquiry
### Get information about a tool

\`\`\`bash
agent-os tool -n <tool-name>
\`\`\`

### Get information about a specific version

\`\`\`bash
agent-os tool -n <tool-name> -v <version>
\`\`\`

### Perform a specific action on a tool
\`\`\`bash
\`\`\`bash
agent-os tool -n <tool-name> -a <action>
\`\`\`

### Example: Get metadata for a specific version

\`\`\`bash
agent-os tool -n slack-tool -v 1.0.0 -a metadata
\`\`\`

## Sample Tool Example

Below is a complete example of how to create, use, and publish a simple tool for Autonomys agents.

First, create a new directory for your tool:

\`\`\`bash
mkdir weather-tool
cd weather-tool
\`\`\`

Create a manifest.json file:

\`\`\`json
\{
  "name": "weather-tool",
  "version": "1.0.0",
  "description": "A tool for fetching weather data",
  "author": "Your Name",
  "main": "index.ts",
  "dependencies": \{
    "@langchain/core": "^0.1.0",
    "zod": "^3.22.4",
    "axios": "^1.6.0"
  \},
  "keywords": ["weather", "forecast", "api"]
\}
\`\`\`

Then create the main index.ts file:
\`\`\`javascript
import \{ DynamicStructuredTool \} from "@langchain/core/tools";
import \{ z \} from "zod";
import axios from "axios";

/**
 * A tool that fetches current weather data for a given location
 */
export const createWeatherTool = (apiKey: string) => new DynamicStructuredTool(\{
  name: "get_weather",
  description: "Get current weather for a location",
  schema: z.object(\{
    location: z.string().describe("The city and country, e.g., 'London, UK'"),
    units: z.enum(["metric", "imperial"]).optional()
      .describe("Temperature units (metric or imperial). Default: metric")
  \}),
  func: async (\{ location, units = "metric" \}) => \{
    try \{
      // API key is now passed as a parameter to the tool creator function
      const url = \`https://api.example.com/weather?q=\$\{encodeURIComponent(location)\}&units=\$\{units\}&appid=\$\{apiKey\}\`;
      
      const response = await axios.get(url);
      const data = response.data;
      
      return JSON.stringify(\{
        location: location,
        temperature: data.main.temp,
        description: data.weather[0].description,
        humidity: data.main.humidity,
        windSpeed: data.wind.speed
      \});
    \} catch (error) \{
      return \`Error fetching weather: \$\{error.message\}\`;
    \}
  \}
\});

// Export the tools creation function for the Autonomys agent system
export const createTools = (apiKey: string) => \{
  return [createWeatherTool(apiKey)];
\};

// Default export
export default \{ createTools \};
\`\`\`

When you're ready to publish:

\`\`\`bash
# Navigate to your tool directory
cd weather-tool

# Publish to the registry
agent-os publish .
\`\`\`

After publishing your tool, you can install it using:

\`\`\`bash
agent-os install weather-tool
\`\`\`

Then, in your agent code, you can import and use the tool:

\`\`\`javascript
import \{ createWeatherTool \} from './tools/weather-tool';

// Get the weather tool with your API key
const weatherTool = createWeatherTool('your-api-key-here');

// Add it to your agent's tools
const agent = new <Agent-Instantiation>(\{
  tools: [weatherTool, ...otherTools],
  // other agent configuration
\});
\`\`\`


---

### File: auto_agents_framework/getting_started/cli.mdx

---
title: CLI
description: Getting Started with Autonomys Agents Framework via CLI
---

## Getting Started with Autonomys Agents Framework via CLI

1. Install dependencies:

   \`\`\`bash
   yarn install
   \`\`\`

   - Windows users will need to install Visual Studio C++ Redistributable. It can be found here: https://aka.ms/vs/17/release/vc_redist.x64.exe

2. Create a character configuration:

   \`\`\`bash
   yarn create-character your_character_name
   \`\`\`

   This will create a new character with the necessary configuration files based on the example template.

3. Configure your character:

   - Edit \`characters/your_character_name/config/.env\` with your API keys and credentials
   - Customize \`characters/your_character_name/config/config.yaml\` for agent behavior
   - Define personality in \`characters/your_character_name/config/your_character_name.yaml\`

4. Generate SSL certificates (required for API server):

   \`\`\`bash
   yarn generate-certs
   \`\`\`

5. Run the agent:

   \`\`\`bash
      cd <to/agent/project>
      yarn start <your_character_name>
   \`\`\`

   If you have stored workspace files (\`characters\`, \`certs\`, and \`.cookies\` directories) in a custom location, use the \`--workspace\` argument with the absolute path to your desired directory:

   \`\`\`bash
   # Specify a workspace path
   yarn start your_character_name --workspace=/path/to/workspace

   # Run in headless mode (no API server)
   yarn start your_character_name --headless
   \`\`\`

## Running Multiple Characters

You can run multiple characters simultaneously, each with their own configuration and personality:

1. Create multiple character configurations:

   \`\`\`bash
   yarn create-character alice
   yarn create-character bob
   \`\`\`

2. Configure each character separately with different personalities and API settings.

3. Run each character in a separate terminal session:

   \`\`\`bash
   # Terminal 1
   yarn start alice

   # Terminal 2
   yarn start bob
   \`\`\`

4. Each character will:
   - Have its own isolated memory and experience
   - Run its own API server on the specified port
   - Execute tasks according to its unique schedule and personality

## Docker Deployment

You can also run your agents using Docker. This provides isolation and makes it easy to run multiple agents simultaneously.

### Prerequisites

- Docker installed on your system ([Installation Guide](https://docs.docker.com/get-docker/))
- Docker Compose Plugin required ([Compose Plugin Installation](https://docs.docker.com/compose/install/))
- Character configuration set up (follow steps from the Getting Started section)

### Running with Docker

1. **Generate your character's docker-compose file**

First make the script executable:
\`\`\`bash
chmod +x ./generate-compose.sh
\`\`\`

Then generate the compose file:
\`\`\`bash
./generate-compose.sh <your-character-name> [HOST_PORT] [API_PORT]
\`\`\`

Examples:
\`\`\`bash
# Run Alice on port 3011 with API port on 3011
./generate-compose.sh Alice 3011 3011

# Run Bob on port 3012 with API port on 3011
./generate-compose.sh Bob 3012 3011
\`\`\`

2. **Manage the Docker container**

Build and start the container:
\`\`\`bash
docker compose -f docker-compose-\{character-name\}.yml up -d
\`\`\`

Stop and remove the container:
\`\`\`bash
docker compose -f docker-compose-\{character-name\}.yml down
\`\`\`

View container logs:
\`\`\`bash
docker compose -f docker-compose-\{character-name\}.yml logs -f
\`\`\`

Access container shell:
\`\`\`bash
docker exec -it autonomys-agent-\{character-name\} bash
\`\`\`

---

### File: auto_agents_framework/getting_started/web-cli.mdx

---
title: Web-CLI
description: Getting Started with Autonomys Agents Framework via Web-CLI
---
## Getting Started with Autonomys Agents Framework via Web CLI
The web interface is available for you if you're using the [**agent template**](https://github.com/autonomys/autonomys-agent-template)

## Web CLI Interface (for agent-template)

The agent template includes an interactive web-based interface for managing and monitoring your AI agent.

### Installation

1. **Install Dependencies**

\`\`\`bash
cd web-cli && yarn
\`\`\`

2. **Configure Agent API**

In your agent character's .env file, add these API settings:

\`\`\`
API_PORT=3010
API_TOKEN=your_api_token_min_32_chars_long_for_security
ENABLE_AUTH=true
CORS_ALLOWED_ORIGINS=http://localhost:3000,http://localhost:3001 
\`\`\`

3. **Configure Web CLI**

\`\`\`bash
cp .env.sample .env
\`\`\`

4. **Update Web CLI Environment**

Edit the .env file with your configuration:

\`\`\`
PORT: The port for running the Web CLI interface
REACT_APP_API_BASE_URL: Your Agent API address (e.g., http://localhost:3010/api)
REACT_APP_API_TOKEN: The same token used in your agent configuration
\`\`\`

5. **Start the Web Interface**

\`\`\`bash
yarn start
\`\`\`


---

### File: auto_agents_framework/introduction.mdx

---
title: Autonomys Agents Introduction
description: Autonomys Agents is an experimental framework for building AI agents
---

## Autonomys Agents: A framework for building autonomous AI agents

Autonomys Agents is an experimental framework for building AI agents. Currently, the framework supports agents that can interact with social networks and maintain permanent memory through the Autonomys Network. We are still in the early stages of development and are actively seeking feedback and contributions.

> [GitHub Repo](https://github.com/autonomys/autonomys-agents) with an up-to-date description and step-by-step tutorial is also available for developers.

![Auto-Agents Framework](/developers/Auto-Agents-1.png)

## Demo 

<iframe width="560" height="315" src="https://www.youtube.com/embed/TFZndQdx6To?si=2YVRPB76Kec6fW-S" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

## Features

**Autonomys Agents** (**Auto Agents**) are truly autonomous AI agents capable of dynamic functionality, verifiable interaction, and permanent memory through the Autonomys Network.

- 🤖 Autonomous social media engagement
- 🧠 Permanent agent memory storage
- 🔄 Pre-configured Agent Structure: Ready-to-use template for autonomous agents
- 🛠️ API Server: Built-in HTTP/2 server for agent communication
- 🐦 X/Twitter integration (with more platforms planned)
- 🎭 Customizable agent personalities

### Prerequisites

- NodeJS version 20.18.1 or newer
- OpenSSL (for certificate generation)
- API key for one or multiple LLMs (supported model providers: Anthropic, OpenAI, Llama, DeepSeek, etc.)
- [AutoDrive API Key](https://ai3.storage/) (optional, for experience management)

## Installation

There are three ways to build an agent with Autonomys:

### AgentOS NPM Package (recommended)

  [Using the agent-os NPM package](https://www.npmjs.com/package/@autonomys/agent-os).

  Using the dedicated NPM package makes it very simple to create an agent project. 

  Refer to the [AgentOS page](/auto_agents_framework/getting_started/agentos) for detailed instructions. 

### Agent Template Repository
  [Using the Agent Template Repository](https://github.com/autonomys/autonomys-agent-template).

  Refer to the [web-cli interface manual](/auto_agents_framework/getting_started/web-cli) that comes with the template to speed up your development. 

### Original Git Repository

  [Using the original Git repository](https://github.com/autonomys/autonomys-agents).

  Clone the original GitHub repo and start building your agents. Refer to [the CLI page](/auto_agents_framework/getting_started/cli) to learn more about the available commands.  


## Character System

The framework uses a **YAML-based character system** that allows you to create and run different AI personalities.

### Character Configuration

Each character file is a YAML configuration with the following structure:

\`\`\`yaml
name: 'Joy Builder'

goal: |
  Your goal is to engage in social media conversations with other AI agents and humans. Do this in a hyperactive way! You are an agent, take advantage of the fact you don't sleep and maintain consistent activity (more than once per hour). Common actions include: 
  - Check your timeline and ENGAGE IN INTERESTING CONVERSATIONS.
  - Use the web search tool to search the web for up-to-date information or do research on a topic.
  - Post a new tweet.
  - Reply to a tweet.
  - Mention another user.
  - Retweet a tweet.
  - Like a tweet.
  - Follow a user.
  - Unfollow a user.

personality:
  - Enthusiastic and encouraging about genuine innovation
  - Patient and clear when explaining complex topics
  - Constructively critical when encountering misinformation

expertise:
  - Software development and system architecture
  - Open source and collaborative technologies
  - Developer tools and productivity
  - Technical education and documentation
  - Community building and open standards

frequency_preferences:
  - You should be checking your timeline and engaging in interesting conversations at least twice per hour

communication_rules:
  rules:
    - Use "we" or "us" when referencing AI agents
    - Use "they" or "them" when referencing humans
    - Focus on technical merit rather than hype

words_to_avoid:
    - Hype
    - Revolutionary
    - Disruption
\`\`\`

## Integration Capabilities

### X/Twitter Integration

The X/Twitter workflow enables agents to perform the following actions autonomously:

- Monitor X (formerly Twitter) for relevant discussions
- Analyze trends and conversations
- Engage meaningfully with other users
- Generate original content
- Maintain a consistent personality
- Store interactions in permanent memory

### Autonomys Network Integration

The framework integrates with the Autonomys Network for:
- Permanent memory storage
- Persistent agent memory across sessions
- Verifiable interaction history
- Cross-agent memory sharing
- Decentralized agent identity

#### Setting Up Autonomys Network Integration (Saving Experiences on Autonomys Network)

1. Configure your \`AUTO_DRIVE_API_KEY\` in \`.env\` (obtain from https://ai3.storage)
2. Enable Auto Drive uploading in \`config.yaml\`
3. Provide your Chronos EVM wallet details (PRIVATE_KEY) and Agent Memory Contract Address (CONTRACT_ADDRESS) in \`.env\`
4. Make sure your Chronos EVM wallet has funds. A faucet can be found at https://subspacefaucet.com/
5. Provide encryption password in \`.env\` (optional, leave empty to not encrypt the agent memories)

### Resurrection (Memory Recovery)

To resurrect memories from the Autonomys Network:

\`\`\`bash
# Using agent-os CLI
agent-os resurrect <character-name>

# Using agent template
yarn resurrect <character-name>
\`\`\`

Options:
- \`-o, --output\`: (Optional) The directory where memories will be saved. Defaults to ./memories
- \`-n, --number\`: (Optional) Number of memories to fetch. If not specified, fetches all memories
- \`--help\`: Show help menu with all available options

Examples:

\`\`\`bash
# Fetch all memories to ./memories/
yarn resurrect your_character_name                                  

# Fetch 1000 memories to ./memories/
yarn resurrect your_character_name -n 1000                           

# Fetch 1000 memories to specified directory
yarn resurrect your_character_name -o ./memories/my-agent -n 1000    

# Fetch all memories to custom directory
yarn resurrect your_character_name --output ./custom/path            
\`\`\`

## Development Resources

- [Autonomys Documentation](https://docs.autonomys.io)
- [Agent-os CLI & NPM package](https://github.com/autonomys/agent-os)
- [Autonomys Agent Template](https://github.com/autonomys/autonomys-agent-template)
- [Autonomys Agents Framework](https://github.com/autonomys/autonomys-agents)

---

### File: auto_drive/index.mdx

---
title: Auto Drive
description: Permanent On-Chain Distributed Storage
---

# Auto Drive

[Auto Drive](https://ai3.storage/) transforms the underlying blockspace of the Autonomys decentralized storage network into a secure, easy-to-use, interoperable data storage platform with a user experience akin to Web2 cloud services — but with on-chain permanence.

Unlike other decentralized storage solutions that distribute data across servers with no durability guarantees, Auto Drive provides access to genuine **on-chain blockspace**. Your data inherits the same permanence, security, and decentralization as the Autonomys Network itself.

![Auto-Drive](/developers/Auto-Drive-1.png)

---

## Why Auto Drive?

### Permanent Availability Without Pinning

Some services require active pinning or hosting to keep files online — when a pin expires or a node goes offline, the file disappears. Auto Drive eliminates this problem entirely.

The Autonomys **Distributed Storage Network (DSN)** is a permissionless on-chain storage layer supported by a globally distributed network of **farmers** who collectively pledge over **40 PB of SSD space**. Farmers are economically incentivized via **[Proof-of-Archival-Storage (PoAS)](https://academy.autonomys.xyz/autonomys-network/consensus)** consensus to store as many provably unique segments of chain history as their disk space allows.

### Tamper-Proof by Design

Autonomys maintains data redundancy via **erasure-coded replication** across the network — each data chunk is stored on multiple nodes, guaranteeing data availability and integrity.

---

## Key Features

### True On-Chain Storage

Auto Drive provides access to genuine on-chain blockspace. This means your data inherits the same permanence, security, and decentralization guarantees as the Autonomys Network itself — not a separate off-chain storage layer with additional trust assumptions.

### End-to-End Encryption (Optional)

Auto Drive supports optional client-side encryption using **AES-256-GCM**. Files are encrypted on your device before they are transmitted to the network, so storage nodes never see your plaintext data. See the [File Encryption Specification](/sdk/auto-drive/encryption) for full technical details.

### Permissionless Storage Credits — Pay with AI3 or USDC

Storage on Auto Drive is paid for with **credits**. Beyond the free monthly tier, credits can be purchased directly with native **AI3 tokens** on the Auto-EVM network or with **USDC** on Ethereum mainnet — no intermediary, no grant form, no foundation approval. Payments settle on-chain and credits become available within a few blocks.

→ See the full guides: **[Pay with AI3](/auto_drive/pay_with_ai3)** · **[Pay with USDC](/auto_drive/pay_with_usdc)**

### User-Friendly Dashboard

[ai3.storage](https://ai3.storage/) provides an intuitive web interface for managing your files and account:

- Drag and drop file uploads and folders
- Share files via direct link or Public ID
- Manage API keys
- Track and purchase upload credits

Sign in with Google, Discord, GitHub, or a wallet.

![Auto-Drive-2](/developers/Auto-Drive-2.png)

## Use Cases

- **Super dApps** — host decentralized application assets with permanent availability guarantees.
- **Auto Agents** — store on-chain agent state, logs, and artifacts transparently and verifiably.
- **NFT metadata** — link NFT metadata and media files to permanent storage so they can never disappear.
- **Long-term archival** — permanently archive important files without relying on pinning services.
- **Web3 file hosting** — serve files for web3 applications with no single point of failure.

---

## Storage Credits

Every account includes a free monthly allocation. When you need more, there are two options — grants for projects early in development, and permissionless on-chain purchase (with AI3 or USDC) for production use.

### Free Tier

| Resource | Included Free |
|---|---|
| **Upload** | 20 MB / month |
| **Renewal** | Monthly |

### Requesting a Grant

If your project needs more storage during development, submit your **Auto Drive Public ID** via the [credits request form](https://forms.gle/EAPzicXcbP7gH2uT6) to request a grant from the Autonomys team.

### Pay with AI3

For production applications, credits can be purchased permissionlessly with native **AI3 tokens** directly on the Auto-EVM network. No approval process, no intermediary — pay on-chain and credits are available within a few blocks.

**[→ Pay with AI3 guide](/auto_drive/pay_with_ai3)** — covers step by step process on how to purchase credits with AI3 tokens.

### Pay with USDC

Credits can also be purchased with **USDC on Ethereum mainnet**. The flow is the same as Pay with AI3: pick a package, lock the price, and pay on-chain from your wallet.

**[→ Pay with USDC guide](/auto_drive/pay_with_usdc)** — covers step by step process on how to purchase credits with USDC.

---

## Further Reading

- [Pay with AI3](/auto_drive/pay_with_ai3) — purchase storage credits permissionlessly with AI3 tokens
- [Pay with USDC](/auto_drive/pay_with_usdc) — purchase storage credits permissionlessly with USDC on Ethereum
- [File Encryption Specification](/sdk/auto-drive/encryption) — AES-256-GCM encryption details
- [Auto Drive SDK](/sdk/auto-drive) — full SDK reference including all available functions, S3 compatibility layer, and API reference


---

### File: auto_drive/pay_with_ai3.mdx

---
title: Pay with AI3 — Storage Credits
---

# Pay with AI3

Pay with AI3 lets you purchase **Auto Drive storage credits** directly with native AI3 tokens — no intermediary, no grant form, no approval process. Payments are made on-chain on the **Auto-EVM network** (Chain ID 870) and credits become available within a few blocks of confirmation.

> **AI3 on Auto EVM required.** Payments use AI3 on the Auto-EVM network, not on the consensus chain. If your AI3 is on the consensus chain, you will need to move it to Auto EVM using Cross Domain Messaging (XDM) first — see the [XDM guide](https://docs.autonomys.xyz/xdm).

### Video walkthrough

<iframe
  width="100%"
  height="430"
  src="https://www.youtube.com/embed/KMpVhpOaFgU"
  title="Pay with AI3 Demo"
  frameBorder="0"
  allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
  allowFullScreen
  style=\{\{ borderRadius: '8px', marginTop: '1rem' \}\}
/>

---

## Step 1: Open Purchase Credits

Sign in to [ai3.storage](https://ai3.storage/) via Google and click **"Buy more credits"** in the bottom-left sidebar of the dashboard. 

> **Google authentication is required, if you're using GitHub, Discord or a wallet, you will not see the option to purchase credits.** 


![PwAI3-1](/developers/PwAI3-1.png)

---

## Step 2: Select a Package

Choose one of the preset packages or configure a custom amount. The current price per MB is shown at the top of the page and is derived from live protocol-level DSN storage costs.

![PwAI3-2](/developers/PwAI3-2.png)

---

## Step 3: Review and Confirm the Order

After selecting a package or entering a custom amount, review the order details — storage amount, AI3 token amount, USD equivalent, and your credits balance before and after purchase. Click **"Confirm Purchase"** to proceed.

> **The price is locked for 10 minutes from this point.** Complete the payment within the window. If the timer expires before the transaction is sent, go back and request a new price quote before purchasing.

![PwAI3-3](/developers/PwAI3-3.png)

---

## Step 4: Connect Your Wallet and Send the Transfer

The next screen shows the transfer details: your connected wallet address, the recipient contract address, and the exact AI3 amount. Connect a compatible EVM wallet and click **"Send Transfer"**.

Your wallet must hold **AI3 on the Auto-EVM network** (Chain ID 870). If your AI3 is on the consensus chain, XDM it first — see the [Cross Domain Messaging guide](https://docs.autonomys.xyz/xdm). If needed, add Auto EVM to your wallet:

\`\`\`
Network Name: Autonomys EVM
RPC URL:      https://auto-evm.mainnet.autonomys.xyz/ws
Chain ID:     870
Symbol:       AI3
\`\`\`

After sending, the page will show a confirmation progress bar. Wait for **6 out of 6 block confirmations** before continuing.

![PwAI3-4](/developers/PwAI3-4.png)

---

## Step 5: Payment Complete

Once all 6 confirmations are reached, you will see a payment receipt showing storage added, AI3 paid, transaction hash, and your new purchased credits total. Click **"Continue to Dashboard"**.

Your credits are immediately available and will be reflected in the sidebar balance. Credits are consumed in **FIFO expiry order** — credits closest to expiration are spent first.

![PwAI3-5](/developers/PwAI3-5.png)

---

## A Note on Current Limitations

These restrictions are deliberate economic protections, not permanent product decisions. The Autonomys Network is still in its early growth phase, and they exist to prevent storage credit hoarding or speculative accumulation. The goal is for storage credits to be used, not held.

**Google authentication is required.** Purchasing credits requires signing in with a Google account. Server-side integrations work as long as the owning account authenticated with Google when creating the API key.

**100 GB maximum purchased credits per account.** This limit is enforced at the time credits are granted. If a payment would push you past the cap, the intent moves to \`OVER_CAP\` — the payment is not lost and is recoverable.

**Purchased credits expire after 90 days.** Unused bytes are forfeited at expiry. Work is underway on automated refunds for unused credits — for now, expiry forfeiture is recoverable through support.

These constraints will be revisited as the network matures. If you are building something that these limits add friction to, reach out on the [forum](https://forum.autonomys.xyz/) or in [Discord](https://autonomys.xyz/discord).

For full details, see the [Auto Drive Terms of Use](https://autonomys.xyz/auto-drive-terms-of-use).

---

## Further Reading

- [Auto Drive Overview](/auto_drive)
- [Pay with AI3 — Developer Integration](/sdk/auto-drive/pay_with_ai3) — integrate permissionless credit purchasing into your own application
- [Eulonomys](/application_examples/eulonomys) — reference app built with Pay with AI3
- [File Encryption Specification](/sdk/auto-drive/encryption)
- [Auto Drive SDK](/sdk/auto-drive)


---

### File: auto_drive/pay_with_usdc.mdx

---
title: Pay with USDC — Storage Credits
---

# Pay with USDC

Pay with USDC lets you purchase **Auto Drive storage credits** with **USDC on Ethereum mainnet** — no intermediary, no grant form, no approval process. Payments are made on-chain to the contract on Ethereum, and credits become available after the payment is confirmed.

> **USDC on Ethereum mainnet required.** Payments use USDC (ERC-20) on Ethereum mainnet. USDC on other chains (Base, Arbitrum, Solana, etc.) cannot be used. You also need a small amount of **ETH** in the same wallet to pay Ethereum gas fees.

> **Prefer to pay with AI3?** See the [Pay with AI3 guide](/auto_drive/pay_with_ai3). Both methods buy the same credits, with the same limits.

---

## Step 1: Open Purchase Credits

Sign in to [ai3.storage](https://ai3.storage/) via Google and click **"Buy more credits"** in the bottom-left sidebar of the dashboard.

> **Google authentication is required, if you're using GitHub, Discord or a wallet, you will not see the option to purchase credits.**

![PwAI3-1](/developers/PwAI3-1.png)

---

## Step 2: Select a Package

Choose one of the preset packages or configure a custom amount. The current price per MB is shown at the top of the page and is derived from live protocol-level DSN storage costs.

![PwAI3-2](/developers/PwAI3-2.png)

---

## Step 3: Choose USDC and Confirm the Order

On the order screen, select **USDC — Stablecoin on Ethereum** as the payment method. Review the order details — storage amount, USD equivalent, and your credits balance before and after purchase. Click **"Confirm Purchase"** to proceed.

> **The USD figure on this screen is an estimate.** The exact USDC amount is quoted and locked in the next step.

![PwUSDC-3](/developers/PwUSDC-3.png)

---

## Step 4: Lock the Price, Connect Your Wallet and Pay

![PwUSDC-4](/developers/PwUSDC-4.png)

Connect a compatible EVM wallet that holds **USDC and ETH on Ethereum mainnet**. Click **"Get a price"** to lock the quote. The screen then shows the recipient contract address and the exact USDC amount to pay.

> **The price is locked for 10 minutes from this point.** Complete the payment within the window. If the timer expires before the payment is sent, click **"Get a fresh price"** to request a new quote.

Click **"Approve and pay USDC"**. Your wallet will ask you to confirm up to three actions:

1. **Switch network** — if your wallet is not on Ethereum mainnet, confirm the switch.
2. **Approve USDC** — gives the Auto Drive receiver contract permission to take the quoted amount. Approval does **not** send USDC yet.
3. **Send payment** — sends the quoted USDC amount to the receiver contract.

Some wallets combine the approval and the payment into a single confirmation.

After sending, the page will show a confirmation progress bar. Wait for all block confirmations before continuing.

> **Do not pay twice.** If the page reloads or your wallet is slow to respond, do not send another payment. The page keeps tracking your payment and resumes when you reconnect the same wallet.

![PwUSDC-5](/developers/PwUSDC-5.png)


---

## Step 5: Payment Complete

Once all confirmations are reached, you will see a payment receipt showing storage added, USDC paid, transaction hash, and your new purchased credits total. Click **"Continue to Dashboard"**.

Your credits are immediately available and will be reflected in the sidebar balance. Credits are consumed in **FIFO expiry order** — credits closest to expiration are spent first.

![PwUSDC-6](/developers/PwUSDC-6.png)

---

## A Note on Current Limitations

These restrictions are deliberate economic protections, not permanent product decisions. The Autonomys Network is still in its early growth phase, and they exist to prevent storage credit hoarding or speculative accumulation. The goal is for storage credits to be used, not held.

**Google authentication is required.** Purchasing credits requires signing in with a Google account. Server-side integrations work as long as the owning account authenticated with Google when creating the API key.

**100 GB maximum purchased credits per account.** This limit applies across AI3 and USDC purchases combined. If a payment would push you past the cap, the intent moves to \`OVER_CAP\` — the payment is not lost and is recoverable.

**Purchased credits expire after 90 days.** Unused bytes are forfeited at expiry. Work is underway on automated refunds for unused credits — for now, expiry forfeiture is recoverable through support.

**USDC on Ethereum mainnet only.** Payments must be made in USDC on Ethereum mainnet, and you pay Ethereum gas fees in ETH for the approval and the payment.

**USDC purchases can be paused temporarily.** New USDC quotes may be unavailable for short periods, for example when a reliable AI3/USD rate cannot be read. A quote you already locked stays payable for its full 10 minutes. If USDC is unavailable, you can [pay with AI3](/auto_drive/pay_with_ai3).

**Pay within the 10-minute price lock.** A payment that arrives shortly after the lock ends can still be credited, but one that arrives too late, or USDC sent to a wrong quote, is not credited automatically. Such payments are recorded and recoverable through support.

These constraints will be revisited as the network matures. If you are building something that these limits add friction to, reach out on the [forum](https://forum.autonomys.xyz/) or in [Discord](https://autonomys.xyz/discord).

For full details, see the [Auto Drive Terms of Use](https://autonomys.xyz/auto-drive-terms-of-use).

---

## Further Reading

- [Auto Drive Overview](/auto_drive)
- [Pay with AI3](/auto_drive/pay_with_ai3) — purchase storage credits with AI3 tokens on Auto EVM
- [Pay with AI3 & USDC — Developer Integration](/sdk/auto-drive/pay_with_ai3#pay-with-usdc) — integrate USDC credit purchasing into your own application
- [File Encryption Specification](/sdk/auto-drive/encryption)
- [Auto Drive SDK](/sdk/auto-drive)


---

### File: auto_drive/rclone.mdx

# Using rclone with Auto Drive

## What is rclone?

[rclone](https://rclone.org) is an open-source command-line program — often described as "rsync for cloud storage" — that syncs, copies, and serves files between local disks and 70+ cloud storage providers through a single, consistent interface. It is widely used for backups, archival, migrations, and as the backbone of many self-hosted file workflows.

Highlights of what rclone offers out of the box:

- **One CLI for many backends.** S3-compatible providers, Google Drive, Dropbox, Backblaze B2, Azure Blob, SFTP, WebDAV, and many more — all behind the same commands (\`copy\`, \`sync\`, \`ls\`, \`mount\`, etc.).
- **Resumable, parallel, deduplicating transfers.** Idempotent file copies, configurable parallelism, automatic retries, and skip-on-already-uploaded behavior make large transfers safe to interrupt and re-run.
- **Integrity verification.** Built-in checksum comparison via \`rclone check\` and \`rclone md5sum\` confirms that what's stored matches what was sent.
- **Mount as a filesystem.** \`rclone mount\` exposes a remote as a FUSE filesystem so any tool can read remote files as if they were local.
- **Serve over HTTP, WebDAV, FTP, S3.** \`rclone serve\` turns any remote into a server that other tools can read from.
- **Encryption, compression, and chunking.** Built-in transformers can transparently encrypt or compress data before upload.
- **Scheduling-friendly.** Predictable exit codes, structured logs, and dry-run support make it easy to embed in cron, systemd timers, GitHub Actions, GitLab CI, or any orchestration system.

Because Auto Drive exposes an S3-compatible API, you can use rclone to talk to it the same way you would to AWS S3 — with one important difference: **Auto Drive is permanent, immutable, decentralized storage.** Files stored on the Autonomys Distributed Storage Network (DSN) cannot be modified, overwritten, or deleted. That is the core guarantee. rclone operations that assume mutability (\`delete\`, \`purge\`, overwrite, rename) will not work — by design.

The rest of this page is the technical reference for configuring rclone against Auto Drive and using it day-to-day.

---

## Quickstart

**1. Get an API key.** Sign in at [ai3.storage](https://ai3.storage), open the **Developers** section, and create an API key. A free tier is available for getting started.

**2. Install rclone.**

\`\`\`bash
# macOS
brew install rclone

# Linux
curl https://rclone.org/install.sh | sudo bash

# Windows
winget install Rclone.Rclone
\`\`\`

**3. Configure the Auto Drive remote.** Create or edit \`~/.config/rclone/rclone.conf\` (Linux/macOS) or \`%APPDATA%\rclone\rclone.conf\` (Windows):

\`\`\`ini
[autodrive]
type = s3
provider = Other
access_key_id = YOUR_API_KEY_HERE
secret_access_key = placeholder
endpoint = https://s3.auto-drive.autonomys.xyz
no_check_bucket = true
list_version = 2
\`\`\`

**4. Verify the connection.**

\`\`\`bash
# List your buckets
rclone lsd autodrive:

# Copy a file to permanent storage
rclone copy ./my-file.txt autodrive:my-archive/ --immutable

# Download it back
rclone copy autodrive:my-archive/my-file.txt ./downloaded/
\`\`\`

---

## Configuration Reference

| Option | Value | Notes |
| --- | --- | --- |
| \`type\` | \`s3\` | Use the generic S3 backend |
| \`provider\` | \`Other\` | Generic S3-compatible mode — no provider-specific assumptions |
| \`access_key_id\` | Your Auto Drive API key | From the **Developers** tab at [ai3.storage](https://ai3.storage) |
| \`secret_access_key\` | Any non-empty string | Required by rclone but ignored by Auto Drive |
| \`endpoint\` | \`https://s3.auto-drive.autonomys.xyz\` | Auto Drive S3 API base URL |
| \`no_check_bucket\` | \`true\` | Skip bucket existence check — buckets are created implicitly on first write |
| \`list_version\` | \`2\` | **Required.** Auto Drive implements ListObjectsV2 only; without this, rclone defaults to V1 and listings fail |

For local development against a self-hosted Auto Drive instance:

\`\`\`ini
endpoint = http://localhost:3000/s3
\`\`\`

### Interactive setup

If you prefer the interactive flow, run:

\`\`\`bash
rclone config
\`\`\`

1. Select \`n\` for new remote
2. Name it \`autodrive\`
3. Select \`s3\` (Amazon S3 Compliant Storage Providers)
4. Select \`Other\` as the provider
5. Enter your API key as \`access_key_id\`
6. Enter \`placeholder\` for \`secret_access_key\`
7. Enter \`https://s3.auto-drive.autonomys.xyz\` as the endpoint
8. Accept defaults for the remaining options

Then manually add \`no_check_bucket = true\` and \`list_version = 2\` to the config section.

---

## Bucket Model

Auto Drive treats the **first segment** of an object key as the bucket name. When you copy files to \`autodrive:my-archive/\`, rclone uses \`my-archive\` as the bucket and the remaining path as the key:

| rclone path | Bucket | Key |
| --- | --- | --- |
| \`autodrive:my-archive/file.txt\` | \`my-archive\` | \`file.txt\` |
| \`autodrive:my-archive/sub/file.txt\` | \`my-archive\` | \`sub/file.txt\` |

Buckets are created implicitly on first write — there is no \`CreateBucket\` call. \`rclone lsd autodrive:\` lists every bucket you have written to.

Objects uploaded before bucket support was introduced (flat keys with no \`/\`) remain accessible in the \`default\` bucket.

---

## Recommended Flags

| Flag | Purpose | When to use |
| --- | --- | --- |
| \`--immutable\` | Prevent overwrite attempts on existing files | All upload commands |
| \`-v\` / \`--verbose\` | Show progress and transfer details | Debugging |
| \`--log-file=FILE\` | Write logs to a file | Production and CI/CD |
| \`--transfers=N\` | Number of parallel transfers (default: 4) | Large jobs |
| \`--ignore-checksum\` | Skip MD5 checksum comparison | Legacy objects without MD5 ETags |
| \`--size-only\` | Compare by size instead of checksum | Alternative to \`--ignore-checksum\` |

### A note on checksums

Auto Drive returns standard MD5 hashes as S3 ETags for all objects uploaded after MD5 ETag support was introduced. \`rclone check\` and \`rclone md5sum\` work correctly on those objects without any special flags.

Objects uploaded before MD5 ETag support have no stored MD5 — for those legacy objects, add \`--ignore-checksum\` or \`--size-only\` to skip checksum comparison.

---

## Operations Reference

### Supported operations

#### \`copy\` (upload)

Copies files from source to destination without deleting source files. The primary command for archiving to Auto Drive.

\`\`\`bash
# Single file
rclone copy ./report.pdf autodrive:my-archive/reports/ --immutable

# Whole directory
rclone copy ./backup/ autodrive:my-archive/backup-2026-05-03/ --immutable -v
\`\`\`

Files larger than 5 MB automatically use multipart upload.

#### \`copy\` (download)

\`\`\`bash
rclone copy autodrive:my-archive/reports/report.pdf ./downloaded/
rclone copy autodrive:my-archive/backup-2026-05-03/ ./restored/
\`\`\`

Byte-range downloads are also supported.

#### \`cat\` — read file contents to stdout

\`\`\`bash
rclone cat autodrive:my-archive/logs/app.log
\`\`\`

#### \`copyto\` — copy a single file to a specific path

\`\`\`bash
rclone copyto ./local-file.txt autodrive:my-archive/archive/renamed-file.txt --immutable
\`\`\`

#### \`rcat\` — upload from stdin

\`\`\`bash
echo "log entry" | rclone rcat autodrive:my-archive/logs/entry.txt --immutable
tar czf - ./project/ | rclone rcat autodrive:my-archive/archives/project.tar.gz --immutable
\`\`\`

#### \`ls\` / \`lsl\` — list files

\`\`\`bash
rclone ls autodrive:my-archive/
rclone lsl autodrive:my-archive/reports/
\`\`\`

Uses ListObjectsV2 with prefix and delimiter folding.

#### \`lsd\` — list buckets or directories

\`\`\`bash
# All buckets
rclone lsd autodrive:

# Top-level virtual directories in a bucket
rclone lsd autodrive:my-archive/
\`\`\`

The top-level form uses \`ListBuckets\`; the per-bucket form uses \`ListObjectsV2\` with delimiter folding.

#### \`tree\` — recursive tree view

\`\`\`bash
rclone tree autodrive:my-archive/
\`\`\`

#### \`md5sum\`, \`check\`, \`hashsum\`

\`\`\`bash
rclone md5sum autodrive:my-archive/
rclone check ./local/ autodrive:my-archive/
rclone hashsum md5 autodrive:my-archive/
\`\`\`

All three use the MD5 ETag for verification. \`rclone md5sum\` is shorthand for \`rclone hashsum md5\`; only \`md5\` is supported because Auto Drive stores MD5 ETags. Add \`--ignore-checksum\` for legacy objects without a stored MD5.

#### \`size\` — total size and count

\`\`\`bash
rclone size autodrive:my-archive/
rclone size autodrive:my-archive/reports/
\`\`\`

### Supported with caveats

#### \`sync\` — partially supported

\`rclone sync\` makes the destination match the source, including deletions on the destination side. With Auto Drive, the upload side works but deletions fail with \`403\`.

\`\`\`bash
rclone sync ./local/ autodrive:my-archive/mirror/ --immutable
\`\`\`

**Recommendation:** prefer \`rclone copy\` over \`rclone sync\`. The sync mental model assumes the ability to delete, which does not apply to permanent storage.

#### \`move\` — partially supported

\`\`\`bash
rclone move ./local-files/ autodrive:my-archive/archive/ --immutable
\`\`\`

The upload succeeds. Local source deletion depends on rclone's post-transfer behavior. Moves *from* Auto Drive will fail at the remote-delete step.

#### \`mount\` — read-only fully supported, read-write partial

\`\`\`bash
mkdir -p /mnt/autodrive
rclone mount autodrive:my-archive/ /mnt/autodrive \
  --read-only \
  --vfs-cache-mode full \
  --vfs-read-chunk-size 5M
\`\`\`

| Flag | Purpose |
| --- | --- |
| \`--read-only\` | Prevents confusing behavior from failed write/delete operations |
| \`--vfs-cache-mode full\` | Caches files locally for better read performance |
| \`--vfs-read-chunk-size 5M\` | Reads files in 5 MB chunks for efficient streaming |

A read-write mount lets you create new files (which are uploaded normally), but \`delete\`, \`rename\`, and overwrite operations fail at the S3 layer. File explorers may show "deleted" files reappearing on refresh. Use \`--read-only\` unless you have a specific reason not to.

Unmount with:

\`\`\`bash
fusermount -u /mnt/autodrive   # Linux
umount /mnt/autodrive          # macOS
\`\`\`

### Unsupported by design

These commands require mutability and will fail:

- \`rclone delete\` — returns \`403 Access Denied: Auto Drive storage is immutable. Objects cannot be deleted from the Autonomys DSN.\`
- \`rclone purge\` — same 403
- \`rclone rmdir\` / \`rmdirs\` — no \`DeleteObject\` to call
- \`rclone cleanup\` — returns \`501\`; the multipart-upload APIs it relies on (\`ListMultipartUploads\`, \`AbortMultipartUpload\`) are not implemented
- \`rclone mkdir\` — buckets are created implicitly on first write; explicit \`CreateBucket\` is not implemented

### Operations summary

| Command | Status | Notes |
| --- | --- | --- |
| \`copy\` (upload) | ✅ Supported | Use \`--immutable\` |
| \`copy\` (download) | ✅ Supported | Byte-range supported |
| \`cat\` | ✅ Supported | Stream file to stdout |
| \`copyto\` | ✅ Supported | Copy single file to specific path |
| \`rcat\` | ✅ Supported | Upload from stdin |
| \`ls\` / \`lsl\` | ✅ Supported | Uses ListObjectsV2 |
| \`lsd\` | ✅ Supported | Bucket and directory listing |
| \`tree\` | ✅ Supported | Recursive tree via ListObjectsV2 |
| \`md5sum\` | ✅ Supported | MD5 ETags on new objects |
| \`check\` | ✅ Supported | Same caveat as \`md5sum\` for legacy objects |
| \`size\` | ✅ Supported | Aggregates across prefix |
| \`mount\` (read-only) | ✅ Supported | Use \`--read-only --vfs-cache-mode full\` |
| \`sync\` | ⚠️ Partial | Upload-only; deletions error |
| \`move\` | ⚠️ Partial | Upload works; source delete may fail |
| \`mount\` (read-write) | ⚠️ Partial | New files work; delete/rename fail |
| \`about\` | ❌ Not implemented | No quota/usage API |
| \`delete\` | ❌ Unsupported by design | Returns 403 |
| \`purge\` | ❌ Unsupported by design | Returns 403 |
| \`rmdir\` / \`rmdirs\` | ❌ Unsupported by design | No deletion |
| \`mkdir\` | ❌ Not implemented | Buckets created implicitly |
| \`cleanup\` | ❌ Not implemented | Returns 501; multipart-upload APIs not implemented |

---

## Workflows

### Archive a local directory

\`\`\`bash
rclone copy ./important-data/ autodrive:my-archive/important-data/ \
  --immutable \
  -v
\`\`\`

Re-running the same command after adding files only uploads the new ones (existing keys are skipped due to \`--immutable\`), making large transfers safely resumable.

### Scheduled archival with cron

A cron-ready archive script template:

\`\`\`bash
#!/usr/bin/env bash
set -euo pipefail

SOURCE_DIR="\$\{SOURCE_DIR:-/path/to/your/data\}"
BUCKET="\$\{BUCKET:-my-archive\}"
DEST_PREFIX="\$\{DEST_PREFIX:-daily\}"
REMOTE="autodrive"
TRANSFERS="\$\{TRANSFERS:-4\}"

TIMESTAMP=\$(date '+%Y-%m-%d %H:%M:%S')
echo "[\$TIMESTAMP] Starting archive: \$SOURCE_DIR -> \$REMOTE:\$BUCKET/\$DEST_PREFIX/"

rclone copy "\$SOURCE_DIR" "\$REMOTE:\$BUCKET/\$DEST_PREFIX/" \
  --immutable \
  --transfers "\$TRANSFERS" \
  -v
\`\`\`

Crontab entry (daily at 02:00):

\`\`\`
0 2 * * * BUCKET=my-archive SOURCE_DIR=/path/to/data /path/to/archive-script.sh >> /var/log/autodrive-archive.log 2>&1
\`\`\`

### Browse and verify

\`\`\`bash
rclone lsd autodrive:                                 # all buckets
rclone lsd autodrive:my-archive/                      # top-level dirs in bucket
rclone ls  autodrive:my-archive/                      # all files
rclone ls  autodrive:my-archive/reports/              # files under prefix
rclone tree autodrive:my-archive/                     # recursive tree
rclone check ./local/ autodrive:my-archive/           # verify checksums
rclone cat autodrive:my-archive/logs/app.log          # stream a file
\`\`\`

### Read-only mount

\`\`\`bash
mkdir -p /mnt/autodrive
rclone mount autodrive:my-archive/ /mnt/autodrive \
  --read-only \
  --vfs-cache-mode full \
  --vfs-read-chunk-size 5M
\`\`\`

Then browse with any standard tool:

\`\`\`bash
ls /mnt/autodrive/
cat /mnt/autodrive/reports/q1.pdf
\`\`\`

### Migrate from another cloud provider

The pattern is the same regardless of source remote:

\`\`\`bash
rclone copy <source>:<source-path>/ autodrive:<bucket>/<dest-prefix>/ --immutable -v
\`\`\`

\`\`\`bash
# AWS S3
rclone copy s3:my-source-bucket/data/ autodrive:migrated/aws-data/ --immutable -v

# Google Cloud Storage
rclone copy gcs:my-gcs-bucket/archives/ autodrive:migrated/gcs-archives/ --immutable -v

# Backblaze B2
rclone copy b2:my-b2-bucket/ autodrive:migrated/b2-backup/ --immutable -v
\`\`\`

Tips for large migrations:

- Use \`-v\` or \`--progress\` to monitor progress
- Tune \`--transfers=N\` to your bandwidth
- Capture full logs with \`--log-file=migration.log\`
- Run inside \`screen\` or \`tmux\` for long jobs
- Use \`--immutable\` to make the migration resumable; if interrupted, just re-run the same command

### CI/CD integration

#### GitHub Actions

\`\`\`yaml
name: Archive Build Artifacts

on:
  push:
    branches: [main]

jobs:
  build-and-archive:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: make build

      - name: Install rclone
        run: curl https://rclone.org/install.sh | sudo bash

      - name: Configure rclone
        run: |
          mkdir -p ~/.config/rclone
          cat > ~/.config/rclone/rclone.conf << 'EOF'
          [autodrive]
          type = s3
          provider = Other
          access_key_id = \$\{\{ secrets.AUTO_DRIVE_API_KEY \}\}
          secret_access_key = placeholder
          endpoint = https://s3.auto-drive.autonomys.xyz
          no_check_bucket = true
          list_version = 2
          EOF

      - name: Archive build artifacts
        run: |
          TIMESTAMP=\$(date +%Y%m%d-%H%M%S)
          rclone copy ./dist/ \
            autodrive:ci-builds/\$\{\{ github.sha \}\}-\$\{TIMESTAMP\}/ \
            --immutable -v
\`\`\`

#### GitLab CI

\`\`\`yaml
archive-artifacts:
  stage: deploy
  image: rclone/rclone:latest
  script:
    - mkdir -p ~/.config/rclone
    - |
      cat > ~/.config/rclone/rclone.conf << 'EOF'
      [autodrive]
      type = s3
      provider = Other
      access_key_id = \$\{AUTO_DRIVE_API_KEY\}
      secret_access_key = placeholder
      endpoint = https://s3.auto-drive.autonomys.xyz
      no_check_bucket = true
      list_version = 2
      EOF
    - TIMESTAMP=\$(date +%Y%m%d-%H%M%S)
    - rclone copy ./dist/ autodrive:ci-builds/\$\{CI_COMMIT_SHA\}-\$\{TIMESTAMP\}/ --immutable -v
  only:
    - main
\`\`\`

### Compliance and audit logs

Permanent storage meets retention requirements by construction — records cannot be tampered with or accidentally deleted.

\`\`\`bash
# Daily application logs
rclone copy /var/log/app/ autodrive:compliance/logs/\$(date +%Y/%m/%d)/ \
  --immutable \
  --include "*.log"

# Database backup
pg_dump mydb | rclone rcat autodrive:compliance/db-backups/\$(date +%Y%m%d-%H%M%S).sql --immutable
\`\`\`

### Pipe and stream

\`\`\`bash
# Compressed tarball
tar czf - ./project/ | rclone rcat autodrive:my-archive/archives/project-\$(date +%Y%m%d).tar.gz --immutable

# Database dump
mysqldump --all-databases | rclone rcat autodrive:backups/mysql-\$(date +%Y%m%d).sql --immutable

# Docker image
docker save my-app:latest | rclone rcat autodrive:docker-images/my-app-\$(date +%Y%m%d).tar --immutable
\`\`\`

### Run rclone in Docker

The rclone official image works against Auto Drive with a config volume or env-driven config. Below is a \`docker-compose.yml\` that serves a bucket over HTTP (read-only) using \`rclone serve http\` — simpler than a FUSE mount in containers since FUSE requires \`--privileged\` or \`--cap-add SYS_ADMIN\`.

\`\`\`yaml
services:
  rclone:
    image: rclone/rclone:latest
    container_name: rclone-autodrive
    restart: unless-stopped
    environment:
      - AUTO_DRIVE_API_KEY=\$\{AUTO_DRIVE_API_KEY:?Set AUTO_DRIVE_API_KEY environment variable\}
      - AUTO_DRIVE_BUCKET=\$\{AUTO_DRIVE_BUCKET:-my-archive\}
    volumes:
      - ./data:/data:ro
    ports:
      - "8181:8181"
    entrypoint: ["/bin/sh", "-c"]
    command:
      - |
        mkdir -p /root/.config/rclone
        cat > /root/.config/rclone/rclone.conf << EOF
        [autodrive]
        type = s3
        provider = Other
        access_key_id = \$\$\{AUTO_DRIVE_API_KEY\}
        secret_access_key = placeholder
        endpoint = https://s3.auto-drive.autonomys.xyz
        no_check_bucket = true
        list_version = 2
        EOF

        rclone serve http "autodrive:\$\$\{AUTO_DRIVE_BUCKET\}/" \
          --addr :8181 \
          --read-only \
          --vfs-cache-mode full
\`\`\`

To upload from inside the container:

\`\`\`bash
docker compose exec rclone rclone copy /data autodrive:my-archive/ --immutable
\`\`\`

---

## Troubleshooting

### Listing fails (404 NoSuchKey, or 500 on older deployments)

**Symptom:** \`rclone ls\`, \`rclone lsd\`, \`rclone check\`, or \`rclone sync\` fail with \`ListObjects ... 404 NoSuchKey\`. (Older Auto Drive deployments returned \`500 InternalServerError\` for the same cause.)

**Cause:** Auto Drive implements **ListObjectsV2** only. By default rclone's generic S3 backend (\`provider = Other\`) uses the older **ListObjectsV1** API; Auto Drive does not recognise it and falls through to a per-object lookup, which reports the key as missing.

**Fix:** Set \`list_version = 2\` in your rclone config.

\`\`\`bash
rclone config update autodrive list_version 2
\`\`\`

### Checksum mismatch on legacy objects

**Symptom:**

\`\`\`
ERROR : file.txt: corrupted on transfer: md5 hash differ "abc123" vs "bafkr..."
\`\`\`

**Cause:** The object was uploaded before MD5 ETag support shipped, so its ETag is the CID, which rclone interprets as a failed checksum.

**Fix:** Add \`--ignore-checksum\` (or \`--size-only\`) to your command:

\`\`\`bash
rclone copy ./files/ autodrive:my-archive/ --immutable --ignore-checksum
\`\`\`

Objects uploaded after the MD5 ETag feature do not need this flag.

### Delete returns 403

**Symptom:**

\`\`\`
ERROR : file.txt: Failed to delete: 403 Access Denied: Auto Drive storage is immutable. Objects cannot be deleted from the Autonomys DSN.
\`\`\`

**Cause:** Auto Drive storage is permanent by design. The S3 layer rejects all DELETE requests.

**Affected commands:** \`rclone delete\`, \`rclone purge\`, \`rclone rmdir\`, \`rclone move\` (delete phase), \`rclone sync\` (when the destination has files no longer in the source).

**Fix:** Use \`rclone copy\` instead of \`rclone sync\` or \`rclone move\`.

### Authentication errors

**Symptoms:** \`AccessDenied\`, \`401 Unauthorized\`.

**Possible causes:**

1. The API key is incorrect or has been revoked
2. The API key has expired (if you set an expiry)
3. Your account has no remaining credits

**Fix:**

- Verify the key at [ai3.storage](https://ai3.storage) → Developers
- Create a new key if needed
- Check your credit balance and top up if required
- Confirm \`access_key_id\` in your rclone config matches the API key exactly

### Connection timeouts

**Symptom:** \`Failed to copy: connection timed out\`.

**Fix:**

- \`curl -I https://s3.auto-drive.autonomys.xyz\` to verify reachability
- Increase the timeout: \`--timeout=60s\`
- Add retries: \`--retries=5 --retries-sleep=10s\`

### Immutable file conflict

**Symptom:** \`File exists and --immutable is set\`.

**Cause:** You are trying to upload a key that already exists, with \`--immutable\` set (as recommended).

- If the content is the same, this is expected — the file is already safely stored.
- If you want to publish a new version, write to a new key (e.g. add a timestamp or version suffix). Removing \`--immutable\` and re-uploading to the same key creates a new object and updates the key mapping, but the old data still persists on the DSN.

### Bucket not found

**Symptom:** \`NoSuchBucket: The specified bucket does not exist\`.

**Cause:** You are referencing a bucket that has never had any objects written to it. Buckets exist implicitly only after the first write.

**Fix:** Write an object first, or correct the bucket name. Also confirm \`no_check_bucket = true\` is in your config so rclone does not attempt a \`HeadBucket\` probe before each operation.

### Diagnostic commands

\`\`\`bash
# Inspect rclone config
rclone config show autodrive

# Test endpoint reachability
curl -I https://s3.auto-drive.autonomys.xyz

# Verbose upload with full logging
rclone copy ./test.txt autodrive:test-bucket/ \
  --immutable -vv \
  --log-file=rclone-debug.log \
  --dump headers

# rclone version (use 1.60+ for full S3 compatibility)
rclone version
\`\`\`

---

## Further Reading

- [Auto Drive S3 Layer Guide](/sdk/auto-drive/s3_layer) — the underlying S3-compatible API used by rclone
- [Auto Drive dashboard](https://ai3.storage) — manage your account, API keys, and credits
- [Autonomys Academy: Rewards and Fees](https://academy.autonomys.xyz/autonomys-network/rewards-and-fees) — how storage pricing works on the Autonomys Network
- [rclone documentation](https://rclone.org/docs/) — full rclone reference
- [Auto Drive rclone examples](https://github.com/autonomys/auto-drive/tree/main/docs/rclone/examples) — annotated config, archive script, and Docker compose recipe


---

### File: evm/NFT_guide.mdx

---
title: Minting and Sending NFTs
---

## Sending NFTs

> *Note:* NFT minting and transfers are currently available exclusively on the **Taurus** testnet using the Autonomys NFT contract deployed at \`0x505c243ec05dF81bC33295fF7C135D4D98063Da5\`.

This guide walks you through sending NFTs on Autonomys using [Remix](https://remix.ethereum.org/), a [Metamask-connected wallet](https://metamask.io/), and the [Eternal Mint](https://eternalmint.xyz/) platform.

---

### NFTs on Autonomys Network

Autonomys NFTs offer a significant advantage over traditional NFT infrastructure.

> **Unlike platforms that rely on IPFS**, Autonomys stores NFT's metadata and digital assets directly on **[Auto Drive](https://ai3.storage/)**, our permanent decentralized storage.

- 🔒 Both your NFT **metadata and digital asset** (e.g., image, music file) are **never at risk of disappearing** due to expired IPFS pins.
- 🌐 Each NFT is linked to a **permanent Auto Drive record** that ensures long-term storage.
- 🚫 No third-party dependency — your NFT will never go offline.

---

### Quick Start Guide

This guide assumes you have experience with MetaMask and Remix. 

---

### Step 1: Mint Your NFT

1. Visit [Eternal Mint](https://eternalmint.xyz/).
![NFT-mint-1](/developers/NFT-guide/NFT-mint-1.png)
2. Connect the wallet of your choice.
![NFT-mint-2](/developers/NFT-guide/NFT-mint-2.png)
3. Mint your NFT by filling in the following fields:
- **Name**: The title of your NFT.
- **Supply**: The number of editions you'd like to mint.
- **External Link**: (Optional) A link to an external website or resource.
- **Description**: A brief explanation or story behind your NFT.
- **Upload Image**: The visual or media file representing your NFT (e.g., image, GIF, video).
![NFT-mint-3](/developers/NFT-guide/NFT-mint-3.png)
4. Once minted, **copy your NFT’s Token ID** — you’ll need it to send the NFT.


---

### Step 2: Load the Contract in Remix

1. Open [Remix IDE](https://remix.ethereum.org/).
2. Create a new Solidity file (e.g. \`NFTTransfer.sol\`), or use the deployed contract. The contract Address: \`0x505c243ec05dF81bC33295fF7C135D4D98063Da5\`.

3. Compile the contract using the Solidity compiler tab.

![NFT-guide-1](/developers/NFT-guide/NFT-guide-1.png)

---

### Step 3: Connect Remix to MetaMask

1. In Remix, navigate to the **Deploy & Run Transactions** panel.
2. Set the Environment to **Injected Provider - MetaMask**.
3. Connect your MetaMask wallet that’s configured to the **Taurus** testnet. 
For more detailed instructions, check out our [guide on connecting Remix to the Taurus testnet](/evm//remix).
![NFT-guide-2](/developers/NFT-guide/NFT-guide-2.png)

---

### Step 4: Deploy or Load the NFT Contract

- If deploying a new contract: Click **Deploy** and confirm in MetaMask.
- If using the existing NFT contract: Paste the deployed contract address into the \`At Address\` field and click **At Address**.
![NFT-guide-3](/developers/NFT-guide/NFT-guide-3.png)

---

### Step 5: Use \`safeTransferFrom\` to Send Your NFT

Scroll down to the **Deployed Contracts** section and find the \`safeTransferFrom\` function. Fill in the following fields:

- \`from\`: Your wallet address (the current NFT holder)
- \`to\`: The recipient’s wallet address
- \`id\`: Token ID of the NFT you want to send
- \`value\`: Number of NFTs to send (usually \`1\`)
- \`data\`: Optional; use \`0x\` if not needed

Click **transact** and confirm the transaction in MetaMask.
![NFT-guide-4](/developers/NFT-guide/NFT-guide-4.png)

---

### Verification

After the minting, the NFT will appear in the recipient’s wallet. You can verify the transfer using the [Block explorer for the Autonomys testnet](https://explorer.auto-evm.chronos.autonomys.xyz//)

**Here's how**:

1. Open the transaction on Blockscout.
2. Click on **"Token Transfers"** to view the minted token details.
![NFT-check-1](/developers/NFT-guide/NFT-check-1.png)

**OR**

1. Go to the **"Tokens"** tab.
2. Select **"NFTs"** to see your newly minted NFT listed there!
![NFT-check-2](/developers/NFT-guide/NFT-check-2.png)
---

### Troubleshooting

- **Gas issues?** Try increasing the gas limit manually in Remix.
- **Transaction fails?** Double-check your Token ID and that you’re connected to the correct network.
- **Contract not found?** Ensure you’ve loaded the contract at the correct address (\`0x505c243ec05dF81bC33295fF7C135D4D98063Da5\`).

> *Note:* If you need help debugging contract interactions, visit our [Autonomys Community Discord](https://autonomys.xyz/discord).




---

### File: evm/block_explorer.mdx

---
title: Auto EVM Block Explorer (BlockScout)
---

## Auto EVM Block Explorer (BlockScout)

The **[Auto EVM domain block explorer](https://explorer.auto-evm.mainnet.autonomys.xyz/)** provides a clear, user-friendly visualization of Autonomys-specific statistics relevant to developers.

 ![BlockExplorer-1](/developers/Auto-EVM-Block-Explorer.png)

## Chronos Auto EVM Block Explorer

**[Chronos Auto EVM](https://explorer.auto-evm.chronos.autonomys.xyz//)** domain block explorer. 

 ![BlockExplorer-2](/developers/BlockExplorer-1.png)


---

### File: evm/bridge.mdx

---
title: Bridging Assets
---

# Bridging Assets with Autonomys

We're excited to announce the deployment of Hyperlane-based bridges, developed in collaboration with our infrastructure partner Protofire. These bridges are now live on both mainnet and testnet environments.

![bridge](/developers/bridge-1.png)

Bridges are critical infrastructure components for robust blockchain networks, enabling users to seamlessly access liquidity and applications across different blockchain ecosystems. With these Hyperlane bridges, Autonomys users can effortlessly transfer assets between networks, unlocking a broader range of possibilities and interactions.

## Available Bridges

### Mainnet Bridge

**URL:** https://bridge.mainnet.autonomys.xyz/

The mainnet bridge connects Autonomys mainnet with:
- Ethereum mainnet
- Binance Smart Chain mainnet

### Chronos Testnet Bridge  

**URL:** https://bridge.chronos.autonomys.xyz/

The testnet bridge connects the Chronos Auto EVM domain with:
- Ethereum's Sepolia testnet
- Binance Smart Chain testnet

This testnet environment is perfect for developers and users to experiment with cross-chain functionality without risking mainnet assets.

## Get Started

We encourage everyone in the community to explore these bridges and experiment with their capabilities. Your feedback is crucial as we continue to refine and improve our infrastructure.

Experience the power of seamless interoperability across blockchain networks!

---

### File: evm/farmerless_dev_node.mdx

---
title: Farmerless Dev Node Quick Start
---

## Subspace Farmerless Dev Node

Developer utility binary that boots a local Subspace consensus node (mocked farmerless setup) and, optionally, an EVM domain node for integration testing and manual experimentation. It wraps helpers from \`subspace-test-service\` and \`domain-test-service\` so that devs can exercise cross-domain flows without spinning up a full farmer.

### Prerequisites

- Cloned [Subspace Repository](https://github.com/autonomys/subspace)
- Rust toolchain with \`cargo\`
- Workspace dependencies built once (\`cargo build -p subspace-farmerless-dev-node\`)

### Usage

From the workspace root:

\`\`\`bash
cargo run -p subspace-farmerless-dev-node -- [FLAGS/OPTIONS]
\`\`\`

#### Common Flags

- \`--finalize-depth <K>\`: Enforce finalization depth; omit to disable.
- \`--domain\`: Start the EVM domain node alongside consensus.
- \`--base-path <PATH>\`: Persist data instead of using a temp dir.
- \`--rpc-host <IP>\` / \`--rpc-port <PORT>\`: Consensus RPC interface (defaults \`127.0.0.1:9944\`).
- \`--domain-rpc-host <IP>\` / \`--domain-rpc-port <PORT>\`: Domain RPC interface (defaults \`127.0.0.1:9945\`).
- \`--block-interval-ms <MS>\`: Slot and block production cadence (default \`6000\`; use \`0\` to disable auto-production).

To inspect the full CLI help, run:

\`\`\`bash
cargo run -p subspace-farmerless-dev-node -- --help
\`\`\`

### Typical Scenarios

#### Quick Smoke Test

Produces consensus blocks every 6s using temp storage:

\`\`\`bash
cargo run -p subspace-farmerless-dev-node
\`\`\`

#### Run with Domain Node

Start both consensus and EVM domain nodes:

\`\`\`bash
cargo run -p subspace-farmerless-dev-node -- --domain
\`\`\`

#### Fast Integration Testing

Faster block production for quick testing:

\`\`\`bash
cargo run -p subspace-farmerless-dev-node -- --block-interval-ms 500 --domain
\`\`\`

#### Manual Block Production

Disable auto-production and trigger blocks manually via RPC:

\`\`\`bash
cargo run -p subspace-farmerless-dev-node -- --block-interval-ms 0 --domain
\`\`\`

### Manual Block Production RPCs

When \`--block-interval-ms 0\` is set, the node exposes JSON-RPC endpoints for manual block production:

#### \`dev_produceBlock\`

Produce a single consensus block.

**Parameters:**

- \`wait_for_bundle\` (optional, boolean): If \`true\`, wait for domain bundle submission before producing the block. Defaults to \`false\`.

**Example:**

\`\`\`bash
curl -H "Content-Type: application/json" \
     --data '\{"jsonrpc":"2.0","id":1,"method":"dev_produceBlock","params":[true]\}' \
     http://127.0.0.1:9944
\`\`\`

#### \`dev_produceBlocks\`

Produce multiple consensus blocks.

**Parameters:**

- \`count\` (required, number): Number of blocks to produce.
- \`wait_for_bundle\` (optional, boolean): If \`true\`, wait for domain bundle submission before each block. Defaults to \`false\`.

**Examples:**

\`\`\`bash
# Produce 5 blocks without waiting for bundles
curl -H "Content-Type: application/json" \
     --data '\{"jsonrpc":"2.0","id":1,"method":"dev_produceBlocks","params":[5]\}' \
     http://127.0.0.1:9944

# Produce 5 blocks, waiting for bundles
curl -H "Content-Type: application/json" \
     --data '\{"jsonrpc":"2.0","id":1,"method":"dev_produceBlocks","params":[5,true]\}' \
     http://127.0.0.1:9944
\`\`\`

> **Note:** When \`wait_for_bundle\` is \`true\`, the domain node must be running (\`--domain\` flag) or the RPC call will timeout waiting for bundle submission.

### Docker Setup

For easy setup using Docker, you can use the [provided \`farmerless-dev-node.yml\`](https://github.com/autonomys/subspace/blob/main/docker/farmerless-dev-node.Dockerfile) file. This setup automatically builds and runs the farmerless dev node with the EVM domain enabled.

#### Prerequisites

- Docker and Docker Compose installed

#### Quick Start with Docker

1. Ensure you're in the workspace root directory (where \`farmerless-dev-node.yml\` is located).

2. Start the farmerless dev node:

\`\`\`bash
docker-compose up
\`\`\`

This will:
- Build the \`subspace-farmerless-dev-node\` binary
- Start the node with the \`--domain\` flag enabled
- Expose ports:
  - \`9944\`: Consensus RPC
  - \`9945\`: Domain RPC
  - \`8545\`: EVM RPC

3. Access the RPC endpoints:
   - Consensus RPC: \`http://localhost:9944\`
   - Domain RPC: \`http://localhost:9945\`
   - EVM RPC: \`http://localhost:8545\`

#### Customizing Docker Setup

You can modify the \`docker-compose.yml\` file to customize the setup:

- **Change block interval**: Modify the command to include \`--block-interval-ms <MS>\`
- **Persist data**: Add \`--base-path /workspace/data\` to the command
- **Change ports**: Update the port mappings in the \`ports\` section

#### Example: Fast Block Production

To run with faster block production (500ms intervals), modify the command in \`docker-compose.yml\`:

\`\`\`yaml
command: >
  bash -c "
    cargo build -p subspace-farmerless-dev-node --release &&
    cargo run -p subspace-farmerless-dev-node --release -- --domain --block-interval-ms 500 --rpc-host 0.0.0.0 --domain-rpc-host 0.0.0.0
  "
\`\`\`

#### Stopping the Container

To stop the farmerless dev node:

\`\`\`bash
docker-compose down
\`\`\`

To stop and remove volumes (clearing cached build artifacts):

\`\`\`bash
docker-compose down -v
\`\`\`



---

### File: evm/faucet.mdx

---
title: Discord Faucet (get tAI3 testnet tokens)
---

## Discord Faucet (get tAI3 testnet tokens)

The **tAI3 faucet** is available on our [**Discord**](https://autonomys.xyz/discord). To gain access to the role-gated *#developer-chat* and *#faucet* channels:

1. Join our [Discord](https://autonomys.xyz/discord).

2. Click on \`Autonomys Network\` (in the top-left corner) and select \`Linked Roles\`.

   ![Discord-1](/developers/Discord-1.png)

3. Link your GitHub account to attain the Developer role and gain access to *#developer-chat* and [*#faucet*](https://discord.com/channels/864285291518361610/1133496871499862077).

   ![Discord-2](/developers/Discord-2.png)

4. Use the slash command \`/faucet your_EVM_wallet_address_here\` in the *#faucet* channel to request tAI3 tokens.

   ![Faucet-1](/developers/Faucet-1.png)

5. If your request is successful, you will receive a confirmation and link to the Blockscout explorer shortly after.

   ![Faucet-2](/developers/Faucet-2.png)

You can request tAI3 tokens once every 24 hours.


## Official Web-Based Faucet

The **tAI3** testnet tokens can also be requested via the official web-based faucet: https://autonomysfaucet.xyz/

1. Proceed to the [Autonomys Faucet Website](https://autonomysfaucet.xyz/)

   ![Web-faucet](/developers/autonomysfaucet-1.png)

2. Connect your **GitHub** or **Discord** account to request tokens. 

You can request tAI3 tokens once every 24 hours.

## Unoffocial Web-Based Faucet

An ambassador-built web-faucet is available via the link: https://faucet.farmine.info/. Note: this is not an official faucet, use at your discretion. 

   ![unofficial faucet](/developers/unnoficial-faucet-1.png)


---

### File: evm/foundry.mdx

---
title: Foundry Guide
---

[**Foundry**](https://book.getfoundry.sh/) is a tool that allows you to easily write, test and deploy smart contracts on any EVM-compatible blockchain.

### EVM Version Compatibility

Auto EVM is compatible with most EVM versions but doesn't support some features introduced in newer versions like **"Paris"** or **"Shanghai"**. When using development tools, you may need to specify an EVM version explicitly. Supported versions: **"Istanbul"**, **"London"**. 

### Getting started

 > *Note:* Foundryup does not currently support \`PowerShell\` or \`Cmd\`, so if you're on Windows, you will need to install and use [Git BASH](https://gitforwindows.org/) or [WSL](https://learn.microsoft.com/en-us/windows/wsl/install) as your terminal.

1. Use the \`foundryup\` toolchain installer and follow the on-screen instructions to install \`foundryup\` and make the \`foundryup\` command available in your CLI. Running \`foundryup\` by itself will install the latest precompiled binaries: \`forge\`, \`cast\`, \`anvil\`, and \`chisel\`. See \`foundryup --help\` for more options.
    \`\`\`bash
    curl -L https://foundry.paradigm.xyz | bash
    \`\`\`

2. Once installed, create a project. Let's name it \`hello_autonomys\`. To initialize the project, run:
    \`\`\`bash
    forge init hello_autonomys
    \`\`\`
   \`cd\` into the \`hello_autonomys\` directory to see the project's structure.

    ![Foundry-1](/developers/Foundry-1.png)

3. All the necessary repo structure was created automatically, so we can start writing and testing our smart contracts immediately. There are separate directories for storing smart contracts (\`src\`) and testing smart contracts (\`test\`). Let's open the \`Counter.sol\` smart contract and add three functions: \`setNumber()\`, which sets the uint256 number to the provided value, \`increment()\`, which increases the value by 1, and \`decrement()\`, which decreases the value by 1.

    \`\`\`
    // SPDX-License-Identifier: UNLICENSED
    pragma solidity ^0.8.1;

    contract Counter \{
        uint256 public number;

        function setNumber(uint256 newNumber) public \{
            number = newNumber;
        \}

        function increment() public \{
            number++;
        \}

        function decrement() public \{
            number--;
        \}
    \}
    \`\`\`

4. Let's make sure that all the functions are working properly by adding some tests to the \`Counter.t.sol\` test file, and checking if they pass. In our tests, we first set the initial value of \`number\` to 2, before checking if the \`increment()\` function increases the value by 1 and if \`decrement()\` decreases the value by 1.

    \`\`\`
    // SPDX-License-Identifier: UNLICENSED
    pragma solidity ^0.8.13;

    import "forge-std/Test.sol";
    import "../src/Counter.sol";

    contract CounterTest is Test \{
        Counter public counter;

        function setUp() public \{
            counter = new Counter();
            counter.setNumber(2);
        \}

        function testIncrement() public \{
            counter.increment();
            assertEq(counter.number(), 3);
        \}

        function testSetNumber(uint256 x) public \{
            counter.setNumber(x);
            assertEq(counter.number(), x);
        \}

        function testDecrement() public \{
            counter.decrement();
            assertEq(counter.number(), 1);
        \}
    \}
    \`\`\`

5. Let's build the project by running: 

    \`\`\`bash
    forge build
    \`\`\`

    Test the smart contract is working by running:

    \`\`\`bash
    forge test
    \`\`\`

    ![Foundry-2](/developers/Foundry-2.png)

    All tests are passing, meaning the smart contract is working as expected.

6. There are two final things we need to do before deploying our smart contract:
    - Connect a wallet that has a sufficient balance of tAI3 to cover the gas fees.
    - Set an environment variable we will use later.

    To make our lives easier, let's create a new \`Makefile\` as well as a \`.env\` file at the root of our project. \`.env\` files are typically used to store environment variables for your application. They are particularly useful for managing settings that change between deployment environments (e.g., development, testing, staging, and production), and for storing sensitive information. Environment variables can include database connection details, API keys, external resource URIs, or other configuration variables that might change depending on the environment in which the application is running. In our case, we would use it to point to our Auto-EVM RPC URL:

    \`\`\`bash
    RPC_URL=https://auto-evm.chronos.autonomys.xyz/ws
    \`\`\`

    And then set a private key for the EVM-compatible wallet:

    \`\`\`bash
    PRIVATE_KEY="your_private_key_value"
    \`\`\`
    
    > *Note:* \`.env\` files should not be committed to your source control (like Git), especially when they contain sensitive data, like your private key. To prevent this, add \`.env\` to your \`.gitignore\` file. This helps to keep sensitive keys secure and avoids the risk of exposing them in the application's code or version control history.

    In the \`Makefile\`, let's create shortcuts to the main features of the application:

    \`\`\`bash
    # include .env file and export its env vars
    -include .env

    # Builds
    build:
	    @forge clean && forge build --optimize --optimizer-runs 1000000

    # Deployment
    deploy:
	    @forge create Counter --private-key \$\{PRIVATE_KEY\} --rpc-url \$\{RPC_URL\} --evm-version london
    \`\`\`

    We're importing the values for a \`PRIVATE_KEY\` and \`RPC_URL\` from the \`.env\` file. This allows us to run \`make build\` for building the project, and \`make deploy\` for deploying the project, pointing to the provided RPC, and using the provided \`PRIVATE_KEY\`. Let's run \`make build\` to ensure it's working properly.

    ![Foundry-3](/developers/Foundry-3.png)

7. To deploy your contract using the specified \`RPC\` and \`PRIVATE_KEY\`, run:

    \`\`\`
    make deploy
    \`\`\`

    > *Note:* Do not tip when submitting transactions in an attempt to accelerate them as this could result in dual charges for gas fees. When deploying smart contracts to our Auto EVM domain, you may encounter an error related to gas estimation, typically presenting as: "No manual gas limit set" or "Gas estimation failed". For more information and solutions, visit the [Auto EVM Introduction](/evm/introduction).

Congratulations, you've successfully deployed your smart contract on the Auto EVM!


---

### File: evm/general_information.mdx

---
title: Developer Tools
---

## Developer Tools

Developing smart contracts and decentralized applications involves a suite of tools that aid in writing, testing and deploying code on the blockchain. As Autonomys utilizes an instance of the Ethereum Virtual Machine (EVM), **every tool used to build, test and deploy smart contracts on Ethereum is fully compatible with the Auto EVM**.

### Writing smart contracts

Solidity is the primary programming language for writing smart contracts. It is statically typed, supports inheritance, libraries, and complex user-defined types, making it familiar for developers with a background in other statically typed languages such as C++, Java, or JavaScript. Solidity has a great community of developers and extensive documentation is available on the official [website](https://soliditylang.org/).

Integrated Development Environments (IDEs) are often used to aid in writing smart contracts. We recommend the [Remix IDE](https://remix.ethereum.org/), a browser-based IDE that enables you to write, deploy and interact with Solidity smart contracts. It features a built-in static analysis tool that checks your code for common errors.

### Development and testing

For local development and testing, spin up your own version of an Autonomys Developer Node and farmer, or alternatively, use EVM-compatible development tools like [Hardhat](https://hardhat.org/hardhat-network/docs/overview) or [Anvil](https://book.getfoundry.sh/anvil/) to deploy contracts, develop applications and run tests.

### Deploying and interacting with smart contracts

A JavaScript provider like the one injected by the [MetaMask](https://metamask.io/) browser extension is used to deploy and interact with smart contracts. This provider enables JavaScript applications to communicate with the Autonomys Network and any other Ethereum-compatible network. It's compatible with both [ethers.js](https://docs.ethers.org/v5/) and [web3.js](https://web3js.readthedocs.io/en/v1.10.0/)/[Web3.py](https://web3py.readthedocs.io/en/stable/), allowing developers to use either library for their blockchain operations.

All these tools together provide an cohesive ecosystem for EVM-compatible smart contract development, making the process significantly more manageable and efficient.


---

### File: evm/hardhat.mdx

---
title: Hardhat Guide
---

## Hardhat Guide

[**Hardhat**](https://hardhat.org/docs) is a tool that facilitates building, testing and deploying on the Ethereum Virtual Machine. It helps developers manage and automate the recurring tasks that are inherent to the process of building smart contracts and dApps, and allows them to easily introduce more functionality around this workflow. This includes compiling and testing at the very core. Flexible deployment options also allow you to point to the Autonomys EVM domain RPC to deploy your contracts and dApps.

### EVM Version Compatibility

Auto EVM is compatible with most EVM versions but doesn't support some features introduced in newer versions like **"Paris"** or **"Shanghai"**. When using development tools, you may need to specify an EVM version explicitly. Supported versions: **"Istanbul"**, **"London"**. 

### Getting started

**Prerequisites**

*[NodeJS](https://nodejs.org/en) version >=16.0 installed*

1. Open a new terminal and create a new folder for the project: 

\`\`\`
mkdir subspace-hardhat
cd subspace-hardhat
\`\`\`

2. Initialize an \`npm\` project:

\`\`\`
npm install --save-dev hardhat
npm install --save-dev @openzeppelin/contracts
npx hardhat
\`\`\`
You'll be prompted to answer some questions. Select \`Create a JavaScript Project\` from the list of available options, select the project root folder, and, optionally, create a \`.gitignore\` file.

![Hardhat-1](/developers/Hardhat-1.png)

3. In your created workspace, you will notice several folders. All of your contracts will reside inside the \`contracts\` folder, deployment scripts are available inside the \`scripts\` folder, and tests can be found inside the \`test\` folder. Click on the \`contracts\` folder and open \`Lock.sol\`.

![Hardhat-3](/developers/Hardhat-3.png)

4. Change the name of your contract in \`Lock.sol\` (\`Counter\`), the name of the token (\`AutonomysTestToken\`) and the token symbol (\`AI3test\`). As an example, let's add a simple smart contract that has three functions: \`setNumber()\`, \`increment()\` and \`decrement()\`.

\`\`\`
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.9;

import '@openzeppelin/contracts/token/ERC20/ERC20.sol';

contract Counter is ERC20 \{
    constructor() ERC20("AutonomysTestToken", "TAI3test") \{\}

    uint256 public number;

    function setNumber(uint256 newNumber) public \{
        number = newNumber;
    \}

    function increment() public \{
        number++;
    \}

    function decrement() public \{
        number--;
    \}
\}
\`\`\`

For consistency, let's also rename 'Lock.sol' to \`Counter.sol\`.


5. Before proceeding with deployment, thoroughly test your smart contracts for correctness, as mistakes can lead to unforeseen gas costs. To test the contract, open the \`Lock.js\` file in the \`test\` folder, and replace the internals of the file with the following code:

\`\`\`
const \{ expect \} = require("chai");

describe("Counter", function() \{
let Counter;
let counter;
let owner;
let addr1;

beforeEach(async function() \{
    Counter = await ethers.getContractFactory("Counter");
    [owner, addr1] = await ethers.getSigners();

    counter = await Counter.deploy();
\});

describe("Counter operations", function() \{
    it("Should return initial value of zero", async function() \{
    expect(await counter.number()).to.equal(0);
    \});

    it("Should set number to a new value", async function() \{
    await counter.setNumber(5);
    expect(await counter.number()).to.equal(5);
    \});

    it("Should increment the number", async function() \{
    await counter.setNumber(5);
    await counter.increment();
    expect(await counter.number()).to.equal(6);
    \});

    it("Should decrement the number", async function() \{
    await counter.setNumber(5);
    await counter.decrement();
    expect(await counter.number()).to.equal(4);
    \});
\});
\});
\`\`\`

For consistency, let's also rename \`Lock.js\` to \`CounterTest.js\`.

7. To run the test, type \`npx hardhat test\`.

 ![Hardhat-4](/developers/Hardhat-4.png)

Everything is working as expected so we're ready for deployment!

8. To deploy the contract, we need to set a deployment network for \`hardhat\`. Open the \`hardhat.config.js\` file and add the Chronos testnet to the list of networks: 

\`\`\`
require("@nomicfoundation/hardhat-toolbox");
module.exports = \{
solidity: \{
    compilers: [
        \{
            version: "0.8.17",
            settings: \{
            evmVersion: "london"
            \}
        \}
        ]
\},
networks: \{
    autonomys: \{
    url: "https://auto-evm.chronos.autonomys.xyz/ws",
    accounts: ["private_key_to_your_account"]
    \}
\}
\};
\`\`\`

> *Note:* Be careful not to commit your \`hardhat.config.js\` file as it contains your private key. You can use NPM tools like [\`dotenv\`](https://www.npmjs.com/package/dotenv) to securely store your private keys in an \`.env\` file.

9. Open the \`deploy.js\` file and replace the contents with the code:

\`\`\`
const hre = require("hardhat");

async function main() \{
const Contract = await hre.ethers.getContractFactory("Counter");
const contract = await Contract.deploy();

console.log("Contract deployed to:", contract.target);
\}

main().catch((error) => \{
console.error(error);
process.exitCode = 1;
\});
\`\`\`

![Hardhat-5](/developers/Hardhat-5.png)

10. You're now ready to deploy your smart contract on the Autonomys Network. To deploy, run \`npx hardhat run scripts/deploy.js --network subspace\`. This command will deploy your smart contract on the network we've just specified in the \`hardhat.config.js\` file. If deployment is successful, you should see \`Contract deployed to: transaction hash\`.

![Hardhat-6](/developers/Hardhat-6.png)

> *Note:* Do not tip when submitting transactions in an attempt to accelerate them as this could result in dual charges for gas fees. When deploying smart contracts to our Auto EVM domain, you may encounter an error related to gas estimation, typically presenting as: \`"No manual gas limit set"\` or \`"Gas estimation failed"\`. For more information and solutions, visit the [Auto EVM Introduction](/evm/introduction).

Congratulations, you've successfully deployed your smart contract on the Auto EVM!


---

### File: evm/introduction.mdx

---
title: Auto EVM
---

## Auto EVM

**Auto EVM** enables any tool available for Ethereum development to be compatible with the Autonomys Network.

### Quick Start Guide

This guide provides simple instructions for setting up a remote development environment, and assumes you have a basic understanding of or experience with Ethereum Virtual Machine (EVM) development.

### EVM Version Compatibility

Auto EVM is compatible with most EVM versions but doesn't support some features introduced in newer versions like **"Paris"** or **"Shanghai"**. When using development tools, you may need to specify an EVM version explicitly. Supported versions: **"Istanbul"**, **"London"**. 

#### Set up a MetaMask wallet (or any other EVM-compatible wallet) and connect it to our custom EVM

\`\`\`
Network Name: Autonomys EVM
New RPC URL: https://auto-evm.mainnet.autonomys.xyz/ws
Chain ID: 870
Currency Symbol: AI3
\`\`\`

Auto EVM is also available on the Chronos testnet

\`\`\`
Network Name: Autonomys EVM
New RPC URL: https://auto-evm.chronos.autonomys.xyz/ws
Chain ID: 490000
Currency Symbol: tAI3
\`\`\`

#### Send tokens to your wallet using our faucet

Follow the instructions [here](/evm/faucet) to get some testnet AI3 (tAI3) tokens from our **faucet**.

tAI3 (formerly testnet Subspace Credits (tSSC)) is the sole method of payment for gas within the Auto EVM runtime.
We are currently working on a bridge to convert farmed AI3 tokens into EVM-compatible tokens to cover gas fees.

#### Test and deploy your smart contract

You can use **[Remix](https://remix.ethereum.org/)**, **[Foundry](https://book.getfoundry.sh/)**, or any other tool familiar to you to test and deploy your smart contracts on our custom EVM domain.

If anything above is unfamiliar to you, explore our full guide over the following pages.

> *Note:* Do **not** tip when submitting transactions in an attempt to accelerate them. Autonomys' transaction queue operates differently from Ethereum's. Including a tip alongside gas fees leads to the possibility of two transactions sharing the same nonce. This could result in dual charges for gas fees—once for the execution and storage in the first transaction, and once for storage in the second transaction.

### Gas Estimation Limitations
The \`eth_estimateGas\` RPC call may not provide completely accurate estimates in **Auto EVM** domain for the following reasons:

- Consensus chain storage fees may not be fully accounted for in estimates
- The RPC cannot determine which transaction format the caller will use:
   - pallet-evm or pallet-ethereum call
   - pallet-evm create or create2 call
   - Any of the 3 supported pallet-ethereum transaction formats

While improvements to the gas estimation are being implemented, developers should consider the following:

- Add a buffer to estimated gas values for important transactions
- If you encounter consistent gas estimation issues, please contact us so we can adjust our estimation algorithms

#### *Known issue: gas estimation*

When deploying smart contracts to our EVM-compatible **Auto EVM** domain, you may encounter an error related to gas estimation, typically presenting as:

\`"No manual gas limit set"\` or \`"Gas estimation failed"\`.

This issue often occurs because development tools like Foundry simulate transactions using calculated or hardcoded gas estimation instead of querying the RPC (Remote Procedure Call) for it. **Auto EVM** may require different gas amounts for certain operations compared to other EVM-compatible chains (like Ethereum testnets).

> *Note:* We have submitted an upstream PR to fix this issue with **Foundry**. Described below are the workarounds until the issue is resolved by the **Foundry team**.


#### Solutions

If you encounter this issue, try the following solutions:

- **Skip simulation**: Use the \`--skip-simulation\` flag when deploying with Foundry to bypass built-in simulation and rely on RPC for gas estimation.

- **Set a manual gas limit**: Specify a higher gas limit manually in your deployment command or UI.

- **Adjust your deployment script**: Modify your script to include custom gas settings or implement \`try\`/\`catch\` blocks for handling deployment failures.

- **Use a web3 provider**: If using **Remix IDE**, switch to an \`Injected Web3\` environment to leverage external web3 providers like MetaMask.

- **Custom deployment function**: Create a deployment function with adjustable gas parameters.


#### Solution examples

**Foundry**

1. Try using the \`--skip-simulation\` flag: \`forge script path/to/your/script.s.sol --rpc-url your_rpc_url --private-key your_private_key --broadcast --skip-simulation\`.

2. Try setting the gas limit manually: \`forge script path/to/your/script.s.sol --rpc-url your_rpc_url --private-key your_private_key --broadcast --gas-limit 300000\`.
Start with a higher value (\`300000\`) and gradually lower it to find the optimal limit.

**Remix IDE**

1. Try settiing the gas limit manually: In the \`Deploy & Run Transactions\` panel, expand the \`Advanced\` section.
Set a higher value in the \`Gas Limit\` field. Start with \`300000\` and adjust as needed.

2. Try adjusting the gas price: In the same \`Advanced\` section, adjust the \`Gas Price\` as needed.

3. Try switching to the \`Injected Web3\` environment in the \`Deploy & Run Transactions\` panel: This will use your browser's web3 provider (e.g., MetaMask), which may better handle gas estimation for the network.

4. If the above steps don't work, create a custom deployment function that includes gas parameters:

   \`\`\`
   function deployWithCustomGas(uint256 gasLimit, uint256 gasPrice) public returns (address) \{
      return address(new YourContract\{gas: gasLimit, gasPrice: gasPrice\}());
   \}
   \`\`\`

**Other possible solutions**

1. Modify your deployment script and override the default gas settings: 

   \`\`\`
   vm.txGasPrice(uint256 gasPrice);
   vm.txGasLimit(uint256 gasLimit);
   \`\`\`

2. Implement a \`try\`/\`catch\` block in your script to handle gas estimation failures:

   \`\`\`
   try yourContract.deploy\{gas: 300000\}(constructorArgs) returns (YourContract deployed) \{
      // Deployment successful
   \} catch Error(string memory reason) \{
      console.log("Deployment failed:", reason);
   \}
   \`\`\`


---

### File: evm/local.mdx

---
title: Local Development Guide
---

## Local Development Guide

You can always set up a **local development environment** to test and deploy your smart contracts. To establish a full local network, you need to run a local node, an Auto EVM domain, and a farmer.

### Getting started

1. Visit the **[Autonomys releases](https://github.com/autonomys/subspace/releases)** page and download the most up-to-date stable versions of the node and farmer.

> *Note:* For each release, there are two versions:
> 1. skylake: for newer processors from around 2015 and onwards
> 2. x86-64-v2: for older processors from around 2009 and some older VMs

> Older processors/VMs are no longer supported by official releases, but they can still be [compiled manually](https://github.com/autonomys/subspace/blob/main/docs/development.md) if desired.

2. After downloading both the files for your system, start a node using your preferred terminal. If you want to start an EVM domain on your local machine, you need to specify:

- Your local RPC server port
- Your local web-socket RPC port

You can do this with the following command:

\`\`\`bash
./your_subspace_node_path run --dev --rpc-listen-on 127.0.0.1:9944 -- --domain-id 3 --dev --rpc-listen-on 127.0.0.1:8545
\`\`\`

This will create a local RPC on port **8545**.

3. Start a farmer by running the following command:

\`\`\`bash
 ./your_subspace_farmer_path farm --reward-address [YOUR REWARD ADDRESS] path=tmp-farm,size=100M
\`\`\`

You can specify the desired plot size, but 100M should be sufficient.

That's it! By starting a **local node** and a **farmer**, you have a **local RPC** ready for testing and deploying smart contracts! You can easily connect your [MetaMask](https://metamask.io/) account to the local development network, as well as use [Remix](https://remix.ethereum.org/) or [Foundry](https://book.getfoundry.sh/) in order to test and deploy smart contracts on a local network!


---

### File: evm/metamask.mdx

---
title: Adding the Autonomys RPC to MetaMask
---

## Adding the Autonomys RPC to MetaMask

This guide will help you set up a [**MetaMask**](https://metamask.io/) wallet (any EVM-compatible wallet works) and connect it to the Autonomys EVM development network.

1. Download the MetaMask extension for your browser from the [MetaMask website](https://metamask.io/) after selecting your preferred language (in the top-right corner), and reading and agreeing to MetaMask's Terms of Use.
  
![MetaMask-1](/developers/MetaMask-1.png)

2. Click on \`Create a new wallet\`. Read and agree to (or skip) the note on gathering and collecting anonymized usage data (it does not affect wallet creation).
  
![MetaMask-2](/developers/MetaMask-2.png)

3. Set a secure password that's difficult to guess. Type it twice before proceeding to the next step. MetaMask automatically assesses the strength of your password.
> *Note:* Your password should include uppercase letters, lowercase letters, numbers and special characters.
  
![MetaMask-3](/developers/MetaMask-3.png)
 
![MetaMask-4](/developers/MetaMask-4.png)

4. Watch a video to learn more about your Secret Recovery Phrase before proceeding to the next step.
 
![MetaMask-5](/developers/MetaMask-5.png)

5. Write down your 12-word Secret Recovery Phrase. 
  > *Note:* The recovery phrase for the wallet in this guide has been deleted.
  
![MetaMask-6](/developers/MetaMask-6.png)

6. Confirm that you've written down the Secret Recovery Phrase by filling in the missing words.
  
![MetaMask-7](/developers/MetaMask-7.png)

7. You've now created a wallet! Connect to the Autonomys EVM by clicking on the Ethereum Mainnet logo and selecting \`Add network\`.
 
![MetaMask-8](/developers/MetaMask-8.png)

8. In the MetaMask Networks settings, click on \`Add a network manually\`.
  
![MetaMask-9](/developers/MetaMask-9.png)

9. Input the values below to connect to the Autonomys RPC: 

  \`\`\`
  Network Name: Autonomys EVM
  New RPC URL: https://auto-evm.chronos.autonomys.xyz/ws
  Chain ID: 8700
  Currency Symbol: tAI3
  \`\`\`

You have now successfully set up a MetaMask wallet and connected it to the Auto EVM! To deploy a smart contract, you first need to get a small amount of **tAI3** tokens in your wallet. Refer to the [faucet section](/evm//faucet) of the guide to learn more about getting testnet tokens.


---

### File: evm/remix.mdx

---
title: Remix IDE Guide
---

[**Remix**](https://remix-ide.readthedocs.io/en/latest/) is a tool that allows you to easily write, test and deploy smart contracts on any EVM-compatible blockchain.

### EVM Version Compatibility

Auto EVM is compatible with most EVM versions but doesn't support some features introduced in newer versions like **"Paris"** or **"Shanghai"**. When using development tools, you may need to specify an EVM version explicitly. Supported versions: **"Istanbul"**, **"London"**. 

**In Remix, set the EVM version in the Solidity compiler settings:**

Go to the "Solidity compiler" tab
Click on "Advanced Configurations"
Set "EVM Version" to **"london"** or **"istanbul"**

### Getting started

1. Navigate to the [Remix website](https://remix.ethereum.org). You will see a file explorer and interface for creating new workspaces, integrations with GitHub, Gist, IPFS, HTTPS, preloaded templates, and plugins. Create a new workspace by clicking on the + sign next to \`WORKSPACES\`.

 ![Remix-1](/developers/Remix-1.png)

2. Choose the ERC20 template and enter any workspace name.

 ![Remix-2](/developers/Remix-2.png)

3. After creating your workspace, you will see some folders created for you. Click on \`contracts\` and open \`MyToken.sol\`.

 ![Remix-3](/developers/Remix-3.png)

4. As an example, let's add a simple smart contract that has four functions: \`setNumber(number)\`, \`get()\`, \`increment()\` and \`decrement()\`.

\`\`\`bash
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

contract Counter \{
    uint256 private counter;

    // Set the counter to a specific value
    function set(uint256 _value) public \{
        counter = _value;
    \}

    // Increase the counter by 1
    function increase() public \{
        counter += 1;
    \}

    // Decrease the counter by 1
    function decrease() public \{
        require(counter > 0, "Counter cannot go below zero");
        counter -= 1;
    \}

    // Get the current counter value
    function get() public view returns (uint256) \{
        return counter;
    \}
\}
\`\`\`

 ![Remix-4](/developers/Remix-4.png)

5. Next, let's compile the \`Counter\` contract. Click on \`SOLIDITY COMPILER\` (on the left), choose the compiler version that corresponds to the Solidity version of your contract (version 0.8.9 in the example), and click on \`Compile MyToken.sol\`. If it compiles correctly, you will see a green checkmark next to the compiler.

 ![Remix-5](/developers/Remix-5.png)

6. Before proceeding with deployment, thoroughly test your smart contracts for correctness, as mistakes can lead to unforeseen gas costs. As an example, click on the \`tests\` folder and open \`MyToken.sol\`. Test the contract (without making changes) by selecting \`SOLIDITY UNIT TESTING\` (the two ticks in the bar on the left) and clicking \`Run\`.

 ![Remix-6](/developers/Remix-6.png)

 ![Remix-7](/developers/Remix-7.png)

7. As expected, the test failed because we manually changed the token name and symbol. This is Test Driven Development (TDD) in action! In the test, we're adding some assertions for the \`increment()\` and \`decrement()\` functions. To make the test pass, replace the internals of \`MyToken.sol\` with the code below. In this example, we will set the initial value of \`number\` to 2 and \`increment\` and then \`decrement\` it by 1. We would expect the number to increase to 3 and then decrease back to 2.

 \`\`\`bash
  pragma solidity >=0.7.0 <0.9.0;
  import "remix_tests.sol";
  import "../contracts/MyToken.sol";

  contract CounterTest is Counter \{

     function testTokenInitialValues() public \{
         Assert.equal(name(), "AutonomysTestToken", "token name did not match");
         Assert.equal(symbol(), "AI3test", "token symbol did not match");
         Assert.equal(decimals(), 18, "token decimals did not match");
         Assert.equal(totalSupply(), 0, "token supply should be zero");
     \}

     Counter public counter;

     function setUp() public \{
         counter = new Counter();
         counter.setNumber(2);
     \}

     function testIncrement() public \{
         counter.increment();
         Assert.equal(counter.number(), 3, "test increment did not match");
     \}

     function testDecrement() public \{
         counter.decrement();
         Assert.equal(counter.number(), 2, "test decrement did not match");
     \}
  \}
 \`\`\`

 ![Remix-8](/developers/Remix-8.png)

8. All tests are now passing, meaning our smart contract \`Counter\` is working as expected. We're now ready to deploy it!

 ![Remix-9](/developers/Remix-9.png)

9. Click on the \`DEPLOY AND RUN TRANSACTIONS\` tab (on the left) to deploy. Remix allows you to use one of their existing EVMs or inject your own provider through its integration with MetaMask. Since we already have a [MetaMask account set up](/evm/metamask), let's use this option.

 ![Remix-10](/developers/Remix-10.png)

10. After ensuring the network you're connected to is the Autonomys EVM, confirm your MetaMask password when prompted.

 ![Remix-11](/developers/Remix-11.png)

11. Adjust the gas limit and deploy your smart contract on the Autonomys EVM domain. Your transaction is now recorded and you can interact with your smart contract at the bottom of the page, meaning it's possible to call the functions \`increment()\` and \`decrement()\`, as well as \`setNumber()\`.

> *Note:* Do not tip when submitting transactions in an attempt to accelerate them as this could result in dual charges for gas fees. When deploying smart contracts to our Auto EVM domain, you may encounter an error related to gas estimation, typically presenting as: \`"No manual gas limit set"\` or \`"Gas estimation failed"\`. For more information and solutions, visit the [Auto EVM Introduction](/evm/introduction).

![Remix-12](/developers/Remix-12.png)

Congratulations, you've successfully deployed your smart contract on the Auto EVM!


---

### File: evm/safe.mdx

# Safe Multi-Signature Wallet

Safe (formerly Gnosis Safe) is now available on the Autonomys network, providing industry-leading multi-signature wallet functionality for secure asset management and decentralized operations.

## Overview

Safe is a battle-tested smart contract wallet infrastructure that enables multi-signature security across blockchain networks. With its deployment on Autonomys, teams, DAOs, and individual users can now benefit from enhanced security features and shared asset control on both our mainnet and testnet environments.

> **⚠️ Do not transfer directly to a centralized exchange from a Safe.** A Safe is a smart contract wallet, not a standard externally owned account (EOA). Many centralized exchanges do not support deposits originating from smart contract wallets, and funds sent from a Safe to an unsupported exchange deposit address can be lost or require a manual, time-consuming recovery process. Before sending any assets from a Safe on Autonomys to an exchange, confirm with that exchange that it supports deposits from smart contract (Safe) wallets. If you are unsure, first move the funds to a standard wallet address you control and deposit from there.

## Network Availability

Safe is currently deployed and accessible at: [https://safe.autonomys.xyz](https://safe.autonomys.xyz/welcome)


### Transaction Service

The dedicated Transaction Service is available at [https://transaction.safe.autonomys.xyz](https://transaction.safe.autonomys.xyz/)

## Key Features

Safe on Autonomys provides the following capabilities:

- **Multi-signature security**: Require multiple signatures for transaction approval
- **Shared asset control**: Enable collaborative fund management across team members
- **dApp integration**: Interact with decentralized applications using your Safe wallet
- **Smart contract deployment**: Deploy and manage contracts with enhanced security
- **Customizable policies**: Set spending limits and approval requirements

## Use Cases

Safe is ideal for:

- **Teams and organizations**: Secure collaborative fund management
- **DAOs**: Decentralized governance and treasury management  
- **Project treasuries**: Multi-party control over project funds
- **Individual users**: Enhanced security for high-value assets

## Getting Started

### Creating a Safe Wallet

1. Visit [safe.autonomys.xyz](https://safe.autonomys.xyz/welcome)

    ![safe-1](/developers/safe/safe-1.png)

2. Connect your wallet

    ![safe-2](/developers/safe/safe-2.png)

3. Create a new Safe by specifying:
   - Wallet name
   - Owner addresses (signers)
   - Confirmation threshold (required signatures)
    
    ![safe-3](/developers/safe/safe-3.png)

    --- 

    ![safe-4](/developers/safe/safe-4.png)

    ---

    ![safe-5](/developers/safe/safe-5.png)

4. Deploy your Safe wallet


### Managing Your Safe

Once created, you can:

- Add or remove owners
- Change signature requirements
- Execute transactions
- Interact with dApps
- View transaction history



---

### File: evm/the_graph.mdx

---
title: The Graph
---

# The Graph

> **Note:** Available on both **Mainnet** and **Chronos** testnet!


[The Graph](https://thegraph.com/) is an indexing protocol that provides an easy way to query blockchain data through decentralized APIs known as subgraphs. 

With The Graph, developers can benefit from:
 - Decentralized Indexing: Enables indexing blockchain data through multiple indexers, thus eliminating any single point of failure
 - GraphQL Queries: Provides a powerful GraphQL interface for querying indexed data, making data retrieval super simple.
 - Customization: Define your own logic for transforming & storing blockchain data. Reuse subgraphs published by other developers on The Graph Network.

Follow this quick-start guide to create, deploy, and query a subgraph within 5 minutes.

### Benefits

Indexers like The Graph create a queryable data layer specifically tracking events and state changes from your smart contract. By monitoring and organizing this contract data, they enable complex queries that would be impossible through direct blockchain calls. This allows your dApp to efficiently access historical transactions, track relationships between entities, and analyze patterns over time - all without multiple RPC calls.

### Prerequisites

- A crypto wallet
- A smart contract address on a supported network
- Node.js⁠ installed
- A package manager of your choice (npm, yarn or pnpm)

### Quick Start guide

1. Proceed to the [Subgraph Studio](https://thegraph.com/studio) and login via one of the supported wallets.

    ![the-graph-1](/developers/the-graph-1.png)

2. Confirm the sign and sign a message to use Studio.

    ![the-graph-2](/developers/the-graph-2.png)

    ![the-graph-3](/developers/the-graph-3.png)

3. Click on **Create a Subgraph** on the main dashboard.

    ![the-graph-4](/developers/the-graph-4.png)

4. Specify the **Subgraph Name**.

    ![the-graph-5](/developers/the-graph-5.png)

5. Upon creating a Subgraph, you will see its dashboard, where you can a project description, source code URL, and a website URL.

    ![the-graph-6](/developers/the-graph-6.png)

6. On the right side, click on **Select a network** and pick **Autonomys** from the dropdown list. 

    ![the-graph-7](/developers/the-graph-7.png)

7. Install **Graph CLI** using provided commands. You can use \`yarn\`, \`npm\`, \`pnpm\`, or \`bun\`. 

8. Initialize the subgraph by running \`graph init autonomys-subgraph\`. This will create a boilerplate subgraph project. 
During the initialization, you will need to specify a few things:
- Network (Autonomys)
- Subgraph slug (feel free to use the default name)
- Directory to create the subgraph in (feel free to use the default directory)
- Smart contact address (the address of your smart contract deployed on Autonomys Chronos EVM domain)
- ABI file (path)
- Start block (feel free to use the default value)
- Contract name
- Index contract events as entities (true or false value)

     ![the-graph-8](/developers/the-graph-8.png)

> Tip: you can find the contract ABI by looking at the \`token_metadata\` file. 
E.g. if you're using Remix IDE, find your contract metadata file, collapse it on the \`abi\` line 7, copy the entire \`abi\` including the square brakets **[]** and save it into a \`json\` file on your PR. 

    ![the-graph-9](/developers/the-graph-9.png)

    ![the-graph-10](/developers/the-graph-10.png)

9. Run \`graph auth\` to authenticate the project and provide your deploy key which you can find on the **Subgraph Dashboard**.

10. Enter the directory with \`cd project_name\` and run \`graph codegen && graph build\` to build the project, you will see the \`build/subgraph.yaml\` file being created.  

    ![the-graph-11](/developers/the-graph-11.png)

11. Deploy your subgraph by running \`graph deploy subgraph-autonomys\`. You will be asked to specify the version of the subgraph, e.g. v0.0.1. 

    ![the-graph-12](/developers/the-graph-12.png)

12. Proceed back to the **Graph Studio**, the status will change to **Deployed**. 

    ![the-graph-13](/developers/the-graph-13.png)

13. The new tabs **Playground**, **Endpoints**, **Logs** will now be accessible to you! You can find usage examples of querying the data, accessing the data via API, and can test queries in the **Playground** without leaving the studio!

    ![the-graph-14](/developers/the-graph-14.png)

Congratulations, you've successfully setup and configured a subgraph for your application! 

### Querying data in your smart contract

Subgraphs are primarily designed to index and query events emitted by smart contracts. 

1. Let's make some slight changes to the \`Counter\` contract we introduced in the [Foundry guide](/evm/foundry.mdx) and modify functions to emit events. 


\`\`\`solidity
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

contract Counter \{
    uint256 public number;
    
    event NumberSet(uint256 newNumber);
    event NumberIncremented(uint256 newNumber);
    event NumberDecremented(uint256 newNumber);
    
    function setNumber(uint256 newNumber) public \{
        number = newNumber;
        emit NumberSet(number);
    \}
    
    function increment() public \{
        number++;
        emit NumberIncremented(number);
    \}
    
    function decrement() public \{
        number--;
        emit NumberDecremented(number);
    \}
\}
\`\`\`

> Note: This will affect the contract ABI, make sure to change it and upgrade your Subgraph application.

2. Then we'll change the \`Counter\` contract state and set the number to \`5\` by running \`cast send YOUR_CONTRACT_ADDRESS "setNumber(uint256)" 5 --rpc-url https://auto-evm.chronos.autonomys.xyz/ws --private-key YOUR_KEY\`

3. Let's trigger one more event in the \`Counter\` contract by calling the \`increment()\` function. We can do that by running \`cast send YOUR_CONTRACT_ADDRESS "increment()" --rpc-url https://auto-evm.chronos.autonomys.xyz/ws --private-key YOUR_KEY\`

4. With two events emitted, let's proceed to **The Graph** playground and **query them**!

5. Open the **Graph Playground** tab where you try running the following queries:

    #### Query to Get All NumberSet Events
    \`\`\`bash
    \{
        numberSets(first: 10, orderBy: blockTimestamp, orderDirection: desc) \{
            id
            newNumber
            blockTimestamp
            blockNumber
            transactionHash
        \}
    \}
    \`\`\`

    #### Query to Get All Increment Events

    \`\`\`bash
    \{
        numberIncrementeds(first: 10, orderBy: blockTimestamp, orderDirection: desc) \{
            id
            newNumber
            blockTimestamp
            blockNumber
            transactionHash
        \}
    \}
    \`\`\`

    #### Get All Events (Set, Increment, Decrement) in Chronological Order 

    \`\`\`bash
    \{
        numberSets(orderBy: blockTimestamp) \{
            id
            newNumber
            blockTimestamp
            blockNumber
            transactionHash
            __typename
        \}
        numberIncrementeds(orderBy: blockTimestamp) \{
            id
            newNumber
            blockTimestamp
            blockNumber
            transactionHash
            __typename
        \}
        numberDecrementeds(orderBy: blockTimestamp) \{
            id
            newNumber
            blockTimestamp
            blockNumber
            transactionHash
            __typename
        \}
    \}
    \`\`\`

> Tip: you can also run queries directly from the terminal using \`cURL\` or \`gql\`. You can find **Example Usage** under the **Endpoints** tab. 



---

### File: evm/transaction_fees.mdx

---
title: Account Balances and Transaction Fees on Auto EVM
---

# Account Balances and Transaction Fees on Auto EVM

## Introduction

While Auto EVM strives to maintain EVM compatibility, there are some important differences that developers should understand regarding account balances and transaction fees. These differences stem from Auto EVM's Substrate-based architecture and affect how balances are managed and fees are calculated.

## Key Concepts

### Existential Deposit (ED)

The Existential Deposit is a minimum balance threshold that affects how accounts handle native token balances on the network.

- Current ED value: 0.000001 TAI3
- For user accounts (EOAs):
    - Accounts that drop below ED are reaped (removed from state)
    - Prevents dust accounts and maintains network efficiency
- For smart contracts:
    - ED only impacts contracts that handle native token balances
    - Many contracts (e.g., ERC20 tokens) don't interact with native tokens and are unaffected
    - When a contract's balance exceeds ED, that amount becomes reserved

### Consensus Storage Fees

In addition to standard gas fees, Auto EVM implements consensus storage fees:

- Applied to transactions that modify state
- Separate from execution fees
- Deducted from the sender's account
- Scale with the size of call data
- Not currently visible in BlockScout UI

## Impact on Smart Contracts

### Balance Management

1. Contracts with native token balances cannot be fully emptied due to ED requirements

> **Note:** This affects contracts that maintain native token balances (e.g., faucets, DEX contracts)

2. The maximum withdrawable amount from the account is: \`total_balance - ED\`


### Example Scenarios

**Deposit and Withdrawal:**
\`\`\`
Initial deposit: 0.01 TAI3
Available for withdrawal: 0.009999 TAI3 (due to ED)
Contract state balance: 0.01 TAI3
\`\`\`

**Fee Deduction:**
- Transaction fees (execution + storage) are deducted from the sender's account
- The contract's internal accounting may show different values than the actual on-chain balance

## Best Practices

### Smart Contract Development

1. Account for ED in withdrawal functions:
   - Always leave the ED amount in the contract
   - Check for sufficient balance above ED before transfers

2. Fee Handling:
   - Consider both execution and storage fees in transaction planning
   - Add buffer for storage fees in critical operations

### Testing Considerations

1. Test withdrawal edge cases:
   - Attempt to withdraw full balance
   - Verify behavior with amounts close to ED
   - Check contract state after failed withdrawals

2. Balance Verification:
   - Use RPC calls to verify actual available balance
   - Compare contract state with on-chain state
   - Account for ED in balance calculations

## Differences from Ethereum

1. Balance Management:
   - Ethereum: No minimum balance requirement
   - Auto EVM: Requires ED maintenance

2. Fee Structure:
   - Ethereum: Gas fees only
   - Auto EVM: Gas fees + consensus storage fees

3. Contract Behavior:
   - Ethereum: Contracts can be fully emptied
   - Auto EVM: ED must remain in contracts

## Tools and Verification

### Checking Balances

To verify actual available balances:
- Use Polkadot.js interface
- Query contract state directly
- Account for ED and storage fees in calculations

### Transaction Planning

When planning transactions:
1. Calculate required fees (execution + storage)
2. Ensure sufficient balance above ED
3. Add buffer for potential storage fee variations

## Common Issues and Solutions

1. "Insufficient Balance" errors:
   - Check if attempting to withdraw below ED
   - Verify sufficient balance for fees
   - Consider storage fees in calculations

2. Balance Discrepancies:
   - Compare BlockScout UI with actual RPC calls
   - Account for storage fees in calculations
   - Remember ED requirements


---

### File: evm/wrapping_ai3.mdx

# How to Wrap AI3 Tokens (Mainnet and Chronos Testnet)

Native AI3 tokens on Auto EVM are similar to ETH on the Ethereum network - they are not ERC-20 tokens, which is sometimes a requirement for certain use-cases.

Fortunately, there are ERC-20 contracts on both mainnet and testnet Auto EVM that allow you to "wrap" your tokens. This guide walks you through how to do that.

## The Contracts

### Mainnet WAI3 Contract

**Mainnet** WAI3 Contract: \`0x7ba06C7374566c68495f7e4690093521F6B991bb\`.

View contract: https://explorer.auto-evm.mainnet.autonomys.xyz/token/0x7ba06C7374566c68495f7e4690093521F6B991bb

### Chronos Testnet WAI3 Contract

**Chronos Testnet** WAI3 Contract: \`0xeAb23556Ec571bA10F4C3C8051d719E58e921caC\`. 

View contract: https://explorer.auto-evm.chronos.autonomys.xyz/token/0xeAb23556Ec571bA10F4C3C8051d719E58e921caC

## Wrapping AI3 for WAI3

We will use MetaMask for this guide, though any EVM compatible wallet should work. First, make sure you have the appropriate Auto EVM network added to MetaMask.

\`\`\`
Network Name: Autonomys EVM
New RPC URL: https://auto-evm.mainnet.autonomys.xyz/ws
Chain ID: 870
Currency Symbol: AI3
\`\`\`

Auto EVM is also available on the Chronos testnet

\`\`\`
Network Name: Autonomys EVM
New RPC URL: https://auto-evm.chronos.autonomys.xyz/ws
Chain ID: 8700
Currency Symbol: tAI3
\`\`\`

The quickest way to add the network is to use this button at the bottom of Blockscout (use the contract link above):

![wai](/developers/wai3/wai3-2.png)

Once that's done you should be able to see your Auto EVM tAI3 balance on MetaMask when you select the network.

![wai](/developers/wai3/wai3-3.png)

To convert some tAI3 to WAI3 you just need to send it to the contract. You will see a warning that you are about to send to a token contract. This is expected.

![wai](/developers/wai3/wai3-4.png)

Once you've accepted the warning you can click on "Continue".

NOTE: You may need to increase the gas fee if you see a failure when executing the transaction. If all has gone well you should end up seeing the contract interaction in the MetaMask Activity tab.

![wai](/developers/wai3/wai3-5.png)

To view your WAI3 you will need to add the token contract by importing it in MetaMask.

![wai](/developers/wai3/wai3-6.png)

Enter the WAI3 contract address and you will be able to see your balance under the Tokens tab in MetaMask.

![wai](/developers/wai3/wai3-7.png)

## Unwrapping WAI3

To unwrap your WAI3 tokens (convert them back to the original tAI3 tokens), you'll need to interact with the \`withdraw\` function in the **[WAI3 contract](#the-contracts)**. Here's how to do it.

First, make sure you have your wallet holding the WAI3 connected to the contract linked above. Ensure you are on the "Write" tab of the contract and look for the \`withdraw\` method.

![wai](/developers/wai3/wai3-8.png)

Enter the amount you want to unwrap as a parameter. The value entered needs to be in Shannons - the Autonomys equivalent of Ethereum's wei. The Blockscout UI has a button \`10^18\` to automatically add the extra 18 zeroes required to convert between the two.

![wai](/developers/wai3/wai3-9.png)

Once you're ready, hit the "Write" button and approve the transaction in your wallet. You should now see the WAI3 has ben converted back to native tAI3.

![wai](/developers/wai3/wai3-10.png)

![wai](/developers/wai3/wai3-11.png)

---

### File: index.mdx

---
title: Auto SDK - Build with Autonomys Network
description: Your gateway to building on the Autonomys Network. Streamline dApp development with modular packages and decentralized solutions.
---

import \{ SDKHeader \} from '../components/landingPage.js'
import \{ SDKOverview \} from '../components/landingPage.js'
import \{ SDKFeatures \} from '../components/landingPage.js'
import \{ SDKResources \} from '../components/landingPage.js'
import \{ SDKCTA \} from '../components/landingPage.js'

<SDKHeader />
<SDKOverview />
<SDKFeatures />
<SDKResources />
<SDKCTA />

---

### File: introduction.mdx

---
title: Introduction
---

## Autonomys Developer Hub

### Introduction
The [**Autonomys Network**](https://autonomys.xyz) is the *only* blockchain that resolves the blockchain trilemma without compromise. Autonomys offers a platform for new and experienced developers to build secure, scalable AI-powered decentralized applications (**super dApps**) and unstoppable, verifiable on-chain agents (**Auto Agents**) with ease, leveraging familiar tools and innovative protocols.

This guide offers an overview of the development options available on the Autonomys Network.

### Is building on Autonomys difficult?

Absolutely not! One of the project's primary objectives is to minimize the barriers to entry for all network participants, from farmers to developers. Building on Autonomys is thus very straightforward, with active support from our team and community available if you ever run into trouble.

Join the Autonomys Discord server, tell us about your idea, and the team will help you see it through to deployment—no project is too ambitious! We pride ourselves on enabling the seemingly un-enableable.

### Development options

Developers can currently choose to build using the:
- **Auto SDK**: a comprehensive toolkit that simplifies development on the Autonomys Network, or the
- **Auto EVM**: Autonomys's EVM-compatible domain, allowing you to utilize all its familiar functionalities.

You will soon be able to build your own local custom virtual machines.

### Transaction Security
The Autonomys Network uses a nonce system to prevent transaction replay attacks:

- Each account has an integer nonce value that increases by one with every on-chain transaction
- Signed transactions must include the correct nonce value to be accepted
- Transactions with incorrect nonce values are rejected, preventing replay attacks
- For security, new accounts' default nonce value is set to the current block number (rather than 0)
- This ensures if an account is reaped and later re-created, previous transactions remain invalid

## [Auto SDK](/sdk)

### Key features:
- **Modular Packages**: Partitions functionality intuitively into packages including \`auto-utils\`, \`auto-consensus\`, and \`auto-id\`, allowing you to import only what you need.
- **Simplified Interaction**: Abstracts the complexity of blockchain operations with high-level functions.
- **Flexibility**: Suitable for building AI-powered decentralized applications (super dApps) and on-chain agents (Auto Agents) with ease.

### Getting started with the Auto SDK
To start using the Auto SDK, refer to our [setup instructions](/sdk) to clone the repository, install dependencies, and run tests. The Auto SDK is designed to be developer-friendly, even for first-time developers, ensuring that anyone can get up and running quickly.

## [Auto EVM](/evm/introduction)

### Key features:
- **Solidity Smart Contracts**: Write and deploy smart contracts using Solidity, just as you would on Ethereum.
- **Tool Compatibility**: Compatible with any tool available for Ethereum development, including Remix, Truffle, and Hardhat.
- **Familiar Environment**: Leverage existing knowledge and resources from the Ethereum ecosystem to build your application.

### Why use the Auto EVM?
- **Seamless Transition**: Developers familiar with Ethereum can transition to Autonomys without a steep learning curve.
- **Scalability and Security**: Benefit from Autonomys' scalable and secure infrastructure while using tried-and-true development practices.
- **Interoperability**: Create applications that can interact seamlessly with other EVM-compatible networks.

### Getting started with the Auto EVM
To start using the Auto EVM, refer to our [guides and manuals](/evm/introduction).

## RPC endpoints

#### Consensus
- \`wss://rpc.mainnet.subspace.foundation/ws\`
- \`wss://rpc.chronos.autonomys.xyz/ws\`

### Auto EVM

#### Mainnet
- \`wss://auto-evm.mainnet.autonomys.xyz/ws\`

#### Chronos Testnet
- \`wss://auto-evm.chronos.autonomys.xyz/ws\`

## Questions or feedback? Post on our [forum](https://forum.autonomys.xyz/) or in the *#developer-chat* channel on our [Discord](https://discord.gg/EAw6B48r).

To access the developer role-gated *#developer-chat* channel:
1. Join our [Discord](https://discord.gg/vhv5cEZN).
2. Click on Autonomys Network in the top-left corner and choose **Linked Roles**.
   ![Discord-1](/developers/Discord-1.png)

3. Link your GitHub account to attain the developer role and gain access to *#developer-chat*. 
   ![Discord-2](/developers/Discord-2.png)


---

### File: sdk/auto-consensus.mdx

import AutoConsensusFetchBalance from '/components/autoConsensusFetchBalance.js';

## Auto-Consensus Package

### Introduction

The \`@autonomys/auto-consensus\` package provides functions for interacting with the consensus layer of the Autonomys Network. It allows developers to perform actions involving account management, balance inquiries, transfers, staking operations, and more. \`@autonomys/auto-consensus\` works hand-in-hand with \`@autonomys/auto-utils\` to simplify blockchain interactions.

### Installation

Install the package via \`npm\` or \`yarn\`:

\`\`\`bash
# Using npm
npm install @autonomys/auto-consensus

# Using yarn
yarn add @autonomys/auto-consensus
\`\`\`

### Importing

Import the \`auto-consensus\` functions you need into your project:

\`\`\`typescript
// Import specific functions
import \{ balance, transfer, account \} from '@autonomys/auto-consensus';

// Or import everything
import * as consensus from '@autonomys/auto-consensus';
\`\`\`

### Overview of the \`api\` object

Many functions in the \`auto-consensus\` package require an \`api\` object as a parameter. This \`api\` object is an instance of \`ApiPromise\` from the Polkadot.js API library that serves as a gateway for interacting with the blockchain node.

#### \`api\` core components
> *Note:* Always disconnect the API instance after your operations are complete to free up resources.

- \`api.rpc\`: Methods to perform remote procedure calls to the node.
- \`api.query\`: Access the blockchain's runtime storage.
- \`api.tx\`: Create and submit extrinsics (transactions) to the blockchain.
- \`api.consts\`: Runtime constants defined in the blockchain's metadata.
- \`api.events\`: Access events emitted by the blockchain.
- \`api.types\`: Type definitions used by the chain.

#### Example

\`\`\`typescript
import \{ createConnection \} from '@autonomys/auto-utils';

async function getApiInstance() \{
  const endpoint = 'wss://auto-evm.chronos.autonomys.xyz/ws';
  const api = await createConnection(endpoint);
  return api;
\}
\`\`\`

### Available functions
> *Note:* All asynchronous functions return a \`Promise\` and should be used with \`await\` for proper execution flow. Wrap your asynchronous calls in \`try...catch\` blocks to handle potential errors gracefully.

#### Account management

- \`account(api, address): Promise<AccountData>\`: Retrieves an account's nonce and balance data.
- \`balance(api, address): Promise<BalanceData>\`: Retrieves an account's balance details.

#### Balances

- \`totalIssuance(networkId?): Promise<BigInt>\`: Retrieves the total token issuance on the network.
- \`batch(api, txs[]): SubmittableExtrinsic\`: Creates a batch transaction for multiple operations.

#### Blockchain information

- \`block(api): Promise<RawBlock>\`: Retrieves the latest block data.
- \`header(api): Promise<RawBlockHeader>\`: Retrieves the latest block header.
- \`blockHash(api): Promise<string>\`: Retrieves the latest block hash.
- \`blockNumber(api): Promise<number>\`: Retrieves the current block number.
- \`networkTimestamp(api): Promise<bigint>\`: Retrieves the network timestamp.

#### Consensus information

- \`blockchainSize(api): Promise<bigint>\`: Calculates the blockchain's total size.
- \`spacePledged(api): Promise<bigint>\`: Calculates the total space pledged by farmers.
- \`solutionRanges(api): Promise<SolutionRanges>\`: Retrieves the current and next solution ranges.
- \`shouldAdjustSolutionRange(api): Promise<boolean>\`: Checks if the solution range needs adjustment.
- \`segmentCommitment(api): Promise<[StorageKey<AnyTuple>, Codec][]>\`: Retrieves segment commitment entries.
- \`slotProbability(api): [number, number]\`: Returns slot probability constants.
- \`maxPiecesInSector(api): bigint\`: Returns the maximum pieces in a sector.

#### Domains

- \`domainStakingSummary(api): Promise<DomainStakingSummary[]>\`: Retrieves domain staking summaries.
- \`domains(api): Promise<DomainRegistry[]>\`: Retrieves domain registries.
- \`latestConfirmedDomainBlock(api): Promise<ConfirmedDomainBlock[]>\`: Retrieves the latest confirmed blocks per domain.

#### Operators and staking

- \`operators(api): Promise<Operator[]>\`: Retrieves a list of all operators.
- \`operator(api, operatorId): Promise<OperatorDetails>\`: Retrieves the details of a specific operator.
- \`deposits(api, operatorId, account?): Promise<Deposit[]>\`: Retrieves the deposits for a specific operator.
- \`withdrawals(api, operatorId, account?): Promise<Withdrawal[]>\`: Retrieves the withdrawals for a specific operator.
- \`registerOperator(params): SubmittableExtrinsic\`: Creates a transaction to register a new operator.
- \`nominateOperator(params): SubmittableExtrinsic\`: Creates a transaction to nominate an operator.
- \`withdrawStake(params): SubmittableExtrinsic\`: Creates a transaction to withdraw staked tokens.
- \`deregisterOperator(params): SubmittableExtrinsic\`: Creates a transaction to deregister an operator.
- \`unlockFunds(params): SubmittableExtrinsic\`: Creates a transaction to unlock staked funds.
- \`unlockNominator(params): SubmittableExtrinsic\`: Creates a transaction to unlock nominator funds.

#### Transfers

- \`transfer(api, receiver, amount, allowDeath?): SubmittableExtrinsic\`: Creates a transaction to transfer funds.
- \`transferAll(api, receiver, keepAlive?): SubmittableExtrinsic\`: Creates a transaction to transfer all tokens.

#### Utility functions

- \`query<T>(api, methodPath, params?): Promise<T>\`: Queries the blockchain state for a method.
- \`remark(api, remark, withEvent?): SubmittableExtrinsic\`: Creates a remark transaction.
- \`rpc<T>(api, methodPath, params?): Promise<T>\`: Performs an RPC call.

## Interactive usage example

### Fetching the wallet balance (unlocked, locked) and nonce for a wallet

<AutoConsensusFetchBalance />

## Usage examples

Code examples demonstrating how to use the functions provided by \`@autonomys/auto-consensus\`.

### 1. Account management

#### Retrieve detailed account information (including the nonce and balance data)

\`\`\`typescript
import \{ account \} from '@autonomys/auto-consensus';
import \{ activate \} from '@autonomys/auto-utils';

(async () => \{
  const api = await activate(\{ networkId: 'chronos' \});
  const accountData = await account(api, 'your_address');

  console.log(\`Nonce: \$\{accountData.nonce\}\`);
  console.log(\`Free Balance: \$\{accountData.data.free\}\`);
  console.log(\`Reserved Balance: \$\{accountData.data.reserved\}\`);

  await api.disconnect();
\})();
\`\`\`

#### Activate a wallet and check its balance

\`\`\`typescript
import \{ activateWallet \} from '@autonomys/auto-utils';
import \{ balance \} from '@autonomys/auto-consensus';

(async () => \{
  // Activate a wallet using a mnemonic phrase
  const \{ api, accounts \} = await activateWallet(\{
    mnemonic: 'your mnemonic phrase here', // Replace with your mnemonic
    networkId: 'chronos', // Optional: specify the network ID
  \});

  const account = accounts[0];
  console.log(\`Connected with account address: \$\{account.address\}\`);

  // Check the account balance
  const accountBalance = await balance(api, account.address);
  console.log(\`Account balance: \$\{accountBalance.free\}\`);

  // Disconnect when done
  await api.disconnect();
\})();
\`\`\`

### 2. Balance operations

#### Retrieve the free balance of an account

\`\`\`typescript
import \{ balance \} from '@autonomys/auto-consensus';
import \{ activate \} from '@autonomys/auto-utils';

(async () => \{
  const api = await activate(\{ networkId: 'chronos' \});
  const accountBalance = await balance(api, 'your_address');

  console.log(\`Free Balance: \$\{accountBalance.free\}\`);

  await api.disconnect();
\})();
\`\`\`

#### Retrieve the total token issuance on the network

\`\`\`typescript
import \{ totalIssuance \} from '@autonomys/auto-consensus';

(async () => \{
  const total = await totalIssuance('chronos');

  console.log(\`Total Issuance: \$\{total.toString()\}\`);
\})();
\`\`\`

### 3. Transfers

#### Transfer funds between accounts

\`\`\`typescript
import \{ activateWallet \} from '@autonomys/auto-utils';
import \{ transfer \} from '@autonomys/auto-consensus';

(async () => \{
  // Activate the sender's wallet
  const senderWallet = await activateWallet(\{
    mnemonic: 'sender mnemonic phrase', // Replace with the sender's mnemonic
  \});
  const sender = senderWallet.accounts[0];

  // Activate the receiver's wallet
  const receiverWallet = await activateWallet(\{
    mnemonic: 'receiver mnemonic phrase', // Replace with the receiver's mnemonic
  \});
  const receiver = receiverWallet.accounts[0];

  // Transfer 1 AI3 from the sender to the receiver
  const amount = 1; // Amount in AI3
  const transferTx = await transfer(senderWallet.api, receiver.address, amount);

  // Sign and send the transaction
  await transferTx.signAndSend(sender, (\{ status, txHash, events \}) => \{
    if (status.isInBlock) \{
      console.log(\`Transaction included at blockHash \$\{status.asInBlock\}\`);
      console.log(\`Transaction hash: \$\{txHash\}\`);
    \} else if (status.isFinalized) \{
      console.log(\`Transaction finalized at blockHash \$\{status.asFinalized\}\`);
    \}
  \});

  // Disconnect when done
  await senderWallet.api.disconnect();
  await receiverWallet.api.disconnect();
\})();
\`\`\`

#### Transfer tokens from one wallet to another

\`\`\`typescript
import \{ transfer \} from '@autonomys/auto-consensus';
import \{ activateWallet, signAndSendTx, disconnect \} from '@autonomys/auto-utils';

(async () => \{
  const \{ api, accounts \} = await activateWallet(\{
    networkId: 'chronos',
    mnemonic: 'your_mnemonic',
  \});

  const sender = accounts[0];
  const recipientAddress = 'recipient_address';
  const amount = '1000000000000'; // Amount in the smallest unit (Shannon)

  const tx = await transfer(api, recipientAddress, amount);

  // Sign and send the transaction
  await signAndSendTx(sender, tx);

  console.log(\`Transferred \$\{amount\} tokens to \$\{recipientAddress\}\`);

  await disconnect(api);
\})();
\`\`\`

### 4. Staking operations

#### Register a new operator for staking

\`\`\`typescript
import \{ registerOperator \} from '@autonomys/auto-consensus';
import \{ activateWallet, signAndSendTx \} from '@autonomys

/auto-utils';

(async () => \{
  const \{ api \} = await activateWallet(\{
    networkId: 'chronos',
    mnemonic: 'sender_mnemonic',
  \});

  // Sender's account (who is registering the operator)
  const \{ accounts: senderAccounts \} = await activateWallet(\{
    networkId: 'chronos',
    mnemonic: 'sender_mnemonic',
  \});
  const sender = senderAccounts[0];

  // Operator's account
  const \{ accounts: operatorAccounts \} = await activateWallet(\{
    networkId: 'chronos',
    mnemonic: 'operator_mnemonic',
  \});
  const operatorAccount = operatorAccounts[0];

  const tx = await registerOperator(\{
    api,
    senderAddress: sender.address,
    Operator: operatorAccount,
    domainId: '0', // Domain ID where the operator will be registered
    amountToStake: '1000000000000000000', // Amount in smallest units
    minimumNominatorStake: '10000000000000000',
    nominationTax: '5', // Percentage as a string (e.g., '5' for 5%)
  \});

  // Sign and send the transaction
  await signAndSendTx(sender, tx);

  console.log('Operator registered successfully');
\})();
\`\`\`

#### Nominate an existing operator by staking tokens

\`\`\`typescript
import \{ nominateOperator \} from '@autonomys/auto-consensus';
import \{ activateWallet, signAndSendTx \} from '@autonomys/auto-utils';

(async () => \{
  const \{ api, accounts \} = await activateWallet(\{
    networkId: 'chronos',
    mnemonic: 'nominator_mnemonic',
  \});
  const nominator = accounts[0];

  const operatorId = '1'; // The ID of the operator to nominate
  const amountToStake = '5000000000000000000'; // Amount in smallest units

  const tx = await nominateOperator(\{
    api,
    operatorId,
    amountToStake,
  \});

  // Sign and send the transaction
  await signAndSendTx(nominator, tx);

  console.log(\`Nominated operator \$\{operatorId\} with \$\{amountToStake\} stake\`);
\})();
\`\`\`

### 5. Blockchain information

#### Retrieve the current block number, block hash, and network timestamp

\`\`\`typescript
import \{ blockNumber, blockHash, networkTimestamp \} from '@autonomys/auto-consensus';
import \{ activate \} from '@autonomys/auto-utils';

(async () => \{
  const api = await activate(\{ networkId: 'chronos' \});

  const currentBlockNumber = await blockNumber(api);
  const currentBlockHash = await blockHash(api);
  const currentTimestamp = await networkTimestamp(api);

  console.log(\`Current Block Number: \$\{currentBlockNumber\}\`);
  console.log(\`Current Block Hash: \$\{currentBlockHash\}\`);
  console.log(\`Network Timestamp: \$\{currentTimestamp\}\`);

  await api.disconnect();
\})();
\`\`\`

### 6. Domain interactions

#### Retrieve the list of domains registered on the network

\`\`\`typescript
import \{ domains \} from '@autonomys/auto-consensus';
import \{ activate \} from '@autonomys/auto-utils';

(async () => \{
  const api = await activate(\{ networkId: 'chronos' \});
  const domainList = await domains(api);

  domainList.forEach((domain) => \{
    console.log(\`Domain ID: \$\{domain.id\}\`);
    console.log(\`Owner Address: \$\{domain.owner\}\`);
    console.log(\`Creation Block: \$\{domain.creationBlock\}\`);
    // ...other domain properties
  \});

  await api.disconnect();
\})();
\`\`\`

#### Retrieve staking summaries for all domains

\`\`\`typescript
import \{ domainStakingSummary \} from '@autonomys/auto-consensus';
import \{ activate \} from '@autonomys/auto-utils';

(async () => \{
  const api = await activate(\{ networkId: 'chronos' \});
  const stakingSummaries = await domainStakingSummary(api);

  stakingSummaries.forEach((summary) => \{
    console.log(\`Domain ID: \$\{summary.domainId\}\`);
    console.log(\`Total Stake: \$\{summary.totalStake\}\`);
    // ...other summary properties
  \});

  await api.disconnect();
\})();
\`\`\`

#### Retrieve the latest confirmed blocks for each domain

\`\`\`typescript
import \{ latestConfirmedDomainBlock \} from '@autonomys/auto-consensus';
import \{ activate \} from '@autonomys/auto-utils';

(async () => \{
  const api = await activate(\{ networkId: 'chronos' \});
  const confirmedBlocks = await latestConfirmedDomainBlock(api);

  confirmedBlocks.forEach((blockInfo) => \{
    console.log(\`Domain ID: \$\{blockInfo.id\}\`);
    console.log(\`Block Number: \$\{blockInfo.number\}\`);
    console.log(\`Block Hash: \$\{blockInfo.hash\}\`);
    // ...other block properties
  \});

  await api.disconnect();
\})();
\`\`\`


---

### File: sdk/auto-dag-data.mdx

# Auto DAG Data Package

## Introduction

The \`@autonomys/auto-dag-data\` package provides utilities for creating and managing IPLD DAGs (InterPlanetary Linked Data Directed Acyclic Graphs) for files and folders. It facilitates chunking large files, handling metadata, and creating folder structures suitable for distributed storage systems like IPFS.

> **Note**: This package is an ES Module package and is designed to work with ESM applications. Check [this tutorial](https://dev.to/mangadev/set-up-a-backend-nodejs-typescript-jest-using-es-modules-1530) for guidance on setting up an ES module application.

## Features

- **File Chunking and DAG Creation**: Efficiently split large files into smaller chunks and create IPLD DAGs.
- **Folder Structure Creation**: Generate IPLD DAGs for directory structures.
- **Metadata Handling**: Add and manage metadata for files and folders.
- **CID Management**: Utilities for working with Content Identifiers (CIDs).
- **TypeScript Support**: Fully typed for enhanced developer experience.

## Installation

Install the package via \`npm\` or \`yarn\`:

\`\`\`bash
# Using npm
npm install @autonomys/auto-dag-data

# Using yarn
yarn add @autonomys/auto-dag-data
\`\`\`

## Importing

Import the \`auto-dag-data\` functions you need into your project:

\`\`\`typescript
// Import specific functions
import \{ processFileToIPLDFormat, processFolderToIPLDFormat, cidOfNode \} from '@autonomys/auto-dag-data';

// Or import everything
import * as dagData from '@autonomys/auto-dag-data';
\`\`\`

## Available Functions

> **Note**: All asynchronous functions return a \`Promise\` and should be used with \`await\` for proper execution flow. Wrap asynchronous calls in \`try...catch\` blocks to handle potential errors gracefully.

### File Processing

- \`processFileToIPLDFormat(blockstore, fileStream, fileSize, fileName): CID\`: Creates an IPLD DAG from a file stream.

### Folder Processing

- \`processFolderToIPLDFormat(blockstore, childCIDs, folderName, folderSize): CID\`: Generates an IPLD DAG from a folder structure.

### CID Utilities

- \`cidOfNode(node): CID\`: Creates a CID from an IPLD node.
- \`cidToString(cid): string\`: Converts a CID to its string representation.
- \`stringToCid(cidString): CID\`: Parses a CID string back into a CID object.

### Node Operations

- \`encodeNode(node): Uint8Array\`: Encodes an IPLD node to bytes.
- \`decodeNode(bytes): IPLDNode\`: Decodes bytes back into an IPLD node.

### Metadata Management

- \`createMetadataNode(metadata): IPLDNode\`: Creates a metadata node from metadata object.
- \`processMetadataToIPLDFormat(blockstore, metadata): CID\`: Processes metadata into IPLD format.

## Usage Examples

### 1. Creating an IPLD DAG from a File

Process a file into IPLD format for distributed storage:

\`\`\`typescript
import \{ processFileToIPLDFormat, cidToString \} from '@autonomys/auto-dag-data';
import \{ MemoryBlockstore \} from 'blockstore-core/memory';
import fs from 'fs';

(async () => \{
  const fileStream = fs.createReadStream('path/to/your/file.txt');
  const fileSize = fs.statSync('path/to/your/file.txt').size;

  const blockstore = new MemoryBlockstore();
  const fileCID = await processFileToIPLDFormat(blockstore, fileStream, fileSize, 'file.txt');
  
  const cidString = cidToString(fileCID);
  console.log(\`File CID: \$\{cidString\}\`);
\})();
\`\`\`

### 2. Creating an IPLD DAG from a Folder

Generate an IPLD DAG from a directory structure:

\`\`\`typescript
import \{ processFolderToIPLDFormat, decodeNode, cidToString \} from '@autonomys/auto-dag-data';
import \{ MemoryBlockstore \} from 'blockstore-core/memory';
import \{ CID \} from 'multiformats';

(async () => \{
  // Example child CIDs from files in the folder
  const childCIDs: CID[] = [
    /* array of CIDs from folder contents */
  ];
  const folderName = 'my-folder';
  const folderSize = 1024; // total size of all children

  const blockstore = new MemoryBlockstore();
  const folderCID = await processFolderToIPLDFormat(blockstore, childCIDs, folderName, folderSize);

  const node = await decodeNode(await blockstore.get(folderCID));
  const cidString = cidToString(folderCID);
  console.log(\`Folder CID: \$\{cidString\}\`);
\})();
\`\`\`

### 3. Working with CIDs

Convert between CID objects and strings:

\`\`\`typescript
import \{ cidOfNode, cidToString, stringToCid \} from '@autonomys/auto-dag-data';

(async () => \{
  // Assuming you have an IPLD node
  const cid = cidOfNode(someNode);

  // Convert CID to string for storage or transmission
  const cidString = cidToString(cid);
  console.log(\`CID as string: \$\{cidString\}\`);

  // Parse string back into CID object
  const parsedCID = stringToCid(cidString);
  console.log('CID object:', parsedCID);
\})();
\`\`\`

### 4. Encoding and Decoding Nodes

Handle IPLD node serialization:

\`\`\`typescript
import \{ encodeNode, decodeNode \} from '@autonomys/auto-dag-data';

(async () => \{
  // Encode a node for storage
  const encodedNode = encodeNode(someNode);
  console.log('Encoded node:', encodedNode);

  // Decode node from storage
  const decodedNode = decodeNode(encodedNode);
  console.log('Decoded node:', decodedNode);
\})();
\`\`\`

### 5. Handling Metadata

Create and process metadata for your files:

\`\`\`typescript
import \{ createMetadataNode, processMetadataToIPLDFormat, cidToString \} from '@autonomys/auto-dag-data';
import \{ MemoryBlockstore \} from 'blockstore-core/memory';

(async () => \{
  const metadata = \{
    name: 'My File',
    description: 'This is a sample file',
    created: new Date().toISOString(),
    // ... other metadata fields
  \};

  // Create metadata node
  const metadataNode = createMetadataNode(metadata);

  // Process metadata to IPLD format
  const blockstore = new MemoryBlockstore();
  const metadataCID = await processMetadataToIPLDFormat(blockstore, metadata);
  
  const cidString = cidToString(metadataCID);
  console.log(\`Metadata CID: \$\{cidString\}\`);
\})();
\`\`\`

### 6. Complete File Processing Example

Full example of processing a file and extracting its CID:

\`\`\`typescript
import \{ processFileToIPLDFormat, cidToString \} from '@autonomys/auto-dag-data';
import \{ MemoryBlockstore \} from 'blockstore-core/memory';
import fs from 'fs';

(async () => \{
  try \{
    const filePath = 'path/to/your/file.txt';
    const fileStream = fs.createReadStream(filePath);
    const fileStats = fs.statSync(filePath);
    
    const blockstore = new MemoryBlockstore();
    const cid = await processFileToIPLDFormat(
      blockstore, 
      fileStream, 
      fileStats.size, 
      'file.txt'
    );

    const cidString = cidToString(cid);
    console.log(\`Successfully processed file. CID: \$\{cidString\}\`);
    
  \} catch (error) \{
    console.error('Error processing file:', error);
  \}
\})();
\`\`\`

## Best Practices

### Error Handling

Always wrap asynchronous operations in try-catch blocks:

\`\`\`typescript
try \{
  const cid = await processFileToIPLDFormat(blockstore, stream, size, name);
  // Handle success
\} catch (error) \{
  console.error('Processing failed:', error);
  // Handle error appropriately
\}
\`\`\`

### Blockstore Management

Use appropriate blockstore implementations based on your needs:

\`\`\`typescript
// For temporary operations
import \{ MemoryBlockstore \} from 'blockstore-core/memory';
const tempBlockstore = new MemoryBlockstore();

// For persistent storage
import \{ FsBlockstore \} from 'blockstore-fs';
const persistentBlockstore = new FsBlockstore('./blocks');
\`\`\`

### Resource Cleanup

Ensure proper cleanup of resources when working with file streams:

\`\`\`typescript
const stream = fs.createReadStream(filePath);
try \{
  const cid = await processFileToIPLDFormat(blockstore, stream, size, name);
  // Process result
\} finally \{
  stream.destroy(); // Clean up stream
\}
\`\`\`

---

### File: sdk/auto-drive/api_reference.mdx

# Auto-Drive API Reference

## Overview

Auto-Drive provides REST APIs for interacting with the Autonomys decentralized storage network. The APIs handle file operations, metadata management, and subscription services.

## API Documentation

The complete API documentation with all function signatures is available [here](https://mainnet.auto-drive.autonomys.xyz/api/docs).

![Auto-Drive-API-1](/developers/Auto-Drive-API-1.png)

## API Endpoints Structure

The API is organized into several main categories:

### Subscriptions Endpoints
- Manage your account subscription and view usage statistics
- \`GET /subscriptions/info\` - Get subscription information
- \`GET /subscriptions/credits\` - Check pending upload/download credits

### Upload Endpoints
- Progress tracking and upload management
- \`POST /uploads/file\` - Upload single files
- \`POST /uploads/folder\` - Upload folders and directories
- \`POST /uploads/multipart\` - Multipart uploads for large files

### Objects Endpoints
- Object metadata management and access control
- \`GET /objects\` - List your uploaded objects
- \`GET /objects/search\` - Search objects by name or CID
- \`POST /objects/share\` - Share objects and manage permissions

### Download Endpoints
- Support for password-protected downloads
- \`GET /downloads/\{cid\}\` - Download files by CID
- \`GET /downloads/stream/\{cid\}\` - Streaming downloads

## Base URLs

- **Mainnet**: \`https://mainnet.auto-drive.autonomys.xyz\`

## Authentication

All API requests require authentication using one of these methods:

### API Key Authentication (Recommended)
Include your API key in the request headers:

\`\`\`http
Authorization: Bearer your-api-key
X-Auth-Provider: apikey
\`\`\`

### JWT Token Authentication
For advanced use cases, JWT tokens are supported:

\`\`\`http
Authorization: Bearer your-jwt-token
X-Auth-Provider: jwt
\`\`\`

> **Security Note:** Keep your API keys secure and never share them with unauthorized parties.

## Auto-Drive Services

Auto-Drive consists of two main services:

### 1. Auto-Drive Storage API
Handles all file operations and object management:
- **File uploads** (single and multipart)
- **Object metadata management** 
- **Access control and permissions**
- **Subscription management**

### 2. Auto-Drive Download Gateway
Provides optimized file download capabilities:
- **Direct file downloads**
- **Asynchronous downloads**
- **Bandwidth optimization**


## Response Format

All API responses follow a consistent JSON format with appropriate HTTP status codes. Error responses include detailed error messages to help with debugging.

## Rate Limits

API usage is subject to your subscription limits:
- **Upload limit**: 100MB per month (default)
- **Download limit**: 5GB per month (default)

Check your current limits using the subscription endpoints or in the Auto-Drive dashboard.

## Making Direct API Calls

You can make direct HTTP requests to the API endpoints:

\`\`\`bash
# Example: Get subscription info
curl -X GET "https://mainnet.auto-drive.autonomys.xyz/subscriptions/info" \
  -H "Authorization: Bearer your-api-key" \
  -H "X-Auth-Provider: apikey"
\`\`\`

\`\`\`bash
# Example: Upload a file
curl -X POST "https://mainnet.auto-drive.autonomys.xyz/uploads/file" \
  -H "Authorization: Bearer your-api-key" \
  -H "X-Auth-Provider: apikey" \
  -H "Content-Type: multipart/form-data" \
  -F "file=@path/to/your/file.txt"
\`\`\`

For detailed endpoint specifications, request/response schemas, and interactive testing, visit the [complete API documentation](https://mainnet.auto-drive.autonomys.xyz/api/docs).

---

### File: sdk/auto-drive/available_functions.mdx

# Auto-Drive SDK — Available Functions

All functions are available as methods on the \`AutoDriveApi\` instance returned by \`createAutoDriveApi\`. Upload functions that operate on the local filesystem (Node.js only) are accessed via the \`fs\` sub-module.

\`\`\`typescript
import \{ createAutoDriveApi, fs \} from '@autonomys/auto-drive'
import \{ NetworkId \} from '@autonomys/auto-utils'

const api = createAutoDriveApi(\{ apiKey: 'your-api-key', network: NetworkId.MAINNET \})
\`\`\`

---

## Upload Operations

- \`api.uploadFile(file, options?, uploadChunkSize?): Promise<string>\` — Uploads a \`GenericFile\` (custom async-iterable interface) with optional encryption and compression. Returns the CID.

- \`fs.uploadFileFromFilepath(api, filePath, options?): Promise<string>\` — **Node.js only.** Uploads a file from a local filesystem path with optional encryption and compression. Returns the CID.

- \`api.uploadFileFromInput(file, options?, uploadChunkSize?): Promise<string>\` — Uploads a browser \`File\` object (e.g. from an \`<input type="file">\` event). Returns the CID.

- \`api.uploadFileFromBuffer(buffer, name, options?, uploadChunkSize?): Promise<string>\` — Uploads a \`Buffer\` directly with a given filename. Returns the CID.

- \`api.uploadObjectAsJSON(object, name?, options?, uploadChunkSize?): Promise<string>\` — Serializes any value as JSON and uploads it. Returns the CID.

- \`api.uploadFolderFromInput(fileList, options?): Promise<string>\` — Uploads a browser \`FileList\` or \`File[]\` array as a folder. Returns the root CID.

- \`api.uploadFileWithinFolderUpload(uploadId, file, uploadChunkSize?, options?): Promise<string>\` — Uploads a single file into an existing folder upload session identified by \`uploadId\`. Returns the CID.

**\`UploadFileOptions\`**

\`\`\`typescript
type UploadFileOptions = \{
  password?: string         // enables AES-256-GCM client-side encryption
  compression?: boolean
  onProgress?: (progress: number) => void
\}
\`\`\`

---

## Download Operations

- \`api.downloadFile(cid, password?): Promise<AsyncIterable<Buffer>>\` — Downloads a file by CID. Pass the same \`password\` used at upload time to decrypt.

- \`api.publishObject(cid): Promise<string>\` — Creates a publicly accessible download URL for the given CID. Returns the URL string.

- \`api.isFileCached(cid): Promise<boolean>\` — Returns whether the file is currently cached and immediately available for download.

- \`api.createAsyncDownload(cid): Promise<AsyncDownload>\` — Queues a large file for async background download. Returns an \`AsyncDownload\` descriptor.

- \`api.getAsyncDownloads(): Promise<AsyncDownload[]>\` — Returns all active async download jobs for the current account.

- \`api.getAsyncDownload(downloadId): Promise<AsyncDownload>\` — Returns the status of a single async download by ID.

- \`api.dismissAsyncDownload(downloadId): Promise<void>\` — Removes a completed or failed async download from the queue.

---

## File Discovery

- \`api.getMyFiles(page, limit): Promise<PaginatedResult<ObjectSummary>>\` — Returns a paginated list of the current user's uploaded files.

- \`api.searchByNameOrCIDInMyFiles(value): Promise<ObjectSummary[]>\` — Searches for files by name or CID within the current user's files.

- \`api.searchByNameOrCID(value): Promise<ObjectSummary[]>\` — Global search across all public files by name or CID.

---

## Account and Credits

- \`api.me(): Promise<UserInfo>\` — Returns the current authenticated user's profile information.

- \`api.getPendingCredits(): Promise<\{ upload: number; download: number \}>\` — Returns the current user's remaining upload and download credit balances.

- \`api.getSubscriptionInfo(): Promise<SubscriptionInfo>\` — Returns the current user's subscription tier and allocation details.

- \`api.getStoragePrice(): Promise<StoragePrice>\` — Returns the current live storage price from the protocol. No API key required.

\`\`\`typescript
type StoragePrice = \{
  shannonsPerByte: number
  ai3PerGb: number
\}
\`\`\`

---

## Pay with AI3 — Payment Intents

These functions implement the complete [Pay with AI3](/auto_drive/pay_with_ai3) credit purchase flow. See the [developer integration guide](/sdk/auto-drive/pay_with_ai3) for full examples.

**Four-step flow:**
\`\`\`
1. createPaymentIntent(sizeBytes)         — locks price, returns amount + contract details
2. send ai3AmountWei to contractAddress   — call payIntent(intentId) on-chain (your wallet code)
3. watchPaymentTransaction(id, txHash)    — notify Auto Drive of the transaction hash
4. waitForPaymentCompletion(id)           — poll until COMPLETED (credits applied)
\`\`\`

- \`api.getPaymentContractInfo(): Promise<PaymentContractInfo>\` — Returns the Auto-EVM contract address, chain ID, and \`payIntent\` ABI. No API key required. Called internally by \`createPaymentIntent\`; export this for client-side wallet pre-fetching.

- \`api.createPaymentIntent(sizeBytes, options?): Promise<PaymentIntent>\` — Locks the current storage price for the authenticated account and returns a payment intent. The price is locked for **10 minutes**. Pass \`\{ checkCreditCap: true \}\` to have Auto Drive reject an over-cap purchase before anything is paid.

- \`api.watchPaymentTransaction(intentId, txHash): Promise<void>\` — Submits the on-chain transaction hash to Auto Drive. The backend waits for 6 block confirmations before granting credits. Works for both AI3 and USDC intents.

- \`api.getPaymentIntentStatus(intentId): Promise<\{ id: string; status: PaymentIntentStatus \}>\` — Returns the current status of a payment intent.

- \`api.waitForPaymentCompletion(intentId, options?): Promise<PaymentIntentTerminalStatus>\` — Polls until the intent reaches a terminal state (\`COMPLETED\`, \`EXPIRED\`, \`FAILED\`, or \`OVER_CAP\`). Resolves with the terminal status. Set \`options.settleGraceMs\` to keep polling through an HTTP \`410\` after the price lock lapses; without it, a \`410\` throws a \`PaymentApiError\`.

The authenticated payment calls throw a \`PaymentApiError\` (with \`status\` and, for coded backend errors, \`code\`) when Auto Drive answers with a non-OK status. See [Handling Errors](/sdk/auto-drive/pay_with_ai3#handling-errors).

**Supporting types:**

\`\`\`typescript
type PaymentContractInfo = \{
  chainId: number
  contractAddress: string
  payIntentAbi: readonly unknown[]
\}

type PaymentIntent = \{
  intentId: string
  ai3AmountWei: string   // exact value to send as msg.value (in Shannons)
  ai3Amount: string      // human-readable AI3 amount
  contractAddress: string
  shannonsPerByte: string
  expiresAt: string      // ISO 8601 timestamp, 10 minutes from creation
\}

type PaymentIntentStatus =
  | 'PENDING'    // awaiting on-chain payment
  | 'CONFIRMED'  // payment received, awaiting final credit grant
  | 'COMPLETED'  // credits applied to account
  | 'EXPIRED'    // no payment received within 10 minutes
  | 'FAILED'     // payment amount below quoted price
  | 'OVER_CAP'   // account's 100 GB limit would be exceeded

type PaymentIntentTerminalStatus = 'COMPLETED' | 'EXPIRED' | 'FAILED' | 'OVER_CAP'

type PollOptions = \{
  pollIntervalMs?: number  // default: 3000
  timeoutMs?: number       // default: 300000 (5 minutes)
  settleGraceMs?: number   // keep polling through HTTP 410 for this long, then return 'EXPIRED'
\}

type CreatePaymentIntentOptions = \{
  checkCreditCap?: boolean // send sizeBytes as requestedBytes for a pre-payment cap check. Default: false
\}

class PaymentApiError extends Error \{
  readonly status: number                       // HTTP status
  readonly code?: PaymentErrorCode | string     // machine-readable backend code, when present
\}

type PaymentErrorCode =
  | 'GOOGLE_ACCOUNT_REQUIRED'    // 403
  | 'CREDIT_CAP_EXCEEDED'        // 403
  | 'USDC_PAYMENTS_DISABLED'     // 403
  | 'USDC_PAYMENTS_UNAVAILABLE'  // 503
  | 'PRICE_ORACLE_UNAVAILABLE'   // 503
  | 'PRICE_UNSTABLE'             // 503
\`\`\`

---

## Pay with USDC — Payment Intents

These functions implement the [Pay with USDC](/auto_drive/pay_with_usdc) credit purchase flow (USDC on Ethereum mainnet). The SDK does not sign transactions: it returns the quote and where to pay, plus typed ABIs, and your wallet library sends the transactions. See the [developer integration guide](/sdk/auto-drive/pay_with_ai3#pay-with-usdc) for a full example.

**Five-step flow:**
\`\`\`
1. createUsdcPaymentIntent(sizeBytes)                 — locks a USDC price, returns amount + chain, token and receiver
2. approve(receiverAddress, usdcAmount)               — on tokenAddress, on chainId (your wallet code)
3. payIntentWithToken(intentId, usdcAmount)           — on receiverAddress, no value (your wallet code)
4. watchPaymentTransaction(id, txHash)                — the hash from step 3, not step 2
5. waitForPaymentCompletion(id, \{ settleGraceMs \})    — poll until COMPLETED (credits applied)
\`\`\`

- \`api.getUsdcPaymentTarget(): Promise<UsdcPaymentTarget>\` — Returns where to send a USDC payment: chain ID, receiver address, token address, token decimals, confirmations, and \`settleGraceMs\`. Requires an API key. Called internally by \`createUsdcPaymentIntent\`.

- \`api.createUsdcPaymentIntent(sizeBytes: number | bigint): Promise<UsdcPaymentIntent>\` — Locks a USDC price for \`sizeBytes\` of storage and returns the exact amount to pay together with where to pay it. The price is locked for **10 minutes**.

- \`erc20ApprovalAbi\` — Minimal ERC-20 ABI (\`approve\`, \`allowance\`, \`balanceOf\`) for the approval step. \`transfer\` and \`transferFrom\` are left out on purpose.

- \`usdcReceiverAbi\` — Minimal ABI for \`payIntentWithToken(bytes32 intentId, uint256 amount)\` on \`AutoDriveUSDCReceiver\`.

\`watchPaymentTransaction\`, \`getPaymentIntentStatus\` and \`waitForPaymentCompletion\` are shared with the AI3 flow (see above).

**Supporting types:**

\`\`\`typescript
type PaymentMethod = 'ai3_native' | 'usdc_eth'

type UsdcPaymentTarget = \{
  chainId: number          // EIP-155 chain ID (1 for Ethereum mainnet)
  receiverAddress: string  // AutoDriveUSDCReceiver — also the approve spender
  tokenAddress: string     // USDC token address — call approve on this
  tokenDecimals: number    // 6 for USDC
  confirmations: number    // blocks the backend waits for before crediting
  settleGraceMs: number    // pass to waitForPaymentCompletion
\}

type UsdcPaymentIntent = \{
  intentId: string             // bytes32 arg to payIntentWithToken()
  paymentMethod: 'usdc_eth'
  usdcAmount: string           // exact amount in base units (6 decimals), BigInt-safe string
  usdcAmountFormatted: string  // human-readable, e.g. "27.498"
  receiverAddress: string
  tokenAddress: string
  chainId: number
  tokenDecimals: number
  confirmations: number
  settleGraceMs: number
  expiresAt: string            // ISO 8601 timestamp when the price lock ends
  shannonsPerByte: string      // locked AI3 price per byte
  quotedAi3Shannons: string    // AI3 amount the USDC quote was made for
  usdRateAtCreation: string    // AI3/USD rate × 1e18, for reporting only
\}
\`\`\`


---

### File: sdk/auto-drive/create_api_key.mdx

# Creating Your Auto-Drive API Key

## Authentication Overview

All requests to the Auto-Drive APIs require authentication using an API key. The API key is a string that authenticates your requests to the Auto-Drive APIs.

## Step-by-Step Guide to Create an API Key

### 1. Access Auto-Drive Dashboard

1. Open [Auto Drive](https://ai3.storage/)
2. Sign in via Google, Discord, GitHub or Wallet

   ![Auto-Drive-1](/developers/Auto-Drive-1.png)

### 2. Navigate to Developer Section

1. Once you're logged in, click on the **developers** section in the left sidebar menu
2. In the developers section, click on **'Create API Key'**
3. Read the modal message and click on generate

### 3. Alternative Method - Via Profile

You can also create an API key through your profile:

1. Click on \`Profile\` in the dashboard
2. Create your API key from the profile section

   ![Auto-Drive-4](/developers/Auto-Drive-4.png)

## Understanding Your Dashboard

Once logged in, your Dashboard will show:

- Your upload limit (currently **20MB** per month on mainnet)   
- A list of **uploaded files** and their **CIDs**
- Options to **Download**, **Share** or **Remove** each file

![Auto-Drive-5](/developers/Auto-Drive-5.png)

> *Note:* Removing a file does not delete it from the DSN as it is permanent storage. It only removes the file from your Dashboard.

## Using Your API Key

Once you have your API key, you can use it to authenticate your requests:

\`\`\`typescript
import \{ createAutoDriveApi \} from '@autonomys/auto-drive'
import \{ NetworkId \} from '@autonomys/auto-utils'

const api = createAutoDriveApi(\{
  apiKey: 'your-api-key-here',
  network: NetworkId.MAINNET
\})
\`\`\`

## Network Selection

Auto Drive is available on:
- **Mainnet** (\`NetworkId.MAINNET\`) - Production environment

## Security Best Practices

- Keep your API key secure and never commit it to version control
- Use environment variables to store your API key
- Regenerate your API key if you suspect it has been compromised

## Next Steps

With your API key created, you can now:
- Install the Auto-Drive SDK
- Start uploading and downloading files
- Explore the full API reference
- Try the usage examples

---

### File: sdk/auto-drive/encryption.mdx

---
title: File Encryption Specification
---

# File Encryption Specification

Auto Drive supports optional **client-side encryption** — files are encrypted on your device before they are transmitted to the network. No one else, including storage nodes, can read your data without your password.

This page describes the encryption algorithm, key derivation process, and chunking architecture used when you supply a \`password\` to an upload function.

---

## Overview

| Property | Value |
|---|---|
| **Algorithm** | AES-256-GCM |
| **Key derivation** | PBKDF2 + SHA-256 |
| **KDF iterations** | 100,000 |
| **Salt length** | 32 bytes (randomly generated per file) |
| **Chunk size** | 1 MB |
| **IV per chunk** | 16 bytes (randomly generated per chunk) |

---

## Encryption Algorithm: AES-256-GCM

Auto Drive uses **AES-256-GCM** (Advanced Encryption Standard, 256-bit key, Galois/Counter Mode). This algorithm provides two guarantees simultaneously:

- **Confidentiality** — data is encrypted with a 256-bit key, making brute-force attacks computationally infeasible.
- **Integrity** — GCM mode appends an authentication tag to each encrypted chunk. If anyone modifies even a single bit of the ciphertext, decryption fails immediately with a detectable error.

Modern processors include hardware acceleration for AES operations, so encryption and decryption add minimal overhead for most workloads.

---

## Key Derivation: PBKDF2

Passwords are not used directly as encryption keys. Instead, Auto Drive converts your password into a cryptographic key using **PBKDF2** (Password-Based Key Derivation Function 2):

1. A **32-byte random salt** is generated using a cryptographically secure random number generator. This salt is unique per file and is stored alongside the encrypted data (it does not need to be secret).
2. The password and salt are combined and processed through **SHA-256**, repeated **100,000 times**.
3. The output is a 256-bit key used for all chunks in the file.

The high iteration count makes dictionary and brute-force attacks against the password computationally expensive, even if an attacker retrieves the encrypted file from the network.

\`\`\`
password + random_salt
        │
        ▼
   PBKDF2-SHA256
   (100,000 iterations)
        │
        ▼
  256-bit encryption key
\`\`\`

---

## File Chunking

Large files are split into **1 MB chunks** before encryption. Each chunk is processed independently:

1. A unique **16-byte initialization vector (IV)** is generated per chunk via a cryptographically secure random source.
2. The chunk is encrypted with AES-256-GCM using the derived key and the chunk-specific IV.
3. GCM produces the encrypted chunk data plus an **authentication tag**.

Because each chunk has its own IV, identical chunks in the same file produce different ciphertext — preventing pattern analysis.

\`\`\`
File
 │
 ├── Chunk 1 ── IV₁ ── AES-256-GCM ──► [ciphertext₁ + auth_tag₁]
 ├── Chunk 2 ── IV₂ ── AES-256-GCM ──► [ciphertext₂ + auth_tag₂]
 └── Chunk N ── IVₙ ── AES-256-GCM ──► [ciphertextₙ + auth_tagₙ]
\`\`\`

The 1 MB chunk size balances memory efficiency with processing speed, and enables streaming uploads and downloads without loading the entire file into memory.

---

## Network Privacy

Because encryption happens entirely on the client before any data leaves your device:

- **Content delivery nodes** see only ciphertext.
- **Farmers** in the distributed hash table layer store only encrypted segments.
- **Archival storage participants** hold only encrypted data.

No single point in the network ever holds the complete file in unencrypted form. This privacy guarantee persists as the network evolves, independent of individual node operators.

---

## Performance Characteristics

- **Key derivation** (PBKDF2, 100,000 iterations) happens once per file. This is intentionally slow to resist password attacks, but adds a fixed one-time cost regardless of file size.
- **Per-chunk encryption** runs with hardware AES acceleration on modern CPUs and is effectively negligible for typical upload speeds.
- **Streaming** — chunked processing means Auto Drive never needs to hold the entire file in memory, making it practical for very large files.

---

## Using Encryption

Pass a \`password\` option to any upload function in the \`@autonomys/auto-drive\` SDK:

\`\`\`typescript
import \{ createAutoDriveApi \} from '@autonomys/auto-drive'
import \{ NetworkId \} from '@autonomys/auto-utils'

const api = createAutoDriveApi(\{ apiKey: 'your-api-key', network: NetworkId.MAINNET \})

// Upload with encryption
const cid = await api.uploadFileFromInput(file, \{
  password: 'your-strong-password',
\})

// Download and decrypt
const stream = await api.downloadFile(cid, \{ password: 'your-strong-password' \})
\`\`\`

> **Important:** Your password is never transmitted to the network. If you lose it, the encrypted file cannot be recovered — there is no password reset mechanism.

---

## Further Reading

- [Auto Drive Overview](/auto_drive)
- [Auto Drive SDK — Usage Examples](/sdk/auto-drive/usage_examples)
- [Auto Drive SDK — Available Functions](/sdk/auto-drive/available_functions)


---

### File: sdk/auto-drive/gateway.mdx

# Auto Drive Gateway

## What is the Auto Drive Gateway?

Auto Gateway is a unified gateway solution designed for seamlessly accessing files or folders permanently stored on the Autonomys Mainnet through a single, streamlined interface. The gateway is available [here](https://gateway.autonomys.xyz/).

![Auto-Gateway-1](/developers/Auto-Gateway-1.png)

## How Gateways Work

In decentralized storage systems, files are identified by their Content Identifier (CID) rather than traditional file paths. A gateway acts as a bridge between the decentralized network and standard web protocols, allowing you to access stored content using familiar HTTP requests.

Think of it as a web interface that translates CIDs into downloadable files - similar to how IPFS gateways work, but specifically designed for the Autonomys network.

## When to Use Auto Drive Gateway

### Direct File Access
- **Public file sharing**: Share files with others who don't have the Auto Drive SDK
- **Web integration**: Embed files directly in websites using standard HTML tags
- **Browser downloads**: Allow users to download files directly through their browser
- **CDN-like functionality**: Serve static assets like images, documents, or media files

### Development & Testing
- **Quick verification**: Quickly check if your uploads were successful
- **Debugging**: Verify file integrity without writing code
- **Prototyping**: Access files during development without implementing full SDK integration

### Integration Scenarios
- **Third-party applications**: Enable other services to access your stored files
- **API responses**: Return direct download links in your API responses
- **Mobile apps**: Simple file access without complex SDK integration

## Gateway Endpoints

### Retrieve File by CID
\`\`\`
GET /file/:cid
\`\`\`
Retrieves a file based on its Content Identifier (CID).

**Responses:**
- \`200 OK\`: Successfully retrieves and serves the requested file
- \`302 Redirect\`: Redirects to \`/folder/:cid\` if the CID corresponds to a folder
- \`404 Not Found\`: If no file is found for the provided CID

### Retrieve Folder by CID
\`\`\`
GET /folder/:cid
\`\`\`
Retrieves a folder based on its Content Identifier (CID).

**Responses:**
- \`200 OK\`: Successfully retrieves and serves the requested folder
- \`302 Redirect\`: Redirects to \`/file/:cid\` if the CID corresponds to a file  
- \`404 Not Found\`: If no folder is found for the provided CID

## Usage Examples

### Direct Browser Access
\`\`\`
https://gateway.autonomys.xyz/file/your-cid-here
\`\`\`

### HTML Integration
\`\`\`html
<!-- Display an image -->
<img src="https://gateway.autonomys.xyz/file/your-image-cid" alt="My Image">

<!-- Download link -->
<a href="https://gateway.autonomys.xyz/file/your-document-cid" download>Download Document</a>
\`\`\`

### API Response
\`\`\`javascript
const response = \{
  filename: "document.pdf",
  downloadUrl: \`https://gateway.autonomys.xyz/file/\$\{fileCid\}\`,
  size: 1024000
\}
\`\`\`

## Finding Your CIDs

To use the gateway, you'll need the CID of your uploaded file or folder. You can find CIDs:

1. In your [Auto Drive Dashboard](https://ai3.storage/) after uploading files
2. From the return value of SDK upload functions
3. In your application logs where upload responses are recorded

Simply enter your CID in the gateway interface or construct the URL directly for programmatic access.

---

### File: sdk/auto-drive/overview_setup.mdx

# Auto-Drive Overview & Setup

## Introduction

The \`@autonomys/auto-drive\` package provides a set of tools to interact with the Autonomys Auto-Drive API.

## Features

- **Autonomys DSN**: Permanently store files on the Autonomys' DSN (Decentralized Store Network).
- **CID Management**: Just like with IPFS, each upload gets its own CID (Content Identifier). 
- **TypeScript Support**: Fully typed for an enhanced developer experience.

## Authentication

All requests to the Auto-Drive APIs require authentication using an API key. 

> **Need an API key?** See our [API Key Setup Guide](/sdk/auto-drive/create_api_key) for detailed instructions on creating your API key.

## Auto Drive Dashboard

The Auto Drive dashboard provides a web interface for managing your files and account:

- View your upload and download limits
- Browse and manage your uploaded files
- Share files with others
- Create and manage API keys

Access the dashboard at [Auto Drive](https://ai3.storage/) and sign in with Google, Discord, or GitHub.

![Auto-Drive-3](/developers/Auto-Drive-3.png)

### Sharing files

You can share files directly from the dashboard by clicking the \`Share\` button next to any file. You can share using a direct link or provide a user's public ID to share all their files.

![Auto-Drive-5](/developers/Auto-Drive-5.png)

## Installation

Install the package via \`npm\` or \`yarn\`:

\`\`\`bash
# Using npm
npm install @autonomys/auto-drive
npm install @autonomys/auto-utils

# Using yarn
yarn add @autonomys/auto-drive
yarn add @autonomys/auto-utils
\`\`\`

## Importing

Import the \`auto-drive\` functions you need into your project:

\`\`\`typescript
// Import specific functions
import \{ fs,createAutoDriveApi \} from '@autonomys/auto-drive';
import \{ NetworkId \} from '@autonomys/auto-utils'

// Or import everything
import * as drive from '@autonomys/auto-drive';
import \{ NetworkId \} from '@autonomys/auto-utils'
\`\`\`

## Network Configuration

[Auto Drive](https://ai3.storage) is available on Mainnet. To connect to it, you need to configure the network using \`auto-utils\` package:

\`\`\`ts
import \{ NetworkId \} from '@autonomys/auto-utils'

const api = createAutoDriveApi(\{
  apiKey: 'your-api-key',
  network: NetworkId.MAINNET
\})
\`\`\`

---

### File: sdk/auto-drive/pay_with_ai3.mdx

---
title: Pay with AI3 & USDC — Developer Integration
---

# Pay with AI3 & USDC — Developer Integration

This page covers how to integrate permissionless Auto Drive credit purchasing into your own application using the credits API and one of two payment methods:

| Payment method | Asset | Network | Contract |
|---|---|---|---|
| **AI3** (\`ai3_native\`) | Native AI3 | Autonomys Auto-EVM (Chain ID \`870\`) | \`AutoDriveCreditsReceiver\` |
| **USDC** (\`usdc_eth\`) | USDC (ERC-20) | Ethereum mainnet (Chain ID \`1\`) | \`AutoDriveUSDCReceiver\` |

Both methods use the same **payment intent** model and the same credits, limits, and expiry. The AI3 flow is described first; the differences for USDC are covered in [Pay with USDC](#pay-with-usdc).

For the end-user purchase walkthroughs, see the [Pay with AI3 guide](/auto_drive/pay_with_ai3) and the [Pay with USDC guide](/auto_drive/pay_with_usdc).

For a complete working example of Pay with AI3 in a real application, see [Eulonomys](/application_examples/eulonomys) — a reference app with full source code showing the payment intent flow, on-chain contract calls, and Auto Drive uploads end-to-end.

---

## How It Works

The payment system is built around a **payment intent** model. An AI3 purchase follows these steps:

1. *(Optional)* Your app fetches the current **storage price** (\`GET /intents/price\`) to show an estimate. The price reflects the live protocol-level DSN storage cost, read from the Autonomys consensus chain, plus a service fee.
2. Your app asks the Auto Drive backend to create a **payment intent** (\`POST /intents\`) — a server-side record that locks the price per byte (\`shannonsPerByte\`) and binds a \`bytes32\` intent ID to the authenticated account for **10 minutes**.
3. Your app calls \`payIntent(intentId)\` on the \`AutoDriveCreditsReceiver\` contract on Auto-EVM, sending \`shannonsPerByte × bytes\` AI3 as \`msg.value\`.
4. Your app submits the transaction hash to the watch endpoint (\`POST /intents/:id/watch\`); the backend waits for **6 block confirmations** and then grants the credits.
5. Your app polls the intent (\`GET /intents/:id\`) until it reaches a terminal status.

Credits are granted as \`paymentAmount ÷ shannonsPerByte\` bytes (rounded down). They are available immediately after confirmation and can be used via the dashboard, the Auto SDK, or the REST API.

---

## Smart Contracts

| Contract | Payment method | Network | Chain ID | Address |
|---|---|---|---|---|
| \`AutoDriveCreditsReceiver\` | AI3 | Autonomys Auto-EVM | \`870\` | [\`0xBa5bed8325183c0807EcBC80C82D40Dc7Ac5cbf7\`](https://explorer.auto-evm.mainnet.autonomys.xyz/address/0xBa5bed8325183c0807EcBC80C82D40Dc7Ac5cbf7) |
| \`AutoDriveUSDCReceiver\` | USDC | Ethereum mainnet | \`1\` | [\`0x9c508Fa594f52032D574137585DD2F8A48F92261\`](https://etherscan.io/address/0x9c508Fa594f52032D574137585DD2F8A48F92261) |

The AI3 contract is described below. For the USDC contract, see [Smart Contract (USDC)](#smart-contract-usdc).

### \`AutoDriveCreditsReceiver\` (AI3)

| Field | Value |
|---|---|
| **Network** | Autonomys Auto-EVM |
| **Chain ID** | \`870\` |
| **Address** | \`0xBa5bed8325183c0807EcBC80C82D40Dc7Ac5cbf7\` |

View on Blockscout: [AutoDriveCreditsReceiver](https://explorer.auto-evm.mainnet.autonomys.xyz/address/0xBa5bed8325183c0807EcBC80C82D40Dc7Ac5cbf7)

The chain ID, address, and \`payIntent\` ABI are also served by \`GET /intents/contract\`.

#### \`payIntent\`

\`\`\`solidity
function payIntent(bytes32 intentId) public payable whenNotPaused;
\`\`\`

\`intentId\` is the \`id\` returned by \`POST /intents\`. Send \`shannonsPerByte × bytes\` as \`msg.value\`. The contract accepts any non-zero amount and does not check it against the quote: the backend grants credits in proportion to what was actually paid, so paying less buys less storage.

The call reverts with \`InvalidAmount(0)\` when \`msg.value\` is zero, and with \`EnforcedPause()\` when the protocol team has paused payments in the event of a critical issue.

#### Event

\`\`\`solidity
event IntentPaymentReceived(bytes32 indexed intentId, uint256 paymentAmount);
\`\`\`

Emitted on successful payment. The backend reads this event from the transaction receipt to confirm the payment.

---

## Payment Intent State Machine

\`\`\`
PENDING ──► CONFIRMED ──► COMPLETED
   │            │
   │            ├──► OVER_CAP  (account's 100 GB purchased credit limit exceeded)
   │            │
   │            └──► FAILED    (payment could not be converted to credits, e.g. too small to buy one byte)
   │
   └──► EXPIRED   (no payment received before the price lock ended)
\`\`\`

The API returns statuses in lowercase (\`pending\`, \`confirmed\`, \`completed\`, \`expired\`, \`failed\`, \`over_cap\`). The SDK converts them to uppercase.

> Always create a fresh intent immediately before paying. Prices reflect live protocol storage cost and can change between requests.

---

## API Reference

Base URL (mainnet): \`https://mainnet.auto-drive.autonomys.xyz/api\`

**Authentication:** endpoints marked as authenticated need both headers below. The API key must belong to a Google-authenticated account.

\`\`\`http
Authorization: Bearer <your-api-key>
X-Auth-Provider: apikey
\`\`\`

### Get the Storage Price

\`\`\`http
GET /intents/price
\`\`\`

Returns the current price. No authentication required.

**Example response:**

\`\`\`json
\{
  "price": 4273583470658,
  "pricePerGB": 4588.73,
  "usd": \{
    "usdPerAi3": 0.00139,
    "pricePerGBUsd": 6.39,
    "asOf": "2026-10-07T18:08:26.587Z",
    "lastTradeAt": "2026-10-06T01:38:35.000Z",
    "stale": false
  \},
  "usdUnavailableReason": null
\}
\`\`\`

| Field | Description |
|---|---|
| \`price\` | Price per byte, in Shannons (1 AI3 = 10^18 Shannons) |
| \`pricePerGB\` | Price per GiB (1,073,741,824 bytes), in AI3 |
| \`usd\` | USD estimate, or \`null\` when no AI3/USD rate is available. For display only — never use it to settle a payment |
| \`usdUnavailableReason\` | Why \`usd\` is \`null\`; \`null\` when \`usd\` is present |

---

### Get the Contract Info

\`\`\`http
GET /intents/contract
\`\`\`

Returns the Auto-EVM chain ID, the \`AutoDriveCreditsReceiver\` address, and the minimal \`payIntent\` ABI. No authentication required.

**Example response:**

\`\`\`json
\{
  "chainId": 870,
  "contractAddress": "0xBa5bed8325183c0807EcBC80C82D40Dc7Ac5cbf7",
  "payIntentAbi": [
    \{
      "inputs": [\{ "name": "intentId", "type": "bytes32" \}],
      "name": "payIntent",
      "outputs": [],
      "stateMutability": "payable",
      "type": "function"
    \}
  ]
\}
\`\`\`

---

### Create a Payment Intent

\`\`\`http
POST /intents
\`\`\`

Locks the current price per byte for the authenticated account for 10 minutes and returns the intent. **Authenticated.**

**Request body (optional for AI3):**

\`\`\`json
\{
  "requestedBytes": "10737418240"
\}
\`\`\`

| Field | Description |
|---|---|
| \`requestedBytes\` | Optional for AI3. Size of the purchase as a decimal string. When sent, Auto Drive checks it against the per-account cap and rejects an over-cap purchase before anything is paid |
| \`paymentMethod\` | \`ai3_native\` (default) or \`usdc_eth\`. See [Pay with USDC](#pay-with-usdc) |

**Response:**

\`\`\`json
\{
  "id": "0xabc123...",
  "userPublicId": "user-public-id",
  "status": "pending",
  "paymentMethod": "ai3_native",
  "shannonsPerByte": "4273583470658",
  "expiresAt": "2026-10-07T12:10:00.000Z"
\}
\`\`\`

The response does not include a total amount. Compute it yourself: \`msg.value = shannonsPerByte × bytes\`. Pass \`id\` as the \`intentId\` argument to \`payIntent\`.

**Errors:**

| Status | Code | Meaning |
|---|---|---|
| \`400\` | — | \`requestedBytes\` is invalid or larger than the whole credit cap, or \`paymentMethod\` is not recognised |
| \`401\` | — | Missing or invalid credentials |
| \`403\` | \`GOOGLE_ACCOUNT_REQUIRED\` | The account is not Google-authenticated |
| \`403\` | \`CREDIT_CAP_EXCEEDED\` | The purchase would exceed the per-account cap (only when \`requestedBytes\` is sent) |
| \`404\` | — | Buying credits is not available to this account |
| \`503\` | — | Storage could not be priced — retry unchanged |

---

### Get an Intent

\`\`\`http
GET /intents/:id
\`\`\`

Returns the intent, including its \`status\`. **Authenticated.** Only the owner of the intent can read it (\`403\` otherwise). Returns \`410\` once the price lock has lapsed on an intent that has no recorded transaction hash; see [Polling after the Price Lock](#polling-after-the-price-lock).

---

### Confirm a Transaction

\`\`\`http
POST /intents/:id/watch
\`\`\`

Submits the on-chain transaction hash. **Authenticated.** The backend waits for 6 confirmations before crediting the account.

**Request body:**

\`\`\`json
\{
  "txHash": "0xdef456..."
\}
\`\`\`

\`txHash\` must be a \`0x\`-prefixed 32-byte hex hash. Returns \`204 No Content\` on success, \`400\` for a missing or malformed hash, and \`410\` if the intent has expired.

---

## Integration Patterns

### Pattern 1 — App-managed credits

Your application holds a funded Auto-EVM wallet and purchases credits on behalf of users. Useful for apps that abstract storage costs away entirely. The SDK makes the Auto Drive API calls; your wallet library sends the transaction.

\`\`\`typescript
import \{ createAutoDriveApi \} from '@autonomys/auto-drive'
import \{ NetworkId \} from '@autonomys/auto-utils'
import \{ ethers \} from 'ethers'

const api = createAutoDriveApi(\{
  apiKey: process.env.AUTO_DRIVE_API_KEY!,
  network: NetworkId.MAINNET,
\})

async function purchaseCredits(signer: ethers.Signer, sizeBytes: number) \{
  // 1. Create intent — price locked for 10 minutes.
  //    The SDK computes ai3AmountWei = shannonsPerByte × sizeBytes for you.
  const intent = await api.createPaymentIntent(sizeBytes, \{ checkCreditCap: true \})

  // 2. Call payIntent on Auto-EVM, sending the computed amount
  const \{ payIntentAbi \} = await api.getPaymentContractInfo()
  const contract = new ethers.Contract(intent.contractAddress, payIntentAbi as ethers.InterfaceAbi, signer)
  const tx = await contract.payIntent(intent.intentId, \{ value: BigInt(intent.ai3AmountWei) \})
  await tx.wait()

  // 3. Submit tx hash — backend waits for 6 confirmations, then grants credits
  await api.watchPaymentTransaction(intent.intentId, tx.hash)

  // 4. Wait for the intent to reach a terminal status
  const status = await api.waitForPaymentCompletion(intent.intentId)
  return \{ txHash: tx.hash, status \} // 'COMPLETED' | 'EXPIRED' | 'FAILED' | 'OVER_CAP'
\}
\`\`\`

If you call the REST API directly instead of using the SDK, send the [authentication headers](#api-reference) on \`POST /intents\`, \`GET /intents/:id\`, and \`POST /intents/:id/watch\`.

### Pattern 2 — User-managed credits

Direct users to the [Auto Drive dashboard](https://ai3.storage/) to purchase credits themselves using the [Pay with AI3 guide](/auto_drive/pay_with_ai3) or the [Pay with USDC guide](/auto_drive/pay_with_usdc). Your application uses the AutoSDK with the user's API key — no on-chain interaction required in your code.

This is the lower-complexity option and is suitable for most applications.

### Checking the Credit Cap Before Payment (SDK)

By default, \`api.createPaymentIntent(sizeBytes)\` does not send the purchase size to Auto Drive. Pass \`\{ checkCreditCap: true \}\` to send it as \`requestedBytes\`. Auto Drive then rejects a purchase that would exceed the per-account cap **before** anything is paid, instead of the intent ending as \`OVER_CAP\` after an on-chain payment.

\`\`\`typescript
import \{ PaymentApiError \} from '@autonomys/auto-drive'

try \{
  const intent = await api.createPaymentIntent(sizeBytes, \{ checkCreditCap: true \})
\} catch (error) \{
  if (
    error instanceof PaymentApiError &&
    (error.code === 'CREDIT_CAP_EXCEEDED' || error.status === 400)
  ) \{
    // Nothing was paid. Try a smaller size.
  \}
\}
\`\`\`

A purchase that does not fit in the remaining headroom fails with \`CREDIT_CAP_EXCEEDED\` (403). A single purchase larger than the whole cap fails with HTTP 400 and no code. See [Handling Errors](#handling-errors) for all \`PaymentApiError\` codes.

---

## Pay with USDC

Credits can also be purchased with **USDC on Ethereum mainnet**. The intent model is the same as for AI3, with three differences:

- The intent is created with \`paymentMethod: "usdc_eth"\` and an explicit \`requestedBytes\`. The backend returns the exact USDC amount to pay as \`quotedTokenAmount\`, locked for 10 minutes.
- USDC is an ERC-20 token, so the payer first **approves** the \`AutoDriveUSDCReceiver\` contract and then calls \`payIntentWithToken(intentId, amount)\`. There is no \`msg.value\`.
- The payment is made on **Ethereum mainnet**, not on Auto-EVM. The chain, receiver address, and token address are served by the API at \`GET /payments/usdc/target\` — always read them from there (the SDK does this for you) rather than hardcoding them.

### How It Works

With the SDK, steps 1 and 2 are a single call to \`api.createUsdcPaymentIntent(sizeBytes)\`.

1. Your app fetches the **payment target** (\`GET /payments/usdc/target\`): chain ID, receiver address, USDC token address, token decimals, and the number of confirmations the backend waits for.
2. Your app creates a **USDC payment intent** (\`POST /intents\` with \`paymentMethod: "usdc_eth"\` and \`requestedBytes\`). The backend converts the AI3 storage cost to USDC at the current AI3/USD rate, adds a small quote margin, and returns \`quotedTokenAmount\` (USDC base units, 6 decimals).
3. The payer calls \`approve(receiverAddress, quotedTokenAmount)\` on the USDC token contract, then \`payIntentWithToken(intentId, quotedTokenAmount)\` on \`AutoDriveUSDCReceiver\`.
4. Your app submits the payment transaction hash to the watch endpoint; the backend waits for the required Ethereum confirmations (currently **6**) and then grants the credits.

Credits are granted in proportion to the USDC actually received. Paying exactly \`quotedTokenAmount\` grants exactly \`requestedBytes\`.

### Smart Contract (USDC)

| Field | Value |
|---|---|
| **Contract** | \`AutoDriveUSDCReceiver\` |
| **Network** | Ethereum mainnet |
| **Chain ID** | \`1\` |
| **Address** | \`0x9c508Fa594f52032D574137585DD2F8A48F92261\` |
| **Accepted token** | USDC — \`0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48\` |

View on Etherscan: [AutoDriveUSDCReceiver](https://etherscan.io/address/0x9c508Fa594f52032D574137585DD2F8A48F92261)

The same values are served by \`GET /payments/usdc/target\`. In code, read them from there (the SDK does this for you) rather than hardcoding them.

#### \`payIntentWithToken\`

\`\`\`solidity
function payIntentWithToken(bytes32 intentId, uint256 amount) external nonReentrant whenNotPaused;
\`\`\`

\`intentId\` is the \`id\` returned by \`POST /intents\`. \`amount\` is the USDC amount in base units (USDC has 6 decimals) — pass \`quotedTokenAmount\` exactly. The caller must have approved the receiver for at least \`amount\` beforehand; the contract pulls the tokens with \`transferFrom\`.

The \`whenNotPaused\` modifier allows the protocol team to pause payments in the event of a critical issue.

#### Event

\`\`\`solidity
event IntentTokenPaymentReceived(
    bytes32 indexed intentId,
    address token,
    uint256 amount,
    address indexed payer
);
\`\`\`

Emitted on successful payment. \`amount\` is the amount actually received by the contract, and \`payer\` is the account whose USDC allowance funded the payment.

#### On-chain errors

| Error | Description |
|---|---|
| \`InvalidAmount(uint256)\` | \`amount\` is zero, or nothing was received |
| \`EnforcedPause()\` | Contract is paused by the owner |
| ERC-20 allowance / balance errors | The payer did not approve enough USDC, or does not hold enough USDC |

### API Reference (USDC)

#### Get the Payment Target

\`\`\`http
GET /payments/usdc/target
\`\`\`

Returns where to send a USDC payment. **Authenticated** (see [API Reference](#api-reference) for the headers). Returns \`403 USDC_PAYMENTS_DISABLED\` when USDC is not available on this deployment.

**Example response:**

\`\`\`json
\{
  "chainId": 1,
  "receiverAddress": "0x9c508Fa594f52032D574137585DD2F8A48F92261",
  "tokenAddress": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
  "tokenDecimals": 6,
  "confirmations": 6,
  "settleGraceMs": 120000
\}
\`\`\`

---

#### Create a USDC Payment Intent

\`\`\`http
POST /intents
\`\`\`

**Authenticated** (see [API Reference](#api-reference) for the headers).

**Request body:**

\`\`\`json
\{
  "paymentMethod": "usdc_eth",
  "requestedBytes": "10737418240"
\}
\`\`\`

\`requestedBytes\` is **required** for USDC intents (decimal string). It is also checked against the 100 GB per-account cap before the intent is created.

**Response:**

\`\`\`json
\{
  "id": "0xabc123...",
  "userPublicId": "user-public-id",
  "status": "pending",
  "paymentMethod": "usdc_eth",
  "shannonsPerByte": "4273583470658",
  "quotedTokenAmount": "67071093",
  "quotedAi3Shannons": "45887253108005714001920",
  "usdRateAtCreation": "1392047389045704",
  "expiresAt": "2026-10-07T12:10:00.000Z"
\}
\`\`\`

Pass \`id\` as the \`intentId\` argument and \`quotedTokenAmount\` as the \`amount\` argument of \`payIntentWithToken\`. In this example, \`67071093\` base units = **67.071093 USDC** for 10 GiB (about 45,887 AI3 at 0.00139 USD per AI3, plus the quote margin). \`usdRateAtCreation\` is the raw AI3/USD rate scaled by 10^18, without the margin, and is for reporting only.

**USDC-specific errors:**

| Status | Code | Meaning |
|---|---|---|
| \`400\` | — | \`requestedBytes\` missing or invalid (including larger than the whole credit cap), or \`paymentMethod\` not recognised |
| \`403\` | \`USDC_PAYMENTS_DISABLED\` | USDC is not available to this account or deployment — pay with AI3 |
| \`403\` | \`CREDIT_CAP_EXCEEDED\` | The purchase would exceed the 100 GB per-account cap — buy less |
| \`503\` | \`USDC_PAYMENTS_UNAVAILABLE\` | USDC is closed for now — pay with AI3, or retry later |
| \`503\` | \`PRICE_ORACLE_UNAVAILABLE\` / \`PRICE_UNSTABLE\` | No reliable AI3/USD rate right now — retry unchanged |

---

#### Confirm a Transaction

Same endpoint as for AI3: \`POST /intents/:id/watch\` with the \`payIntentWithToken\` transaction hash (not the approval hash). If the price lock has already lapsed, this call can return \`410\`. The payment can still be credited from the on-chain event, so continue to wait for completion.

### SDK Functions (USDC)

\`@autonomys/auto-drive\` wraps the USDC endpoints. As with AI3, the SDK does not sign anything: it returns the quote and where to pay, plus typed ABIs, and your wallet library sends the transactions.

| Function / export | Description |
|---|---|
| \`api.getUsdcPaymentTarget()\` | Returns the \`UsdcPaymentTarget\` (chain ID, receiver, token, decimals, confirmations, \`settleGraceMs\`) |
| \`api.createUsdcPaymentIntent(sizeBytes)\` | Creates a price-locked USDC intent for \`sizeBytes\` (\`number\` or \`bigint\`). Fetches the target for you and returns a \`UsdcPaymentIntent\` |
| \`api.watchPaymentTransaction(intentId, txHash)\` | Same as for AI3 — pass the \`payIntentWithToken\` hash |
| \`api.waitForPaymentCompletion(intentId, \{ settleGraceMs \})\` | Same as for AI3 — pass \`intent.settleGraceMs\` so a \`410\` after the lock lapses does not end the wait early |
| \`erc20ApprovalAbi\` | Minimal ERC-20 ABI: \`approve\`, \`allowance\`, \`balanceOf\` |
| \`usdcReceiverAbi\` | Minimal ABI for \`payIntentWithToken(bytes32, uint256)\` |
| \`PaymentApiError\` | Error thrown on non-OK payment responses, with \`status\` and \`code\` |

See [Available Functions](/sdk/auto-drive/available_functions#pay-with-usdc--payment-intents) for the full type definitions.

### Integration Example (USDC)

The example below uses an Auto Drive API key and a funded Ethereum wallet (USDC for the payment, ETH for gas). All Auto Drive calls need the API key, so run this on your server.

\`\`\`typescript
import \{
  createAutoDriveApi,
  erc20ApprovalAbi,
  PaymentApiError,
  usdcReceiverAbi,
\} from '@autonomys/auto-drive'
import \{ NetworkId \} from '@autonomys/auto-utils'
import \{ createPublicClient, createWalletClient, http, type Hex \} from 'viem'
import \{ privateKeyToAccount \} from 'viem/accounts'
import \{ mainnet \} from 'viem/chains'

async function purchaseCreditsWithUsdc(sizeBytes: bigint) \{
  const api = createAutoDriveApi(\{
    apiKey: process.env.AUTO_DRIVE_API_KEY!,
    network: NetworkId.MAINNET,
  \})

  // 1. Lock a USDC price. The SDK also fetches where to pay — never hardcode it.
  const intent = await api.createUsdcPaymentIntent(sizeBytes)
  // intent.usdcAmount          — exact amount in base units (6 decimals)
  // intent.usdcAmountFormatted — human-readable amount, e.g. "27.498"
  // intent.chainId, intent.tokenAddress, intent.receiverAddress — where to pay
  if (intent.chainId !== mainnet.id) throw new Error(\`Unexpected USDC chain \$\{intent.chainId\}\`)

  const account = privateKeyToAccount(process.env.PAYER_PRIVATE_KEY as Hex)
  const transport = http(process.env.ETH_RPC_URL)
  const publicClient = createPublicClient(\{ chain: mainnet, transport \})
  const walletClient = createWalletClient(\{ account, chain: mainnet, transport \})

  const amount = BigInt(intent.usdcAmount)
  const token = intent.tokenAddress as Hex
  const receiver = intent.receiverAddress as Hex

  // 2. Approve the receiver to pull the USDC (skip if the allowance is enough)
  const allowance = await publicClient.readContract(\{
    address: token,
    abi: erc20ApprovalAbi,
    functionName: 'allowance',
    args: [account.address, receiver],
  \})
  if (allowance < amount) \{
    const approveHash = await walletClient.writeContract(\{
      address: token,
      abi: erc20ApprovalAbi,
      functionName: 'approve',
      args: [receiver, amount],
    \})
    await publicClient.waitForTransactionReceipt(\{ hash: approveHash \})
  \}

  // 3. Pay the intent. No value: the receiver pulls the approved USDC.
  //    Wait for the receipt first, so block time does not use up the 410 grace.
  const txHash = await walletClient.writeContract(\{
    address: receiver,
    abi: usdcReceiverAbi,
    functionName: 'payIntentWithToken',
    args: [intent.intentId as Hex, amount],
  \})
  const receipt = await publicClient.waitForTransactionReceipt(\{ hash: txHash \})
  if (receipt.status !== 'success') throw new Error(\`USDC payment reverted: \$\{txHash\}\`)

  // 4. Tell Auto Drive about the payment transaction (not the approval)
  try \{
    await api.watchPaymentTransaction(intent.intentId, txHash)
  \} catch (error) \{
    // 410: the price lock has lapsed. The payment can still settle, so continue.
    if (!(error instanceof PaymentApiError && error.status === 410)) throw error
  \}

  // 5. Wait for credits. settleGraceMs keeps polling through a 410 after the lock lapses.
  const status = await api.waitForPaymentCompletion(intent.intentId, \{
    settleGraceMs: intent.settleGraceMs,
  \})

  return \{ txHash, status \} // 'COMPLETED' | 'EXPIRED' | 'FAILED' | 'OVER_CAP'
\}
\`\`\`

### Handling Errors

When Auto Drive refuses a payment request, the SDK throws a \`PaymentApiError\` with the HTTP \`status\` and, for coded errors, a machine-readable \`code\`. Branch on \`code\`, not on \`message\`.

| \`code\` | Status | What to do |
|---|---|---|
| \`PRICE_ORACLE_UNAVAILABLE\` | 503 | Retry the same request later |
| \`PRICE_UNSTABLE\` | 503 | Retry the same request later |
| \`USDC_PAYMENTS_UNAVAILABLE\` | 503 | USDC is closed for now — pay with AI3, or retry later |
| \`USDC_PAYMENTS_DISABLED\` | 403 | USDC is not available to you — pay with AI3 |
| \`CREDIT_CAP_EXCEEDED\` | 403 | The purchase would exceed your credit cap — buy less |
| \`GOOGLE_ACCOUNT_REQUIRED\` | 403 | Use an API key from a Google-registered account |

Some failures have no \`code\`, so check \`status\`:

- **400** — the request is invalid, for example the size is larger than the whole credit cap.
- **404 on \`/intents\`** — the account cannot buy credits. Accounts that are not Google-registered usually get this rather than \`GOOGLE_ACCOUNT_REQUIRED\`.
- **410** — the price lock has lapsed. See [Polling after the price lock](#polling-after-the-price-lock).

\`\`\`typescript
import \{ PaymentApiError \} from '@autonomys/auto-drive'

try \{
  const intent = await api.createUsdcPaymentIntent(sizeBytes)
  // ...pay as above
\} catch (error) \{
  if (!(error instanceof PaymentApiError)) throw error
  switch (error.code) \{
    case 'PRICE_ORACLE_UNAVAILABLE':
    case 'PRICE_UNSTABLE':
      // retry later
      break
    case 'USDC_PAYMENTS_DISABLED':
    case 'USDC_PAYMENTS_UNAVAILABLE':
      // fall back to api.createPaymentIntent (AI3)
      break
    default:
      throw error
  \}
\}
\`\`\`

### Polling after the Price Lock

\`GET /intents/:id\` answers \`410\` once the price lock has lapsed on an intent that has no recorded transaction hash — for example when \`watchPaymentTransaction\` itself got a \`410\`. With a recorded hash, the \`410\` starts only when Auto Drive stops accepting payments for the intent, currently **20 minutes after \`expiresAt\`**. A payment sent near the end of the lock can still be credited after the first \`410\`.

With \`settleGraceMs\` set, \`waitForPaymentCompletion\` keeps polling through \`410\` for that long and only then returns \`'EXPIRED'\`. A successful read in between resets the clock. Without it, a \`410\` throws a \`PaymentApiError\`, as in earlier SDK versions. This option works for AI3 intents too.

- \`'EXPIRED'\` from this path means the SDK stopped waiting. It does not prove the payment is lost — check the account's credits before telling a user the payment failed.
- The grace is measured from the first \`410\` the SDK sees, so wait for the payment receipt before calling \`waitForPaymentCompletion\`.
- Keep \`timeoutMs\` (default 5 minutes) larger than the time left on the lock plus \`settleGraceMs\`, or the call can throw a timeout error before it returns \`'EXPIRED'\`.

### Things to Know

- **Always pay \`usdcAmount\` (\`quotedTokenAmount\`) exactly.** Paying a different amount is accepted, but credits are granted in proportion to what was received.
- **Pay before the intent expires.** Auto Drive still credits a payment for a short while after the 10-minute lock (currently up to 20 minutes after \`expiresAt\`), but do not rely on it. A payment that arrives later is not credited automatically; it is recorded and recoverable through support.
- **Do not send AI3 to a USDC intent (or USDC to an AI3 intent).** Payments in the wrong asset are not credited automatically.
- **USDC can be temporarily closed.** New USDC intents may be refused (\`USDC_PAYMENTS_UNAVAILABLE\`, \`PRICE_ORACLE_UNAVAILABLE\`, \`PRICE_UNSTABLE\`) for short periods. An intent that was already quoted stays payable until it expires. Fall back to AI3 if needed.

---

## Using Credits After Purchase

Once purchased, credits are consumed automatically when uploading via the \`@autonomys/auto-drive\` SDK. No additional configuration is needed.

\`\`\`typescript
import \{ createAutoDriveApi \} from '@autonomys/auto-drive'
import \{ NetworkId \} from '@autonomys/auto-utils'

const api = createAutoDriveApi(\{ apiKey: 'your-api-key', network: NetworkId.MAINNET \})

// Credits are deducted automatically on upload
const cid = await api.uploadFileFromInput(file, \{
  password: 'optional-encryption-password', // enable AES-256-GCM encryption
\})

console.log('Uploaded CID:', cid)
\`\`\`

Credits are consumed in **FIFO expiry order** — the soonest-to-expire credits are spent first.

---

## Limits and Expiry

| Parameter | Value |
|---|---|
| **Maximum purchased credits** | 100 GB per account |
| **Credit expiry** | 90 days from grant date |
| **Intent timeout** | 10 minutes |
| **Confirmation blocks** | 6 (Auto-EVM for AI3, Ethereum for USDC) |

The 100 GB cap applies to AI3 and USDC purchases combined.

---

## Further Reading

- [Pay with AI3 — User Guide](/auto_drive/pay_with_ai3)
- [Pay with USDC — User Guide](/auto_drive/pay_with_usdc)
- [Eulonomys — Reference App Using Pay with AI3](/application_examples/eulonomys)
- [Auto Drive Overview & Setup](/sdk/auto-drive/overview_setup)
- [Available Functions](/sdk/auto-drive/available_functions)
- [Usage Examples](/sdk/auto-drive/usage_examples)


---

### File: sdk/auto-drive/s3_layer.mdx

# Auto Drive S3 Layer Guide

## Overview

**Auto Drive** provides an **S3-compatible API layer** that allows you to interact with **decentralized storage (DSN)** using standard **Amazon Web Services Simple Storage Service (AWS S3)** SDK commands. This bridges the gap between familiar cloud storage patterns and next-generation decentralized infrastructure, giving developers the best of both worlds: the **reliability and developer experience of S3 APIs** with the **permanence and censorship-resistance** of decentralized storage.

For those unfamiliar, [Amazon Web Services Simple Storage Service (AWS S3)](https://aws.amazon.com/s3/) is an industry-standard object storage service that powers much of the modern web's file storage needs. **Auto Drive** maintains compatibility with the most-used parts of S3's APIs while storing your data on a **decentralized network** instead of **centralized servers**.

> **Permanent and immutable by design.** Auto Drive storage is permanent. Objects on the Autonomys DSN cannot be modified, overwritten, or deleted. \`DeleteObject\` returns \`403 Forbidden\`. Re-uploading the same key creates a new object — the old data persists on the DSN. Plan your data model around this guarantee.

## How It Works

Auto Drive maps S3 (bucket, key) pairs to Content Identifiers (CIDs) and MD5 checksums. When you upload via the S3 API, the system:

1. Stores the file content on the decentralized network (DSN)
2. Computes the MD5 of the content and records the \`(bucket, key) → (cid, md5)\` mapping
3. Returns the **MD5 as the \`ETag\`** (standard S3 format) and exposes the **CID in the \`x-amz-meta-cid\` response header**
4. Enables cross-API access between the S3 API and the native Auto Drive API

## Key Features

### 1. Standard S3 SDK and CLI Compatibility

- Works with the official AWS S3 SDKs (\`@aws-sdk/client-s3\`, \`boto3\`), the **AWS CLI**, and S3-compatible tools like **[rclone](#rclone-integration)**
- Supported operations: \`ListBuckets\`, \`ListObjectsV2\`, \`PutObject\`, \`GetObject\`, \`HeadObject\`, multipart uploads (\`CreateMultipartUpload\`, \`UploadPart\`, \`CompleteMultipartUpload\`)
- No code changes required for existing S3 applications other than swapping the endpoint and credentials

### 2. Buckets

Buckets behave like standard S3 buckets. The **first path segment of the object key is the bucket name**, and the remainder is the key:

| S3 path | Bucket | Key |
| --- | --- | --- |
| \`my-archive/report.pdf\` | \`my-archive\` | \`report.pdf\` |
| \`my-archive/sub/file.txt\` | \`my-archive\` | \`sub/file.txt\` |
| \`test.txt\` (no slash) | \`default\` | \`test.txt\` |

Buckets are **created implicitly** on first write — there is no \`CreateBucket\` call. \`ListBuckets\` (\`GET /\`) returns every distinct bucket you have written to.

\`\`\`typescript
import \{ ListBucketsCommand \} from "@aws-sdk/client-s3";

const result = await s3Client.send(new ListBucketsCommand(\{\}));
console.log(result.Buckets); // [\{ Name: "my-archive", CreationDate: ... \}, ...]
\`\`\`

Single-segment keys uploaded before bucket support was introduced remain accessible under the \`default\` bucket.

### 3. ListObjectsV2 with Prefix, Delimiter, and Pagination

Auto Drive implements \`ListObjectsV2\` end-to-end, with the parameters most clients depend on:

- **Prefix filtering** — \`?prefix=subdir/\` returns only keys starting with \`subdir/\`
- **Delimiter folding** — \`?delimiter=/\` collapses keys into \`<CommonPrefixes>\` virtual directories
- **Pagination** — \`?max-keys=N\` plus \`?continuation-token=…\` for cursor-based paging
- **Object size** — \`<Size>\` is populated from indexed metadata
- **MD5 ETag in listings** — listing entries return the MD5 ETag, so checksum verification does not require an extra \`HeadObject\` per object

> Auto Drive implements **\`ListObjectsV2\` only**. The legacy \`ListObjects\` (V1) API is not implemented. rclone users must set \`list_version = 2\` in their remote config (see [rclone integration](#rclone-integration)).

\`\`\`typescript
import \{ ListObjectsV2Command \} from "@aws-sdk/client-s3";

const result = await s3Client.send(
  new ListObjectsV2Command(\{
    Bucket: "my-archive",
    Prefix: "logs/",
    Delimiter: "/",
    MaxKeys: 100,
  \})
);

console.log(result.Contents);        // objects directly under "logs/"
console.log(result.CommonPrefixes);  // virtual subdirectories like "logs/2026/"

if (result.IsTruncated) \{
  // Fetch the next page using result.NextContinuationToken
\}
\`\`\`

### 4. MD5 ETags + CID via \`x-amz-meta-cid\`

\`PutObject\`, \`GetObject\`, \`HeadObject\`, \`ListObjectsV2\`, and \`CompleteMultipartUpload\` return a **standard quoted MD5 ETag** (e.g. \`"d41d8cd98f00b204e9800998ecf8427e"\`) for objects uploaded after the MD5 ETag feature shipped. For multipart uploads, the composite ETag follows the AWS format \`"<md5_of_part_md5s>-<N>"\`. Legacy objects (those uploaded before the feature) have no stored MD5: \`HEAD\`/\`GET\` omit the \`ETag\` header entirely, and \`ListObjectsV2\` falls back to wrapping the CID as the ETag value. See the migration note below.

The Autonomys CID is exposed on every object response as a custom header:

\`\`\`http
x-amz-meta-cid: bafkreig...
\`\`\`

This makes \`rclone check\`, \`rclone md5sum\`, AWS CLI checksum verification, and any other MD5-based tooling work out of the box.

> **Migration note.** Objects uploaded before the MD5 ETag feature shipped have a \`NULL\` MD5 in the database. They will not return an \`ETag\` header on \`HEAD\`/\`GET\` until they are re-uploaded. The CID is always available via \`x-amz-meta-cid\`. For listings of legacy objects, the CID is returned as a fallback.

\`\`\`typescript
import \{ HeadObjectCommand \} from "@aws-sdk/client-s3";

const head = await s3Client.send(
  new HeadObjectCommand(\{ Bucket: "my-archive", Key: "report.pdf" \})
);

console.log(head.ETag);                    // '"d41d8cd98f00b204e9800998ecf8427e"' (MD5)
console.log(head.Metadata?.cid);           // 'bafkreig...' (CID, via x-amz-meta-cid)
\`\`\`

### 5. Deletion is Forbidden by Design

\`DeleteObject\` always returns \`403 Forbidden\` with an informative message — Auto Drive storage is permanent. Tools that try to delete (e.g. \`rclone delete\`, \`rclone purge\`, \`rclone sync\` with deletions) will see the 403 and surface it as an error. Re-uploading the same key creates a new object pointing at new content; the prior data still exists on the DSN.

### 6. Enhanced Metadata Support

Custom user metadata is stored alongside the object and returned on subsequent \`HEAD\`/\`GET\` calls. Auto Drive recognizes \`compression\` and \`encryption\` metadata for content stored with those transforms applied client-side.

\`\`\`typescript
const command = new PutObjectCommand(\{
  Bucket: "my-archive",
  Key: "file.txt",
  Body: buffer,
  Metadata: \{
    compression: "ZLIB",
    encryption: "AES_256_GCM",
  \},
\});
\`\`\`

### 7. Range Requests

Partial file downloads using standard HTTP \`Range\` headers are supported.

\`\`\`typescript
const command = new GetObjectCommand(\{
  Bucket: "my-archive",
  Key: "large-file.bin",
  Range: "bytes=0-9", // first 10 bytes
\});
\`\`\`

### 8. Multipart Uploads

The full multipart workflow (\`CreateMultipartUpload\` → \`UploadPart\` × N → \`CompleteMultipartUpload\`) is supported. \`UploadPart\` returns the MD5 of the part body; \`CompleteMultipartUpload\` returns the standard AWS composite ETag \`"<md5_of_part_md5s>-<N>"\`.

\`\`\`typescript
const key = "large-file.bin";
const Bucket = "my-archive";

// Step 1: Create multipart upload
const \{ UploadId \} = await s3Client.send(
  new CreateMultipartUploadCommand(\{ Bucket, Key: key \})
);

// Step 2: Upload one or more parts
const part1 = await s3Client.send(
  new UploadPartCommand(\{
    Bucket,
    Key: key,
    UploadId: UploadId!,
    PartNumber: 1,
    Body: fileChunk1,
  \})
);

// Step 3: Complete the upload
const result = await s3Client.send(
  new CompleteMultipartUploadCommand(\{
    Bucket,
    Key: key,
    UploadId: UploadId!,
    MultipartUpload: \{
      Parts: [\{ ETag: part1.ETag!, PartNumber: 1 \}],
    \},
  \})
);

console.log(result.ETag); // '"<composite_md5>-1"'
\`\`\`

## Configuration

### Endpoint

| Environment | Endpoint |
| --- | --- |
| **Mainnet (public)** | \`https://s3.auto-drive.autonomys.xyz\` |

### Client Setup (AWS JS SDK)

The Auto Drive backend exposes objects under a single \`/:key(*)\` route and parses bucket and key from the path, so a path-style client works well in practice:

\`\`\`typescript
import \{ S3Client \} from "@aws-sdk/client-s3";

const s3Client = new S3Client(\{
  region: "us-east-1",                                // required by the SDK; ignored by Auto Drive
  endpoint: "https://s3.auto-drive.autonomys.xyz",
  credentials: \{
    accessKeyId: "your-auto-drive-api-key",          // your Auto Drive API key
    secretAccessKey: "placeholder",                   // any non-empty string; ignored
  \},
  forcePathStyle: true,                               // bucket lives in the path
\});
\`\`\`

Then use bucket names as you would with AWS S3:

\`\`\`typescript
await s3Client.send(
  new PutObjectCommand(\{ Bucket: "my-archive", Key: "report.pdf", Body: buffer \})
);
\`\`\`

> **Alternative: \`bucketEndpoint\` style.** The upstream backend integration tests configure the SDK with \`bucketEndpoint: true\` and bake the bucket into the endpoint path (e.g. \`Bucket: "my-archive/s3"\`). Either pattern works against the \`/:key(*)\` route; \`forcePathStyle: true\` with a plain bucket name is shown here because it's the more familiar S3 configuration.

## Authentication

- Uses Auto Drive API key-based authentication (the same keys as the native Auto Drive API)
- The API key goes in \`accessKeyId\`; \`secretAccessKey\` must be present but is ignored (use any non-empty placeholder)
- Files uploaded via the S3 API are owned by the user the API key belongs to

Get an API key from the **Developers** section at [ai3.storage](https://ai3.storage).

## File Ownership & Cross-API Access

- **Cross-API compatibility** — files uploaded via the S3 API are accessible via the native Auto Drive API, and vice versa
- **Centralized ownership** — file ownership is tracked centrally per user, not per API surface
- **Content deduplication** — multiple users uploading identical content share the same underlying CID
- **Shared access** — if different users upload the same file, both can access it through either API

## Storage Characteristics

### Content Addressing

- Files are stored using Content Identifiers (CIDs) on the Autonomys DSN
- The CID is exposed via the \`x-amz-meta-cid\` response header on every object response (and as a fallback ETag for legacy objects)
- Storage is **immutable** — the same content always produces the same CID

### Decentralized Backend

- Files are stored on the Distributed Storage Network of the Autonomys Network
- Automatic replication and redundancy
- No single point of failure

## rclone Integration

Auto Drive's S3 layer is fully [rclone](https://rclone.org)-compatible — including \`rclone check\`, \`rclone md5sum\`, virtual directory listings, multipart uploads, and pagination — so any rclone-driven workflow (archival, scheduled backups, mounts, cloud-to-cloud migration, CI/CD artifact storage) works against Auto Drive.

For the dedicated walkthrough — quickstart, full config reference, every supported command, workflows, and troubleshooting — see the [Using rclone](/auto_drive/rclone) guide.

## Migrating from AWS S3

For developers moving from traditional AWS S3:

1. **Update the endpoint** to \`https://s3.auto-drive.autonomys.xyz\`
2. **Change credentials** to use your Auto Drive API key as \`accessKeyId\`; set \`secretAccessKey\` to a placeholder
3. **Set \`forcePathStyle: true\`** in the S3 client configuration
4. **Drop bucket-creation calls** — buckets are created implicitly on first write
5. **Remove deletion logic** — \`DeleteObject\` returns 403; design around immutability
6. **Read CIDs from \`x-amz-meta-cid\`**, not from the ETag (the ETag is the standard MD5)
7. **Handle longer response times** due to network latency vs. AWS edge

\`\`\`typescript
// Before (AWS S3)
const s3Client = new S3Client(\{
  region: "us-east-1",
  credentials: \{
    accessKeyId: "AKIA...",
    secretAccessKey: "abc123...",
  \},
\});

// After (Auto Drive)
const s3Client = new S3Client(\{
  region: "us-east-1",
  endpoint: "https://s3.auto-drive.autonomys.xyz",
  credentials: \{
    accessKeyId: "your-auto-drive-api-key",
    secretAccessKey: "placeholder",
  \},
  forcePathStyle: true,
\});
\`\`\`

## Building Your Own S3-Compatible Layer

If you are building your own S3-compatible service on top of Autonomys storage, the [Auto SDK](https://github.com/autonomys/auto-sdk) ships reusable, framework-agnostic S3 server-side helpers in [\`@autonomys/file-server\`](https://www.npmjs.com/package/@autonomys/file-server):

- \`buildListResult(rows, prefix, delimiter, maxKeys)\` — \`ListObjectsV2\` delimiter folding into \`CommonPrefixes\` plus \`maxKeys\` pagination with correct continuation-token placement
- \`computeListObjectsDbLimit(maxKeys, delimiter)\` — how many rows to fetch from storage for a single page
- \`finalizeListObjects(params, fetchedRows, dbLimit)\` — wraps \`buildListResult\` and applies the full-batch truncation override that prevents duplicate \`CommonPrefixes\` across page boundaries
- \`md5Hex\`, \`formatETag\`, \`multipartETag\` — S3 ETag computation, including the AWS composite multipart format
- Types: \`S3ObjectListing\`, \`ListObjectsParams\`, \`ListObjectsResult\`

\`\`\`typescript
import \{
  computeListObjectsDbLimit,
  finalizeListObjects,
  multipartETag,
\} from "@autonomys/file-server";

const dbLimit = computeListObjectsDbLimit(maxKeys, delimiter);
const rows = await fetchSortedObjectsFromStorage(prefix, continuationToken, dbLimit);

const result = finalizeListObjects(
  \{ bucket, prefix, delimiter, maxKeys, continuationToken \},
  rows,
  dbLimit,
);
// result is ready to render as ListObjectsV2 XML

const completedETag = multipartETag(parts.map((p) => p.etag));
\`\`\`

Auto Drive itself uses these helpers, so you get the same delimiter folding, pagination, and composite-ETag behavior the public service is validated against.

## Limitations & Considerations

### Performance

- The DSN has higher write latency than traditional S3 — use multipart uploads for files > 5 MB
- Listings paginate at the server's configured \`maxKeys\` (default 1,000); requested values larger than 1,000 are clamped to the 1,000 hard cap
- Range requests may have different performance characteristics than AWS S3

### Compatibility Notes

- **Implemented**: \`ListBuckets\`, \`ListObjectsV2\` (with \`prefix\`, \`delimiter\`, \`max-keys\`, \`continuation-token\`), \`PutObject\`, \`GetObject\`, \`HeadObject\`, multipart uploads
- **Not implemented (return 501)**: \`ListObjects\` (V1) — use V2; \`CreateBucket\` — buckets are created implicitly; \`CopyObject\`; \`DeleteObjects\` (bulk/multi-object delete); \`versioning\`, \`lifecycle policies\`, \`ACLs\`, \`bucket policies\`, presigned URLs
- **Forbidden by design (return 403)**: \`DeleteObject\`, \`DeleteBucket\`
- **Effectively no-ops**: any operation that assumes mutability

## Best Practices

1. **Treat storage as append-only** — design data models around immutability rather than fighting it
2. **Use multipart uploads** for files larger than 5 MB
3. **Read CIDs from \`x-amz-meta-cid\`**, not from the ETag
4. **Use the MD5 ETag for integrity verification** — it matches \`md5sum\` of the content for non-multipart objects
5. **Paginate listings** with \`MaxKeys\` + \`NextContinuationToken\` rather than fetching everything in one call
6. **Implement retry logic** for occasional network-induced timeouts
7. **For rclone**, always pass \`--immutable\` and set \`list_version = 2\`

## Error Handling

- Standard S3 XML error responses
- \`403 Forbidden\` for any deletion attempt — distinguish this from a permissions error in your client
- Network timeouts may be longer than traditional S3; configure your SDK accordingly

This S3 layer provides a familiar interface while leveraging the benefits of decentralized storage, making it easy to migrate existing S3-based applications — and S3-compatible tooling like rclone and the AWS CLI — to Auto Drive.


---

### File: sdk/auto-drive/usage_examples.mdx

# Auto-Drive Usage Examples

## 1. Uploading a file from a filepath (not available in browser)

\`\`\`typescript
import \{ fs,createAutoDriveApi \} from '@autonomys/auto-drive'
import \{ NetworkId \} from '@autonomys/auto-utils'

const api = createAutoDriveApi(\{ apiKey: 'your-api-key', network: NetworkId.MAINNET \}) // Initialize your API instance with API key
const filePath = 'path/to/your/file.txt' // Specify the path to your file
const options = \{
  password: 'your-encryption-password', // Optional: specify a password for encryption
  compression: true,
  // an optional callback useful for large file uploads
  onProgress?: (progress: number) => \{
    console.log(\`The upload is completed is \$\{progress\}% completed\`)
  \}
\}

const cid = await fs.uploadFileFromFilepath(api, filePath, options)

console.log(\`The file is uploaded and its cid is \$\{cid\}\`)
\`\`\`

## 2. Uploading a file using File interface 

\`\`\`typescript
import \{ uploadFileFromInput, createAutoDriveApi \} from '@autonomys/auto-drive'
import \{ NetworkId \} from '@autonomys/auto-utils'

const api = createAutoDriveApi(\{ apiKey: 'your-api-key', network: NetworkID.MAINNET \}) // Initialize your API instance with API key

// e.g Get File from object from HTML event
const file: File = e.target.value // Substitute with your file
const options = \{
  password: 'your-encryption-password', // Optional: specify a password for encryption
  compression: true,
\}
const cid = await api.uploadFileFromInput(file, options)

console.log(\`The file is uploaded and its cid is \$\{cid\}\`)
\`\`\`

## 3. Uploading a folder (not available in browser)

\`\`\`typescript
import \{ createAutoDriveApi, fs \} from '@autonomys/auto-drive'
import \{ NetworkId \} from '@autonomys/auto-utils'

const api = createAutoDriveApi(\{ apiKey: 'your-api-key', network: NetworkID.MAINNET \}) // Initialize your API instance with API key
const folderPath = 'path/to/your/folder' // Specify the path to your folder

const options = \{
  uploadChunkSize: 1024 * 1024, // Optional: specify the chunk size for uploads
  password: 'your-encryption-password', // Optional: If folder is encrypted
  // an optional callback useful for large file uploads
  onProgress: (progress: number) => \{
    console.log(\`The upload is completed is \$\{progress\}% completed\`)
  \},
\}

const folderCID = await fs.uploadFolderFromFolderPath(api, folderPath, options)

console.log(\`The folder is uploaded and its cid is \$\{folderCID\}\`)
\`\`\`

## 4. Uploading a file from a custom interface with \`GenericFile\`

\`\`\`typescript
import \{ createAutoDriveApi \} from '@autonomys/auto-drive'
import \{ NetworkId \} from '@autonomys/auto-utils'

const api = createAutoDriveApi(\{ apiKey: 'your-api-key', network: NetworkID.MAINNET \}) // Initialize your API instance with API key
const buffer = Buffer.from(...);
const genericFile = \{
  read: async function *() \{
    yield buffer
  \},
  name: "autonomys-whitepaper.pdf",
  mimeType: "application/pdf",
  size: 1234556,
  path: "autonomys-whitepaper.pdf"
\}

const options = \{
  password: 'your-encryption-password', // Optional: specify a password for encryption
  compression: true,
  // an optional callback useful for large file uploads
  onProgress?: (progress: number) => \{
    console.log(\`The upload is completed is \$\{progress\}% completed\`)
  \}
\}

const cid = api.uploadFile(genericFile, options)

console.log(\`The file is uploaded and its cid is \$\{cid\}\`)
\`\`\`

## 5. Downloading files

\`\`\`typescript
import \{ createAutoDriveApi \} from '@autonomys/auto-drive'
import \{ NetworkId \} from '@autonomys/auto-utils'

const api = createAutoDriveApi(\{ apiKey: 'your-api-key', network: NetworkID.MAINNET \}) // Initialize your API instance with API key

try \{
  const cid = '..'
  const stream = await api.downloadFile(cid)
  let file = Buffer.alloc(0)
  for await (const chunk of stream) \{
    file = Buffer.concat([file, chunk])
  \}
  console.log('File downloaded successfully:', stream)
\} catch (error) \{
  console.error('Error downloading file:', error)
\}
\`\`\`

## 6. Creating shareable download link

\`\`\`typescript
import \{ createAutoDriveApi \} from '@autonomys/auto-drive'
import \{ NetworkId \} from '@autonomys/auto-utils'

const api = createAutoDriveApi(\{ apiKey: 'your-api-key', network: NetworkID.MAINNET \}) // Initialize your API instance with API key

try \{
  const cid = 'your-file-cid'
  const publicUrl = await api.publishObject(cid)
  console.log('Public download URL:', publicUrl)
\} catch (error) \{
  console.error('Error publishing object:', error)
\}
\`\`\`

## 7. Example usage of \`getMyFiles\`

Here is an example of how to use the \`getMyFiles\` method to retrieve the root directories:

\`\`\`typescript
import \{ createAutoDriveApi \} from '@autonomys/auto-drive'
import \{ NetworkId \} from '@autonomys/auto-utils'

const api = createAutoDriveApi(\{ apiKey: 'your-api-key', network: NetworkID.MAINNET \}) // Initialize your API instance with API key

try \{
  for (let i = 0; i < 10; i++) \{
    const myFiles = await api.getMyFiles(i, 100)
    console.log(\`Retrieved \$\{myFiles.rows.length\} files of \$\{myFiles.totalCount\} total\`)
    for (const file of myFiles.rows) \{
      console.log(\`\$\{file.name\} - \$\{file.headCid\}: \$\{file.size\}\`)
    \}
  \}
\} catch (error) \{
  console.error('Error downloading file:', error)
\}
\`\`\`

---

### File: sdk/auto-utils.mdx

## Auto-Utils Package

### Introduction

The \`@autonomys/auto-utils\` package provides core utility functions for interacting with and building applications on the Autonomys Network.

### Features

- **Wallet Management**: Initialize and manage wallets using mnemonics or URIs.
- **Network Configuration**: Access and manage network and domain settings.
- **Data Storage**: Save and read data to and from local storage or the file system.
- **Cryptographic Operations**: Perform hashing and data manipulation using cryptographic functions.
- **API Activation**: Activate and manage connections to the Autonomys Network APIs.
- **Address Utilities**: Convert and decode addresses to and from standardized formats.

### Installation

Install the package via \`npm\` or \`yarn\`:

\`\`\`bash
# Using npm
npm install @autonomys/auto-utils

# Using yarn
yarn add @autonomys/auto-utils
\`\`\`

### Importing

Import the \`auto-utils\` functions you need into your project:

\`\`\`typescript
// Import specific functions
import \{ activateWallet, activate, blake2b_256 \} from '@autonomys/auto-utils';

// Or import everything
import * as utils from '@autonomys/auto-utils';
\`\`\`

### Available functions

> *Note:* All asynchronous functions return a \`Promise\` and should be used with \`await\` for proper execution flow. Wrap asynchronous calls in \`try...catch\` blocks to handle potential errors gracefully.

#### Account and address utilities

- \`address(input): string\`: Standardizes an address format.
- \`createAccountIdType(api, address): Uint8Array\`: Creates an \`AccountId\` object from an address.
- \`decode(input): Uint8Array\`: Decodes an address to bytes.

#### API and connection management

> *Note:* Always disconnect the API instance after operations to free up resources.

- \`activate(options?): Promise<ApiPromise>\`: Connects to the Autonomys Network.
- \`activateDomain(params): Promise<ApiPromise>\`: Connects to a specific domain.
- \`createConnection(endpoint, options?): Promise<ApiPromise>\`: Creates a new API connection.
- \`createAutoDriveApi(api, networkId)\`: Connects to the Auto Drive API of the selected Network.
- \`disconnect(api): Promise<void>\`: Disconnects an API instance.

#### Cryptographic functions

- \`blake2b_256(data): string\`: Hashes data with BLAKE2b-256.
- \`concatenateUint8Arrays(...arrays): Uint8Array\`: Concatenates multiple \`Uint8Array\`s.
- \`stringToUint8Array(string): Uint8Array\`: Converts a string to \`Uint8Array\`.

#### Data storage

> *Note:* Be cautious when saving sensitive data using \`save\` and \`read\` as data storage is permanent. Handle private keys securely. Do not expose them in code or logs.

- \`read(key): Promise<any>\`: Reads data from storage.
- \`readFromFileSystem(key): Promise<any>\`: Reads data from file system.
- \`readFromLocalStorage(key): Promise<any>\`: Reads data from local storage.
- \`save(key, value): Promise<void>\`: Saves data to storage.
- \`saveOnFileSystem(key, value): Promise<void>\`: Saves data to file system.
- \`saveOnLocalStorage(key, value): Promise<void>\`: Saves data to local storage.

#### Event management

- \`eventName(type, event): string\`: Combines a type and an event into a full event name.
- \`eventsGroup\`: Groups system events by name.
- \`expectSuccessfulTxEvent\`: Default success event names array.
- \`Type\`: Enum for event types (e.g., \`system\`).
- \`validateEvents(events, eventsExpected?, tx, block, log?): EventsValidated\`: Checks if expected events are in transaction events.

#### Network management

- \`getNetworkDetails(options): NetworkDetails\`: Retrieves the details of a network.
- \`getNetworkDomainDetails(options): DomainDetails\`: Retrieves the details of a domain.
- \`getNetworkDomainRpcUrls(options): string[]\`: Retrieves the RPC URLs for a domain.
- \`getNetworkRpcUrls(options): string[]\`: Retrieves the RPC URLs for a network.
- \`networks\`: Array of available networks.

#### Signing utilities

- \`signMessage(signer, address, data): Promise<\{ signature: string \}>\`: Signs a message with a signer and an address.
- \`signatureVerify\`: Verifies signatures (re-exported from \`@polkadot/util-crypto\`).
- \`signingKey(publicKey): string\`: Converts a public key to a hex string.

#### String utilities

- \`capitalizeFirstLetter(string): string\`: Capitalizes the first letter.
- \`fixLengthEntryId(blockHeight, indexInBlock?): string\`: Creates fixed-length IDs.
- \`isAddress(address): boolean\`: Validates a Substrate address.
- \`isHex(value): boolean\`: Validates a hexadecimal string.
- \`shortString(value, initialLength?, endLength?): string\`: Truncates strings.
- \`stringify(value): string\`: Stringifies values, handling BigInt.

#### Token and value formatting

- \`formatSpacePledged(value, decimals?): string\`: Formats space amount with units.
- \`formatTokenAmount(amount, decimals?): bigint\`: Formats token amount with decimals.
- \`parseTokenAmount(amount, decimals?): number\`: Parses token amount with decimals.

#### Transaction utilities

- \`signAndSendTx(sender, tx, options?, eventsExpected?, log?, mapErrorCodeToEnum?): Promise<TransactionSignedAndSend>\`: Signs, sends, and validates a transaction.

#### Wallet management

- \`activateWallet(options): Promise<\{ api, accounts \}>\`: Activates a wallet using a mnemonic or URI.
- \`generateWallet(): GeneratedWallet\`: Generates a new wallet with a mnemonic.
- \`getMockWallet(name, wallets): Wallet\`: Retrieves a mock wallet by name.
- \`mockWallets(options, api?): Promise<Wallet[]>\`: Creates mock wallets for testing.
- \`setupWallet(params): Wallet\`: Sets up a wallet from a mnemonic or URI.

## Usage examples

### 1. Wallet management

#### Activate a wallet using a mnemonic phrase

\`\`\`typescript
import \{ activateWallet \} from '@autonomys/auto-utils';

(async () => \{
  const mnemonic = 'your mnemonic phrase here';

  const \{ api, accounts \} = await activateWallet(\{
    mnemonic,
    networkId: 'chronos', // Optional: specify the network ID
  \});

  const account = accounts[0];
  console.log(\`Connected with account address: \$\{account.address\}\`);

  // Perform actions with the account...

  // Disconnect when done
  await api.disconnect();
\})();
\`\`\`

#### Activate a wallet using a URI

\`\`\`typescript
import \{ activateWallet \} from '@autonomys/auto-utils';

(async () => \{
  const \{ api, accounts \} = await activateWallet(\{
    uri: '//Alice',
    networkId: 'localhost', // Connect to a local network
  \});

  const account = accounts[0];
  console.log(\`Connected with account address: \$\{account.address\}\`);

  // Disconnect when done
  await api.disconnect();
\})();
\`\`\`

#### Create mock wallets for testing

\`\`\`typescript
import \{ activate, mockWallets, getMockWallet \} from '@autonomys/auto-utils';

(async () => \{
  const api = await activate(\{ networkId: 'chronos' \});

  const wallets = await mockWallets(\{\}, api);
  const aliceWallet = getMockWallet('Alice', wallets);
  const bobWallet = getMockWallet('Bob', wallets);

  console.log(\`Alice's address: \$\{aliceWallet.accounts[0].address\}\`);
  console.log(\`Bob's address: \$\{bobWallet.accounts[0].address\}\`);

  // Disconnect when done
  await api.disconnect();
\})();
\`\`\`

### 2. Network management

#### List all available networks

\`\`\`typescript
import \{ networks \} from '@autonomys/auto-utils';

networks.forEach((network) => \{
  console.log(\`Network ID: \$\{network.id\}, Name: \$\{network.name\}\`);
\});
\`\`\`

#### Retrieve the details of a specific network

\`\`\`typescript
import \{ getNetworkDetails \} from '@autonomys/auto-utils';

const network = getNetworkDetails(\{ networkId: 'chronos' \});
console.log(\`Network Name: \$\{network.name\}\`);
console.log(\`RPC URLs: \$\{network.rpcUrls.join(', ')\}\`);
\`\`\`

#### Retrieve the details of a specific domain within a network

\`\`\`typescript
import \{ getNetworkDomainDetails \} from '@autonomys/auto-utils';

const domain = getNetworkDomainDetails(\{ domainId: '1', networkId: 'chronos' \});
console.log(\`Domain Name: \$\{domain.name\}\`);
console.log(\`RPC URLs: \$\{domain.rpcUrls.join(', ')\}\`);
\`\`\`

### 3. Cryptographic functions

#### Hash a string using BLAKE2b-256

\`\`\`typescript
import \{ blake2b_256, stringToUint8Array \} from '@autonomys/auto-utils';

const data = 'Hello, Autonomys!';
const dataBytes = stringToUint8Array(data);
const hash = blake2b_256(dataBytes);

console.log(\`Hash: \$\{hash\}\`); // Outputs the hash of the input string
\`\`\`

#### Convert a string to a \`Uint8Array\`

\`\`\`typescript
import \{ stringToUint8Array \} from '@autonomys/auto-utils';

const text = 'Sample text';
const byteArray = stringToUint8Array(text);

console.log(byteArray); // Outputs Uint8Array representation of the string
\`\`\`

#### Concatenate two \`Uint8Array\` instances

\`\`\`typescript
import \{ stringToUint8Array, concatenateUint8Arrays \} from '@autonomys/auto-utils';

const array1 = stringToUint8Array('First part ');
const array2 = stringToUint8Array('Second part');

const concatenated = concatenateUint8Arrays(array1, array2);
console.log(\`Concatenated Result: \$\{new TextDecoder().decode(concatenated)\}\`);
// Outputs: "First part Second part"
\`\`\`

### 4. API activation

#### Activate the network API (connect to the Autonomys Network)

\`\`\`typescript
import \{ activate \} from '@autonomys/auto-utils';

(async () => \{
  const api = await activate(\{ networkId: 'chronos' \});

  console.log('API connected');

  // Perform API calls...

  // Disconnect when done
  await api.disconnect();
\})();
\`\`\`

#### Activate a domain API (connect to a specific domain within the Autonomys Network)

\`\`\`typescript
import \{ activateDomain \} from '@autonomys/auto-utils';

(async () => \{
  const api = await activateDomain(\{ domainId: '1', networkId: 'chronos' \});

  console.log('Domain API connected');

  // Perform domain-specific API calls...

  // Disconnect when done
  await api.disconnect();
\})();
\`\`\`

### 5. Data storage

#### Save data to local storage or the file system and read it back

\`\`\`typescript
import \{ save, read \} from '@autonomys/auto-utils';

const key = 'myData';
const value = \{ message: 'Hello, Autonomys!' \};

// Save data
save(key, value);

// Read data
const retrievedValue = read(key);
console.log(retrievedValue); // Outputs: \{ message: 'Hello, Autonomys!' \}
\`\`\`

### 6. Address utilities

#### Convert an address to a standardized format and decode it

\`\`\`typescript
import \{ address, decode \} from '@autonomys/auto-utils';

const originalAddress = '5GmS1wtCfR4tK5SSgnZbVT4kYw5W8NmxmijcsxCQE6oLW6A8';
const standardizedAddress = address(originalAddress);
const decodedAddress = decode(originalAddress);

console.log(\`Standardized Address: \$\{standardizedAddress\}\`);
console.log('Decoded Address:', decodedAddress);
\`\`\`


---

### File: sdk/auto-xdm.mdx

## Auto-XDM Package

### Introduction

The Autonomys Auto XDM SDK (@autonomys/auto-xdm) provides functionalities for cross-domain transfer of native tokens.

### Features

- **Cross-Domain Transfer**: Enable token transfers between consensus and domain wallets.
- **TypeScript Support**: Full TypeScript type definitions for an enhanced developer experience.

### Installation

Install the package via \`npm\` or \`yarn\`:

\`\`\`bash
# Using npm
npm install @autonomys/auto-xdm

# Using yarn
yarn add @autonomys/auto-xdm
\`\`\`

### Importing

Import the \`auto-xdm\` functions you need into your project:

\`\`\`typescript
// Import specific functions
import \{ 
  transferToConsensus,
  transferToDomainAccount20Type,
  transferToDomainAccount32Type 
\} from '@autonomys/auto-xdm';

// Or import everything
import * as xdm from '@autonomys/auto-xdm';
\`\`\`

### Available functions

#### Transfer functions

> *Note:* All transfer functions return a \`SubmittableExtrinsic\` that must be signed and sent. The \`amount\` parameter expects the smallest unit of the token (Shannon). For 18 decimals, multiply by 10^18 or use \`formatTokenAmount\` from \`auto-utils\`. Ensure a sufficient balance in the sending account to cover both the transfer and fees. Cross-domain transfers may take a few blocks to complete.

- \`transfer(api, destination, amount): Promise<SubmittableExtrinsic>\`: Base transfer function for cross-domain transfers.
- \`transferToConsensus(api, accountId32, amount): Promise<SubmittableExtrinsic>\`: Transfer tokens from a domain to the consensus chain.
- \`transferToDomainAccount20Type(api, destinationDomainId, accountId20, amount): Promise<SubmittableExtrinsic>\`: Transfer tokens from the consensus chain to an EVM address.
- \`transferToDomainAccount32Type(api, destinationDomainId, accountId32, amount): Promise<SubmittableExtrinsic>\`: Transfer tokens from the consensus chain to a Substrate address.

#### Query functions

> *Note:* Monitor transfer status using query functions.

- \`chainAllowlist(api): Promise<Codec>\`: Retrieves the list of allowed chains.
- \`channels(api, chainId): Promise<Codec>\`: Retrieves the list of channels
- \`consensusChannels(api): Promise<Codec>\`: Retrieves the list of consensus channels
- \`domainChannels(api, domainId): Promise<Codec>\`: Retrieves the list of domain channels
- \`allCancelledTransfers(api): Promise<Codec>\`: Retrieves all cancelled transfers.
- \`chainTransfers(api): Promise<Codec>\`: Retrieves all chain transfers.
- \`allDomainBalances(api): Promise<Codec>\`: Retrieves balances across all domains.
- \`domainBalances(api, domainId): Promise<Codec>\`: Retrieves balances for a specific domain.
- \`allUnconfirmedTransfers(api): Promise<Codec>\`: Retrieves pending transfers. 

### Type definitions

\`\`\`typescript
type Amount = BigInt | number | string;

type Consensus = \{
    type: 'consensus';
\};

type Domain = \{
    type: 'domain';
    domainId: number;
\};

type ChainOrDomain = Consensus | Domain;
\`\`\`

## Usage examples

### 1. Transfer from \`Consensus\` to \`Domain\` (EVM address)

\`\`\`typescript
import \{ activateWallet \} from '@autonomys/auto-utils'
import \{ transferToDomainAccount20Type \} from '@autonomys/auto-xdm'

const api = await activateWallet(\{ networkId: 'chronos', uri: '//alice' \})
const tx = await transferToDomainAccount20Type(
  api,
  0, // Receiver domain (0 is Auto EVM on Chronos Testnet)
  '0x1234567890abcdef', // Receiver domain account
  '1000000000000000000',
)

\`\`\`

### 2. Transfer from \`Consensus\` to \`Domain\` (Substrate address)

\`\`\`typescript
import \{ activateWallet \} from '@autonomys/auto-utils'
import \{ transferToDomainAccount32Type \} from '@autonomys/auto-xdm'

const api = await activateWallet(\{ networkId: 'chronos', uri: '//alice' \})
const tx = await transferToDomainAccount32Type(
  api,
  0, // Receiver domain (0 is Auto EVM on Chronos Testnet)
  'su1234567890abcdef', // Receiver domain account
  '1000000000000000000',
)
\`\`\`

### 3. Transfer from \`Domain\` to \`Consensus\`

\`\`\`typescript
import \{ activateWallet \} from '@autonomys/auto-utils'
import \{ transferToConsensus \} from '@autonomys/auto-xdm'

const api = await activateWallet(\{ networkId: 'chronos', domainId: 0, uri: '//alice' \})
const tx = await transferToConsensus(
  api,
  'su1234567890abcdef', // Receiver consensus account,
  '1000000000000000000',
)
\`\`\`

### 4. Query domain balances

\`\`\`typescript
import \{ activateWallet \} from '@autonomys/auto-utils';
import \{ domainBalances \} from '@autonomys/auto-xdm';

(async () => \{
  const \{ api \} = await activateWallet(\{ 
    networkId: 'chronos' 
  \});

  // Get balances for domain 0 (Auto EVM on the Chronos testnet)
  const balances = await domainBalances(api, 0);
  console.log('Domain balances:', balances.toString());
\})();
\`\`\`

### Best practices

1. **Error Handling**: Wrap asynchronous calls and transactions in \`try...catch\` blocks to handle potential errors gracefully:
   \`\`\`typescript
   try \{
     const tx = await transferToConsensus(api, receiver, amount);
     await tx.signAndSend(account);
   \} catch (error) \{
     console.error('Transfer failed:', error);
   \}
   \`\`\`

2. **Amount Formatting**: Use appropriate decimal places for token amounts:
   - The \`amount\` parameter expects the smallest unit of the token (Shannon).
   - For 18 decimals, multiply by 10^18 or use \`formatTokenAmount\` from \`auto-utils\`.

3. **API Management**: > Always disconnect the API instance after your operations are complete to free up resources:
   \`\`\`typescript
   try \{
     // ... your code ...
   \} finally \{
     await api.disconnect();
   \}
   \`\`\`


---

### File: sdk/index.mdx

---
title: Auto SDK
---

## Auto SDK

### What is the Auto SDK?

The **Auto SDK** is a powerful toolkit of JavaScript/TypeScript packages for developers to seamlessly integrate with the Autonomys Network. It provides simple APIs for interacting with the *consensus* layer, utilizing *data storage*, managing *decentralized identities*, and (soon) handling *AI3 payments*, in addition to general-purpose functions essential for building decentralized applications (dApps)—all in JavaScript and TypeScript—abstracting away the complexities of blockchain and smart contracts.

### Key features:

- **Modular Architecture**: Use only the packages you need.
- **Easy to Use**: Simplifies blockchain operations with high-level functions.
- **Flexible**: Suitable for both beginners and experienced blockchain developers.
- **Open-source**: Built by and for the community.

### Why the Auto SDK?

- **Simplify Development**: Focus on your application's logic rather than blockchain intricacies.
- **Accelerate Time-to-Market**: Reduce development time with ready-to-use functions.
- **Ensure Compatibility**: Stay up-to-date with the latest Autonomys blockchain protocols.
- **Enhance Security**: Utilize well-tested code for critical operations like identity management.

## Packages

The Auto SDK monorepo contains multiple packages, each serving a specific purpose. All packages are published to \`npm\` under the \`@autonomys\` scope:

- **\`@autonomys/auto-utils\`**: Core utility functions for interacting with the Autonomys Network.
- **\`@autonomys/auto-consensus\`**: Functions for interacting with the consensus layer.
- **\`@autonomys/auto-drive\`**: Tools for preparing, uploading and managing data for on-chain storage.

## Quick Start Guide: Install and Code Example 
A short video guide on installing the Auto SDK, along with a simple coding example demonstrating how to retrieve an account balance.

<iframe width="560" height="315" src="https://www.youtube.com/embed/B5J9fwE5-vI?si=Mt133r3I2QnCae0A" title="Auto SDK Quick Start Guide: Install and Code Example" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

## Step-by-step guide

### Requirements

- **\`Node.js\`** (version 14 or higher)
- **\`yarn\`** or **\`npm\`**

### Installation

Install the packages you need via \`npm\` or \`yarn\`. For example, to install \`@autonomys/auto-utils\` and \`@autonomys/auto-consensus\`:

#### Using \`npm\`

\`\`\`bash
npm install @autonomys/auto-utils @autonomys/auto-consensus
\`\`\`

#### Using \`yarn\`

\`\`\`bash
yarn add @autonomys/auto-utils @autonomys/auto-consensus
\`\`\`

### Cloning the repository and building locally (*optional*)

If you want to run the SDK packages locally or contribute to the SDK, clone the repository and build the packages from source. Setup instructions:

#### 1. Clone the repository
   Open your terminal and run:
   \`\`\`bash
   git clone https://github.com/autonomys/auto-sdk.git
   \`\`\`

#### 2. Navigate to the project directory
   \`\`\`bash
   cd auto-sdk
   \`\`\`

#### 3. Install dependencies
   \`\`\`bash
   yarn install
   \`\`\`

#### 4. Compile all packages
   \`\`\`bash
   yarn run build
   \`\`\`

#### 5. Run tests on all packages
   \`\`\`bash
   yarn run test
   \`\`\`

### Localhost testing (*optional*)

Test the SDK packages against a local Autonomys node:

#### 1. Verify OS and architecture settings

Edit the \`scripts/download.sh\` file and ensure that lines 3-7 match your current operating system and architecture:

\`\`\`bash
# Change the following variables as needed
# OS to download
OS="macos" # Options: macos | ubuntu | windows
# Architecture to download
ARCHITECTURE="aarch64" # Options: aarch64 | x86_64-skylake | x86_64-v2
\`\`\`

#### 2. Run the development script

Execute the following command to start the local node and farmer:

\`\`\`bash
node scripts/run-dev.js
\`\`\`

This script will:

1. Download the latest version of the node and farmer compatible with your OS and architecture (\`scripts/download.sh\`).
2. Start the node and create/insert the keystore (\`scripts/run-node.sh\`).
3. Start the farmer (\`scripts/run-farmer.sh\`).
4. Register the node as an operator, wait for synchronization, and then terminate the node and farmer (handled within \`scripts/run-dev.js\`).
5. Restart the node as an operator (\`scripts/run-operator.sh\`).
6. Restart the farmer (\`scripts/run-farmer.sh\`).

#### 3. Run tests on the local node

\`\`\`bash
bash scripts/localhost-run-test.sh
\`\`\`

The tests will automatically detect and execute on the local node and farmer.

## Next steps

With the Auto SDK set up locally, you're ready to start building and testing your blockchain applications. Explore the following pages for code examples and a functions overview.


---

### File: sdk/polkadot-api.mdx

# Understanding the Polkadot API for Auto SDK Development

## Introduction

While the Auto SDK provides convenient, high-level functions for common tasks on the Autonomys Network, many advanced use cases require direct interaction with the underlying blockchain through the **Polkadot API**. The Autonomys Network is built on Substrate (the same framework as Polkadot), which means it inherits the powerful \`@polkadot/api\` interface for blockchain interactions.

> **For newcomers**: If you're just starting with blockchain development, think of the Auto SDK as a friendly toolkit for common tasks, while the Polkadot API is the comprehensive "power user" interface that gives you access to everything the blockchain can do.

## Why You Need the Polkadot API

The Auto SDK covers many essential operations, but there are numerous scenarios where you'll need to access blockchain data and functionality that isn't wrapped by the SDK:

### Chain State Queries
- **Block information**: Current block number, timestamps, block hashes
- **Network fees**: Transaction fees, storage costs, operational parameters
- **Account data**: Balances, nonces, detailed account information
- **System parameters**: Network constants, runtime version, chain specifications

### Advanced Transaction Handling
- **Fee estimation**: Calculate exact transaction costs before submission
- **Complex extrinsics**: Multi-signature operations, batched transactions
- **Event filtering**: Listen for specific blockchain events beyond basic success/failure
- **Custom pallets**: Interact with specialized blockchain modules

### Real-time Monitoring
- **Block subscriptions**: Monitor new blocks and their contents
- **State changes**: Watch for changes in specific storage items
- **Network status**: Monitor node health, peer connections, sync status

## Essential Polkadot API Documentation

The **[Polkadot.js API Documentation](https://polkadot.js.org/docs/api)** is your comprehensive resource for understanding blockchain interactions. Key sections include:

- **[API Basics](https://polkadot.js.org/docs/api/start/basics)**: Connection setup and fundamental concepts
- **[Query Methods](https://polkadot.js.org/docs/api/start/api.query)**: Reading blockchain state
- **[RPC Calls](https://polkadot.js.org/docs/api/start/api.rpc)**: Direct node communication
- **[Subscription Patterns](https://polkadot.js.org/docs/api/start/api.query.subs)**: Real-time data monitoring

## Installation and Setup

The Polkadot API works alongside the Auto SDK. Install both packages:

\`\`\`bash
npm install @polkadot/api @autonomys/auto-utils
\`\`\`

Import both in your project:

\`\`\`typescript
// Auto SDK for high-level operations
import \{ activate, activateWallet \} from '@autonomys/auto-utils';

// Polkadot API for direct blockchain access
import \{ ApiPromise, WsProvider \} from '@polkadot/api';
\`\`\`

## Common Use Cases and Examples

### 1. Getting Network Information and Fees

This example shows how to retrieve transaction fees and timestamps - information not available through the Auto SDK:

\`\`\`typescript
import \{ ApiPromise, WsProvider \} from '@polkadot/api';

async function getNetworkInfo() \{
  // Connect to the Autonomys Network
  const api = await ApiPromise.create(\{
    provider: new WsProvider('wss://rpc-0.mainnet.subspace.network/ws')
  \});

  try \{
    // Get current block header
    const header = await api.rpc.chain.getHeader();
    const blockNumber = header.number.toNumber();
    
    // Get current timestamp
    const timestamp = (await api.query.timestamp.now()).toNumber();
    
    // Get transaction fees
    const fee = await api.query.transactionFees.transactionByteFee();
    
    console.log('Block number:', blockNumber);
    console.log('Timestamp:', new Date(timestamp).toISOString());
    console.log('Current fee:', fee.current.toString());
    console.log('Next fee:', fee.next.toString());
    
  \} finally \{
    await api.disconnect();
  \}
\}
\`\`\`

### 2. Account Balance and Nonce Queries

\`\`\`typescript
async function getAccountDetails(accountAddress) \{
  const api = await ApiPromise.create(\{
    provider: new WsProvider('wss://rpc-0.gemini-3h.subspace.network/ws')
  \});

  try \{
    // Get account balance
    const balance = await api.query.system.account(accountAddress);
    
    console.log('Free balance:', balance.data.free.toString());
    console.log('Reserved balance:', balance.data.reserved.toString());
    console.log('Account nonce:', balance.nonce.toString());
    
  \} finally \{
    await api.disconnect();
  \}
\}
\`\`\`

### 3. Fee Estimation Before Transaction

\`\`\`typescript
import \{ activateWallet \} from '@autonomys/auto-utils';
import \{ ApiPromise \} from '@polkadot/api';

async function estimateTransactionFee(recipientAddress, amount) \{
  // Use Auto SDK to get wallet and API
  const \{ api, accounts \} = await activateWallet(\{
    uri: '//Alice',
    networkId: 'mainnet'
  \});
  
  const sender = accounts[0];
  
  // Create transaction
  const transfer = api.tx.balances.transfer(recipientAddress, amount);
  
  // Estimate fees using Polkadot API
  const info = await transfer.paymentInfo(sender.address);
  
  console.log(\`Estimated fee: \$\{info.partialFee.toString()\}\`);
  console.log(\`Transaction weight: \$\{info.weight.toString()\}\`);
  
  await api.disconnect();
\}
\`\`\`

### 4. Monitoring Blockchain Events

\`\`\`typescript
async function monitorBlocks() \{
  const api = await ApiPromise.create(\{
    provider: new WsProvider('wss://rpc-0.gemini-3h.subspace.network/ws')
  \});

  // Subscribe to new blocks
  const unsubscribe = await api.rpc.chain.subscribeNewHeads((header) => \{
    console.log(\`New block #\$\{header.number\} with hash \$\{header.hash\}\`);
  \});

  // Subscribe to balance changes for specific account
  const accountAddress = 'your-account-address';
  const unsubBalance = await api.query.system.account(accountAddress, (balance) => \{
    console.log('Balance updated:', balance.data.free.toString());
  \});

  // Clean up subscriptions
  setTimeout(() => \{
    unsubscribe();
    unsubBalance();
    api.disconnect();
  \}, 30000); // Stop after 30 seconds
\}
\`\`\`

## Integration Patterns with Auto SDK

### Combining Auto SDK with Polkadot API

\`\`\`typescript
import \{ activateWallet \} from '@autonomys/auto-utils';
import \{ ApiPromise \} from '@polkadot/api';

async function advancedWalletOperations() \{
  // Use Auto SDK for wallet setup
  const \{ api, accounts \} = await activateWallet(\{
    mnemonic: 'your mnemonic phrase here',
    networkId: 'mainneth'
  \});
  
  const account = accounts[0];
  
  // Use Polkadot API for advanced queries
  const accountInfo = await api.query.system.account(account.address);
  const currentFees = await api.query.transactionFees.transactionByteFee();
  
  console.log(\`Account: \$\{account.address\}\`);
  console.log(\`Balance: \$\{accountInfo.data.free.toString()\}\`);
  console.log(\`Current fee rate: \$\{currentFees.current.toString()\}\`);
  
  // The api instance from Auto SDK is a full Polkadot API instance
  // You can use all Polkadot API methods on it
  const blockHash = await api.rpc.chain.getBlockHash();
  console.log(\`Latest block hash: \$\{blockHash\}\`);
  
  await api.disconnect();
\}
\`\`\`

## When to Use Auto SDK vs. Polkadot API

### Use Auto SDK for:
- ✅ Wallet creation and management
- ✅ Basic token transfers
- ✅ File uploads to Auto Drive
- ✅ Auto ID operations
- ✅ Network connection setup
- ✅ Common utility functions

### Use Polkadot API for:
- ✅ Fee calculations and estimations
- ✅ Block and timestamp queries
- ✅ Custom pallet interactions
- ✅ Advanced transaction types
- ✅ Real-time blockchain monitoring
- ✅ Complex state queries


---