@defdone/annon 0.1.0-alpha.1 → 0.1.0-alpha.3

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 (87) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/CLI.md +173 -13
  3. package/README.md +47 -10
  4. package/dist/api/annon-types.d.ts +2 -1
  5. package/dist/api/annon.js +9 -2
  6. package/dist/browser/index.d.ts +1 -1
  7. package/dist/browser/login-bundle.js +61 -60
  8. package/dist/browser/login-dom.d.ts +13 -0
  9. package/dist/browser/login-dom.js +71 -0
  10. package/dist/browser/login-dropdown.d.ts +32 -0
  11. package/dist/browser/login-dropdown.js +129 -0
  12. package/dist/browser/login-format.d.ts +16 -0
  13. package/dist/browser/login-format.js +52 -0
  14. package/dist/browser/login-status.d.ts +70 -0
  15. package/dist/browser/login-status.js +85 -0
  16. package/dist/browser/login-steps.d.ts +6 -0
  17. package/dist/browser/login-steps.js +35 -0
  18. package/dist/browser/login-terms.d.ts +10 -0
  19. package/dist/browser/login-terms.js +69 -0
  20. package/dist/browser/login-view.d.ts +34 -0
  21. package/dist/browser/login-view.js +227 -0
  22. package/dist/browser/login-wallet.d.ts +28 -0
  23. package/dist/browser/login-wallet.js +179 -0
  24. package/dist/browser/login.js +154 -142
  25. package/dist/browser/purchase-bundle.js +29 -29
  26. package/dist/browser/purchases.d.ts +4 -0
  27. package/dist/browser/purchases.js +14 -0
  28. package/dist/browser/reconcile.d.ts +41 -0
  29. package/dist/browser/reconcile.js +77 -0
  30. package/dist/node/adapter-checks.d.ts +3 -1
  31. package/dist/node/adapter-checks.js +3 -1
  32. package/dist/node/adapter.js +10 -3
  33. package/dist/node/agent.js +2 -1
  34. package/dist/node/approval-status.d.ts +34 -0
  35. package/dist/node/approval-status.js +71 -0
  36. package/dist/node/backup-secret-init.d.ts +9 -0
  37. package/dist/node/backup-secret-init.js +103 -0
  38. package/dist/node/backup-secret.d.ts +35 -0
  39. package/dist/node/backup-secret.js +104 -0
  40. package/dist/node/browser-login.d.ts +2 -0
  41. package/dist/node/browser-login.js +95 -16
  42. package/dist/node/buy-commands.js +17 -9
  43. package/dist/node/buy-flow.d.ts +18 -0
  44. package/dist/node/buy-flow.js +89 -0
  45. package/dist/node/cli-flags.d.ts +10 -0
  46. package/dist/node/cli-flags.js +68 -0
  47. package/dist/node/cli.d.ts +9 -1
  48. package/dist/node/cli.js +87 -95
  49. package/dist/node/command-context.js +1 -1
  50. package/dist/node/config.d.ts +4 -0
  51. package/dist/node/config.js +6 -2
  52. package/dist/node/core-adapter.js +4 -0
  53. package/dist/node/login-page.d.ts +7 -0
  54. package/dist/node/login-page.js +77 -0
  55. package/dist/node/main.js +20 -2
  56. package/dist/node/output/discovery.d.ts +23 -0
  57. package/dist/node/output/discovery.js +52 -0
  58. package/dist/node/output/human.d.ts +10 -0
  59. package/dist/node/output/human.js +46 -0
  60. package/dist/node/output/purchase.d.ts +10 -0
  61. package/dist/node/output/purchase.js +78 -0
  62. package/dist/node/output/text.d.ts +10 -0
  63. package/dist/node/output/text.js +43 -0
  64. package/dist/node/purchase-commands.d.ts +2 -2
  65. package/dist/node/purchase-commands.js +14 -6
  66. package/dist/node/purchase-ref.d.ts +15 -0
  67. package/dist/node/purchase-ref.js +93 -0
  68. package/dist/node/saved-state.d.ts +4 -0
  69. package/dist/node/saved-state.js +50 -0
  70. package/dist/node/shell/complete.d.ts +2 -0
  71. package/dist/node/shell/complete.js +17 -0
  72. package/dist/node/shell/session.d.ts +20 -0
  73. package/dist/node/shell/session.js +219 -0
  74. package/dist/node/shell/welcome.d.ts +9 -0
  75. package/dist/node/shell/welcome.js +39 -0
  76. package/dist/node/shell/words.d.ts +1 -0
  77. package/dist/node/shell/words.js +36 -0
  78. package/dist/node/shops.d.ts +5 -0
  79. package/dist/node/shops.js +22 -0
  80. package/dist/node/version.d.ts +1 -0
  81. package/dist/node/version.js +3 -0
  82. package/dist/node/wallets.d.ts +1 -1
  83. package/dist/node/wallets.js +2 -10
  84. package/dist/pay/purchase.d.ts +2 -1
  85. package/dist/wallet/uncertain.d.ts +6 -3
  86. package/dist/wallet/uncertain.js +4 -1
  87. package/package.json +1 -1
