apinow-sdk 0.16.0 → 0.17.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.
package/dist/cli.js CHANGED
@@ -1,12 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
  import { Command } from 'commander';
3
3
  import { createClient } from './index.js';
4
+ import { privateKeyToAccount } from 'viem/accounts';
4
5
  const API_BASE = 'https://apinow.fun';
5
6
  const program = new Command();
6
7
  program
7
8
  .name('apinow')
8
9
  .description('CLI for APINow.fun — search, inspect, and call pay-per-request APIs')
9
- .version('0.16.0');
10
+ .version('0.17.0');
10
11
  // ─── Helpers ───
11
12
  function getPrivateKey(opts) {
12
13
  const raw = opts.key || process.env.APINOW_WALLET_PKEY || process.env.PRIVATE_KEY;
@@ -42,6 +43,14 @@ function printTable(rows) {
42
43
  function truncate(s, max) {
43
44
  return s.length > max ? s.slice(0, max - 1) + '…' : s;
44
45
  }
46
+ function getWallet(opts) {
47
+ const privateKey = getPrivateKey(opts);
48
+ const account = privateKeyToAccount(privateKey);
49
+ return { privateKey, address: account.address };
50
+ }
51
+ function walletHeaders(address) {
52
+ return { 'Content-Type': 'application/json', 'x-wallet-address': address };
53
+ }
45
54
  // ─── search ───
46
55
  program
47
56
  .command('search <query>')
@@ -312,4 +321,194 @@ program
312
321
  process.exit(1);
313
322
  }
314
323
  });
