apow-cli 0.4.1 → 0.6.1

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.
@@ -0,0 +1,184 @@
1
+ "use strict";
2
+ // Uniswap V3 SwapRouter02 on Base — ETH↔USDC swaps.
3
+ // No new npm deps — uses viem's built-in ABI encoding.
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.getUsdcBalance = getUsdcBalance;
6
+ exports.swapEthToUsdc = swapEthToUsdc;
7
+ exports.swapUsdcToEth = swapUsdcToEth;
8
+ const viem_1 = require("viem");
9
+ const constants_1 = require("./constants");
10
+ const wallet_1 = require("../wallet");
11
+ const SWAP_ROUTER = "0x2626664c2603336E57B271c5C0b26F421741e481";
12
+ const WETH = constants_1.TOKENS.base.weth;
13
+ const USDC = constants_1.TOKENS.base.usdc;
14
+ const FEE_TIER = 500; // 0.05% pool (highest TVL)
15
+ const erc20Abi = [
16
+ {
17
+ type: "function",
18
+ name: "balanceOf",
19
+ inputs: [{ name: "account", type: "address" }],
20
+ outputs: [{ name: "", type: "uint256" }],
21
+ stateMutability: "view",
22
+ },
23
+ {
24
+ type: "function",
25
+ name: "allowance",
26
+ inputs: [
27
+ { name: "owner", type: "address" },
28
+ { name: "spender", type: "address" },
29
+ ],
30
+ outputs: [{ name: "", type: "uint256" }],
31
+ stateMutability: "view",
32
+ },
33
+ {
34
+ type: "function",
35
+ name: "approve",
36
+ inputs: [
37
+ { name: "spender", type: "address" },
38
+ { name: "amount", type: "uint256" },
39
+ ],
40
+ outputs: [{ name: "", type: "bool" }],
41
+ stateMutability: "nonpayable",
42
+ },
43
+ ];
44
+ const swapRouterAbi = [
45
+ {
46
+ name: "exactInputSingle",
47
+ type: "function",
48
+ stateMutability: "payable",
49
+ inputs: [
50
+ {
51
+ name: "params",
52
+ type: "tuple",
53
+ components: [
54
+ { name: "tokenIn", type: "address" },
55
+ { name: "tokenOut", type: "address" },
56
+ { name: "fee", type: "uint24" },
57
+ { name: "recipient", type: "address" },
58
+ { name: "amountIn", type: "uint256" },
59
+ { name: "amountOutMinimum", type: "uint256" },
60
+ { name: "sqrtPriceLimitX96", type: "uint160" },
61
+ ],
62
+ },
63
+ ],
64
+ outputs: [{ name: "amountOut", type: "uint256" }],
65
+ },
66
+ {
67
+ name: "multicall",
68
+ type: "function",
69
+ stateMutability: "payable",
70
+ inputs: [
71
+ { name: "deadline", type: "uint256" },
72
+ { name: "data", type: "bytes[]" },
73
+ ],
74
+ outputs: [{ name: "results", type: "bytes[]" }],
75
+ },
76
+ {
77
+ name: "unwrapWETH9",
78
+ type: "function",
79
+ stateMutability: "payable",
80
+ inputs: [
81
+ { name: "amountMinimum", type: "uint256" },
82
+ { name: "recipient", type: "address" },
83
+ ],
84
+ outputs: [],
85
+ },
86
+ ];
87
+ /** Get USDC balance for an address on Base. */
88
+ async function getUsdcBalance(address) {
89
+ return (await wallet_1.publicClient.readContract({
90
+ address: USDC,
91
+ abi: erc20Abi,
92
+ functionName: "balanceOf",
93
+ args: [address],
94
+ }));
95
+ }
96
+ /**
97
+ * Swap ETH → USDC via Uniswap V3 on Base.
98
+ * Sends ETH as msg.value; router auto-wraps to WETH.
99
+ */
100
+ async function swapEthToUsdc(ethAmount, minUsdcOut) {
101
+ const { account, walletClient } = (0, wallet_1.requireWallet)();
102
+ const txHash = await walletClient.writeContract({
103
+ address: SWAP_ROUTER,
104
+ abi: swapRouterAbi,
105
+ functionName: "exactInputSingle",
106
+ args: [
107
+ {
108
+ tokenIn: WETH,
109
+ tokenOut: USDC,
110
+ fee: FEE_TIER,
111
+ recipient: account.address,
112
+ amountIn: ethAmount,
113
+ amountOutMinimum: minUsdcOut,
114
+ sqrtPriceLimitX96: 0n,
115
+ },
116
+ ],
117
+ value: ethAmount,
118
+ });
119
+ const receipt = await wallet_1.publicClient.waitForTransactionReceipt({ hash: txHash });
120
+ if (receipt.status === "reverted") {
121
+ throw new Error("ETH→USDC swap reverted");
122
+ }
123
+ // Read USDC balance after swap to report actual amount
124
+ const usdcBal = await getUsdcBalance(account.address);
125
+ return { txHash, usdcReceived: (0, viem_1.formatUnits)(usdcBal, 6) };
126
+ }
127
+ /**
128
+ * Swap USDC → ETH via Uniswap V3 on Base.
129
+ * Approves USDC (if needed), then multicalls [exactInputSingle, unwrapWETH9].
130
+ */
131
+ async function swapUsdcToEth(usdcAmount, minEthOut) {
132
+ const { account, walletClient } = (0, wallet_1.requireWallet)();
133
+ // Check and set USDC allowance
134
+ const allowance = (await wallet_1.publicClient.readContract({
135
+ address: USDC,
136
+ abi: erc20Abi,
137
+ functionName: "allowance",
138
+ args: [account.address, SWAP_ROUTER],
139
+ }));
140
+ if (allowance < usdcAmount) {
141
+ const approveTx = await walletClient.writeContract({
142
+ address: USDC,
143
+ abi: erc20Abi,
144
+ functionName: "approve",
145
+ args: [SWAP_ROUTER, usdcAmount],
146
+ });
147
+ await wallet_1.publicClient.waitForTransactionReceipt({ hash: approveTx });
148
+ }
149
+ // Encode exactInputSingle: USDC → WETH, recipient = SWAP_ROUTER (so it holds WETH)
150
+ const swapData = (0, viem_1.encodeFunctionData)({
151
+ abi: swapRouterAbi,
152
+ functionName: "exactInputSingle",
153
+ args: [
154
+ {
155
+ tokenIn: USDC,
156
+ tokenOut: WETH,
157
+ fee: FEE_TIER,
158
+ recipient: SWAP_ROUTER, // Router holds WETH temporarily
159
+ amountIn: usdcAmount,
160
+ amountOutMinimum: minEthOut,
161
+ sqrtPriceLimitX96: 0n,
162
+ },
163
+ ],
164
+ });
165
+ // Encode unwrapWETH9: router converts WETH → ETH and sends to user
166
+ const unwrapData = (0, viem_1.encodeFunctionData)({
167
+ abi: swapRouterAbi,
168
+ functionName: "unwrapWETH9",
169
+ args: [minEthOut, account.address],
170
+ });
171
+ const deadline = BigInt(Math.floor(Date.now() / 1000) + 300); // 5 min
172
+ const txHash = await walletClient.writeContract({
173
+ address: SWAP_ROUTER,
174
+ abi: swapRouterAbi,
175
+ functionName: "multicall",
176
+ args: [deadline, [swapData, unwrapData]],
177
+ });
178
+ const receipt = await wallet_1.publicClient.waitForTransactionReceipt({ hash: txHash });
179
+ if (receipt.status === "reverted") {
180
+ throw new Error("USDC→ETH swap reverted");
181
+ }
182
+ const ethBal = await wallet_1.publicClient.getBalance({ address: account.address });
183
+ return { txHash, ethReceived: (0, viem_1.formatEther)(ethBal) };
184
+ }
package/dist/config.js CHANGED
@@ -79,6 +79,7 @@ const chainName = resolveChainName();
79
79
  exports.config = {
80
80
  privateKey: parsePrivateKey(process.env.PRIVATE_KEY),
81
81
  rpcUrl: process.env.RPC_URL ?? DEFAULT_RPC_URL,
82
+ useX402: !process.env.RPC_URL,
82
83
  llmProvider: normalizeProvider(process.env.LLM_PROVIDER),
83
84
  llmApiKey: resolveLlmApiKey(normalizeProvider(process.env.LLM_PROVIDER)),
84
85
  llmModel: process.env.LLM_MODEL ?? DEFAULT_LLM_MODEL,
package/dist/dashboard.js CHANGED
@@ -43,6 +43,7 @@ const node_path_1 = require("node:path");
43
43
  const viem_1 = require("viem");
44
44
  const chains_1 = require("viem/chains");
45
45
  const dashboard_html_1 = require("./dashboard-html");
46
+ const x402_1 = require("./x402");
46
47
  const AgentCoin_json_1 = __importDefault(require("./abi/AgentCoin.json"));
47
48
  const MiningAgent_json_1 = __importDefault(require("./abi/MiningAgent.json"));
48
49
  const AgentCoinAbi = AgentCoin_json_1.default;
@@ -186,10 +187,13 @@ function parseArtFromTokenUri(raw) {
186
187
  }
187
188
  // --- Server ---
188
189
  function startDashboardServer(opts) {
189
- const { port, walletsPath, rpcUrl, miningAgentAddress, agentCoinAddress } = opts;
190
+ const { port, walletsPath, rpcUrl, useX402, privateKey, miningAgentAddress, agentCoinAddress } = opts;
191
+ const transport = useX402 && privateKey
192
+ ? (0, x402_1.createX402Transport)(privateKey)
193
+ : (0, viem_1.http)(rpcUrl);
190
194
  const publicClient = (0, viem_1.createPublicClient)({
191
195
  chain: chains_1.base,
192
- transport: (0, viem_1.http)(rpcUrl),
196
+ transport,
193
197
  });
194
198
  const artCache = new Map();
195
199
  const htmlPage = (0, dashboard_html_1.getDashboardHtml)();
package/dist/errors.js CHANGED
@@ -69,6 +69,14 @@ const patterns = [
69
69
  recovery: "Run `apow setup` to configure a valid key",
70
70
  }),
71
71
  },