@@ -0,0 +1,39 @@
1
+ /** The session's opening lines. Read-only: no prompt, no network, no secret, nothing written. */
2
+ import { join } from 'node:path';
3
+ import { fileStore } from '../../pay/store-node.js';
4
+ import { agentPolicy } from '../agent.js';
5
+ import { loadConfig, trustId } from '../config.js';
6
+ import { cleanText, networkName } from '../output/text.js';
7
+ import { version } from '../version.js';
8
+ const probe = { command: 'shops' };
9
+ /**
10
+ * A session needs a person at a terminal. Pipes, agent mode and a config that cannot say whether
11
+ * it is an agent config all keep the one-shot behavior.
12
+ */
13
+ export async function sessionAllowed(argv, terminal, env) {
14
+ if (!terminal || !(argv.length === 0 || (argv.length === 1 && argv[0] === 'shell')))
15
+ return false;
16
+ try {
17
+ return !(await agentPolicy(probe, env));
18
+ }
19
+ catch {
20
+ return false;
21
+ }
22
+ }
23
+ /** Human text only for a person at a terminal outside agent mode. */
24
+ export const humanOutput = async (terminal, env) => terminal &&
25
+ (await agentPolicy(probe, env).then((agent) => !agent, () => false));
26
+ export async function welcome(env) {
27
+ const lines = [`Annon ${version}`];
28
+ try {
29
+ const c = await loadConfig({ command: 'login' }, env, true);
30
+ const trusted = c.trustContract === true ||
31
+ (await fileStore(join(c.stateDir, 'trust')).load(trustId(c))) !== null;
32
+ lines.push(`Network: ${networkName(c.network)}`, `Account: ${c.signer ? cleanText(c.signer.identity.id) : 'not signed in (run login)'}`, `Contract: ${c.contractId ? `${c.contractId} (${trusted ? 'trusted' : 'not trusted yet'})` : 'not configured'}`);
33
+ }
34
+ catch {
35
+ lines.push('Config: could not be read. Run a command to see why.');
36
+ }
37
+ lines.push('Type help for commands, exit to leave. Tab completes.');
38
+ return lines.join('\n');
39
+ }
@@ -0,0 +1 @@
1
+ export declare function splitWords(line: string): string[];
@@ -0,0 +1,36 @@
1
+ /** Splits a session line into arguments: spaces separate, quotes and backslashes keep them. */
2
+ import { AdapterError } from '../errors.js';
3
+ export function splitWords(line) {
4
+ const words = [];
5
+ let word;
6
+ let quote;
7
+ for (let i = 0; i < line.length; i++) {
8
+ const ch = line.charAt(i);
9
+ if (quote) {
10
+ if (ch === quote)
11
+ quote = undefined;
12
+ else if (ch === '\\' && quote === '"' && i + 1 < line.length)
13
+ word += line.charAt(++i);
14
+ else
15
+ word += ch;
16
+ }
17
+ else if (ch === '"' || ch === "'") {
18
+ quote = ch;
19
+ word ??= '';
20
+ }
21
+ else if (ch === '\\' && i + 1 < line.length)
22
+ word = (word ?? '') + line.charAt(++i);
23
+ else if (/\s/.test(ch)) {
24
+ if (word !== undefined)
25
+ words.push(word);
26
+ word = undefined;
27
+ }
28
+ else
29
+ word = (word ?? '') + ch;
30
+ }
31
+ if (quote)
32
+ throw new AdapterError('invalid_arguments', 'A quote is not closed.', 2);
33
+ if (word !== undefined)
34
+ words.push(word);
35
+ return words;
36
+ }
@@ -15,3 +15,8 @@ export declare function selectedShopRules(config: DiscoveryConfig, id: string |
15
15
  };
