nodpay 0.2.14 → 0.2.15
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/SKILL.md +1 -1
- package/package.json +1 -1
- package/scripts/propose.mjs +18 -15
package/SKILL.md
CHANGED
|
@@ -17,7 +17,7 @@ You propose payments, your human approves with one tap. 2-of-3 multisig — you
|
|
|
17
17
|
- **You can only propose.** Execution requires human co-sign (passkey). No single party can move funds.
|
|
18
18
|
- **Wallet info is public key material.** Safe address, passkey X/Y, recovery signer — all safe to store.
|
|
19
19
|
- **Recovery key is user-held.** The 12-word phrase generates a third signer the user controls. If the agent key or passkey is lost, the user can still recover funds — the agent never has unilateral access.
|
|
20
|
-
- **NodPay server is stateless.** It
|
|
20
|
+
- **NodPay server is a stateless relay.** It forwards signed operations to the chain — no private keys, no custody, no accounts. Self-hostable via `OP_STORE_URL`. If the server goes offline, funds stay safe on-chain.
|
|
21
21
|
- **The web app is a convenience layer.** It helps users create wallets and approve transactions. All crypto operations happen client-side; nothing sensitive is stored server-side.
|
|
22
22
|
- **Verify the agent address matches yours** before storing wallet info. Mismatch = wrong key binding.
|
|
23
23
|
|
package/package.json
CHANGED
package/scripts/propose.mjs
CHANGED
|
@@ -6,13 +6,16 @@
|
|
|
6
6
|
* The agent signs first (1 of 2). The serialized SafeOperation is
|
|
7
7
|
* output so the web app can have the user co-sign and submit.
|
|
8
8
|
*
|
|
9
|
-
* Agent key
|
|
9
|
+
* Agent key: read from .nodpay/.env (never from env vars or CLI args).
|
|
10
|
+
* Chain config: resolved via --chain from @nodpay/core networks registry.
|
|
11
|
+
* Bundler: NodPay public proxy (override with OP_STORE_URL for self-hosted).
|
|
10
12
|
*
|
|
11
13
|
* Args:
|
|
14
|
+
* --chain <name> - Chain name (ethereum, base, sepolia, etc.)
|
|
12
15
|
* --to <address> - Recipient address
|
|
13
16
|
* --value-eth <amount> - Value in ETH (default: 0)
|
|
14
17
|
* --purpose <text> - Human-readable purpose
|
|
15
|
-
* --safe <address> -
|
|
18
|
+
* --safe <address> - Wallet (Safe) address
|
|
16
19
|
* --counterfactual - Safe not yet deployed; include deployment in UserOp
|
|
17
20
|
* --user-signer <address> - User's signer address (required for counterfactual)
|
|
18
21
|
* --salt <nonce> - Salt nonce (required for counterfactual)
|
|
@@ -43,6 +46,9 @@ const chainArg = process.argv.includes('--chain')
|
|
|
43
46
|
? process.argv[process.argv.indexOf('--chain') + 1]
|
|
44
47
|
: null;
|
|
45
48
|
|
|
49
|
+
// CHAIN RESOLUTION: --chain flag looks up RPC and chain ID from @nodpay/core's
|
|
50
|
+
// network registry (public RPC endpoints). No secrets involved — these are the
|
|
51
|
+
// same public endpoints listed on chainlist.org.
|
|
46
52
|
let RPC_URL, CHAIN_ID;
|
|
47
53
|
if (chainArg) {
|
|
48
54
|
const net = allChains[chainArg];
|
|
@@ -50,7 +56,7 @@ if (chainArg) {
|
|
|
50
56
|
console.error(`Error: Unknown chain "${chainArg}". Supported: ${Object.keys(allChains).join(', ')}`);
|
|
51
57
|
process.exit(1);
|
|
52
58
|
}
|
|
53
|
-
RPC_URL =
|
|
59
|
+
RPC_URL = net.rpcUrl;
|
|
54
60
|
CHAIN_ID = String(net.chainId);
|
|
55
61
|
} else {
|
|
56
62
|
RPC_URL = process.env.RPC_URL;
|
|
@@ -83,15 +89,13 @@ function loadAgentKey() {
|
|
|
83
89
|
const NODPAY_AGENT_KEY = loadAgentKey();
|
|
84
90
|
const DEFAULT_SAFE = process.env.SAFE_ADDRESS;
|
|
85
91
|
|
|
86
|
-
//
|
|
87
|
-
//
|
|
88
|
-
//
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
const opStoreBase = process.env.OP_STORE_URL ||
|
|
92
|
-
const BUNDLER_URL =
|
|
93
|
-
? `https://api.pimlico.io/v2/${CHAIN_ID}/rpc?apikey=${PIMLICO_API_KEY}`
|
|
94
|
-
: `${opStoreBase}/bundler/${CHAIN_ID}`;
|
|
92
|
+
// BUNDLER: NodPay provides a public bundler proxy at nodpay.ai/api/bundler so
|
|
93
|
+
// agents don't need their own bundler API key. This is a thin relay — it
|
|
94
|
+
// forwards the UserOp to a bundler service and returns the result. The proxy
|
|
95
|
+
// only sees the already-signed (partial) UserOp; it cannot modify or execute it.
|
|
96
|
+
// For self-hosted setups, override with OP_STORE_URL env var.
|
|
97
|
+
const opStoreBase = process.env.OP_STORE_URL || 'https://nodpay.ai/api';
|
|
98
|
+
const BUNDLER_URL = `${opStoreBase}/bundler/${CHAIN_ID}`;
|
|
95
99
|
|
|
96
100
|
if (!NODPAY_AGENT_KEY) {
|
|
97
101
|
console.error(JSON.stringify({ error: 'Missing NODPAY_AGENT_KEY in .nodpay/.env — run npx nodpay keygen first' }));
|
|
@@ -320,8 +324,7 @@ try {
|
|
|
320
324
|
const customNonceArg = getArg('--nonce');
|
|
321
325
|
const reuseGasFrom = getArg('--reuse-gas-from'); // shortHash of a previous op to copy gas values from
|
|
322
326
|
let txOptions = {};
|
|
323
|
-
const
|
|
324
|
-
const opStoreUrl = process.env.OP_STORE_URL || (isProd ? 'https://nodpay.ai/api' : 'http://localhost:8766');
|
|
327
|
+
const opStoreUrl = process.env.OP_STORE_URL || 'https://nodpay.ai/api';
|
|
325
328
|
const safeAddr = await safe4337Pack.protocolKit.getAddress();
|
|
326
329
|
|
|
327
330
|
// Determine nonce: on-chain nonce is the source of truth.
|
|
@@ -507,7 +510,7 @@ try {
|
|
|
507
510
|
result.opStoreError = storeData.error || `HTTP ${storeRes.status}`;
|
|
508
511
|
}
|
|
509
512
|
if (storeData.shortHash) {
|
|
510
|
-
const webBase = process.env.WEB_APP_URL ||
|
|
513
|
+
const webBase = process.env.WEB_APP_URL || 'https://nodpay.ai/';
|
|
511
514
|
const purposeParam = purpose && purpose !== 'Unspecified' ? `&purpose=${encodeURIComponent(purpose)}` : '';
|
|
512
515
|
approveUrl = `${webBase}approve?safeOpHash=${storeData.safeOpHash}${purposeParam}`;
|
|
513
516
|
result.approveUrl = approveUrl;
|