nodpay 0.2.37 → 0.2.39
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/package.json +1 -1
- package/scripts/propose.mjs +31 -20
package/package.json
CHANGED
package/scripts/propose.mjs
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
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: from process.env.NODPAY_AGENT_KEY (real env > ~/.nodpay/.env file
|
|
9
|
+
* Agent key: from process.env.NODPAY_AGENT_KEY (real env > ~/.nodpay/.env file), or remote_wallet proxy.
|
|
10
10
|
* Chain config: resolved via --chain from @nodpay/core networks registry.
|
|
11
11
|
* Bundler: NodPay public proxy (override with OP_STORE_URL for self-hosted).
|
|
12
12
|
*
|
|
@@ -17,7 +17,6 @@
|
|
|
17
17
|
* --safe <address> - Wallet (Safe) address
|
|
18
18
|
* --counterfactual - Safe not yet deployed; include deployment in UserOp
|
|
19
19
|
* --human-signer-eoa <address> - Human's EOA signer address (for EOA mode)
|
|
20
|
-
* --remote-signer <url> - SafeClaw proxy URL for remote signing (mutually exclusive with --human-signer-eoa)
|
|
21
20
|
* --salt <nonce> - Salt nonce (required for counterfactual)
|
|
22
21
|
* --reuse-gas-from <shortHash> - Reuse gas values from a previous op (shortHash prefix of safeOpHash)
|
|
23
22
|
* --nonce <n> - Required. Use `txs` to find current nonce.
|
|
@@ -32,6 +31,7 @@ import { join, dirname } from 'path';
|
|
|
32
31
|
import { fileURLToPath } from 'url';
|
|
33
32
|
import { computeUserOpHash, ENTRYPOINT } from '@nodpay/core';
|
|
34
33
|
import { loadDotEnv, env, HOME } from './env.mjs';
|
|
34
|
+
import { loadConfig } from './config.mjs';
|
|
35
35
|
|
|
36
36
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
37
37
|
const PENDING_DIR = join(__dirname, '..', '.pending-txs');
|
|
@@ -85,30 +85,36 @@ const DEFAULT_SAFE = null; // always use --safe flag
|
|
|
85
85
|
const opStoreBase = env('OP_STORE_URL', 'https://nodpay.ai/api');
|
|
86
86
|
const BUNDLER_URL = `${opStoreBase}/bundler/${CHAIN_ID}`;
|
|
87
87
|
|
|
88
|
-
// --- Agent key:
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
: undefined;
|
|
88
|
+
// --- Agent key resolution: remote_wallet (config.json) or local key ---
|
|
89
|
+
const _config = loadConfig();
|
|
90
|
+
const _remoteWalletUrl = _config.remote_wallet || null;
|
|
92
91
|
|
|
93
92
|
let AGENT_ADDRESS;
|
|
94
93
|
let signHash;
|
|
95
94
|
let _localAgentKey; // only set in local mode, used for SDK init (EOA signer)
|
|
95
|
+
let _remoteWalletsCache = null; // cached wallets from remote_wallet fetch
|
|
96
96
|
|
|
97
|
-
if (
|
|
98
|
-
//
|
|
99
|
-
const
|
|
100
|
-
if (!
|
|
101
|
-
const err = await
|
|
97
|
+
if (_remoteWalletUrl) {
|
|
98
|
+
// remote_wallet mode (config.json): get agent address from wallets, sign via proxy
|
|
99
|
+
const walletsRes = await fetch(`${_remoteWalletUrl.replace(/\/$/, '')}/wallets`);
|
|
100
|
+
if (!walletsRes.ok) {
|
|
101
|
+
const err = await walletsRes.json().catch(() => ({}));
|
|
102
102
|
console.error(JSON.stringify({
|
|
103
|
-
error: err.error || 'Failed to get
|
|
104
|
-
code: err.code || '
|
|
103
|
+
error: err.error || 'Failed to get wallets from remote_wallet',
|
|
104
|
+
code: err.code || 'REMOTE_WALLET_ERROR'
|
|
105
105
|
}));
|
|
106
106
|
process.exit(1);
|
|
107
107
|
}
|
|
108
|
-
|
|
108
|
+
const wallets = await walletsRes.json();
|
|
109
|
+
_remoteWalletsCache = wallets;
|
|
110
|
+
if (!wallets.length || !wallets[0].agentSigner) {
|
|
111
|
+
console.error(JSON.stringify({ error: 'No wallets found on remote_wallet' }));
|
|
112
|
+
process.exit(1);
|
|
113
|
+
}
|
|
114
|
+
AGENT_ADDRESS = wallets[0].agentSigner;
|
|
109
115
|
|
|
110
116
|
signHash = async (hash) => {
|
|
111
|
-
const signRes = await fetch(`${
|
|
117
|
+
const signRes = await fetch(`${_remoteWalletUrl.replace(/\/$/, '')}/sign`, {
|
|
112
118
|
method: 'POST',
|
|
113
119
|
headers: { 'Content-Type': 'application/json' },
|
|
114
120
|
body: JSON.stringify({ hash })
|
|
@@ -123,7 +129,7 @@ if (_remoteSignerUrl) {
|
|
|
123
129
|
// Local mode: read key from process.env (loaded from real env or ~/.nodpay/.env)
|
|
124
130
|
const NODPAY_AGENT_KEY = env('NODPAY_AGENT_KEY');
|
|
125
131
|
if (!NODPAY_AGENT_KEY) {
|
|
126
|
-
console.error(JSON.stringify({ error: 'Missing NODPAY_AGENT_KEY — set env var, add to ~/.nodpay/.env, or
|
|
132
|
+
console.error(JSON.stringify({ error: 'Missing NODPAY_AGENT_KEY — set env var, add to ~/.nodpay/.env, or set remote_wallet in ~/.nodpay/config.json' }));
|
|
127
133
|
process.exit(1);
|
|
128
134
|
}
|
|
129
135
|
_localAgentKey = NODPAY_AGENT_KEY;
|
|
@@ -160,9 +166,9 @@ const passkeyVerifier = getArg('--passkey-verifier') || '0x445a0683e494ea0c5AF3E
|
|
|
160
166
|
const recoverySigner = getArg('--recovery-signer');
|
|
161
167
|
const isPasskey = !!(passkeyX && passkeyY);
|
|
162
168
|
|
|
163
|
-
//
|
|
164
|
-
if (
|
|
165
|
-
console.error(JSON.stringify({ error: '
|
|
169
|
+
// remote_wallet + --human-signer-eoa is not supported
|
|
170
|
+
if (_remoteWalletUrl && humanSigner) {
|
|
171
|
+
console.error(JSON.stringify({ error: 'remote_wallet and --human-signer-eoa cannot be combined. Remote mode only supports passkey wallets.' }));
|
|
166
172
|
process.exit(1);
|
|
167
173
|
}
|
|
168
174
|
|
|
@@ -179,8 +185,13 @@ if (!ethers.isAddress(to)) {
|
|
|
179
185
|
const SAFE_ADDRESS = safeOverride || DEFAULT_SAFE;
|
|
180
186
|
|
|
181
187
|
// Read optional wallet JSON for rpId (SafeClaw cross-origin passkey support)
|
|
188
|
+
// In remote_wallet mode, wallets were already fetched — use that data.
|
|
182
189
|
let walletRpId = null;
|
|
183
|
-
if (SAFE_ADDRESS) {
|
|
190
|
+
if (SAFE_ADDRESS && _remoteWalletUrl && _remoteWalletsCache) {
|
|
191
|
+
const match = _remoteWalletsCache.find(w => w.safe?.toLowerCase() === SAFE_ADDRESS.toLowerCase());
|
|
192
|
+
if (match?.rpId) walletRpId = match.rpId;
|
|
193
|
+
}
|
|
194
|
+
if (!walletRpId && SAFE_ADDRESS) {
|
|
184
195
|
const walletJsonPath = join(HOME, '.nodpay', 'wallets', `${SAFE_ADDRESS}.json`);
|
|
185
196
|
if (existsSync(walletJsonPath)) {
|
|
186
197
|
try {
|