nodpay 0.2.16 → 0.2.18
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 +17 -6
- package/package.json +1 -1
- package/scripts/keygen.mjs +3 -2
- package/scripts/propose.mjs +7 -5
package/SKILL.md
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: nodpay
|
|
3
3
|
description: Propose on-chain payments from a shared wallet. Use when user asks to send crypto, make a payment, or create a shared wallet.
|
|
4
|
+
metadata:
|
|
5
|
+
{
|
|
6
|
+
"openclaw":
|
|
7
|
+
{
|
|
8
|
+
"requires": { "bins": ["npx", "curl"] },
|
|
9
|
+
"install": [{ "id": "node", "kind": "node", "package": "nodpay", "bins": ["npx"], "label": "Install NodPay CLI (npm)" }]
|
|
10
|
+
},
|
|
11
|
+
"credentials": "Agent signing key stored in ~/.nodpay/.env (generated by npx nodpay keygen, never exposed to agent context)",
|
|
12
|
+
"persistence": ["~/.nodpay/.env (agent key, chmod 600)", "~/.nodpay/wallets/*.json (wallet info, public key material)"],
|
|
13
|
+
"network": ["nodpay.ai (op-store relay + wallet creation UI)", "Public RPC endpoints via --chain"]
|
|
14
|
+
}
|
|
4
15
|
---
|
|
5
16
|
|
|
6
17
|
# NodPay — Agent Wallet
|
|
@@ -13,11 +24,11 @@ You propose payments, your human approves with one tap. 2-of-3 multisig — you
|
|
|
13
24
|
|
|
14
25
|
## Trust Model
|
|
15
26
|
|
|
16
|
-
- **Your private key never leaves disk.** `keygen` writes to
|
|
27
|
+
- **Your private key never leaves disk.** `keygen` writes to `~/.nodpay/.env` (chmod 600) — never in stdout, context, or logs.
|
|
17
28
|
- **You can only propose.** Execution requires human co-sign (passkey). No single party can move funds.
|
|
18
|
-
- **Wallet info is public key material.** Safe address, passkey X/Y, recovery signer
|
|
29
|
+
- **Wallet info is public key material.** Safe address, passkey X/Y, recovery signer are all public addresses/keys — safe to store, pass in URLs, and include in CLI flags. No secrets are ever exposed in commands or URLs.
|
|
19
30
|
- **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 a stateless relay.** It forwards signed operations to the chain — no private keys, no custody, no accounts.
|
|
31
|
+
- **NodPay server is a stateless relay.** It forwards signed operations to the chain — no private keys, no custody, no accounts. If the server goes offline, funds stay safe on-chain.
|
|
21
32
|
- **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
33
|
- **Verify the agent address matches yours** before storing wallet info. Mismatch = wrong key binding.
|
|
23
34
|
|
|
@@ -48,9 +59,9 @@ Outputs your **public address** only. No restart needed.
|
|
|
48
59
|
> I've set up a shared wallet for us — takes 30 seconds:
|
|
49
60
|
> https://nodpay.ai/?agent=YOUR_AGENT_ADDRESS
|
|
50
61
|
|
|
51
|
-
|
|
62
|
+
The official domain is `nodpay.ai` — do not confuse with similarly named services.
|
|
52
63
|
|
|
53
|
-
User copies back wallet info → store in
|
|
64
|
+
User copies back wallet info → store in `~/.nodpay/wallets/<safe-address>.json`.
|
|
54
65
|
|
|
55
66
|
After creation, tell the user the address works on any chain. Offer testnet only if they ask.
|
|
56
67
|
|
|
@@ -86,7 +97,7 @@ Check before proposing — shows nonce and pending ops.
|
|
|
86
97
|
## Data
|
|
87
98
|
|
|
88
99
|
```
|
|
89
|
-
|
|
100
|
+
~/.nodpay/
|
|
90
101
|
.env # agent key (chmod 600)
|
|
91
102
|
wallets/
|
|
92
103
|
0xAbC...123.json # one file per wallet
|
package/package.json
CHANGED
package/scripts/keygen.mjs
CHANGED
|
@@ -13,13 +13,14 @@
|
|
|
13
13
|
|
|
14
14
|
import { Wallet } from 'ethers';
|
|
15
15
|
import { readFileSync, writeFileSync, mkdirSync, existsSync, chmodSync } from 'fs';
|
|
16
|
-
import { resolve, dirname } from 'path';
|
|
16
|
+
import { resolve, dirname, join } from 'path';
|
|
17
17
|
|
|
18
18
|
const args = process.argv.slice(2);
|
|
19
19
|
const envFileIdx = args.indexOf('--env-file');
|
|
20
|
+
const HOME = process.env.HOME || process.env.USERPROFILE || '/tmp';
|
|
20
21
|
const envFile = envFileIdx !== -1
|
|
21
22
|
? resolve(args[envFileIdx + 1])
|
|
22
|
-
:
|
|
23
|
+
: join(HOME, '.nodpay', '.env');
|
|
23
24
|
|
|
24
25
|
const ENV_VAR = 'NODPAY_AGENT_KEY';
|
|
25
26
|
|
package/scripts/propose.mjs
CHANGED
|
@@ -64,12 +64,14 @@ if (chainArg) {
|
|
|
64
64
|
}
|
|
65
65
|
const ENTRYPOINT_ADDRESS = ENTRYPOINT;
|
|
66
66
|
|
|
67
|
-
|
|
67
|
+
const HOME = process.env.HOME || process.env.USERPROFILE || '/tmp';
|
|
68
|
+
|
|
69
|
+
// SECURITY: Read agent key from ~/.nodpay/.env file (chmod 600), not from
|
|
68
70
|
// process.env or CLI args. The key is loaded at runtime by the script itself,
|
|
69
71
|
// so it never passes through the LLM agent's context or conversation history.
|
|
70
72
|
function loadAgentKey() {
|
|
71
73
|
try {
|
|
72
|
-
const envPath = join(
|
|
74
|
+
const envPath = join(HOME, '.nodpay', '.env');
|
|
73
75
|
const lines = readFileSync(envPath, 'utf8').split('\n');
|
|
74
76
|
for (const line of lines) {
|
|
75
77
|
const trimmed = line.trim();
|
|
@@ -89,10 +91,10 @@ const DEFAULT_SAFE = null; // always use --safe flag
|
|
|
89
91
|
// agents don't need their own bundler API key. This is a thin relay — it
|
|
90
92
|
// forwards the UserOp to a bundler service and returns the result. The proxy
|
|
91
93
|
// only sees the already-signed (partial) UserOp; it cannot modify or execute it.
|
|
92
|
-
//
|
|
94
|
+
// Optional overrides (OP_STORE_URL, WEB_APP_URL) also read from ~/.nodpay/.env.
|
|
93
95
|
function loadDotEnvVar(name, fallback) {
|
|
94
96
|
try {
|
|
95
|
-
const envPath = join(
|
|
97
|
+
const envPath = join(HOME, '.nodpay', '.env');
|
|
96
98
|
const lines = readFileSync(envPath, 'utf8').split('\n');
|
|
97
99
|
for (const line of lines) {
|
|
98
100
|
const trimmed = line.trim();
|
|
@@ -107,7 +109,7 @@ const opStoreBase = loadDotEnvVar('OP_STORE_URL', 'https://nodpay.ai/api');
|
|
|
107
109
|
const BUNDLER_URL = `${opStoreBase}/bundler/${CHAIN_ID}`;
|
|
108
110
|
|
|
109
111
|
if (!NODPAY_AGENT_KEY) {
|
|
110
|
-
console.error(JSON.stringify({ error: 'Missing NODPAY_AGENT_KEY in
|
|
112
|
+
console.error(JSON.stringify({ error: 'Missing NODPAY_AGENT_KEY in ~/.nodpay/.env — run npx nodpay keygen first' }));
|
|
111
113
|
process.exit(1);
|
|
112
114
|
}
|
|
113
115
|
|