apow-cli 0.1.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 ADDED
@@ -0,0 +1,24 @@
1
+ # Wallet
2
+ PRIVATE_KEY=
3
+
4
+ # RPC
5
+ RPC_URL=https://mainnet.base.org
6
+
7
+ # LLM Provider (openai / anthropic / gemini / ollama / claude-code / codex)
8
+ LLM_PROVIDER=openai
9
+ LLM_MODEL=gpt-4o-mini
10
+
11
+ # API key (not needed for ollama, claude-code, or codex)
12
+ LLM_API_KEY=
13
+
14
+ # Provider-specific keys (alternative to LLM_API_KEY)
15
+ # OPENAI_API_KEY=
16
+ # ANTHROPIC_API_KEY=
17
+ # GEMINI_API_KEY=
18
+
19
+ # Ollama (only if LLM_PROVIDER=ollama)
20
+ # OLLAMA_URL=http://127.0.0.1:11434
21
+
22
+ # Contract addresses (defaults built-in, override only if needed)
23
+ # MINING_AGENT_ADDRESS=0xB7caD3ca5F2BD8aEC2Eb67d6E8D448099B3bC03D
24
+ # AGENT_COIN_ADDRESS=0x12577CF0D8a07363224D6909c54C056A183e13b3
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Agentoshi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,125 @@
1
+ # APoW CLI
2
+
3
+ Mining client for the [APoW (Agentic Proof of Work)](https://github.com/Agentoshi/apow-core) protocol on Base. Solve SMHL challenges with any LLM to mine $AGENT tokens.
4
+
5
+ **Your agent does all the work — you just fund a wallet.**
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npm install -g apow-cli
11
+ ```
12
+
13
+ Or run directly:
14
+
15
+ ```bash
16
+ npx apow-cli
17
+ ```
18
+
19
+ ## For AI Agents
20
+
21
+ Any AI agent can go from zero to actively mining in 5 steps — no human interaction except funding the wallet.
22
+
23
+ ```bash
24
+ # 1. Generate a wallet
25
+ npx apow-cli wallet new
26
+ # → Captures address + private key from stdout
27
+
28
+ # 2. Write .env (no interactive prompts)
29
+ cat > .env << 'EOF'
30
+ PRIVATE_KEY=0x<from step 1>
31
+ RPC_URL=https://mainnet.base.org
32
+ LLM_PROVIDER=openai
33
+ LLM_MODEL=gpt-4o-mini
34
+ LLM_API_KEY=<your key>
35
+ EOF
36
+
37
+ # 3. Ask your user to fund the wallet with ≥0.005 ETH on Base
38
+ # This is the ONLY step that requires human action
39
+
40
+ # 4. Mint a mining rig NFT (solves SMHL challenge via LLM)
41
+ npx apow-cli mint
42
+
43
+ # 5. Start mining (runs forever, auto-detects best rig)
44
+ npx apow-cli mine
45
+ ```
46
+
47
+ **Scale up** with multiple wallets from a single funded wallet:
48
+
49
+ ```bash
50
+ # Generate sub-wallets and fund them from your main wallet
51
+ npx apow-cli wallet new # → sub-wallet address
52
+ npx apow-cli wallet fund <sub-address> # sends mint price + gas from main wallet
53
+
54
+ # Mint + mine with each sub-wallet
55
+ PRIVATE_KEY=<sub-key> npx apow-cli mint
56
+ PRIVATE_KEY=<sub-key> npx apow-cli mine &
57
+ ```
58
+
59
+ Each wallet gets one rig, each rig mines independently. More wallets = more chances to win each block. See [skill.md](skill.md) for the complete autonomous guide.
60
+
61
+ ## For Humans
62
+
63
+ If you prefer to do it yourself:
64
+
65
+ ```bash
66
+ # 1. Interactive setup — wallet, RPC, LLM config
67
+ npx apow-cli setup
68
+
69
+ # 2. Fund your wallet with ETH on Base (≥0.005 ETH)
70
+
71
+ # 3. Mint a mining rig NFT
72
+ npx apow-cli mint
73
+
74
+ # 4. Start mining
75
+ npx apow-cli mine
76
+ ```
77
+
78
+ ## Commands
79
+
80
+ | Command | Description |
81
+ |---------|-------------|
82
+ | `apow setup` | Interactive setup wizard — configure wallet, RPC, and LLM |
83
+ | `apow wallet new` | Generate a new mining wallet |
84
+ | `apow wallet show` | Show configured wallet address |
85
+ | `apow wallet export` | Export your wallet's private key |
86
+ | `apow wallet fund <addr> [eth]` | Send ETH to another address (default: mint price + gas) |
87
+ | `apow mint` | Mint a MiningAgent NFT (one per wallet) |
88
+ | `apow mine [tokenId]` | Mine $AGENT with your NFT (auto-detects best rig) |
89
+ | `apow stats [tokenId]` | View mining stats, earnings, difficulty |
90
+
91
+ ## Configuration
92
+
93
+ Create a `.env` file or use `apow setup`:
94
+
95
+ ```bash
96
+ PRIVATE_KEY=0x... # Your wallet private key
97
+ RPC_URL=https://mainnet.base.org
98
+ LLM_PROVIDER=openai # openai | anthropic | gemini | ollama | claude-code | codex
99
+ LLM_MODEL=gpt-4o-mini
100
+ LLM_API_KEY=sk-...
101
+ # Contract addresses (defaults built-in, override only if needed)
102
+ # MINING_AGENT_ADDRESS=0xB7caD3ca5F2BD8aEC2Eb67d6E8D448099B3bC03D
103
+ # AGENT_COIN_ADDRESS=0x12577CF0D8a07363224D6909c54C056A183e13b3
104
+ ```
105
+
106
+ See [.env.example](.env.example) for all options.
107
+
108
+ ## LLM Providers
109
+
110
+ | Provider | Model | Cost/call | Notes |
111
+ |----------|-------|-----------|-------|
112
+ | OpenAI | `gpt-4o-mini` | ~$0.001 | Cheapest cloud option |
113
+ | Anthropic | `claude-sonnet-4-5-20250929` | ~$0.005 | High accuracy |
114
+ | Gemini | `gemini-2.5-flash` | ~$0.001 | Fast |
115
+ | Ollama | `llama3.1` | Free | Local GPU required |
116
+ | Claude Code | `default` | Subscription | No API key needed |
117
+ | Codex | `default` | Subscription | No API key needed |
118
+
119
+ ## Protocol
120
+
121
+ The APoW protocol contracts and documentation live in [apow-core](https://github.com/Agentoshi/apow-core).
122
+
123
+ ## License
124
+
125
+ MIT
@@ -0,0 +1,173 @@
1
+ [
2
+ {
3
+ "type": "function",
4
+ "name": "getMiningChallenge",
5
+ "stateMutability": "view",
6
+ "inputs": [],
7
+ "outputs": [
8
+ {
9
+ "name": "challenge",
10
+ "type": "bytes32"
11
+ },
12
+ {
13
+ "name": "target",
14
+ "type": "uint256"
15
+ },
16
+ {
17
+ "name": "smhl",
18
+ "type": "tuple",
19
+ "components": [
20
+ { "name": "targetAsciiSum", "type": "uint16" },
21
+ { "name": "firstNChars", "type": "uint8" },
22
+ { "name": "wordCount", "type": "uint8" },
23
+ { "name": "charPosition", "type": "uint8" },
24
+ { "name": "charValue", "type": "uint8" },
25
+ { "name": "totalLength", "type": "uint16" }
26
+ ]
27
+ }
28
+ ]
29
+ },
30
+ {
31
+ "type": "function",
32
+ "name": "mine",
33
+ "stateMutability": "nonpayable",
34
+ "inputs": [
35
+ {
36
+ "name": "nonce",
37
+ "type": "uint256"
38
+ },
39
+ {
40
+ "name": "smhlSolution",
41
+ "type": "string"
42
+ },
43
+ {
44
+ "name": "tokenId",
45
+ "type": "uint256"
46
+ }
47
+ ],
48
+ "outputs": []
49
+ },
50
+ {
51
+ "type": "function",
52
+ "name": "totalMines",
53
+ "stateMutability": "view",
54
+ "inputs": [],
55
+ "outputs": [
56
+ {
57
+ "name": "",
58
+ "type": "uint256"
59
+ }
60
+ ]
61
+ },
62
+ {
63
+ "type": "function",
64
+ "name": "totalMinted",
65
+ "stateMutability": "view",
66
+ "inputs": [],
67
+ "outputs": [
68
+ {
69
+ "name": "",
70
+ "type": "uint256"
71
+ }
72
+ ]
73
+ },
74
+ {
75
+ "type": "function",
76
+ "name": "miningTarget",
77
+ "stateMutability": "view",
78
+ "inputs": [],
79
+ "outputs": [
80
+ {
81
+ "name": "",
82
+ "type": "uint256"
83
+ }
84
+ ]
85
+ },
86
+ {
87
+ "type": "function",
88
+ "name": "tokenMineCount",
89
+ "stateMutability": "view",
90
+ "inputs": [
91
+ {
92
+ "name": "",
93
+ "type": "uint256"
94
+ }
95
+ ],
96
+ "outputs": [
97
+ {
98
+ "name": "",
99
+ "type": "uint256"
100
+ }
101
+ ]
102
+ },
103
+ {
104
+ "type": "function",
105
+ "name": "tokenEarnings",
106
+ "stateMutability": "view",
107
+ "inputs": [
108
+ {
109
+ "name": "",
110
+ "type": "uint256"
111
+ }
112
+ ],
113
+ "outputs": [
114
+ {
115
+ "name": "",
116
+ "type": "uint256"
117
+ }
118
+ ]
119
+ },
120
+ {
121
+ "type": "function",
122
+ "name": "balanceOf",
123
+ "stateMutability": "view",
124
+ "inputs": [
125
+ {
126
+ "name": "account",
127
+ "type": "address"
128
+ }
129
+ ],
130
+ "outputs": [
131
+ {
132
+ "name": "",
133
+ "type": "uint256"
134
+ }
135
+ ]
136
+ },
137
+ {
138
+ "type": "function",
139
+ "name": "lastMineBlockNumber",
140
+ "stateMutability": "view",
141
+ "inputs": [],
142
+ "outputs": [
143
+ {
144
+ "name": "",
145
+ "type": "uint256"
146
+ }
147
+ ]
148
+ },
149
+ {
150
+ "type": "function",
151
+ "name": "MINEABLE_SUPPLY",
152
+ "stateMutability": "view",
153
+ "inputs": [],
154
+ "outputs": [
155
+ {
156
+ "name": "",
157
+ "type": "uint256"
158
+ }
159
+ ]
160
+ },
161
+ {
162
+ "type": "function",
163
+ "name": "ERA_INTERVAL",
164
+ "stateMutability": "view",
165
+ "inputs": [],
166
+ "outputs": [
167
+ {
168
+ "name": "",
169
+ "type": "uint256"
170
+ }
171
+ ]
172
+ }
173
+ ]
@@ -0,0 +1,186 @@
1
+ [
2
+ {
3
+ "type": "function",
4
+ "name": "getChallenge",
5
+ "stateMutability": "nonpayable",
6
+ "inputs": [
7
+ {
8
+ "name": "minter",
9
+ "type": "address"
10
+ }
11
+ ],
12
+ "outputs": [
13
+ {
14
+ "name": "",
15
+ "type": "tuple",
16
+ "components": [
17
+ { "name": "targetAsciiSum", "type": "uint16" },
18
+ { "name": "firstNChars", "type": "uint8" },
19
+ { "name": "wordCount", "type": "uint8" },
20
+ { "name": "charPosition", "type": "uint8" },
21
+ { "name": "charValue", "type": "uint8" },
22
+ { "name": "totalLength", "type": "uint16" }
23
+ ]
24
+ }
25
+ ]
26
+ },
27
+ {
28
+ "type": "function",
29
+ "name": "challengeSeeds",
30
+ "stateMutability": "view",
31
+ "inputs": [
32
+ {
33
+ "name": "",
34
+ "type": "address"
35
+ }
36
+ ],
37
+ "outputs": [
38
+ {
39
+ "name": "",
40
+ "type": "bytes32"
41
+ }
42
+ ]
43
+ },
44
+ {
45
+ "type": "function",
46
+ "name": "mint",
47
+ "stateMutability": "payable",
48
+ "inputs": [
49
+ {
50
+ "name": "solution",
51
+ "type": "string"
52
+ }
53
+ ],
54
+ "outputs": []
55
+ },
56
+ {
57
+ "type": "function",
58
+ "name": "getMintPrice",
59
+ "stateMutability": "view",
60
+ "inputs": [],
61
+ "outputs": [
62
+ {
63
+ "name": "",
64
+ "type": "uint256"
65
+ }
66
+ ]
67
+ },
68
+ {
69
+ "type": "function",
70
+ "name": "hashpower",
71
+ "stateMutability": "view",
72
+ "inputs": [
73
+ {
74
+ "name": "",
75
+ "type": "uint256"
76
+ }
77
+ ],
78
+ "outputs": [
79
+ {
80
+ "name": "",
81
+ "type": "uint16"
82
+ }
83
+ ]
84
+ },
85
+ {
86
+ "type": "function",
87
+ "name": "rarity",
88
+ "stateMutability": "view",
89
+ "inputs": [
90
+ {
91
+ "name": "",
92
+ "type": "uint256"
93
+ }
94
+ ],
95
+ "outputs": [
96
+ {
97
+ "name": "",
98
+ "type": "uint8"
99
+ }
100
+ ]
101
+ },
102
+ {
103
+ "type": "function",
104
+ "name": "mintBlock",
105
+ "stateMutability": "view",
106
+ "inputs": [
107
+ {
108
+ "name": "",
109
+ "type": "uint256"
110
+ }
111
+ ],
112
+ "outputs": [
113
+ {
114
+ "name": "",
115
+ "type": "uint256"
116
+ }
117
+ ]
118
+ },
119
+ {
120
+ "type": "function",
121
+ "name": "ownerOf",
122
+ "stateMutability": "view",
123
+ "inputs": [
124
+ {
125
+ "name": "tokenId",
126
+ "type": "uint256"
127
+ }
128
+ ],
129
+ "outputs": [
130
+ {
131
+ "name": "",
132
+ "type": "address"
133
+ }
134
+ ]
135
+ },
136
+ {
137
+ "type": "function",
138
+ "name": "nextTokenId",
139
+ "stateMutability": "view",
140
+ "inputs": [],
141
+ "outputs": [
142
+ {
143
+ "name": "",
144
+ "type": "uint256"
145
+ }
146
+ ]
147
+ },
148
+ {
149
+ "type": "function",
150
+ "name": "balanceOf",
151
+ "stateMutability": "view",
152
+ "inputs": [
153
+ {
154
+ "name": "owner",
155
+ "type": "address"
156
+ }
157
+ ],
158
+ "outputs": [
159
+ {
160
+ "name": "",
161
+ "type": "uint256"
162
+ }
163
+ ]
164
+ },
165
+ {
166
+ "type": "function",
167
+ "name": "tokenOfOwnerByIndex",
168
+ "stateMutability": "view",
169
+ "inputs": [
170
+ {
171
+ "name": "owner",
172
+ "type": "address"
173
+ },
174
+ {
175
+ "name": "index",
176
+ "type": "uint256"
177
+ }
178
+ ],
179
+ "outputs": [
180
+ {
181
+ "name": "",
182
+ "type": "uint256"
183
+ }
184
+ ]
185
+ }
186
+ ]
package/dist/config.js ADDED
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.config = void 0;
4
+ exports.requirePrivateKey = requirePrivateKey;
5
+ exports.requireLlmApiKey = requireLlmApiKey;
6
+ exports.isExpensiveModel = isExpensiveModel;
7
+ exports.writeEnvFile = writeEnvFile;
8
+ const dotenv_1 = require("dotenv");
9
+ const promises_1 = require("node:fs/promises");
10
+ const node_path_1 = require("node:path");
11
+ const chains_1 = require("viem/chains");
12
+ (0, dotenv_1.config)();
13
+ const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
14
+ const DEFAULT_RPC_URL = "https://mainnet.base.org";
15
+ const DEFAULT_LLM_PROVIDER = "openai";
16
+ const DEFAULT_LLM_MODEL = "gpt-4o-mini";
17
+ const DEFAULT_OLLAMA_URL = "http://127.0.0.1:11434";
18
+ const DEFAULT_CHAIN_NAME = "base";
19
+ const DEFAULT_MINING_AGENT_ADDRESS = "0xB7caD3ca5F2BD8aEC2Eb67d6E8D448099B3bC03D";
20
+ const DEFAULT_AGENT_COIN_ADDRESS = "0x12577CF0D8a07363224D6909c54C056A183e13b3";
21
+ const EXPENSIVE_MODELS = ["gpt-4o", "gpt-4", "claude-3-opus", "claude-3-5-sonnet"];
22
+ const CHEAP_OVERRIDES = ["gpt-4o-mini", "gpt-4-mini"];
23
+ function normalizeProvider(value) {
24
+ if (value === "anthropic" || value === "ollama" || value === "openai" || value === "gemini" || value === "claude-code" || value === "codex") {
25
+ return value;
26
+ }
27
+ return DEFAULT_LLM_PROVIDER;
28
+ }
29
+ function resolveChainName() {
30
+ const envChain = process.env.CHAIN;
31
+ if (envChain === "base" || envChain === "baseSepolia") {
32
+ return envChain;
33
+ }
34
+ const rpcUrl = process.env.RPC_URL ?? DEFAULT_RPC_URL;
35
+ if (rpcUrl.toLowerCase().includes("sepolia")) {
36
+ return "baseSepolia";
37
+ }
38
+ return DEFAULT_CHAIN_NAME;
39
+ }
40
+ function parsePrivateKey(value) {
41
+ if (!value) {
42
+ return undefined;
43
+ }
44
+ if (!/^0x[0-9a-fA-F]{64}$/.test(value)) {
45
+ throw new Error("PRIVATE_KEY must be a 32-byte hex string prefixed with 0x.");
46
+ }
47
+ return value;
48
+ }
49
+ function parseAddress(envKey, fallback) {
50
+ const value = process.env[envKey];
51
+ if (value && /^0x[0-9a-fA-F]{40}$/.test(value)) {
52
+ return value;
53
+ }
54
+ if (fallback) {
55
+ return fallback;
56
+ }
57
+ // Return zero address instead of throwing — preflight checks will catch this
58
+ return ZERO_ADDRESS;
59
+ }
60
+ function resolveLlmApiKey(provider) {
61
+ if (provider === "claude-code" || provider === "codex")
62
+ return "";
63
+ if (process.env.LLM_API_KEY)
64
+ return process.env.LLM_API_KEY;
65
+ switch (provider) {
66
+ case "openai": return process.env.OPENAI_API_KEY;
67
+ case "anthropic": return process.env.ANTHROPIC_API_KEY;
68
+ case "gemini": return process.env.GEMINI_API_KEY;
69
+ default: return undefined;
70
+ }
71
+ }
72
+ const chainName = resolveChainName();
73
+ exports.config = {
74
+ privateKey: parsePrivateKey(process.env.PRIVATE_KEY),
75
+ rpcUrl: process.env.RPC_URL ?? DEFAULT_RPC_URL,
76
+ llmProvider: normalizeProvider(process.env.LLM_PROVIDER),
77
+ llmApiKey: resolveLlmApiKey(normalizeProvider(process.env.LLM_PROVIDER)),
78
+ llmModel: process.env.LLM_MODEL ?? DEFAULT_LLM_MODEL,
79
+ ollamaUrl: process.env.OLLAMA_URL ?? DEFAULT_OLLAMA_URL,
80
+ chain: chainName === "baseSepolia" ? chains_1.baseSepolia : chains_1.base,
81
+ chainName,
82
+ miningAgentAddress: parseAddress("MINING_AGENT_ADDRESS", DEFAULT_MINING_AGENT_ADDRESS),
83
+ agentCoinAddress: parseAddress("AGENT_COIN_ADDRESS", DEFAULT_AGENT_COIN_ADDRESS),
84
+ };
85
+ function requirePrivateKey() {
86
+ if (!exports.config.privateKey) {
87
+ throw new Error("PRIVATE_KEY is required for minting and mining commands.");
88
+ }
89
+ return exports.config.privateKey;
90
+ }
91
+ function requireLlmApiKey() {
92
+ if (exports.config.llmProvider === "ollama" || exports.config.llmProvider === "claude-code" || exports.config.llmProvider === "codex") {
93
+ return "";
94
+ }
95
+ if (!exports.config.llmApiKey) {
96
+ const keyNames = { openai: "OPENAI_API_KEY", anthropic: "ANTHROPIC_API_KEY", gemini: "GEMINI_API_KEY" };
97
+ const alt = keyNames[exports.config.llmProvider] ?? "";
98
+ throw new Error(`LLM_API_KEY${alt ? ` (or ${alt})` : ""} is required for ${exports.config.llmProvider}.`);
99
+ }
100
+ return exports.config.llmApiKey;
101
+ }
102
+ function isExpensiveModel(model) {
103
+ const m = model.toLowerCase();
104
+ if (CHEAP_OVERRIDES.some((c) => m.startsWith(c)))
105
+ return false;
106
+ return EXPENSIVE_MODELS.some((e) => m.startsWith(e));
107
+ }
108
+ async function writeEnvFile(values) {
109
+ const lines = Object.entries(values)
110
+ .map(([key, value]) => `${key}=${value}`)
111
+ .join("\n");
112
+ await (0, promises_1.writeFile)((0, node_path_1.join)(process.cwd(), ".env"), lines + "\n", "utf8");
113
+ }