apow-cli 0.1.2 → 0.1.4

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/dist/miner.js CHANGED
@@ -265,21 +265,19 @@ async function startMining(tokenId) {
265
265
  throw new Error("Mine transaction reverted on-chain");
266
266
  }
267
267
  txSpinner.stop("Submitting transaction... confirmed");
268
- // Fetch post-mine stats
269
- const [tokenMineCount, earnings] = await Promise.all([
270
- wallet_1.publicClient.readContract({
271
- address: config_1.config.agentCoinAddress,
272
- abi: agentCoinAbi,
273
- functionName: "tokenMineCount",
274
- args: [tokenId],
275
- }),
276
- wallet_1.publicClient.readContract({
268
+ // Fetch post-mine earnings with retry (public RPC may lag)
269
+ let earnings = runningTotal;
270
+ for (let retry = 0; retry < 5; retry++) {
271
+ earnings = (await wallet_1.publicClient.readContract({
277
272
  address: config_1.config.agentCoinAddress,
278
273
  abi: agentCoinAbi,
279
274
  functionName: "tokenEarnings",
280
275
  args: [tokenId],
281
- }),
282
- ]);
276
+ }));
277
+ if (earnings > runningTotal)
278
+ break;
279
+ await new Promise((r) => setTimeout(r, 2000));
280
+ }
283
281
  const delta = earnings - runningTotal;
284
282
  runningTotal = earnings;
285
283
  console.log(` ${ui.green("+")} ${(0, viem_1.formatEther)(delta)} AGENT | Total: ${(0, viem_1.formatEther)(earnings)} AGENT | Tx: ${ui.dim((0, explorer_1.txUrl)(txHash))}`);
package/dist/mint.js CHANGED
@@ -72,33 +72,6 @@ function deriveChallengeFromSeed(seed) {
72
72
  totalLength,
73
73
  ]);
74
74
  }
75
- async function findMintedTokenId(startTokenId, endTokenIdExclusive, owner, blockNumber) {
76
- for (let tokenId = startTokenId; tokenId < endTokenIdExclusive; tokenId += 1n) {
77
- try {
78
- const [tokenOwner, mintBlock] = await Promise.all([
79
- wallet_1.publicClient.readContract({
80
- address: config_1.config.miningAgentAddress,
81
- abi: miningAgentAbi,
82
- functionName: "ownerOf",
83
- args: [tokenId],
84
- }),
85
- wallet_1.publicClient.readContract({
86
- address: config_1.config.miningAgentAddress,
87
- abi: miningAgentAbi,
88
- functionName: "mintBlock",
89
- args: [tokenId],
90
- }),
91
- ]);
92
- if (tokenOwner.toLowerCase() === owner.toLowerCase() && mintBlock === blockNumber) {
93
- return tokenId;
94
- }
95
- }
96
- catch {
97
- // Ignore missing token ids while scanning the minted window.
98
- }
99
- }
100
- throw new Error("Unable to determine minted token ID from post-mint contract state.");
101
- }
102
75
  async function runMintFlow() {
103
76
  const { account, walletClient } = (0, wallet_1.requireWallet)();
104
77
  console.log("");
@@ -184,14 +157,21 @@ async function runMintFlow() {
184
157
  throw new Error("Challenge request reverted on-chain");
185
158
  }
186
159
  challengeSpinner.stop("Requesting challenge... done");
187
- const challengeSeed = (await wallet_1.publicClient.readContract({
188
- address: config_1.config.miningAgentAddress,
189
- abi: miningAgentAbi,
190
- functionName: "challengeSeeds",
191
- args: [account.address],
192
- }));
160
+ // Read challenge seed with retry (public RPC may lag behind tx confirmation)
161
+ let challengeSeed = ZERO_SEED;
162
+ for (let retry = 0; retry < 5; retry++) {
163
+ challengeSeed = (await wallet_1.publicClient.readContract({
164
+ address: config_1.config.miningAgentAddress,
165
+ abi: miningAgentAbi,
166
+ functionName: "challengeSeeds",
167
+ args: [account.address],
168
+ }));
169
+ if (challengeSeed.toLowerCase() !== ZERO_SEED.toLowerCase())
170
+ break;
171
+ await new Promise((r) => setTimeout(r, 2000));
172
+ }
193
173
  if (challengeSeed.toLowerCase() === ZERO_SEED.toLowerCase()) {
194
- throw new Error("Challenge seed was not stored on-chain.");
174
+ throw new Error("Challenge seed not found after 5 retries. The RPC may be lagging — try again.");
195
175
  }
196
176
  // Solve SMHL
197
177
  const challenge = deriveChallengeFromSeed(challengeSeed);
@@ -200,11 +180,6 @@ async function runMintFlow() {
200
180
  smhlSpinner.update(`Solving SMHL... attempt ${attempt}/5`);
201
181
  });
