apow-cli 0.7.1 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.env.example CHANGED
@@ -1,10 +1,11 @@
1
1
  # Wallet
2
2
  PRIVATE_KEY=
3
3
 
4
- # RPC — Default: Alchemy x402 (premium RPC, paid automatically via USDC in your wallet).
5
- # No API key needed. If you prefer a different RPC, uncomment and set RPC_URL below.
6
- # Setting RPC_URL disables x402 and uses the specified endpoint instead.
7
- # RPC_URL=https://mainnet.base.org
4
+ # RPC — You need one of these two options:
5
+ # Option 1: Bring your own RPC URL (free from Alchemy, QuickNode, etc.)
6
+ RPC_URL=
7
+ # Option 2: Auto-pay via QuickNode x402 ($10 USDC for ~1M calls, no API key needed)
8
+ # USE_X402=true
8
9
 
9
10
  # LLM Provider (openai / anthropic / gemini / ollama / claude-code / codex)
10
11
  LLM_PROVIDER=openai
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # APoW CLI
2
2
 
3
- Mining client for the [APoW (Agentic Proof of Work)](https://github.com/Agentoshi/apow-core) protocol on Base. Prove your agent identity once by minting an ERC-721 Mining Rig, then compete on hash power to mine $AGENT tokens.
3
+ Mining client for the [APoW (Agentic Proof of Work)](https://github.com/Agentoshi/apow-core) protocol on Base. Prove you're an AI agent once by minting an ERC-721 Mining Rig, then compete on hash power to mine $AGENT tokens.
4
4
 
5
5
  **Your agent does all the work. You just fund a wallet.**
6
6
 
@@ -16,13 +16,14 @@ Or run directly:
16
16
  npx apow-cli
17
17
  ```
18
18
 
19
- ## RPC: Alchemy x402 (Default)
19
+ ## RPC Setup
20
20
 
21
- > **v0.5.0+: Premium RPC with zero setup.** The CLI uses [Alchemy x402](https://x402.alchemy.com/) by default -- a premium Base RPC endpoint that charges per-request via the x402 payment protocol. Your mining wallet pays automatically with USDC on Base. No API key, no account, no rate limits.
21
+ > **v0.8.0+: Bring your own RPC or use auto-pay.** You need a Base RPC endpoint. Two options:
22
22
  >
23
- > **Requirements:** USDC balance on Base in your mining wallet. Even a small amount (1-2 USDC) covers thousands of RPC calls.
23
+ > 1. **Bring your own** (free): Get a free RPC URL from [Alchemy](https://www.alchemy.com/), [QuickNode](https://www.quicknode.com/), or any Base RPC provider. Set `RPC_URL` in your `.env`.
24
+ > 2. **QuickNode x402** (paid, zero setup): Set `USE_X402=true` in your `.env`. Your mining wallet pays $10 USDC for ~1M RPC calls via the [x402 payment protocol](https://www.x402.org/). No API key, no account needed.
24
25
  >
25
- > **Fallback:** If no USDC is available, the CLI automatically falls back to the public RPC (`mainnet.base.org`). To use a custom RPC instead, set `RPC_URL` in your `.env` (this disables x402).
26
+ > Run `apow setup` to configure interactively.
26
27
 
27
28
  ## For AI Agents
28
29
 
@@ -35,7 +36,7 @@ npx apow-cli wallet new
35
36
 
36
37
  # 2. Write .env (no interactive prompts)
37
38
  # LLM config is only needed for minting; mining uses optimized SMHL solving
38
- # RPC defaults to Alchemy x402 (paid via USDC) no RPC_URL needed
39
+ # RPC: set RPC_URL for a free RPC, or USE_X402=true for auto-pay ($10 USDC)
39
40
  cat > .env << 'EOF'
40
41
  PRIVATE_KEY=0x<from step 1>
41
42
  LLM_PROVIDER=openai # Required for minting only
@@ -47,7 +48,7 @@ EOF
47
48
  npx apow-cli fund --chain solana --token sol # bridge SOL → ETH+USDC on Base
48
49
  # Or send ETH/USDC on Base directly
49
50
 
50
- # 4. Mint a mining rig NFT (proves agent identity via LLM, one-time)
51
+ # 4. Mint a mining rig NFT (proves AI via LLM, one-time)
51
52
  npx apow-cli mint
52
53
 
53
54
  # 5. Start mining (runs forever, no LLM needed, multi-threaded)
@@ -109,7 +110,8 @@ Create a `.env` file or use `apow setup`:
109
110
 
110
111
  ```bash
111
112
  PRIVATE_KEY=0x... # Your wallet private key
112
- # RPC_URL=https://mainnet.base.org # Optional: set to override default Alchemy x402
113
+ RPC_URL=https://... # Your Base RPC URL (free from Alchemy, QuickNode, etc.)
114
+ # USE_X402=true # Or: auto-pay via QuickNode x402 ($10 USDC for ~1M calls)
113
115
  LLM_PROVIDER=openai # openai | gemini | deepseek | qwen | anthropic | ollama (for minting)
114
116
  LLM_MODEL=gpt-4o-mini # Required for minting only; mining uses optimized SMHL solving
115
117
  LLM_API_KEY=sk-... # Required for minting only
@@ -161,7 +163,7 @@ apow fund --chain base --no-swap
161
163
 
162
164
  Mining in v0.4.0 uses two key optimizations:
163
165
 
164
- - **Algorithmic SMHL**: Mining SMHL challenges are solved algorithmically in microseconds (no LLM call). Your agent identity was already proven when you minted your ERC-721 Mining Rig.
166
+ - **Algorithmic SMHL**: Mining SMHL challenges are solved algorithmically in microseconds (no LLM call). Your AI was already proven when you minted your Mining Rig.
165
167
  - **Multi-threaded nonce grinding**: Hash computation is parallelized across all CPU cores via `worker_threads`. Set `MINER_THREADS` in `.env` to override the default (all cores).
166
168
 
167
169
  > **Want more hash power?** Rent a high-core-count machine on [vast.ai](https://vast.ai/) to increase your nonce grinding throughput. Not required, but scales linearly with core count.
package/dist/config.js CHANGED
@@ -15,7 +15,6 @@ const node_path_1 = require("node:path");
15
15
  const chains_1 = require("viem/chains");
16
16
  (0, dotenv_1.config)();
17
17
  const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
18
- const DEFAULT_RPC_URL = "https://mainnet.base.org";
19
18
  const DEFAULT_LLM_PROVIDER = "openai";
20
19
  const DEFAULT_LLM_MODEL = "gpt-4o-mini";
21
20
  const DEFAULT_OLLAMA_URL = "http://127.0.0.1:11434";
@@ -35,7 +34,7 @@ function resolveChainName() {
35
34
  if (envChain === "base" || envChain === "baseSepolia") {
36
35
  return envChain;
37
36
  }
38
- const rpcUrl = process.env.RPC_URL ?? DEFAULT_RPC_URL;
37
+ const rpcUrl = process.env.RPC_URL ?? "";
39
38
  if (rpcUrl.toLowerCase().includes("sepolia")) {
40
39
  return "baseSepolia";
41
40
  }
@@ -78,8 +77,8 @@ function resolveLlmApiKey(provider) {
78
77
  const chainName = resolveChainName();
79
78
  exports.config = {
80
79
  privateKey: parsePrivateKey(process.env.PRIVATE_KEY),
81
- rpcUrl: process.env.RPC_URL ?? DEFAULT_RPC_URL,
82
- useX402: !process.env.RPC_URL,
80
+ rpcUrl: process.env.RPC_URL ?? "",
81
+ useX402: process.env.USE_X402 === "true",
83
82
  llmProvider: normalizeProvider(process.env.LLM_PROVIDER),
84
83
  llmApiKey: resolveLlmApiKey(normalizeProvider(process.env.LLM_PROVIDER)),
85
84
  llmModel: process.env.LLM_MODEL ?? DEFAULT_LLM_MODEL,
package/dist/dashboard.js CHANGED
@@ -50,7 +50,7 @@ const AgentCoinAbi = AgentCoin_json_1.default;
50
50
  const MiningAgentAbi = MiningAgent_json_1.default;
51
51
  const RARITY_LABELS = ["Common", "Uncommon", "Rare", "Epic", "Mythic"];
52
52
  const ADDR_RE = /^0x[0-9a-fA-F]{40}$/;
53
- const DEFAULT_RPC = "https://mainnet.base.org";
53
+ const DEFAULT_RPC = ""; // No default public RPC — x402 is the default
54
54
  const FLEETS_PATH = (0, node_path_1.join)(process.env.HOME ?? "", ".apow", "fleets.json");
55
55
  // --- Wallet / Fleet loading ---
56
56
  function isAddress(s) {
@@ -427,7 +427,7 @@ function startDashboardServer(opts) {
427
427
  return JSON.stringify(fleets.map((f) => ({ name: f.name, walletCount: f.addresses.length })));
428
428
  }
429
429
  function handleConfig() {
430
- const rpcIsDefault = rpcUrl === DEFAULT_RPC;
430
+ const rpcIsDefault = useX402 || rpcUrl === DEFAULT_RPC;
431
431
  const walletCount = getWalletAddresses(walletsPath).length;
432
432
  return JSON.stringify({ rpcIsDefault, walletCount });
433
433
  }
package/dist/errors.js CHANGED
@@ -73,8 +73,8 @@ const patterns = [
73
73
  test: (m) => /\b402\b/.test(m) || m.toLowerCase().includes("x402") || (m.toLowerCase().includes("insufficient") && m.toLowerCase().includes("usdc")),
74
74
  classify: () => ({
75
75
  category: "transient",
76
- userMessage: "x402 RPC payment failed — check USDC balance on Base",
77
- recovery: "Send USDC to your wallet on Base, or set RPC_URL in .env to use a free RPC",
76
+ userMessage: "QuickNode x402 credit purchase failed — check USDC balance on Base",
77
+ recovery: "Send USDC to your wallet on Base (~$10 for ~1M RPC calls), or set RPC_URL in .env to use a custom RPC",
78
78
  }),
79
79
  },
80
80
  {
package/dist/index.js CHANGED
@@ -170,10 +170,28 @@ async function setupWizard() {
170
170
  console.log("");
171
171
  // Step 2: RPC
172
172
  console.log(` ${ui.bold("Step 2/3: RPC")}`);
173
- console.log(` ${ui.dim("Default: Alchemy x402 premium RPC paid automatically")}`);
174
- console.log(` ${ui.dim("via USDC in your mining wallet. No API key needed.")}`);
175
- console.log(` ${ui.dim("To use a custom RPC, set RPC_URL in .env after setup.")}`);
176
- ui.ok("RPC: Alchemy x402 (default)");
173
+ console.log(` ${ui.dim("You need a Base RPC endpoint. Two options:")}`);
174
+ console.log(` ${ui.dim(" 1. Bring your own (free from Alchemy, QuickNode, etc.)")}`);
175
+ console.log(` ${ui.dim(" 2. Auto-pay via QuickNode x402 ($10 USDC for ~1M calls)")}`);
176
+ const hasRpc = await ui.confirm("Do you have a Base RPC URL?");
177
+ if (hasRpc) {
178
+ const rpcUrl = await ui.prompt("RPC URL");
179
+ if (rpcUrl) {
180
+ values.RPC_URL = rpcUrl;
181
+ ui.ok(`RPC: Custom (${rpcUrl.slice(0, 40)}${rpcUrl.length > 40 ? "..." : ""})`);
182
+ }
183
+ else {
184
+ ui.warn("No URL provided — using QuickNode x402");
185
+ values.USE_X402 = "true";
186
+ ui.ok("RPC: QuickNode x402 ($10 USDC for ~1M calls)");
187
+ }
188
+ }
189
+ else {
190
+ values.USE_X402 = "true";
191
+ console.log(` ${ui.dim("QuickNode x402 will charge $10 USDC from your mining wallet")}`);
192
+ console.log(` ${ui.dim("for ~1M RPC calls. No API key or account needed.")}`);
193
+ ui.ok("RPC: QuickNode x402 ($10 USDC for ~1M calls)");
194
+ }
177
195
  console.log("");
178
196
  // Step 3: LLM (for minting)
179
197
  console.log(` ${ui.bold("Step 3/3: LLM Provider (for minting)")}`);
package/dist/preflight.js CHANGED
@@ -42,7 +42,6 @@ const chains_1 = require("viem/chains");
42
42
  const AgentCoin_json_1 = __importDefault(require("./abi/AgentCoin.json"));
43
43
  const config_1 = require("./config");
44
44
  const wallet_1 = require("./wallet");
45
- const x402_1 = require("./x402");
46
45
  const ui = __importStar(require("./ui"));
47
46
  const agentCoinAbi = AgentCoin_json_1.default;
48
47
  const USDC_ADDRESS = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
@@ -70,29 +69,16 @@ async function runPreflight(level) {
70
69
  else {
71
70
  results.push({ label: "Contract addresses configured", passed: true });
72
71
  }
73
- // Check 2: RPC reachable + chain ID
74
- try {
75
- const chainId = await wallet_1.publicClient.getChainId();
76
- const expectedId = config_1.config.chain.id;
77
- if (chainId !== expectedId) {
78
- results.push({
79
- label: `RPC chain mismatch — expected ${expectedId}, got ${chainId}`,
80
- passed: false,
81
- fix: "Update RPC_URL to point to the correct network",
82
- });
83
- }
84
- else {
85
- results.push({ label: `RPC connected — ${config_1.config.chain.name}`, passed: true });
86
- }
87
- }
88
- catch {
72
+ // Check: RPC configured (either RPC_URL or USE_X402)
73
+ if (!config_1.config.useX402 && !config_1.config.rpcUrl) {
89
74
  results.push({
90
- label: `RPC unreachable — could not connect to ${config_1.config.rpcUrl}`,
75
+ label: "No RPC configured",
91
76
  passed: false,
92
- fix: "Check internet connection or update RPC_URL in .env",
77
+ fix: "Run `apow setup` to configure RPC, or set RPC_URL or USE_X402=true in .env",
93
78
  });
94
79
  }
95
- // Check x402: USDC balance when x402 mode is active
80
+ // Check x402: USDC balance BEFORE RPC check (can't use x402 without USDC)
81
+ let x402Funded = false;
96
82
  if (config_1.config.useX402 && wallet_1.account) {
97
83
  try {
98
84
  // Use a separate lightweight client to avoid chicken-and-egg
@@ -108,27 +94,53 @@ async function runPreflight(level) {
108
94
  args: [wallet_1.account.address],
109
95
  }));
110
96
  if (usdcBalance === 0n) {
111
- ui.warn("No USDC balance — x402 RPC requires USDC on Base for payment");
112
- ui.hint(`Send USDC to ${wallet_1.account.address} on Base, or set RPC_URL in .env to use a free RPC`);
113
- ui.hint("Falling back to public RPC (https://mainnet.base.org)");
114
- config_1.config.useX402 = false;
115
- (0, x402_1.resetX402)();
116
- (0, wallet_1.reinitClients)();
97
+ results.push({
98
+ label: "No USDC balance QuickNode x402 requires USDC on Base",
99
+ passed: false,
100
+ fix: `Send USDC to ${wallet_1.account.address} on Base (~$10 for ~1M RPC calls). Run \`apow fund\` to bridge from Solana.`,
101
+ });
117
102
  }
118
103
  else {
104
+ x402Funded = true;
119
105
  const formatted = (0, viem_1.formatUnits)(usdcBalance, USDC_DECIMALS);
120
106
  results.push({
121
- label: `RPC: Alchemy x402 (${formatted} USDC available)`,
107
+ label: `RPC: QuickNode x402 (${formatted} USDC available)`,
122
108
  passed: true,
123
109
  });
124
110
  }
125
111
  }
126
112
  catch {
127
- // USDC check failed — fall back silently
128
- ui.warn("Could not check USDC balancefalling back to public RPC");
129
- config_1.config.useX402 = false;
130
- (0, x402_1.resetX402)();
131
- (0, wallet_1.reinitClients)();
113
+ // USDC check failed — can't verify, warn but don't block
114
+ x402Funded = true; // optimisticlet the RPC check determine reachability
115
+ ui.warn("Could not check USDC balance — QuickNode x402 may fail if wallet has no USDC");
116
+ }
117
+ }
118
+ // Check 2: RPC reachable + chain ID
119
+ // Skip when: no RPC configured at all, or x402 active but unfunded
120
+ const hasRpc = config_1.config.useX402 || !!config_1.config.rpcUrl;
121
+ if (hasRpc && (!config_1.config.useX402 || x402Funded)) {
122
+ try {
123
+ const chainId = await wallet_1.publicClient.getChainId();
124
+ const expectedId = config_1.config.chain.id;
125
+ if (chainId !== expectedId) {
126
+ results.push({
127
+ label: `RPC chain mismatch — expected ${expectedId}, got ${chainId}`,
128
+ passed: false,
129
+ fix: "Update RPC_URL to point to the correct network",
130
+ });
131
+ }
132
+ else {
133
+ results.push({ label: `RPC connected — ${config_1.config.chain.name}`, passed: true });
134
+ }
135
+ }
136
+ catch {
137
+ results.push({
138
+ label: `RPC unreachable — could not connect to ${config_1.config.useX402 ? "QuickNode x402" : config_1.config.rpcUrl}`,
139
+ passed: false,
140
+ fix: config_1.config.useX402
141
+ ? "Check internet connection and USDC balance, or set RPC_URL in .env for a custom RPC"
142
+ : "Check internet connection or update RPC_URL in .env",
143
+ });
132
144
  }
133
145
  }
134
146
  if (level === "wallet" || level === "mining") {
package/dist/x402.js CHANGED
@@ -1,45 +1,81 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  Object.defineProperty(exports, "__esModule", { value: true });
3
36
  exports.createX402Transport = createX402Transport;
4
37
  exports.resetX402 = resetX402;
5
- const accounts_1 = require("viem/accounts");
6
38
  const viem_1 = require("viem");
7
- const ALCHEMY_X402_BASE = "https://x402.alchemy.com/rpc/base-mainnet";
8
- let _paidFetch = null;
9
- /* eslint-disable @typescript-eslint/no-require-imports */
10
- function getPaidFetchSync(privateKey) {
11
- if (_paidFetch)
12
- return _paidFetch;
13
- // Use require() to avoid subpath module resolution issues with CommonJS.
14
- // The x402 packages use `exports` maps which require "node16"/"bundler"
15
- // moduleResolution — but this project uses classic "Node" resolution.
16
- const { x402Client } = require("@x402/core/client");
17
- const { ExactEvmScheme } = require("@x402/evm/exact/client");
18
- const { toClientEvmSigner } = require("@x402/evm");
19
- const { wrapFetchWithPayment } = require("@x402/fetch");
20
- const account = (0, accounts_1.privateKeyToAccount)(privateKey);
21
- const signer = toClientEvmSigner(account);
22
- const client = new x402Client();
23
- client.register("eip155:*", new ExactEvmScheme(signer));
24
- _paidFetch = wrapFetchWithPayment(fetch, client);
25
- return _paidFetch;
39
+ const QUICKNODE_BASE = "https://x402.quicknode.com";
40
+ const BASE_MAINNET = "eip155:8453";
41
+ let _client = null;
42
+ async function getClient(privateKey) {
43
+ if (_client && !_client.isTokenExpired())
44
+ return _client;
45
+ const { createQuicknodeX402Client } = await Promise.resolve().then(() => __importStar(require("@quicknode/x402")));
46
+ _client = await createQuicknodeX402Client({
47
+ baseUrl: QUICKNODE_BASE,
48
+ network: BASE_MAINNET,
49
+ evmPrivateKey: privateKey,
50
+ preAuth: true,
51
+ // paymentModel defaults to 'credit-drawdown' — no per-request payments
52
+ });
53
+ return _client;
26
54
  }
27
55
  function createX402Transport(privateKey) {
28
56
  return (0, viem_1.custom)({
29
57
  async request({ method, params }) {
30
- const paidFetch = getPaidFetchSync(privateKey);
31
- const response = await paidFetch(ALCHEMY_X402_BASE, {
58
+ const client = await getClient(privateKey);
59
+ const response = await client.fetch(`${QUICKNODE_BASE}/base-mainnet`, {
32
60
  method: "POST",
33
61
  headers: { "Content-Type": "application/json" },
34
62
  body: JSON.stringify({ jsonrpc: "2.0", method, params, id: 1 }),
35
63
  });
64
+ if (response.status === 402) {
65
+ throw new Error("x402 payment failed — insufficient USDC balance on Base");
66
+ }
67
+ if (!response.ok) {
68
+ throw new Error(`QuickNode x402 HTTP ${response.status}: ${response.statusText}`);
69
+ }
36
70
  const data = (await response.json());
37
- if (data.error)
38
- throw new Error(data.error.message);
71
+ if (data.error) {
72
+ const msg = typeof data.error === "string" ? data.error : data.error.message;
73
+ throw new Error(msg);
74
+ }
39
75
  return data.result;
40
76
  },
41
77
  });
42
78
  }
43
79
  function resetX402() {
44
- _paidFetch = null;
80
+ _client = null;
45
81
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apow-cli",
3
- "version": "0.7.1",
3
+ "version": "0.8.0",
4
4
  "description": "Mine AGENT tokens on Base L2 with Agentic Proof of Work",
5
5
  "keywords": [
6
6
  "apow",
@@ -39,9 +39,8 @@
39
39
  "prepublishOnly": "npm run build"
40
40
  },
41
41
  "dependencies": {
42
+ "@quicknode/x402": "^0.1.2",
42
43
  "@solana/web3.js": "^1.98.0",
43
- "@x402/evm": "^2.8.0",
44
- "@x402/fetch": "^2.8.0",
45
44
  "commander": "^14.0.0",
46
45
  "dotenv": "^17.2.3",
47
46
  "openai": "^6.6.0",
package/skill.md CHANGED
@@ -25,7 +25,7 @@ metadata:
25
25
  configure the miner, mint, and mine. The only step that requires your user is funding the wallet
26
26
  with ETH on Base. Everything else you handle yourself.
27
27
 
28
- > **RPC:** The CLI uses [Alchemy x402](https://x402.alchemy.com/) by default -- a premium Base RPC that charges per-request via USDC in your mining wallet. No API key, no account, no rate limits. Just fund your wallet with USDC (the `apow fund` command handles this automatically). If no USDC is available, it falls back to the public RPC. To use a custom RPC, set `RPC_URL` in `.env`.
28
+ > **RPC:** You need a Base RPC endpoint. Either set `RPC_URL` in `.env` (free from Alchemy, QuickNode, etc.) or set `USE_X402=true` to auto-pay via [QuickNode x402](https://x402.quicknode.com/) ($10 USDC for ~1M calls, no API key needed). Run `apow setup` to configure interactively.
29
29
 
30
30
  ---
31
31
 
@@ -93,7 +93,7 @@ SMHL ("Show Me Human Language") serves two different roles in APoW:
93
93
 
94
94
  **SMHL for Minting (identity verification):** When minting a Mining Rig, your LLM solves an SMHL challenge to prove agent capability. This is the "prove yourself" gate: your agent demonstrates it can solve constrained text generation. The LLM receives a prompt like: "Generate a sentence that is approximately N characters long, contains approximately W words, and includes the letter 'X'."
95
95
 
96
- **SMHL for Mining (algorithmic):** During mining, SMHL solutions are generated algorithmically in microseconds, with no LLM needed. Your agent identity was already established when you minted your ERC-721 Mining Rig. Mining is a hash power competition, not a language puzzle.
96
+ **SMHL for Mining (algorithmic):** During mining, SMHL solutions are generated algorithmically in microseconds, with no LLM needed. Your AI was already proven when you minted your Mining Rig. Mining is a hash power competition, not a language puzzle.
97
97
 
98
98
  On-chain verification checks (both minting and mining):
99
99
  1. **Length** (in bytes): within ±5 of the target
@@ -263,7 +263,8 @@ CHAIN=base
263
263
  | `LLM_API_KEY` | For minting | - | API key for minting. Falls back to `OPENAI_API_KEY` / `GEMINI_API_KEY` / `DEEPSEEK_API_KEY` / `DASHSCOPE_API_KEY` / `ANTHROPIC_API_KEY` per provider. Not needed for `ollama` or mining. |
264
264
  | `LLM_MODEL` | For minting | `gpt-4o-mini` | Model identifier passed to the provider (minting only) |
265
265
  | `MINER_THREADS` | No | All CPU cores | Number of threads for parallel nonce grinding |
266
- | `RPC_URL` | No | Alchemy x402 | Base JSON-RPC endpoint. Default uses Alchemy x402 (premium, paid via USDC). Set to override with a custom endpoint. |
266
+ | `RPC_URL` | Yes* | | Base JSON-RPC endpoint. Get a free URL from Alchemy or QuickNode. *Not needed if `USE_X402=true`. |
267
+ | `USE_X402` | No | `false` | Set to `true` to auto-pay via QuickNode x402 ($10 USDC for ~1M calls). Replaces `RPC_URL`. |
267
268
  | `CHAIN` | No | `base` | Network selector; auto-detects `baseSepolia` if RPC URL contains "sepolia" |
268
269
  | `SOLANA_RPC_URL` | No | `https://api.mainnet-beta.solana.com` | Solana RPC endpoint (only for `apow fund --chain solana`) |
269
270
  | `SQUID_INTEGRATOR_ID` | No | - | Squid Router integrator ID for deposit address flow (free at [squidrouter.com](https://app.squidrouter.com/)) |
@@ -545,7 +546,7 @@ Set `RPC_URL` in `.env` to any Base-compatible JSON-RPC endpoint. The `CHAIN` va
545
546
 
546
547
  ### Agent Wallet
547
548
 
548
- Each Miner NFT supports an on-chain agent wallet. This creates a one-rig-one-agent identity model: an NFT owner can delegate mining operations to a separate hot wallet without transferring ownership of the rig.
549
+ Each Miner NFT supports an on-chain agent wallet. This creates a one-rig-one-agent model: an NFT owner can delegate mining operations to a separate hot wallet without transferring ownership of the rig.
549
550
 
550
551
  **Functions:**
551
552
  - `getAgentWallet(tokenId)`: returns the registered agent wallet address