324
+ // ─── factory-balance ───
325
+ program
326
+ .command('factory-balance')
327
+ .description('Check $APINOW token balance and factory access')
328
+ .option('-k, --key <privateKey>', 'Wallet private key')
329
+ .action(async (opts) => {
330
+ try {
331
+ const { address } = getWallet(opts);
332
+ const data = await fetchJson(`${API_BASE}/api/user-factory/check-balance`, {
333
+ headers: walletHeaders(address),
334
+ });
335
+ console.log(`\n Wallet: ${address}`);
336
+ console.log(` Balance: ${data.balance} $APINOW`);
337
+ console.log(` Required: ${data.required}`);
338
+ console.log(` Access: ${data.hasAccess ? 'YES' : 'NO'}\n`);
339
+ }
340
+ catch (err) {
341
+ console.error(`Error: ${err.message}`);
342
+ process.exit(1);
343
+ }
344
+ });
345
+ // ─── factory-list ───
346
+ program
347
+ .command('factory-list')
348
+ .description('List your user-factory endpoints')
349
+ .option('-k, --key <privateKey>', 'Wallet private key')
350
+ .action(async (opts) => {
351
+ try {
352
+ const { address } = getWallet(opts);
353
+ const data = await fetchJson(`${API_BASE}/api/user-factory`, {
354
+ headers: walletHeaders(address),
355
+ });
356
+ const endpoints = data.endpoints || [];
357
+ if (!endpoints.length) {
358
+ console.log('No factory endpoints found.');
359
+ return;
360
+ }
361
+ const rows = [['ENDPOINT', 'MODEL', 'COST', 'STATUS']];
362
+ for (const ep of endpoints) {
363
+ rows.push([
364
+ `${ep.namespace}/${ep.endpointName}`,
365
+ ep.model || '—',
366
+ formatUsd(ep.paymentOptions),
367
+ ep.status || '—',
368
+ ]);
369
+ }
370
+ printTable(rows);
371
+ }
372
+ catch (err) {
373
+ console.error(`Error: ${err.message}`);
374
+ process.exit(1);
375
+ }
376
+ });
377
+ // ─── factory-generate ───
378
+ program
379
+ .command('factory-generate <idea>')
380
+ .description('Generate endpoint config from a natural-language idea')
381
+ .option('-k, --key <privateKey>', 'Wallet private key')
382
+ .action(async (idea, opts) => {
383
+ try {
384
+ const { address } = getWallet(opts);
385
+ console.error('Generating endpoint config…');
386
+ const data = await fetchJson(`${API_BASE}/api/user-factory/generate`, {
387
+ method: 'POST',
388
+ headers: walletHeaders(address),
389
+ body: JSON.stringify({ idea }),
390
+ });
391
+ console.log(JSON.stringify(data, null, 2));
392
+ }
393
+ catch (err) {
394
+ console.error(`Error: ${err.message}`);
395
+ process.exit(1);
396
+ }
397
+ });
398
+ // ─── factory-create ───
399
+ program
400
+ .command('factory-create')
401
+ .description('Create an LLM endpoint via user-factory')
402
+ .requiredOption('--name <name>', 'Endpoint name')
403
+ .requiredOption('--prompt <prompt>', 'System prompt for the LLM')
404
+ .option('--namespace <ns>', 'Namespace (defaults to u-<wallet>)')
405
+ .option('--description <desc>', 'Endpoint description')
406
+ .option('--model <model>', 'LLM model', 'google/gemini-2.0-flash-001')
407
+ .option('--price <usdc>', 'USDC price per call', '0.01')
408
+ .option('--recipient <wallet>', 'Payment recipient wallet')
409
+ .option('--input-params <json>', 'Input params JSON array')
410
+ .option('--output-params <json>', 'Output params JSON array')
411
+ .option('-k, --key <privateKey>', 'Wallet private key')
412
+ .action(async (opts) => {
413
+ try {
414
+ const { address } = getWallet(opts);
415
+ const body = {
416
+ name: opts.name,
417
+ prompt: opts.prompt,
418
+ model: opts.model,
419
+ usdcPrice: opts.price,
420
+ };
421
+ if (opts.namespace)
422
+ body.namespace = opts.namespace;
423
+ if (opts.description)
424
+ body.description = opts.description;
425
+ if (opts.recipient)
426
+ body.recipientWallet = opts.recipient;
427
+ if (opts.inputParams)
428
+ body.inputParams = JSON.parse(opts.inputParams);
429
+ if (opts.outputParams)
430
+ body.outputParams = JSON.parse(opts.outputParams);
431
+ console.error(`Creating endpoint "${opts.name}"…`);
432
+ const data = await fetchJson(`${API_BASE}/api/user-factory`, {
433
+ method: 'POST',
434
+ headers: walletHeaders(address),
435
+ body: JSON.stringify(body),
436
+ });
437
+ const ep = data.endpoint;
438
+ console.log(`\n Created: ${ep.namespace}/${ep.endpointName}`);
439
+ console.log(` Model: ${ep.model}`);
440
+ console.log(` Price: $${ep.price} USDC`);
441
+ console.log(` Try: https://apinow.fun${ep.tryUrl}`);
442
+ console.log(` API: https://apinow.fun${ep.apiUrl}\n`);
443
+ }
444
+ catch (err) {
445
+ console.error(`Error: ${err.message}`);
446
+ process.exit(1);
447
+ }
448
+ });
449
+ // ─── factory-markup ───
450
+ program
451
+ .command('factory-markup <endpointId>')
452
+ .description('Create a markup workflow that wraps an existing endpoint')
453
+ .option('--markup <percent>', 'Markup percentage', '20')
454
+ .option('--name <name>', 'Workflow name')
455
+ .option('-k, --key <privateKey>', 'Wallet private key')
456
+ .action(async (endpointId, opts) => {
457
+ try {
458
+ const { address } = getWallet(opts);
459
+ const body = { endpointId, markupPercent: Number(opts.markup) };
460
+ if (opts.name)
461
+ body.workflowName = opts.name;
462
+ console.error(`Creating markup workflow (${opts.markup}%)…`);
463
+ const data = await fetchJson(`${API_BASE}/api/user-factory/markup`, {
464
+ method: 'POST',
465
+ headers: walletHeaders(address),
466
+ body: JSON.stringify(body),
467
+ });
468
+ const w = data.workflow;
469
+ console.log(`\n Created: ${w.name}`);
470
+ console.log(` ID: ${w.workflowId}`);
471
+ console.log(` Base: $${w.basePrice} USDC`);
472
+ console.log(` Markup: ${w.markupPercent}%`);
473
+ console.log(` Total: $${w.totalPrice} USDC`);
474
+ console.log(` View: https://apinow.fun${w.viewUrl}\n`);
475
+ }
476
+ catch (err) {
477
+ console.error(`Error: ${err.message}`);
478
+ process.exit(1);
479
+ }
480
+ });
481
+ // ─── factory-test ───
482
+ program
483
+ .command('factory-test <endpoint>')
484
+ .description('Test-call an endpoint without payment')
485
+ .option('-d, --data <json>', 'JSON input')
486
+ .option('--save', 'Save as example')
487
+ .option('-k, --key <privateKey>', 'Wallet private key')
488
+ .action(async (endpoint, opts) => {
489
+ try {
490
+ if (!endpoint.includes('/'))
491
+ throw new Error('Format: namespace/endpoint-name');
492
+ const { address } = getWallet(opts);
493
+ const [namespace, endpointName] = endpoint.split('/');
494
+ const body = { namespace, endpointName };
495
+ if (opts.data)
496
+ body.input = JSON.parse(opts.data);
497
+ if (opts.save)
498
+ body.saveExample = true;
499
+ console.error(`Testing ${endpoint}…`);
500
+ const data = await fetchJson(`${API_BASE}/api/user-factory/test-call`, {
501
+ method: 'POST',
502
+ headers: walletHeaders(address),
503
+ body: JSON.stringify(body),
504
+ });
505
+ console.log(JSON.stringify(data.output, null, 2));
506
+ if (data.saved)
507
+ console.error('(saved as example)');
508
+ }
509
+ catch (err) {
510
+ console.error(`Error: ${err.message}`);
511
+ process.exit(1);
512
+ }
513
+ });
315
514
  program.parse();
