nodpay 0.2.32 → 0.2.33
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 +7 -5
- package/package.json +1 -1
- package/scripts/propose.mjs +44 -1
package/SKILL.md
CHANGED
|
@@ -31,7 +31,7 @@ You propose payments, your human approves with one tap. 2-of-3 multisig — you
|
|
|
31
31
|
| **Zero Trust** | **End-to-end verification:** no party is implicitly trusted. Server validates signatures; client and CLI independently verify server responses (decode calldata → recompute hash → recover signer → check owner set). The blockchain serves as the canonical source of truth. |
|
|
32
32
|
| **Disaster Recovery** | **Key redundancy & continuity:** uses a locally-stored 12-word mnemonic as recovery signer. Any two of the three signers can reconstruct authority to unlock the wallet, ensuring the user is never locked out by a single lost credential. |
|
|
33
33
|
| **Hardened Key Isolation** | `keygen` writes to `~/.nodpay/.env` (chmod 600). The CLI reads the key via file I/O at runtime — not passed through CLI arguments, environment variables, or stdout. Only the public address is returned to the caller. |
|
|
34
|
-
| **Keyless & Non-Custodial Server** | **Stateless relayer:** the server stores no private keys and
|
|
34
|
+
| **Keyless & Non-Custodial Server** | **Stateless relayer:** the server stores no private keys, no passkey credentials, and no session state. Identity verification uses CREATE2 address prediction + cryptographic signatures — zero trusted storage. Funds stay on-chain if the server goes offline. |
|
|
35
35
|
|
|
36
36
|
All wallet parameters (Safe address, passkey X/Y, recovery signer address) are public key material — safe to store, pass in URLs, and include in CLI flags.
|
|
37
37
|
|
|
@@ -181,16 +181,18 @@ Wallet address is the same across all chains. **Ask which chain if not specified
|
|
|
181
181
|
|
|
182
182
|
## Reconnect
|
|
183
183
|
|
|
184
|
-
Browser data cleared? Build a reconnect link from the wallet's stored parameters (all public — no secrets)
|
|
184
|
+
Browser data cleared? Build a reconnect link from the wallet's stored parameters (all public — no secrets).
|
|
185
|
+
|
|
186
|
+
**You MUST include `signerType`** — the client uses it to show the correct verification flow.
|
|
185
187
|
|
|
186
188
|
**Passkey:**
|
|
187
189
|
```
|
|
188
|
-
https://nodpay.ai/?agent=AGENT_SIGNER&safe=SAFE_ADDRESS&recovery=RECOVERY_SIGNER&x=PASSKEY_X&y=PASSKEY_Y
|
|
190
|
+
https://nodpay.ai/?agent=AGENT_SIGNER&safe=SAFE_ADDRESS&recovery=RECOVERY_SIGNER&signerType=passkey&x=PASSKEY_X&y=PASSKEY_Y
|
|
189
191
|
```
|
|
190
192
|
|
|
191
193
|
**EOA:**
|
|
192
194
|
```
|
|
193
|
-
https://nodpay.ai/?agent=AGENT_SIGNER&safe=SAFE_ADDRESS&recovery=RECOVERY_SIGNER&eoa=HUMAN_SIGNER_EOA
|
|
195
|
+
https://nodpay.ai/?agent=AGENT_SIGNER&safe=SAFE_ADDRESS&recovery=RECOVERY_SIGNER&signerType=eoa&eoa=HUMAN_SIGNER_EOA
|
|
194
196
|
```
|
|
195
197
|
|
|
196
|
-
User opens → verifies identity → wallet restored.
|
|
198
|
+
User opens → verifies identity (passkey assertion or MetaMask connect) → wallet restored.
|
package/package.json
CHANGED
package/scripts/propose.mjs
CHANGED
|
@@ -309,7 +309,50 @@ try {
|
|
|
309
309
|
|
|
310
310
|
const safe4337Pack = await Safe4337Pack.init(initOptions);
|
|
311
311
|
|
|
312
|
-
|
|
312
|
+
let safeAddress = await safe4337Pack.protocolKit.getAddress();
|
|
313
|
+
|
|
314
|
+
// --- Ethereum mainnet: force L2 singleton for cross-chain address consistency ---
|
|
315
|
+
//
|
|
316
|
+
// Safe SDK defaults to the L1 singleton on chainId 1, but all other chains use the L2
|
|
317
|
+
// singleton. Different singleton → different CREATE2 address → cross-chain mismatch.
|
|
318
|
+
//
|
|
319
|
+
// The L2 singleton (0x29fc...) IS deployed on Ethereum mainnet. Using it there costs
|
|
320
|
+
// ~2.3% more gas per tx (~$0.14 at 15 Gwei) due to extra event emissions — acceptable.
|
|
321
|
+
//
|
|
322
|
+
// Trade-off: safe.global may not fully index L2-singleton Safes on mainnet (their L1
|
|
323
|
+
// indexer uses trace-based filtering by known singleton addresses). NodPay uses its own
|
|
324
|
+
// op-store, so this doesn't affect us.
|
|
325
|
+
//
|
|
326
|
+
// Long-term plan: support separate L1/L2 wallet families — user chooses at creation time.
|
|
327
|
+
// For now, we unify on L2 singleton across all chains for address consistency.
|
|
328
|
+
if (
|
|
329
|
+
isCounterfactual &&
|
|
330
|
+
CHAIN_ID === '1' &&
|
|
331
|
+
SAFE_ADDRESS &&
|
|
332
|
+
safeAddress.toLowerCase() !== SAFE_ADDRESS.toLowerCase()
|
|
333
|
+
) {
|
|
334
|
+
const Safe = (await import('@safe-global/protocol-kit')).default;
|
|
335
|
+
// getPredictedSafe() returns the full config Safe4337Pack assembled — owners, threshold,
|
|
336
|
+
// module setup (to/data), fallbackHandler, salt, etc. We re-init with the same config
|
|
337
|
+
// but isL1SafeSingleton=false so the SDK picks L2 singleton.
|
|
338
|
+
const predictedSafe = safe4337Pack.protocolKit.getPredictedSafe();
|
|
339
|
+
safe4337Pack.protocolKit = await Safe.init({
|
|
340
|
+
provider: RPC_URL,
|
|
341
|
+
signer: initOptions.signer,
|
|
342
|
+
isL1SafeSingleton: false,
|
|
343
|
+
predictedSafe,
|
|
344
|
+
});
|
|
345
|
+
safeAddress = await safe4337Pack.protocolKit.getAddress();
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// Safety check: if --safe was explicitly given, the computed address MUST match.
|
|
349
|
+
// Mismatch means owner set / salt / SDK version differs from wallet creation — abort.
|
|
350
|
+
if (SAFE_ADDRESS && safeAddress.toLowerCase() !== SAFE_ADDRESS.toLowerCase()) {
|
|
351
|
+
console.error(JSON.stringify({
|
|
352
|
+
error: `Address mismatch: --safe ${SAFE_ADDRESS} but SDK computed ${safeAddress}. Check --human-signer-eoa, --recovery-signer, and --salt match the original wallet creation params.`
|
|
353
|
+
}));
|
|
354
|
+
process.exit(1);
|
|
355
|
+
}
|
|
313
356
|
|
|
314
357
|
// Auto-detect deployment status: if Safe is already deployed, drop counterfactual
|
|
315
358
|
if (isCounterfactual) {
|