apinow-sdk 0.26.0 → 0.27.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 +1 -1
- package/dist/index.d.ts +21 -1
- package/dist/index.js +46 -24
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -7,7 +7,7 @@ const program = new Command();
|
|
|
7
7
|
program
|
|
8
8
|
.name('apinow')
|
|
9
9
|
.description('CLI for APINow.fun — search, inspect, and call pay-per-request APIs')
|
|
10
|
-
.version('0.
|
|
10
|
+
.version('0.27.0');
|
|
11
11
|
// ─── Helpers ───
|
|
12
12
|
function getPrivateKey(opts) {
|
|
13
13
|
const raw = opts.key || process.env.APINOW_WALLET_PKEY || process.env.PRIVATE_KEY;
|
package/dist/index.d.ts
CHANGED
|
@@ -18,11 +18,31 @@ export interface PriceDiscovery {
|
|
|
18
18
|
network: string;
|
|
19
19
|
upstreamAccepts: any[];
|
|
20
20
|
}
|
|
21
|
-
|
|
21
|
+
/**
|
|
22
|
+
* Agent/server path — signs everything with a raw private key. Enables
|
|
23
|
+
* both x402 paid calls and signed-auth write calls.
|
|
24
|
+
*/
|
|
25
|
+
export interface ApinowServerConfig {
|
|
22
26
|
privateKey: `0x${string}`;
|
|
23
27
|
baseUrl?: string;
|
|
24
28
|
fetch?: typeof globalThis.fetch;
|
|
25
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* Browser/wallet path — you provide a `signer` (any EIP-191 `personal_sign`
|
|
32
|
+
* function, e.g. from wagmi's `walletClient.signMessage`) and the connected
|
|
33
|
+
* `address`. Enables signed-auth writes. Paid x402 calls are NOT provided by
|
|
34
|
+
* this path — construct the x402 fetch yourself (see useX402Fetch pattern in
|
|
35
|
+
* the skill docs) and pass it to `paidFetch` if you need unified behaviour.
|
|
36
|
+
*/
|
|
37
|
+
export interface ApinowBrowserConfig {
|
|
38
|
+
signer: (message: string) => Promise<`0x${string}` | string>;
|
|
39
|
+
address: `0x${string}`;
|
|
40
|
+
baseUrl?: string;
|
|
41
|
+
fetch?: typeof globalThis.fetch;
|
|
42
|
+
/** Optional externally-prepared x402 fetch for paid calls. */
|
|
43
|
+
paidFetch?: typeof globalThis.fetch;
|
|
44
|
+
}
|
|
45
|
+
export type ApinowConfig = ApinowServerConfig | ApinowBrowserConfig;
|
|
26
46
|
export interface GenerateUIOptions {
|
|
27
47
|
endpointName: string;
|
|
28
48
|
namespace: string;
|
package/dist/index.js
CHANGED
|
@@ -2,6 +2,9 @@ import { x402Client, wrapFetchWithPayment } from '@x402/fetch';
|
|
|
2
2
|
import { registerExactEvmScheme } from '@x402/evm/exact/client';
|
|
3
3
|
import { privateKeyToAccount } from 'viem/accounts';
|
|
4
4
|
const APINOW_BASE = 'https://apinow.fun';
|
|
5
|
+
function isServerConfig(c) {
|
|
6
|
+
return 'privateKey' in c && typeof c.privateKey === 'string';
|
|
7
|
+
}
|
|
5
8
|
// ─── SDK ───
|
|
6
9
|
// Prevent undici (Node 20+ / Vercel) from crashing when @x402/fetch retries
|
|
7
10
|
// a POST with a cloned Request body stream and the server returns a 3xx redirect.
|
|
@@ -23,31 +26,50 @@ async function followRedirects(res) {
|
|
|
23
26
|
return res;
|
|
24
27
|
}
|
|
25
28
|
export function createClient(config) {
|
|
26
|
-
const
|
|
27
|
-
const
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
const
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
29
|
+
const server = isServerConfig(config);
|
|
30
|
+
const baseUrl = config.baseUrl ?? APINOW_BASE;
|
|
31
|
+
const customFetch = config.fetch;
|
|
32
|
+
// Resolve address + signer from whichever config shape the caller passed.
|
|
33
|
+
const account = server ? privateKeyToAccount(config.privateKey) : null;
|
|
34
|
+
const address = server
|
|
35
|
+
? account.address
|
|
36
|
+
: config.address.toLowerCase();
|
|
37
|
+
const signMessage = server
|
|
38
|
+
? (msg) => account.signMessage({ message: msg })
|
|
39
|
+
: (msg) => Promise.resolve(config.signer(msg)).then((s) => String(s));
|
|
40
|
+
// x402 paid fetch — only available when a private key is provided. Browsers
|
|
41
|
+
// should build their own x402 fetch (see skill.md useX402Fetch) and pass it
|
|
42
|
+
// as `paidFetch` to fall back through here.
|
|
43
|
+
const paidFetchExternal = !server ? config.paidFetch : undefined;
|
|
44
|
+
const fetchWithPayment = server
|
|
45
|
+
? (() => {
|
|
46
|
+
const client = new x402Client();
|
|
47
|
+
registerExactEvmScheme(client, { signer: account });
|
|
48
|
+
const safeFetch = makeSafeFetch(customFetch ?? fetch);
|
|
49
|
+
const rawFetchWithPayment = wrapFetchWithPayment(safeFetch, client);
|
|
50
|
+
return (async (input, init) => {
|
|
51
|
+
const res = await rawFetchWithPayment(input, init);
|
|
52
|
+
return followRedirects(res);
|
|
53
|
+
});
|
|
54
|
+
})()
|
|
55
|
+
: (paidFetchExternal ??
|
|
56
|
+
(() => {
|
|
57
|
+
throw new Error('createClient: paid calls require a `privateKey` config or an explicit `paidFetch`. Pass an x402-wrapped fetch to make paid calls from the browser.');
|
|
58
|
+
}));
|
|
36
59
|
/**
|
|
37
60
|
* Produce an `Authorization: Bearer <msg>||<sig>||<addr>` header signed by
|
|
38
|
-
* the wallet
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
* Exposed as a public helper so agents can sign custom write calls too.
|
|
61
|
+
* the wallet. Backend verifies with ethers.recoverAddress and rejects
|
|
62
|
+
* messages older than ~10 min. Works for both server (privateKey) and
|
|
63
|
+
* browser (walletClient.signMessage) configs.
|
|
42
64
|
*/
|
|
43
65
|
async function signAuthHeader() {
|
|
44
66
|
const issuedAt = new Date().toISOString();
|
|
45
67
|
const nonce = Math.random().toString(36).slice(2) + Date.now().toString(36);
|
|
46
|
-
const message = `APINow auth\naddress: ${
|
|
47
|
-
const signature = await
|
|
68
|
+
const message = `APINow auth\naddress: ${address}\nissuedAt: ${issuedAt}\nnonce: ${nonce}`;
|
|
69
|
+
const signature = await signMessage(message);
|
|
48
70
|
return {
|
|
49
|
-
Authorization: `Bearer ${message}||${signature}||${
|
|
50
|
-
'x-wallet-address':
|
|
71
|
+
Authorization: `Bearer ${message}||${signature}||${address}`,
|
|
72
|
+
'x-wallet-address': address,
|
|
51
73
|
};
|
|
52
74
|
}
|
|
53
75
|
/**
|
|
@@ -75,7 +97,7 @@ export function createClient(config) {
|
|
|
75
97
|
return res.json();
|
|
76
98
|
}
|
|
77
99
|
return {
|
|
78
|
-
wallet:
|
|
100
|
+
wallet: address,
|
|
79
101
|
/**
|
|
80
102
|
* Produce a signed `Authorization` header for custom write calls.
|
|
81
103
|
* Pairs with `x-wallet-address`. Backend accepts msg within ~10 min.
|
|
@@ -210,7 +232,7 @@ export function createClient(config) {
|
|
|
210
232
|
* List workflows you created (convenience for `listWorkflows({ creator: yourWallet })`).
|
|
211
233
|
*/
|
|
212
234
|
async listMyWorkflows(opts = {}) {
|
|
213
|
-
return this.listWorkflows({ ...opts, creator:
|
|
235
|
+
return this.listWorkflows({ ...opts, creator: address });
|
|
214
236
|
},
|
|
215
237
|
// ─── Workflow Versions ───
|
|
216
238
|
/**
|
|
@@ -374,7 +396,7 @@ export function createClient(config) {
|
|
|
374
396
|
const res = await fetch(`${baseUrl}/api/ai/generate-ui`, {
|
|
375
397
|
method: 'POST',
|
|
376
398
|
headers: { 'Content-Type': 'application/json' },
|
|
377
|
-
body: JSON.stringify({ ...opts, walletAddress:
|
|
399
|
+
body: JSON.stringify({ ...opts, walletAddress: address }),
|
|
378
400
|
});
|
|
379
401
|
if (!res.ok) {
|
|
380
402
|
const text = await res.text();
|
|
@@ -409,7 +431,7 @@ export function createClient(config) {
|
|
|
409
431
|
* Check free-tier UI generation eligibility for a wallet.
|
|
410
432
|
*/
|
|
411
433
|
async checkFreeUI() {
|
|
412
|
-
const params = new URLSearchParams({ checkFree: '1', wallet:
|
|
434
|
+
const params = new URLSearchParams({ checkFree: '1', wallet: address });
|
|
413
435
|
const res = await fetch(`${baseUrl}/api/ai/generate-ui?${params}`);
|
|
414
436
|
if (!res.ok)
|
|
415
437
|
throw new Error(`Failed to check free tier: ${res.status}`);
|
|
@@ -419,7 +441,7 @@ export function createClient(config) {
|
|
|
419
441
|
* Like, dislike, or comment on a generated UI.
|
|
420
442
|
*/
|
|
421
443
|
async reactToUI(id, action, comment) {
|
|
422
|
-
const body = { id, action, wallet:
|
|
444
|
+
const body = { id, action, wallet: address };
|
|
423
445
|
if (comment)
|
|
424
446
|
body.comment = comment;
|
|
425
447
|
const res = await fetch(`${baseUrl}/api/ai/generate-ui`, {
|
|
@@ -440,7 +462,7 @@ export function createClient(config) {
|
|
|
440
462
|
const res = await fetch(`${baseUrl}/api/ai/generate-ui`, {
|
|
441
463
|
method: 'DELETE',
|
|
442
464
|
headers: { 'Content-Type': 'application/json' },
|
|
443
|
-
body: JSON.stringify({ id, wallet:
|
|
465
|
+
body: JSON.stringify({ id, wallet: address }),
|
|
444
466
|
});
|
|
445
467
|
if (!res.ok) {
|
|
446
468
|
const text = await res.text();
|
package/package.json
CHANGED