16
16
  rules: import("../shops/discovery.js").ShopRules;
17
17
  }>;
18
+ /**
19
+ * `buy <row>`: the resource URL of that row in the listing `catalog` prints for the same `--shop`
20
+ * and `--search`. The buy then checks the file and its terms as for a URL typed by hand.
21
+ */
22
+ export declare function catalogRow(input: Input, env: Environment, notify: ((message: string) => void) | undefined, fetcher?: typeof fetch): Promise<Input>;
@@ -4,6 +4,8 @@ import { dirname } from 'node:path';
4
4
  import { AnnonError } from '../errors.js';
5
5
  import { canonicalManifestUrl, catalog, listShops, readShop, validateDiscoveryConfig, } from '../shops/discovery.js';
6
6
  import { configPath } from './agent.js';
7
+ import { AdapterError } from './errors.js';
8
+ import { cleanText } from './output/text.js';
7
9
  export const isDiscovery = (input) => ['shops', 'shop', 'catalog'].includes(input.command);
8
10
  async function readConfig(path) {
9
11
  try {
@@ -72,3 +74,23 @@ export async function selectedShopRules(config, id, fetcher) {
72
74
  ? { shop: { manifest: shop.manifest, name: shop.info.name }, rules: shop.info.rules }
73
75
  : {};
74
76
  }
77
+ /**
78
+ * `buy <row>`: the resource URL of that row in the listing `catalog` prints for the same `--shop`
79
+ * and `--search`. The buy then checks the file and its terms as for a URL typed by hand.
80
+ */
81
+ export async function catalogRow(input, env, notify, fetcher = globalThis.fetch) {
82
+ const row = Number(input.target);
83
+ const config = validateDiscoveryConfig(await readConfig(configPath(input, env)));
84
+ const listing = await catalog(config, {
85
+ offset: row - 1,
86
+ limit: 1,
87
+ ...(input.search !== undefined ? { search: input.search } : {}),
88
+ ...(input.shop !== undefined ? { shop: input.shop } : {}),
89
+ }, fetcher);
90
+ const [entry] = listing.items;
91
+ if (!entry)
92
+ throw new AdapterError('invalid_arguments', `The catalog has no row ${row}. Run annon catalog to list the rows.`, 2);
93
+ notify?.(`Row ${row}: ${cleanText(entry.title)} (${entry.url})`);
94
+ const { shop: _shop, search: _search, ...rest } = input;
95
+ return { ...rest, target: entry.url };
96
+ }
@@ -0,0 +1 @@
1
+ export declare const version: string;
@@ -0,0 +1,3 @@
1
+ /** The installed package version; package.json sits two levels above both src/node and dist/node. */
2
+ import { createRequire } from 'node:module';
3
+ export const { version } = createRequire(import.meta.url)('../../package.json');
@@ -3,11 +3,11 @@ import type { SplitCall } from '../pay/split.js';
3
3
  import { type IdentityWallet } from '../wallet/wallet.js';
4
4
  import type { Input } from './cli.js';
5
5
  import { type Keychain } from './keychain.js';
6
+ export { readBackupSecret } from './backup-secret.js';
6
7
  export type Environment = Record<string, string | undefined>;
7
8
  export type LocalWallet = IdentityWallet & {
8
9
  signUpload?: (intent: UploadIntent) => Promise<UploadAuth>;
9
10
  sendBase?: (call: SplitCall, rpc: string) => Promise<void>;
10
11
  };
11
12
  export declare function identity(value: string): import("../settle-near/identity.js").Identity;
12
- export declare function readBackupSecret(o: Partial<Input>, env: Environment): Promise<Uint8Array>;
13
13
  export declare function loadWallet(o: Partial<Input>, env: Environment, nearRpc: string, keychain?: Keychain): Promise<LocalWallet>;
@@ -7,11 +7,12 @@ import { privateKeyToAccount } from 'viem/accounts';
7
7
  import { base } from 'viem/chains';
8
8
  import { signNearUpload } from '../browser/wallets.js';
9
9
  import { nep413Hash } from '../near/nep413.js';
10
- import { bytes, hex } from '../settle-near/codec.js';
10
+ import { hex } from '../settle-near/codec.js';
11
11
  import { identityJson, parseIdentity } from '../settle-near/identity.js';
12
12
  import { nearKeyPairWallet } from '../wallet/wallet.js';
13
13
  import { AdapterError } from './errors.js';
14
14
  import { decodeKeychain, osKeychain } from './keychain.js';
15
+ export { readBackupSecret } from './backup-secret.js';
15
16
  const credentialsError = () => new AdapterError('credentials_required', 'Select a wallet and provide its key through the documented environment variable or a named key file. Check the recovery identity matches.', 2);
16
17
  export function identity(value) {
17
18
  const at = value.indexOf(':');
@@ -24,15 +25,6 @@ async function source(file, env) {
24
25
  return env.trim();
25
26
  throw credentialsError();
26
27
  }
27
- export async function readBackupSecret(o, env) {
28
- try {
29
- const text = await source(o.backupSecretFile ?? env.ANNON_BACKUP_SECRET_FILE, env.ANNON_BACKUP_SECRET);
30
- return bytes(text.startsWith('0x') ? text : `0x${text}`, 32);
31
- }
32
- catch {
33
- throw new AdapterError('backup_secret_required', 'Provide a 32-byte random backup secret as 64 hex characters in ANNON_BACKUP_SECRET or a named backup secret file.', 2);
34
- }
35
- }
36
28
  export async function loadWallet(o, env, nearRpc, keychain = osKeychain) {
37
29
  try {
38
30
  const selected = o.wallet ?? (o.recovery ? identity(o.recovery).kind : env.ANNON_WALLET);
@@ -76,9 +76,10 @@ export interface PurchaseRecord extends Versioned {
76
76
  recoveryProved: boolean;
77
77
  /** Source details are the reviewed 1Click quote. */
78
78
  payment: PaymentSummary;
79
+ /** A NEAR send that may be on chain; `txHash` only when the wallet returned one. */
79
80
  nearSubmission?: {
80
81
  state: 'uncertain';
81
- txHash: string;
82
+ txHash?: string;
82
83
  };
83
84
  paymentState?: 'expired' | 'canceled';
84
85
  purchase: Purchase;
@@ -1,8 +1,11 @@
1
1
  import { AnnonError } from '../errors.js';
2
- /** Public evidence to retain whenever a submitted NEAR transaction cannot be confirmed. */
2
+ /**
3
+ * Public evidence to retain whenever a submitted NEAR transaction cannot be confirmed. `txHash` is
4
+ * absent when a wallet may have broadcast but never returned a hash: unknown, never invented.
5
+ */
3
6
  export declare class TransactionUncertain extends AnnonError {
4
- readonly txHash: string;
7
+ readonly txHash: string | undefined;
5
8
  readonly purchaseId?: string | undefined;
6
9
  readonly code = "transaction_uncertain";
7
- constructor(txHash: string, purchaseId?: string | undefined);
10
+ constructor(txHash: string | undefined, purchaseId?: string | undefined);
8
11
  }
@@ -1,5 +1,8 @@
1
1
  import { AnnonError } from '../errors.js';
2
- /** Public evidence to retain whenever a submitted NEAR transaction cannot be confirmed. */
2
+ /**
3
+ * Public evidence to retain whenever a submitted NEAR transaction cannot be confirmed. `txHash` is
4
+ * absent when a wallet may have broadcast but never returned a hash: unknown, never invented.
5
+ */
3
6
  export class TransactionUncertain extends AnnonError {
4
7
  txHash;
5
8
  purchaseId;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@defdone/annon",
3
- "version": "0.1.0-alpha.1",
3
+ "version": "0.1.0-alpha.3",
4
4
  "description": "Files only the buyer can open: encrypted on the client, the key released by NEAR once the payment is verified.",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://annon.dev",