@attocash/cli 0.2.1 → 0.2.2

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/README.md CHANGED
@@ -373,6 +373,12 @@ outstanding checks, including native credential probes and their subprocesses.
373
373
  Doctor does not check npm for updates.
374
374
 
375
375
  An agent should call the MCP **`doctor` tool** to inspect the server's own process.
376
+ `wallet_status.initialized` describes the saved public wallet identity; status
377
+ does not read the password store. If a signing operation returns
378
+ `WALLET_CREDENTIAL_MISSING`, the profile remains initialized but its credential
379
+ lookup returned empty. Run doctor in that session before attempting recovery;
380
+ do not reset or replace the wallet to repair credential access.
381
+
376
382
  A terminal result cannot establish that an already-running MCP has the same
377
383
  environment. When a user-owned Linux session socket is available, doctor may test
378
384
  environment overrides in an isolated credential probe. It returns
@@ -615,6 +621,8 @@ atto wallet configure --representative <atto-address>
615
621
  Configuration updates preserve omitted settings. Supply at least one option.
616
622
  `--representative` changes the default used to open accounts; use
617
623
  `atto representative change <address>` to change an existing account's representative.
624
+ Selecting the account's current representative returns `REPRESENTATIVE_UNCHANGED`
625
+ without signing or publishing a transaction.
618
626
  `wallet status` shows the profile directory and whether receiving runs in that
619
627
  process; it does not report receiving sessions in other terminals.
620
628
 
@@ -173,8 +173,12 @@ export class AttoApplication {
173
173
  this.recoveryReads++;
174
174
  try {
175
175
  const phrase = await this.secrets.get();
176
- if (!phrase)
176
+ if (!phrase) {
177
+ this.requireResetFinished();
178
+ if (this.identity())
179
+ throw new AttoError('WALLET_CREDENTIAL_MISSING', 'The wallet is initialized, but the OS password store returned no recovery phrase for this profile. Run doctor in this session to check credential access. Do not reset or replace the wallet.');
177
180
  throw new AttoError('WALLET_NOT_INITIALIZED', 'Create or import a wallet through the CLI first.');
181
+ }
178
182
  return phrase;
179
183
  }
180
184
  finally {
@@ -69,7 +69,7 @@ export const operations = [
69
69
  { name: 'terms_accept', description: 'Persist acknowledgement of the specified terms version for USD-priced payments. Call only after the user has read and explicitly accepted those terms.', schema: z.strictObject({ version: z.string().min(1).max(128), accepted: z.literal(true) }), readOnly: false },
70
70
  { name: 'receive', description: 'Receive one pending payment by hash, opening the account if needed.', schema: z.strictObject({ index: index.default(0), hash, representative: address.optional() }), readOnly: false },
71
71
  { name: 'receive_all', description: 'Receive a bounded set of pending payments for a key index, opening the account if needed.', schema: z.strictObject({ index: index.default(0), limit: limit.default(100), timeoutMs: timeoutMs.default(2000), representative: address.optional() }), readOnly: false },
72
- { name: 'representative_change', description: 'Publish a representative change for an existing account.', schema: z.strictObject({ index: index.default(0), representative: address }), readOnly: false },
72
+ { name: 'representative_change', description: 'Publish a representative change for an existing account. Selecting its current representative returns REPRESENTATIVE_UNCHANGED without publishing.', schema: z.strictObject({ index: index.default(0), representative: address }), readOnly: false },
73
73
  { name: 'limits_get', description: 'Read spending policy, approved send pool, MCP access, proposal status, historical usage, reservations, and remaining allowances.', schema: z.strictObject({}), readOnly: true },
74
74
  { name: 'limits_propose', description: 'Propose spending limits, MCP access, and optional send-pool settings for local terminal approval. Omitted pool preserves the approved pool. Does not change active settings or grant access. A new proposal replaces the previous proposal and expires after 24 hours. Read limits_get for active settings and proposal status. Amounts are ATTO or RAW; null perRequest with empty rolling means unlimited spending if approved.', schema: z.strictObject({ policy, access: z.enum(['read-only', 'spend']).default('spend'), pool: pool.optional() }), readOnly: false },
75
75
  { name: 'watch_start', description: 'Start an observational, reconnecting watch for this session, defaulting to active wallet addresses. Choose one saved index, explicit addresses (including foreign accounts), a transaction/entry hash, or networkWide=true. Network-wide receivables are unsupported. Read buffered events and connection status with watch_read. Does not enable automatic receiving.', schema: z.strictObject({ event: z.enum(['account', 'transaction', 'entry', 'receivable']), ...streamFields, index: index.optional(), networkWide: z.boolean().optional() }).refine(singleSelection, 'Choose one watch selection.').refine(value => !(value.networkWide && value.event === 'receivable'), 'Receivable watches require addresses.'), readOnly: false },
@@ -119,7 +119,13 @@ export async function signingWallet(seed, index, settings, beforeSign, suppliedW
119
119
  },
120
120
  async change(value, representative, timestamp) {
121
121
  requireIndex(value);
122
- return perform(time => attoAccountChange(requireAccount(), representative, time), timestamp);
122
+ return perform(time => {
123
+ const current = requireAccount();
124
+ if (current.representativeAddress.value === representative.value) {
125
+ throw new AttoError('REPRESENTATIVE_UNCHANGED', 'This account already uses the requested representative. Choose a different representative to publish a change.');
126
+ }
127
+ return attoAccountChange(current, representative, time);
128
+ }, timestamp);
123
129
  },
124
130
  async getAccountByIndex(value) { requireIndex(value); return account ?? null; },
125
131
  close() { signer = undefined; },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@attocash/cli",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "Atto wallet CLI and reusable wallet engine with local key custody and shared spending limits",
5
5
  "license": "BSD-3-Clause",
6
6
  "type": "module",