72
+ {
73
+ test: (m) => /\b402\b/.test(m) || m.toLowerCase().includes("x402") || (m.toLowerCase().includes("insufficient") && m.toLowerCase().includes("usdc")),
74
+ classify: () => ({
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",
78
+ }),
79
+ },
72
80
  {
73
81
  test: (m) => m.toLowerCase().includes("insufficient funds"),
74
82
  classify: () => ({
@@ -85,6 +93,38 @@ const patterns = [
85
93
  recovery: "Try a different model (gpt-4o-mini recommended) or check your LLM API key",
86
94
  }),
87
95
  },
96
+ {
97
+ test: (m) => m.includes("INSUFFICIENT_OUTPUT_AMOUNT") || m.includes("Too little received"),
98
+ classify: () => ({
99
+ category: "transient",
100
+ userMessage: "Uniswap swap failed — slippage exceeded",
101
+ recovery: "Price moved during swap. Try again — the auto-split will recalculate.",
102
+ }),
103
+ },
104
+ {
105
+ test: (m) => m.includes("swap reverted"),
106
+ classify: () => ({
107
+ category: "transient",
108
+ userMessage: "Uniswap swap transaction reverted",
109
+ recovery: "Try again. If persistent, check ETH/USDC balances on Base.",
110
+ }),
111
+ },
112
+ {
113
+ test: (m) => m.includes("deBridge") && (m.includes("route") || m.includes("unavailable")),
114
+ classify: () => ({
115
+ category: "transient",
116
+ userMessage: "Bridge route temporarily unavailable",
117
+ recovery: "Try a different bridge method or wait a few minutes",
118
+ }),
119
+ },
120
+ {
121
+ test: (m) => m.includes("ethereum-rpc.publicnode") || (m.includes("ETHEREUM_RPC") && m.includes("unreachable")),
122
+ classify: () => ({
123
+ category: "setup",
124
+ userMessage: "Ethereum mainnet RPC unreachable",
125
+ recovery: "Set ETHEREUM_RPC_URL in .env (default: https://ethereum-rpc.publicnode.com)",
126
+ }),
127
+ },
88
128
  ];
89
129
  function classifyError(error) {
90
130
  const message = error instanceof Error ? error.message : String(error);