apow-cli 0.4.0 → 0.6.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 +9 -4
- package/README.md +90 -27
- package/dist/bridge/constants.js +34 -0
- package/dist/bridge/debridge.js +151 -28
- package/dist/bridge/solana.js +13 -0
- package/dist/bridge/squid.js +54 -21
- package/dist/bridge/uniswap.js +184 -0
- package/dist/config.js +1 -0
- package/dist/dashboard.js +6 -2
- package/dist/errors.js +40 -0
- package/dist/fund.js +506 -133
- package/dist/index.js +10 -23
- package/dist/preflight.js +52 -0
- package/dist/wallet.js +24 -2
- package/dist/x402.js +45 -0
- package/package.json +3 -1
- package/skill.md +150 -101
package/dist/index.js
CHANGED
|
@@ -170,27 +170,10 @@ async function setupWizard() {
|
|
|
170
170
|
console.log("");
|
|
171
171
|
// Step 2: RPC
|
|
172
172
|
console.log(` ${ui.bold("Step 2/3: RPC")}`);
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
const { createPublicClient, http } = await Promise.resolve().then(() => __importStar(require("viem")));
|
|
178
|
-
const { base, baseSepolia } = await Promise.resolve().then(() => __importStar(require("viem/chains")));
|
|
179
|
-
const isSepolia = rpcUrl.toLowerCase().includes("sepolia");
|
|
180
|
-
const testClient = createPublicClient({
|
|
181
|
-
chain: isSepolia ? baseSepolia : base,
|
|
182
|
-
transport: http(rpcUrl),
|
|
183
|
-
});
|
|
184
|
-
const blockNumber = await testClient.getBlockNumber();
|
|
185
|
-
const networkName = isSepolia ? "Base Sepolia" : "Base mainnet";
|
|
186
|
-
ui.ok(`Connected — ${networkName}, block #${blockNumber.toLocaleString()}`);
|
|
187
|
-
if (isSepolia)
|
|
188
|
-
values.CHAIN = "baseSepolia";
|
|
189
|
-
}
|
|
190
|
-
catch {
|
|
191
|
-
ui.fail("Could not connect to RPC");
|
|
192
|
-
ui.hint("Continuing anyway — you can fix RPC_URL in .env later");
|
|
193
|
-
}
|
|
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)");
|
|
194
177
|
console.log("");
|
|
195
178
|
// Step 3: LLM (for minting)
|
|
196
179
|
console.log(` ${ui.bold("Step 3/3: LLM Provider (for minting)")}`);
|
|
@@ -277,10 +260,12 @@ async function main() {
|
|
|
277
260
|
});
|
|
278
261
|
program
|
|
279
262
|
.command("fund")
|
|
280
|
-
.description("Fund your wallet — bridge
|
|
281
|
-
.option("--
|
|
263
|
+
.description("Fund your wallet — bridge from Solana/Ethereum or swap on Base")
|
|
264
|
+
.option("--chain <chain>", "Source chain: solana, ethereum, base")
|
|
265
|
+
.option("--token <token>", "Source token: sol, eth, usdc")
|
|
282
266
|
.option("--key <base58>", "Solana private key for direct signing")
|
|
283
267
|
.option("--amount <eth>", "Target ETH amount (default: 0.005)")
|
|
268
|
+
.option("--no-swap", "Skip auto-split after bridging")
|
|
284
269
|
.hook("preAction", async () => {
|
|
285
270
|
await (0, preflight_1.runPreflight)("readonly");
|
|
286
271
|
})
|
|
@@ -513,6 +498,8 @@ async function main() {
|
|
|
513
498
|
port: 3847,
|
|
514
499
|
walletsPath,
|
|
515
500
|
rpcUrl: config_1.config.rpcUrl,
|
|
501
|
+
useX402: config_1.config.useX402,
|
|
502
|
+
privateKey: config_1.config.privateKey,
|
|
516
503
|
miningAgentAddress: config_1.config.miningAgentAddress,
|
|
517
504
|
agentCoinAddress: config_1.config.agentCoinAddress,
|
|
518
505
|
});
|
package/dist/preflight.js
CHANGED
|
@@ -38,11 +38,24 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
39
|
exports.runPreflight = runPreflight;
|
|
40
40
|
const viem_1 = require("viem");
|
|
41
|
+
const chains_1 = require("viem/chains");
|
|
41
42
|
const AgentCoin_json_1 = __importDefault(require("./abi/AgentCoin.json"));
|
|
42
43
|
const config_1 = require("./config");
|
|
43
44
|
const wallet_1 = require("./wallet");
|
|
45
|
+
const x402_1 = require("./x402");
|
|
44
46
|
const ui = __importStar(require("./ui"));
|
|
45
47
|
const agentCoinAbi = AgentCoin_json_1.default;
|
|
48
|
+
const USDC_ADDRESS = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
|
|
49
|
+
const USDC_DECIMALS = 6;
|
|
50
|
+
const erc20BalanceAbi = [
|
|
51
|
+
{
|
|
52
|
+
type: "function",
|
|
53
|
+
name: "balanceOf",
|
|
54
|
+
inputs: [{ name: "account", type: "address" }],
|
|
55
|
+
outputs: [{ name: "", type: "uint256" }],
|
|
56
|
+
stateMutability: "view",
|
|
57
|
+
},
|
|
58
|
+
];
|
|
46
59
|
async function runPreflight(level) {
|
|
47
60
|
const results = [];
|
|
48
61
|
// Check 1: Contract addresses set
|
|
@@ -79,6 +92,45 @@ async function runPreflight(level) {
|
|
|
79
92
|
fix: "Check internet connection or update RPC_URL in .env",
|
|
80
93
|
});
|
|
81
94
|
}
|
|
95
|
+
// Check x402: USDC balance when x402 mode is active
|
|
96
|
+
if (config_1.config.useX402 && wallet_1.account) {
|
|
97
|
+
try {
|
|
98
|
+
// Use a separate lightweight client to avoid chicken-and-egg
|
|
99
|
+
// (can't use x402 to check if we can pay for x402)
|
|
100
|
+
const checkClient = (0, viem_1.createPublicClient)({
|
|
101
|
+
chain: chains_1.base,
|
|
102
|
+
transport: (0, viem_1.http)("https://mainnet.base.org"),
|
|
103
|
+
});
|
|
104
|
+
const usdcBalance = (await checkClient.readContract({
|
|
105
|
+
address: USDC_ADDRESS,
|
|
106
|
+
abi: erc20BalanceAbi,
|
|
107
|
+
functionName: "balanceOf",
|
|
108
|
+
args: [wallet_1.account.address],
|
|
109
|
+
}));
|
|
110
|
+
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)();
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
const formatted = (0, viem_1.formatUnits)(usdcBalance, USDC_DECIMALS);
|
|
120
|
+
results.push({
|
|
121
|
+
label: `RPC: Alchemy x402 (${formatted} USDC available)`,
|
|
122
|
+
passed: true,
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
// USDC check failed — fall back silently
|
|
128
|
+
ui.warn("Could not check USDC balance — falling back to public RPC");
|
|
129
|
+
config_1.config.useX402 = false;
|
|
130
|
+
(0, x402_1.resetX402)();
|
|
131
|
+
(0, wallet_1.reinitClients)();
|
|
132
|
+
}
|
|
133
|
+
}
|
|
82
134
|
if (level === "wallet" || level === "mining") {
|
|
83
135
|
// Check 3: Private key valid
|
|
84
136
|
if (wallet_1.account) {
|
package/dist/wallet.js
CHANGED
|
@@ -1,16 +1,25 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.walletClient = exports.account = exports.publicClient = void 0;
|
|
4
|
+
exports.reinitClients = reinitClients;
|
|
4
5
|
exports.requireWallet = requireWallet;
|
|
5
6
|
exports.getEthBalance = getEthBalance;
|
|
6
7
|
const viem_1 = require("viem");
|
|
7
8
|
const accounts_1 = require("viem/accounts");
|
|
8
9
|
const erc8021_1 = require("ox/erc8021");
|
|
9
10
|
const config_1 = require("./config");
|
|
11
|
+
const x402_1 = require("./x402");
|
|
10
12
|
const DATA_SUFFIX = erc8021_1.Attribution.toDataSuffix({ codes: ["bc_6wfeb1kd"] });
|
|
13
|
+
function getTransport() {
|
|
14
|
+
if (config_1.config.useX402 && config_1.config.privateKey) {
|
|
15
|
+
return (0, x402_1.createX402Transport)(config_1.config.privateKey);
|
|
16
|
+
}
|
|
17
|
+
return (0, viem_1.http)(config_1.config.rpcUrl);
|
|
18
|
+
}
|
|
19
|
+
const transport = getTransport();
|
|
11
20
|
exports.publicClient = (0, viem_1.createPublicClient)({
|
|
12
21
|
chain: config_1.config.chain,
|
|
13
|
-
transport
|
|
22
|
+
transport,
|
|
14
23
|
});
|
|
15
24
|
exports.account = config_1.config.privateKey
|
|
16
25
|
? (0, accounts_1.privateKeyToAccount)(config_1.config.privateKey)
|
|
@@ -19,10 +28,23 @@ exports.walletClient = exports.account
|
|
|
19
28
|
? (0, viem_1.createWalletClient)({
|
|
20
29
|
account: exports.account,
|
|
21
30
|
chain: config_1.config.chain,
|
|
22
|
-
transport
|
|
31
|
+
transport,
|
|
23
32
|
dataSuffix: DATA_SUFFIX,
|
|
24
33
|
})
|
|
25
34
|
: null;
|
|
35
|
+
/** Reinitialize clients after config changes (e.g., x402 fallback). */
|
|
36
|
+
function reinitClients() {
|
|
37
|
+
const t = getTransport();
|
|
38
|
+
exports.publicClient = (0, viem_1.createPublicClient)({ chain: config_1.config.chain, transport: t });
|
|
39
|
+
if (exports.account) {
|
|
40
|
+
exports.walletClient = (0, viem_1.createWalletClient)({
|
|
41
|
+
account: exports.account,
|
|
42
|
+
chain: config_1.config.chain,
|
|
43
|
+
transport: t,
|
|
44
|
+
dataSuffix: DATA_SUFFIX,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
}
|
|
26
48
|
function requireWallet() {
|
|
27
49
|
if (!exports.account || !exports.walletClient) {
|
|
28
50
|
throw new Error("Wallet is not configured. Set PRIVATE_KEY in .env.");
|
package/dist/x402.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createX402Transport = createX402Transport;
|
|
4
|
+
exports.resetX402 = resetX402;
|
|
5
|
+
const accounts_1 = require("viem/accounts");
|
|
6
|
+
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;
|
|
26
|
+
}
|
|
27
|
+
function createX402Transport(privateKey) {
|
|
28
|
+
return (0, viem_1.custom)({
|
|
29
|
+
async request({ method, params }) {
|
|
30
|
+
const paidFetch = getPaidFetchSync(privateKey);
|
|
31
|
+
const response = await paidFetch(ALCHEMY_X402_BASE, {
|
|
32
|
+
method: "POST",
|
|
33
|
+
headers: { "Content-Type": "application/json" },
|
|
34
|
+
body: JSON.stringify({ jsonrpc: "2.0", method, params, id: 1 }),
|
|
35
|
+
});
|
|
36
|
+
const data = (await response.json());
|
|
37
|
+
if (data.error)
|
|
38
|
+
throw new Error(data.error.message);
|
|
39
|
+
return data.result;
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
function resetX402() {
|
|
44
|
+
_paidFetch = null;
|
|
45
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "apow-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Mine AGENT tokens on Base L2 with Agentic Proof of Work",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"apow",
|
|
@@ -40,6 +40,8 @@
|
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"@solana/web3.js": "^1.98.0",
|
|
43
|
+
"@x402/evm": "^2.8.0",
|
|
44
|
+
"@x402/fetch": "^2.8.0",
|
|
43
45
|
"commander": "^14.0.0",
|
|
44
46
|
"dotenv": "^17.2.3",
|
|
45
47
|
"openai": "^6.6.0",
|