neozip-cli 0.90.0 → 0.95.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.
Files changed (74) hide show
  1. package/AGENTS.md +93 -0
  2. package/CHANGELOG.md +58 -1
  3. package/DOCUMENTATION.md +22 -30
  4. package/README.md +104 -42
  5. package/dist/src/account/account-state.js +95 -0
  6. package/dist/src/account/format-account-status.js +62 -0
  7. package/dist/src/account/identity-provision.js +79 -0
  8. package/dist/src/account/identity-wrap.js +106 -0
  9. package/dist/src/account/profile-crypto.js +85 -0
  10. package/dist/src/account/profile-store.js +129 -0
  11. package/dist/src/account/require-account.js +32 -0
  12. package/dist/src/account/types.js +3 -0
  13. package/dist/src/account/wallet-evm.js +46 -0
  14. package/dist/src/account/wallet-setup.js +33 -0
  15. package/dist/src/archive/crypto-self.js +117 -0
  16. package/dist/src/archive/identity-key.js +217 -0
  17. package/dist/src/archive/recipient-lookup.js +61 -0
  18. package/dist/src/cli/output.js +100 -0
  19. package/dist/src/cli/params.js +122 -0
  20. package/dist/src/cli/schema.js +186 -0
  21. package/dist/src/cli/validate.js +119 -0
  22. package/dist/src/commands/mintTimestampProof.js +26 -14
  23. package/dist/src/config/ConfigSetup.js +82 -423
  24. package/dist/src/connect/command.js +364 -0
  25. package/dist/src/connection/bootstrap.js +50 -0
  26. package/dist/src/connection/cli-guidance.js +101 -0
  27. package/dist/src/connection/cli-prefs.js +180 -0
  28. package/dist/src/connection/cli-settings.js +140 -0
  29. package/dist/src/connection/cli-types.js +14 -0
  30. package/dist/src/connection/coordinator.js +83 -0
  31. package/dist/src/connection/credentials.js +33 -0
  32. package/dist/src/connection/crypto.js +96 -0
  33. package/dist/src/connection/dump.js +117 -0
  34. package/dist/src/connection/funding.js +187 -0
  35. package/dist/src/connection/incomplete-setup.js +89 -0
  36. package/dist/src/connection/interactive.js +871 -0
  37. package/dist/src/connection/legacy-profile-reader.js +87 -0
  38. package/dist/src/connection/magic-link.js +142 -0
  39. package/dist/src/connection/migrate.js +115 -0
  40. package/dist/src/connection/onboarding.js +616 -0
  41. package/dist/src/connection/origin.js +69 -0
  42. package/dist/src/connection/phase.js +101 -0
  43. package/dist/src/connection/phone.js +26 -0
  44. package/dist/src/connection/promote-active.js +56 -0
  45. package/dist/src/connection/reset.js +56 -0
  46. package/dist/src/connection/status-report.js +52 -0
  47. package/dist/src/connection/store.js +406 -0
  48. package/dist/src/connection/token-auth.js +44 -0
  49. package/dist/src/connection/types.js +3 -0
  50. package/dist/src/connection/wallet-json-migration.js +155 -0
  51. package/dist/src/connection/wallet-login.js +65 -0
  52. package/dist/src/connection/wallet-setup.js +83 -0
  53. package/dist/src/constants/wallet-identity.js +14 -0
  54. package/dist/src/exit-codes.js +54 -10
  55. package/dist/src/neolist.js +93 -9
  56. package/dist/src/neounzip.js +217 -59
  57. package/dist/src/neozip/blockchain.js +18 -18
  58. package/dist/src/neozip/createZip.js +114 -91
  59. package/dist/src/neozip/upgradeZip.js +14 -11
  60. package/dist/src/neozip.js +252 -75
  61. package/dist/src/skills/command.js +256 -0
  62. package/dist/src/skills/locate.js +99 -0
  63. package/dist/src/util/mask.js +34 -0
  64. package/dist/src/util/token-service-fetch.js +26 -0
  65. package/env.example +18 -85
  66. package/package.json +89 -82
  67. package/skills/neozip-connect/SKILL.md +95 -0
  68. package/skills/neozip-create/SKILL.md +57 -0
  69. package/skills/neozip-extract/SKILL.md +58 -0
  70. package/skills/neozip-legacy/SKILL.md +48 -0
  71. package/skills/neozip-list/SKILL.md +56 -0
  72. package/skills/neozip-shared/SKILL.md +60 -0
  73. package/dist/src/commands/verifyEmail.js +0 -146
  74. package/dist/src/config/ConfigStore.js +0 -406