package/dist/index.d.ts CHANGED
@@ -46,6 +46,57 @@ export declare function createClient(config: ApinowConfig): {
46
46
  * const result = await apinow.runWorkflow('90931d9c8fb94df9', { query: 'hello world' });
47
47
  */
48
48
  runWorkflow(workflowId: string, input: Record<string, any>): Promise<any>;
49
+ /**
50
+ * Check $APINOW token balance and factory access.
51
+ */
52
+ factoryBalance(): Promise<any>;
53
+ /**
54
+ * List your user-factory endpoints.
55
+ */
56
+ factoryList(): Promise<any>;
57
+ /**
58
+ * Generate endpoint config from a natural-language idea.
59
+ */
60
+ factoryGenerate(idea: string): Promise<any>;
61
+ /**
62
+ * Create an LLM endpoint via user-factory.
63
+ */
64
+ factoryCreate(config: {
65
+ name: string;
66
+ prompt: string;
67
+ namespace?: string;
68
+ description?: string;
69
+ model?: string;
70
+ usdcPrice?: string;
71
+ recipientWallet?: string;
72
+ inputParams?: Array<{
73
+ name: string;
74
+ type: string;
75
+ description?: string;
76
+ }>;
77
+ outputParams?: Array<{
78
+ name: string;
79
+ type: string;
80
+ description?: string;
81
+ }>;
82
+ }): Promise<any>;
83
+ /**
84
+ * Create a markup workflow wrapping an existing endpoint.
85
+ */
86
+ factoryMarkup(opts: {
87
+ endpointId: string;
88
+ markupPercent?: number;
89
+ workflowName?: string;
90
+ }): Promise<any>;
91
+ /**
92
+ * Test-call an endpoint without payment (free, server-side LLM call).
93
+ */
94
+ factoryTestCall(opts: {
95
+ namespace: string;
96
+ endpointName: string;
97
+ input?: any;
98
+ saveExample?: boolean;
99
+ }): Promise<any>;
49
100
  /**
50
101
  * The underlying x402-wrapped fetch, for advanced use.
51
102
  */
package/dist/index.js CHANGED
@@ -96,6 +96,87 @@ export function createClient(config) {
96
96
  body: input,
97
97
  });