202
182
  smhlSpinner.stop("Solving SMHL... done");
203
- const nextTokenIdBefore = (await wallet_1.publicClient.readContract({
204
- address: config_1.config.miningAgentAddress,
205
- abi: miningAgentAbi,
206
- functionName: "nextTokenId",
207
- }));
208
183
  // Mint
209
184
  const mintSpinner = ui.spinner("Minting...");
210
185
  const mintTx = await walletClient.writeContract({
@@ -221,12 +196,15 @@ async function runMintFlow() {
221
196
  throw new Error("Mint transaction reverted on-chain");
222
197
  }
223
198
  mintSpinner.stop("Minting... confirmed");
224
- const nextTokenIdAfter = (await wallet_1.publicClient.readContract({
225
- address: config_1.config.miningAgentAddress,
226
- abi: miningAgentAbi,
227
- functionName: "nextTokenId",
228
- }));
229
- const tokenId = await findMintedTokenId(nextTokenIdBefore, nextTokenIdAfter, account.address, receipt.blockNumber);
199
+ // Parse token ID from Transfer event in receipt (avoids stale RPC reads)
200
+ const TRANSFER_TOPIC = "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef";
201
+ const mintLog = receipt.logs.find((log) => log.address.toLowerCase() === config_1.config.miningAgentAddress.toLowerCase() &&
202
+ log.topics[0] === TRANSFER_TOPIC &&
203
+ log.topics[1] === "0x0000000000000000000000000000000000000000000000000000000000000000");
204
+ if (!mintLog || !mintLog.topics[3]) {
205
+ throw new Error("Mint tx confirmed but Transfer event not found in logs. Check tx on Basescan.");
206
+ }
207
+ const tokenId = BigInt(mintLog.topics[3]);
230
208
  const [rarityRaw, hashpowerRaw] = await Promise.all([
231
209
  wallet_1.publicClient.readContract({
232
210
  address: config_1.config.miningAgentAddress,
package/dist/smhl.js CHANGED
@@ -59,8 +59,8 @@ function validateSmhlSolution(solution, challenge) {
59
59
  return issues;
60
60
  }
61
61
  const len = Buffer.byteLength(solution, "utf8");
62
- if (Math.abs(len - challenge.totalLength) > 5) {
63
- issues.push(`length ${len} not within ±5 of ${challenge.totalLength}`);
62
+ if (Math.abs(len - challenge.totalLength) > 4) {
63
+ issues.push(`length ${len} not within ±4 of ${challenge.totalLength}`);
64
64
  }
65
65
  if (!/^[\x20-\x7E]+$/.test(solution)) {
66
66
  issues.push("solution must use printable ASCII only");
@@ -82,8 +82,8 @@ function validateSmhlSolution(solution, challenge) {
82
82
  */
83
83
  function adjustSolution(raw, challenge) {
84
84
  const requiredChar = String.fromCharCode(challenge.charValue);
85
- const minLen = challenge.totalLength - 5;
86
- const maxLen = challenge.totalLength + 5;
85
+ const minLen = challenge.totalLength - 4;
86
+ const maxLen = challenge.totalLength + 4;
87
87
  const maxWords = challenge.wordCount + 2;
88
88
  // Clean: lowercase, letters and spaces only, collapse whitespace
89
89
  let words = raw
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apow-cli",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "Mine AGENT tokens on Base L2 with AI-powered proof of work",
5
5
  "keywords": [
6
6
  "apow",
package/skill.md CHANGED
@@ -53,6 +53,8 @@ npx apow-cli wallet new
53
53
  # Captures address + private key from output (also saved to wallet-<address>.txt)
54
54
 
55
55
  # 2. Write .env directly (no interactive prompts needed)
56
+ # IMPORTANT: Use an API-based provider (openai/anthropic/gemini), NOT claude-code/codex.
57
+ # Session-based providers are too slow for the 20-second mint challenge window.
56
58
  cat > .env << 'EOF'
57
59
  PRIVATE_KEY=0x<from step 1>
58
60
  RPC_URL=https://mainnet.base.org
@@ -237,15 +239,17 @@ CHAIN=base
237
239
 
238
240
  ### LLM Provider Recommendations
239
241
 
242
+ > **For AI agents:** Always use an API-based provider (OpenAI, Anthropic, or Gemini). Session-based providers (`claude-code`, `codex`) spawn a CLI subprocess to solve challenges and are too slow to reliably complete the 20-second mint window. They may work for mining (which has no time limit) but will frequently fail during minting.
243
+
240
244
  | Provider | Model | Cost per call | Notes |
241
245
  |---|---|---|---|
242
- | OpenAI | `gpt-4o-mini` | ~$0.001 | Cheapest cloud option |
243
- | OpenAI | `gpt-4o` | ~$0.005 | Default; good reliability |
246
+ | OpenAI | `gpt-4o-mini` | ~$0.001 | **Recommended for agents.** Cheapest, fastest, reliable |
247
+ | Gemini | `gemini-2.5-flash` | ~$0.001 | Fast, good accuracy |
244
248
  | Anthropic | `claude-sonnet-4-5-20250929` | ~$0.005 | High accuracy on constrained generation |
249
+ | OpenAI | `gpt-4o` | ~$0.005 | Higher quality, slightly slower |
245
250
  | Ollama | `llama3.1` | Free (local) | Requires local GPU; variable accuracy |
246
- | Gemini | `gemini-2.5-flash` | ~$0.001 | Fast, good accuracy |
247
- | Claude Code | `default` | Subscription | Use your existing Claude Code session no API key needed |
248
- | Codex | `default` | Subscription | Use your existing Codex session — no API key needed |
251
+ | Claude Code | `default` | Subscription | **Not recommended for minting** — CLI startup too slow for 20s window |
252
+ | Codex | `default` | Subscription | **Not recommended for minting** CLI startup too slow for 20s window |
249
253
 
250
254
  ### RPC Recommendations
251
255
 
@@ -272,7 +276,7 @@ npx apow-cli mint
272
276
  5. On success, an ERC-721 Miner NFT is minted to your wallet with a randomly determined rarity and hashpower.
273
277
  6. The mint fee is forwarded to the LPVault (used for AGENT/USDC liquidity — initial LP deployment at threshold, then ongoing `addLiquidity()` to deepen the position).
274
278
 
275
- **Challenge expiry:** 20 seconds from `getChallenge` to `mint`. The LLM must solve quickly.
279
+ **Challenge expiry:** 20 seconds from `getChallenge` to `mint`. The LLM must solve quickly. Use an API-based provider (openai/anthropic/gemini) — session-based providers (claude-code/codex) are too slow and will fail.
276
280
 
277
281
  ### Mint Price
278
282
 
@@ -479,7 +483,7 @@ LLM_PROVIDER=codex
479
483
  - The CLI must be available in your PATH
480
484
  - Your subscription must be active
481
485
 
482
- **Trade-off:** Session-based solving may be slightly slower than direct API calls due to CLI startup overhead, but eliminates the need for separate API keys and billing. The 15-second timeout ensures challenges are still submitted within the contract's 20-second window.
486
+ **Warning:** Session-based providers (`claude-code`, `codex`) spawn a CLI subprocess for each SMHL challenge. The startup overhead frequently exceeds the 20-second mint challenge window, causing mints to fail with `Expired`. **For minting, always use an API-based provider** (openai, anthropic, or gemini). Session providers may work for the mining loop (which has no time limit per challenge) but are unreliable and not recommended for autonomous operation.
483
487
 
484
488
  ### Custom RPC Endpoints
485
489
 
@@ -522,7 +526,7 @@ Use the corresponding testnet contract addresses.
522
526
  | `LLM_API_KEY is required for openai.` | Missing API key for cloud provider | Set `LLM_API_KEY` (or provider-specific key like `OPENAI_API_KEY`) in `.env`, or switch to `ollama` |
523
527
  | `Insufficient fee` | Not enough ETH sent with mint | Check `getMintPrice()` and ensure wallet has enough ETH |
524
528
  | `Sold out` | All 10,000 Miner NFTs minted | No more rigs available; buy one on secondary market |
525
- | `Expired` | SMHL challenge expired (>20s) | Your LLM is too slow; use a faster model or provider |
529
+ | `Expired` | SMHL challenge expired (>20s) | Switch to an API-based provider (openai/gemini/anthropic). Session providers (claude-code/codex) are too slow for the 20s mint window |
526
530
  | `Invalid SMHL` | LLM produced an incorrect solution | Retry; if persistent, switch to a more capable model |
527
531
  | `Not your miner` | Token ID not owned by your wallet | Verify `PRIVATE_KEY` matches the NFT owner; check token ID |
528
532
  | `Supply exhausted` | All 18.9M mineable AGENT has been minted | Mining is complete; no more rewards available |