@@ -0,0 +1,187 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isLowWalletBalance = isLowWalletBalance;
4
+ exports.formatLowBalanceFundingHint = formatLowBalanceFundingHint;
5
+ exports.connectFund = connectFund;
6
+ exports.formatFundResult = formatFundResult;
7
+ /**
8
+ * neozip connect fund — request native gas for the local Data Wallet from the
9
+ * Token Service funding API.
10
+ *
11
+ * The Token Service sends a small fixed grant (policy-defined, e.g. 0.001 ETH,
12
+ * 4-hour cooldown) to the user's primary linked Data Wallet so on-chain
13
+ * operations can pay for gas. The recipient is chosen server-side from the
14
+ * account's primary wallet link — the client cannot redirect funds.
15
+ *
16
+ * Actions:
17
+ * policy Show the grant size/cooldown for a chain (no auth).
18
+ * status Show eligibility + recent grants (Bearer).
19
+ * request Request a grant to the Data Wallet (Bearer). [default]
20
+ */
21
+ const neozip_blockchain_1 = require("neozip-blockchain");
22
+ const token_service_1 = require("neozip-blockchain/token-service");
23
+ const origin_1 = require("./origin");
24
+ const cli_prefs_1 = require("./cli-prefs");
25
+ const wallet_login_1 = require("./wallet-login");
26
+ const store_1 = require("./store");
27
+ const FAUCET_HINT = "Or get testnet ETH from https://www.coinbase.com/faucets/base-ethereum-sepolia-faucet";
28
+ /** Typical Token Service grant size — balances below this cannot reliably pay for gas. */
29
+ const LOW_BALANCE_ETH = 0.001;
30
+ /** True when the wallet likely needs a funding grant before on-chain operations. */
31
+ function isLowWalletBalance(balanceEth) {
32
+ const n = typeof balanceEth === "number" ? balanceEth : Number.parseFloat(balanceEth);
33
+ return Number.isFinite(n) && n < LOW_BALANCE_ETH;
34
+ }
35
+ /** One-line hint for blockchain summaries and insufficient-balance errors. */
36
+ function formatLowBalanceFundingHint() {
37
+ return "Low balance — request gas from the Token Service: neozip connect fund";
38
+ }
39
+ function resolveChain(input) {
40
+ if (typeof input.chainId === "number" && Number.isFinite(input.chainId)) {
41
+ return { chainId: input.chainId, network: input.network?.trim() || "" };
42
+ }
43
+ const network = (0, cli_prefs_1.resolveNetwork)(input.network);
44
+ const chainId = (0, neozip_blockchain_1.getChainIdByName)(network);
45
+ return { chainId: chainId ?? null, network };
46
+ }
47
+ async function connectFund(input) {
48
+ const action = input.action ?? "request";
49
+ const origin = (0, origin_1.resolveTokenServiceOrigin)(input.tokenServiceUrl);
50
+ const { chainId, network } = resolveChain(input);
51
+ if (chainId == null) {
52
+ return {
53
+ success: false,
54
+ action,
55
+ network,
56
+ chainId: null,
57
+ message: network
58
+ ? `Unknown network "${network}". Pass --chain <id> or a supported --network name.`
59
+ : "Could not resolve a chain. Pass --chain <id> or --network <name>.",
60
+ };
61
+ }
62
+ if (action === "policy") {
63
+ try {
64
+ const res = await (0, token_service_1.getFundingPolicy)(origin, chainId);
65
+ return {
66
+ success: true,
67
+ action,
68
+ network: res.network || network,
69
+ chainId: res.chainId,
70
+ policy: res.policy,
71
+ message: res.policy.enabled
72
+ ? `Funding is available on ${res.network || network} (chain ${res.chainId}): ${res.policy.grantEth} per grant, ${res.policy.cooldownHours}h cooldown.`
73
+ : `Funding is not enabled on ${res.network || network} (chain ${res.chainId}).`,
74
+ };
75
+ }
76
+ catch (err) {
77
+ return fundError(action, network, chainId, err);
78
+ }
79
+ }
80
+ // status + request both require a Bearer token. Renew silently if possible.
81
+ await (0, wallet_login_1.ensureFreshTokenServiceToken)({ tokenServiceUrl: input.tokenServiceUrl });
82
+ (0, store_1.applyActiveConnectionToEnv)();
83
+ const secrets = (0, store_1.readActiveConnectionSecrets)();
84
+ const accessToken = secrets?.accessToken?.trim();
85
+ const meta = (0, store_1.getActiveConnection)();
86
+ const recipientAddress = meta?.evmAddress ?? null;
87
+ if (!accessToken) {
88
+ return {
89
+ success: false,
90
+ action,
91
+ network,
92
+ chainId,
93
+ recipientAddress,
94
+ message: "No Token Service access token. Run neozip connect to set up an account, then retry.",
95
+ nextCommand: "neozip connect",
96
+ };
97
+ }
98
+ if (action === "status") {
99
+ try {
100
+ const status = await (0, token_service_1.getFundingStatus)(origin, accessToken, chainId);
101
+ const lines = [];
102
+ lines.push(status.enabled
103
+ ? `Funding enabled on chain ${chainId}.`
104
+ : `Funding not enabled on chain ${chainId}.`);
105
+ lines.push(`Data Wallet: ${status.recipientAddress ?? recipientAddress ?? "unknown"}`);
106
+ if (status.lastGrantAt)
107
+ lines.push(`Last grant: ${status.lastGrantAt}`);
108
+ if (status.nextEligibleAt) {
109
+ lines.push(`Next eligible: ${status.nextEligibleAt}`);
110
+ }
111
+ else if (status.enabled) {
112
+ lines.push("Eligible now.");
113
+ }
114
+ return {
115
+ success: true,
116
+ action,
117
+ network,
118
+ chainId,
119
+ recipientAddress: status.recipientAddress ?? recipientAddress,
120
+ status,
121
+ message: lines.join("\n"),
122
+ nextCommand: status.enabled ? "neozip connect fund" : undefined,
123
+ };
124
+ }
125
+ catch (err) {
126
+ return fundError(action, network, chainId, err, recipientAddress);
127
+ }
128
+ }
129
+ // action === "request"
130
+ try {
131
+ const grant = await (0, token_service_1.requestFundingGrant)(origin, accessToken, chainId);
132
+ if (grant.success) {
133
+ const where = grant.recipientAddress || recipientAddress || "your Data Wallet";
134
+ const tx = grant.transactionHash ? ` (tx ${grant.transactionHash})` : "";
135
+ return {
136
+ success: true,
137
+ action,
138
+ network,
139
+ chainId,
140
+ recipientAddress: grant.recipientAddress || recipientAddress,
141
+ grant,
142
+ message: `Sent ${grant.amountEth} to ${where}${tx}. Status: ${grant.status}.`,
143
+ };
144
+ }
145
+ // Server-side refusal (cooldown, no wallet, low treasury, …).
146
+ return {
147
+ success: false,
148
+ action,
149
+ network,
150
+ chainId,
151
+ recipientAddress: grant.recipientAddress || recipientAddress,
152
+ grant,
153
+ message: grant.error ?? `Funding request failed (${grant.errorCode ?? "unknown"}).`,
154
+ nextCommand: grant.errorCode === "NO_DATA_WALLET" ? "neozip connect" : undefined,
155
+ };
156
+ }
157
+ catch (err) {
158
+ return fundError(action, network, chainId, err, recipientAddress);
159
+ }
160
+ }
161
+ function fundError(action, network, chainId, err, recipientAddress) {
162
+ if (err instanceof token_service_1.FundingUnavailableError) {
163
+ return {
164
+ success: false,
165
+ action,
166
+ network,
167
+ chainId,
168
+ recipientAddress,
169
+ message: `This Token Service does not offer wallet funding. ${FAUCET_HINT}`,
170
+ };
171
+ }
172
+ return {
173
+ success: false,
174
+ action,
175
+ network,
176
+ chainId,
177
+ recipientAddress,
178
+ message: err instanceof Error ? err.message : String(err),
179
+ };
180
+ }
181
+ function formatFundResult(res) {
182
+ const lines = [res.message];
183
+ if (res.nextCommand)
184
+ lines.push(`Next: ${res.nextCommand}`);
185
+ return lines.join("\n");
186
+ }
187
+ //# sourceMappingURL=funding.js.map
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.INTERACTIVE_CONNECT_COMMAND = void 0;
4
+ exports.listReadableConnectionIds = listReadableConnectionIds;
5
+ exports.tryAutoRecoverConnectionStore = tryAutoRecoverConnectionStore;
6
+ exports.diagnoseUnrecoverableStore = diagnoseUnrecoverableStore;
7
+ exports.formatUnrecoverableStoreMessage = formatUnrecoverableStoreMessage;
8
+ exports.recommendedConnectCommand = recommendedConnectCommand;
9
+ const store_1 = require("./store");
10
+ const phase_1 = require("./phase");
11
+ const promote_active_1 = require("./promote-active");
12
+ exports.INTERACTIVE_CONNECT_COMMAND = "neozip connect";
13
+ function listReadableConnectionIds() {
14
+ return (0, store_1.listConnectionIds)().filter((id) => {
15
+ return Boolean((0, store_1.readConnectionPublic)(id) && (0, store_1.readConnectionSecrets)(id));
16
+ });
17
+ }
18
+ /** Switch active to a ready or readable account when the current one cannot be unlocked. */
19
+ function tryAutoRecoverConnectionStore() {
20
+ const promoted = (0, promote_active_1.promoteReadyActiveConnection)();
21
+ if (promoted.promoted && promoted.label) {
22
+ return {
23
+ recovered: true,
24
+ message: `Active account was incomplete; switched to ready account "${promoted.label}".`,
25
+ };
26
+ }
27
+ const activeId = (0, store_1.getActiveConnectionId)();
28
+ if (!activeId) {
29
+ return { recovered: false };
30
+ }
31
+ const activeMeta = (0, store_1.readConnectionPublic)(activeId);
32
+ const activeReadable = Boolean((0, store_1.readConnectionSecrets)(activeId));
33
+ if (activeMeta && activeReadable) {
34
+ return { recovered: false };
35
+ }
36
+ const readableIds = listReadableConnectionIds();
37
+ if (readableIds.length === 0) {
38
+ return { recovered: false };
39
+ }
40
+ const fallbackId = readableIds.find((id) => (0, phase_1.listReadyConnectionIds)().includes(id)) ?? readableIds[0];
41
+ const fallback = (0, store_1.selectConnection)(fallbackId);
42
+ return {
43
+ recovered: true,
44
+ message: `Previous active account could not be unlocked; switched to "${fallback.label}".`,
45
+ };
46
+ }
47
+ /** True when every saved account lacks readable secrets (corrupt, wrong machine, or test residue). */
48
+ function diagnoseUnrecoverableStore() {
49
+ const ids = (0, store_1.listConnectionIds)();
50
+ if (ids.length === 0) {
51
+ return null;
52
+ }
53
+ const readableIds = listReadableConnectionIds();
54
+ if (readableIds.length > 0) {
55
+ return null;
56
+ }
57
+ const activeId = (0, store_1.getActiveConnectionId)();
58
+ const activeMeta = activeId ? (0, store_1.readConnectionPublic)(activeId) : null;
59
+ return {
60
+ kind: "all_secrets_unreadable",
61
+ connectionCount: ids.length,
62
+ activeConnectionId: activeId,
63
+ activeLabel: activeMeta?.label ?? null,
64
+ activeEmail: activeMeta?.email ?? null,
65
+ };
66
+ }
67
+ function formatUnrecoverableStoreMessage(diagnosis) {
68
+ const who = diagnosis.activeLabel && diagnosis.activeEmail
69
+ ? `${diagnosis.activeLabel} (${diagnosis.activeEmail})`
70
+ : diagnosis.activeLabel ?? diagnosis.activeConnectionId ?? "unknown";
71
+ return [
72
+ `Found ${diagnosis.connectionCount} saved account(s) but none can be unlocked.`,
73
+ `Active: ${who}.`,
74
+ "Credentials may be from another machine, corrupted, or an incomplete test setup.",
75
+ "Reset is recommended before continuing.",
76
+ ].join(" ");
77
+ }
78
+ function recommendedConnectCommand() {
79
+ const phase = (0, phase_1.computeConnectionPhase)();
80
+ if (phase === "ready") {
81
+ return `${exports.INTERACTIVE_CONNECT_COMMAND} status`;
82
+ }
83
+ const meta = (0, store_1.getActiveConnection)();
84
+ return ((0, phase_1.nextConnectCommand)(phase, {
85
+ email: meta?.email,
86
+ phoneE164: meta?.phoneE164,
87
+ }) ?? exports.INTERACTIVE_CONNECT_COMMAND);
88
+ }
89
+ //# sourceMappingURL=incomplete-setup.js.map