98
98
  },
99
+ // ─── User Factory ───
100
+ /**
101
+ * Check $APINOW token balance and factory access.
102
+ */
103
+ async factoryBalance() {
104
+ const res = await fetch(`${baseUrl}/api/user-factory/check-balance`, {
105
+ headers: { 'x-wallet-address': account.address },
106
+ });
107
+ if (!res.ok)
108
+ throw new Error(`Failed to check balance: ${res.status}`);
109
+ return res.json();
110
+ },
111
+ /**
112
+ * List your user-factory endpoints.
113
+ */
114
+ async factoryList() {
115
+ const res = await fetch(`${baseUrl}/api/user-factory`, {
116
+ headers: { 'x-wallet-address': account.address },
117
+ });
118
+ if (!res.ok)
119
+ throw new Error(`Failed to list factory endpoints: ${res.status}`);
120
+ return res.json();
121
+ },
122
+ /**
123
+ * Generate endpoint config from a natural-language idea.
124
+ */
125
+ async factoryGenerate(idea) {
126
+ const res = await fetch(`${baseUrl}/api/user-factory/generate`, {
127
+ method: 'POST',
128
+ headers: { 'Content-Type': 'application/json', 'x-wallet-address': account.address },
129
+ body: JSON.stringify({ idea }),
130
+ });
131
+ if (!res.ok)
132
+ throw new Error(`Failed to generate: ${res.status}`);
133
+ return res.json();
134
+ },
135
+ /**
136
+ * Create an LLM endpoint via user-factory.
137
+ */
138
+ async factoryCreate(config) {
139
+ const res = await fetch(`${baseUrl}/api/user-factory`, {
140
+ method: 'POST',
141
+ headers: { 'Content-Type': 'application/json', 'x-wallet-address': account.address },
142
+ body: JSON.stringify(config),
143
+ });
144
+ if (!res.ok) {
145
+ const text = await res.text();
146
+ throw new Error(`Failed to create endpoint: ${res.status} ${text}`);
147
+ }
148
+ return res.json();
149
+ },
150
+ /**
151
+ * Create a markup workflow wrapping an existing endpoint.
152
+ */
153
+ async factoryMarkup(opts) {
154
+ const res = await fetch(`${baseUrl}/api/user-factory/markup`, {
155
+ method: 'POST',
156
+ headers: { 'Content-Type': 'application/json', 'x-wallet-address': account.address },
157
+ body: JSON.stringify(opts),
158
+ });
159
+ if (!res.ok) {
160
+ const text = await res.text();
161
+ throw new Error(`Failed to create markup: ${res.status} ${text}`);
162
+ }
163
+ return res.json();
164
+ },
165
+ /**
166
+ * Test-call an endpoint without payment (free, server-side LLM call).
167
+ */
168
+ async factoryTestCall(opts) {
169
+ const res = await fetch(`${baseUrl}/api/user-factory/test-call`, {
170
+ method: 'POST',
171
+ headers: { 'Content-Type': 'application/json', 'x-wallet-address': account.address },
172
+ body: JSON.stringify(opts),
173
+ });
174
+ if (!res.ok) {
175
+ const text = await res.text();
176
+ throw new Error(`Failed to test call: ${res.status} ${text}`);
177
+ }
178
+ return res.json();
179
+ },
99
180
  /**
100
181
  * The underlying x402-wrapped fetch, for advanced use.
101
182
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apinow-sdk",
3
- "version": "0.16.0",
3
+ "version": "0.17.0",
4
4
  "description": "Pay-per-call API SDK & CLI for APINow.fun — endpoints + workflows, wraps x402 so you don't have to",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -26,7 +26,8 @@
26
26
  "llm",
27
27
  "cli",
28
28
  "workflow",
29
- "dag"
29
+ "dag",
30
+ "user-factory"
30
31
  ],
31
32
  "author": "ApiNow.fun",
32
33
  "license": "MIT",