apinow-sdk 0.27.0 → 0.28.1
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 +16 -4
- package/dist/index.d.ts +82 -16
- package/dist/index.js +58 -4
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -210,6 +210,7 @@ program
|
|
|
210
210
|
.requiredOption('--description <desc>', 'Description')
|
|
211
211
|
.option('--method <method>', 'HTTP method', 'POST')
|
|
212
212
|
.option('--price <usdc>', 'USDC price per call', '0.01')
|
|
213
|
+
.option('--splits <json>', 'Splits JSON array [{address, basisPoints, label?, tokenAddress?}] — basisPoints must sum to 10000')
|
|
213
214
|
.option('-k, --key <privateKey>', 'Wallet private key')
|
|
214
215
|
.action(async (opts) => {
|
|
215
216
|
try {
|
|
@@ -222,6 +223,8 @@ program
|
|
|
222
223
|
httpMethod: opts.method.toUpperCase(),
|
|
223
224
|
paymentOptions: [{ usdAmount: opts.price, amount: opts.price }],
|
|
224
225
|
};
|
|
226
|
+
if (opts.splits)
|
|
227
|
+
body.splits = JSON.parse(opts.splits);
|
|
225
228
|
const data = await fetchJson(`${API_BASE}/api/endpoints`, {
|
|
226
229
|
method: 'POST',
|
|
227
230
|
headers: await walletHeaders(privateKey),
|
|
@@ -242,6 +245,7 @@ program
|
|
|
242
245
|
.option('--url <url>', 'New URL')
|
|
243
246
|
.option('--price <usdc>', 'New USDC price')
|
|
244
247
|
.option('--status <status>', 'New status')
|
|
248
|
+
.option('--splits <json>', 'Splits JSON array — changing splits redeploys the splitter contract (V2 is immutable)')
|
|
245
249
|
.option('-k, --key <privateKey>', 'Wallet private key')
|
|
246
250
|
.action(async (id, opts) => {
|
|
247
251
|
try {
|
|
@@ -255,6 +259,8 @@ program
|
|
|
255
259
|
body.status = opts.status;
|
|
256
260
|
if (opts.price)
|
|
257
261
|
body.paymentOptions = [{ usdAmount: opts.price, amount: opts.price }];
|
|
262
|
+
if (opts.splits)
|
|
263
|
+
body.splits = JSON.parse(opts.splits);
|
|
258
264
|
const data = await fetchJson(`${API_BASE}/api/endpoints/${id}`, {
|
|
259
265
|
method: 'PUT',
|
|
260
266
|
headers: await walletHeaders(privateKey),
|
|
@@ -518,11 +524,13 @@ program
|
|
|
518
524
|
// ─── workflow-update ───
|
|
519
525
|
program
|
|
520
526
|
.command('workflow-update <id>')
|
|
521
|
-
.description('Update a workflow by ID')
|
|
522
|
-
.option('--name <name>', 'New name')
|
|
523
|
-
.option('--description <desc>', 'New description')
|
|
527
|
+
.description('Update a workflow by ID (price/splits/graph changes auto-create a new version)')
|
|
528
|
+
.option('--name <name>', 'New name (7-day cooldown; 429 if on cooldown)')
|
|
529
|
+
.option('--description <desc>', 'New description (7-day cooldown)')
|
|
524
530
|
.option('--status <status>', 'New status')
|
|
525
|
-
.option('--price <usdc>', 'New total price')
|
|
531
|
+
.option('--price <usdc>', 'New total price — auto-bumps version')
|
|
532
|
+
.option('--splits <json>', 'Splits JSON array — auto-bumps version; redeploys splitter if structurally changed')
|
|
533
|
+
.option('--changelog <msg>', 'Label for the auto-created version snapshot')
|
|
526
534
|
.option('-k, --key <privateKey>', 'Wallet private key')
|
|
527
535
|
.action(async (id, opts) => {
|
|
528
536
|
try {
|
|
@@ -536,6 +544,10 @@ program
|
|
|
536
544
|
body.status = opts.status;
|
|
537
545
|
if (opts.price)
|
|
538
546
|
body.totalPrice = opts.price;
|
|
547
|
+
if (opts.splits)
|
|
548
|
+
body.splits = JSON.parse(opts.splits);
|
|
549
|
+
if (opts.changelog)
|
|
550
|
+
body.changelog = opts.changelog;
|
|
539
551
|
const data = await fetchJson(`${API_BASE}/api/workflows/${id}`, {
|
|
540
552
|
method: 'PUT',
|
|
541
553
|
headers: await walletHeaders(privateKey),
|
package/dist/index.d.ts
CHANGED
|
@@ -43,6 +43,25 @@ export interface ApinowBrowserConfig {
|
|
|
43
43
|
paidFetch?: typeof globalThis.fetch;
|
|
44
44
|
}
|
|
45
45
|
export type ApinowConfig = ApinowServerConfig | ApinowBrowserConfig;
|
|
46
|
+
export interface SplitConfig {
|
|
47
|
+
address: string;
|
|
48
|
+
basisPoints: number;
|
|
49
|
+
label?: string;
|
|
50
|
+
tokenAddress?: string;
|
|
51
|
+
recipientAddress?: string;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Thrown by authed writes when the backend returns a non-2xx. Exposes status
|
|
55
|
+
* code and parsed JSON body so callers can branch on e.g. 429 cooldowns
|
|
56
|
+
* without re-parsing error text.
|
|
57
|
+
*/
|
|
58
|
+
export declare class ApinowApiError extends Error {
|
|
59
|
+
readonly status: number;
|
|
60
|
+
readonly body: any;
|
|
61
|
+
readonly retryAfterMs?: number;
|
|
62
|
+
readonly retryAfterDays?: number;
|
|
63
|
+
constructor(status: number, body: any);
|
|
64
|
+
}
|
|
46
65
|
export interface GenerateUIOptions {
|
|
47
66
|
endpointName: string;
|
|
48
67
|
namespace: string;
|
|
@@ -98,6 +117,13 @@ export declare function createClient(config: ApinowConfig): {
|
|
|
98
117
|
* Get public endpoint info (free, no payment).
|
|
99
118
|
*/
|
|
100
119
|
info(namespace: string, endpointName: string): Promise<any>;
|
|
120
|
+
/**
|
|
121
|
+
* Create an endpoint. If `splits` are provided they must sum to exactly
|
|
122
|
+
* `10000` basis points; the server deploys a 0xSplits V2 splitter after
|
|
123
|
+
* creation and stores `splitterAddress` on the endpoint. Non-fatal if
|
|
124
|
+
* the splitter deploy fails — endpoint will exist without one and can be
|
|
125
|
+
* retried via `updateEndpoint({ splits })`.
|
|
126
|
+
*/
|
|
101
127
|
createEndpoint(config: {
|
|
102
128
|
namespace: string;
|
|
103
129
|
endpointName: string;
|
|
@@ -116,9 +142,34 @@ export declare function createClient(config: ApinowConfig): {
|
|
|
116
142
|
exampleQuery?: any;
|
|
117
143
|
exampleOutput?: any;
|
|
118
144
|
docsUrl?: string;
|
|
145
|
+
splits?: SplitConfig[];
|
|
119
146
|
}): Promise<any>;
|
|
120
147
|
getEndpoint(id: string): Promise<any>;
|
|
121
|
-
|
|
148
|
+
/**
|
|
149
|
+
* Update an endpoint. Changing `splits` (structurally) redeploys the
|
|
150
|
+
* splitter contract (V2 is immutable); the old address is archived on
|
|
151
|
+
* `previousSplitters[]` and the platform drains leftover USDC from it.
|
|
152
|
+
* `splits` must sum to `10000` basis points when non-empty.
|
|
153
|
+
*/
|
|
154
|
+
updateEndpoint(id: string, updates: {
|
|
155
|
+
url?: string;
|
|
156
|
+
description?: string;
|
|
157
|
+
httpMethod?: "GET" | "POST";
|
|
158
|
+
paymentOptions?: Array<{
|
|
159
|
+
amount?: string;
|
|
160
|
+
usdAmount?: string;
|
|
161
|
+
tokenAddress?: string;
|
|
162
|
+
tokenSymbol?: string;
|
|
163
|
+
}>;
|
|
164
|
+
status?: string;
|
|
165
|
+
splits?: SplitConfig[];
|
|
166
|
+
querySchema?: any;
|
|
167
|
+
responseSchema?: any;
|
|
168
|
+
exampleQuery?: any;
|
|
169
|
+
exampleOutput?: any;
|
|
170
|
+
docsUrl?: string;
|
|
171
|
+
[key: string]: any;
|
|
172
|
+
}): Promise<any>;
|
|
122
173
|
deleteEndpoint(id: string): Promise<any>;
|
|
123
174
|
listEndpoints(opts?: {
|
|
124
175
|
limit?: number;
|
|
@@ -153,15 +204,32 @@ export declare function createClient(config: ApinowConfig): {
|
|
|
153
204
|
};
|
|
154
205
|
prompt?: string;
|
|
155
206
|
totalPrice?: string;
|
|
156
|
-
splits?:
|
|
157
|
-
address: string;
|
|
158
|
-
basisPoints: number;
|
|
159
|
-
label?: string;
|
|
160
|
-
tokenAddress?: string;
|
|
161
|
-
}>;
|
|
207
|
+
splits?: SplitConfig[];
|
|
162
208
|
chain?: string;
|
|
163
209
|
}): Promise<any>;
|
|
164
|
-
|
|
210
|
+
/**
|
|
211
|
+
* Update a workflow. Changing `graph`, `totalPrice`, or `splits`
|
|
212
|
+
* auto-creates a new `WorkflowVersion` snapshot server-side; pass
|
|
213
|
+
* `changelog` to label it. `name`/`description` are subject to a 7-day
|
|
214
|
+
* cooldown — throws `ApinowApiError` with `status=429` and `retryAfterMs`
|
|
215
|
+
* when the cooldown is active.
|
|
216
|
+
*/
|
|
217
|
+
updateWorkflow(workflowId: string, updates: {
|
|
218
|
+
name?: string;
|
|
219
|
+
description?: string;
|
|
220
|
+
status?: string;
|
|
221
|
+
totalPrice?: string;
|
|
222
|
+
splits?: SplitConfig[];
|
|
223
|
+
graph?: {
|
|
224
|
+
nodes: any[];
|
|
225
|
+
outputNode: string;
|
|
226
|
+
outputMapping?: any;
|
|
227
|
+
};
|
|
228
|
+
executionMode?: "balanced" | "optimistic" | "settle_first";
|
|
229
|
+
mermaidDiagram?: string;
|
|
230
|
+
changelog?: string;
|
|
231
|
+
[key: string]: any;
|
|
232
|
+
}): Promise<any>;
|
|
165
233
|
deleteWorkflow(workflowId: string): Promise<any>;
|
|
166
234
|
/**
|
|
167
235
|
* List workflows you created (convenience for `listWorkflows({ creator: yourWallet })`).
|
|
@@ -181,8 +249,11 @@ export declare function createClient(config: ApinowConfig): {
|
|
|
181
249
|
*/
|
|
182
250
|
getWorkflowVersion(workflowId: string, versionIdOrNumber: string | number): Promise<any>;
|
|
183
251
|
/**
|
|
184
|
-
* Create a new workflow version (creator only). Defaults to setting it as
|
|
185
|
-
* Omit fields to inherit from current workflow.
|
|
252
|
+
* Create a new workflow version (creator only). Defaults to setting it as
|
|
253
|
+
* default. Omit fields to inherit from current workflow. If `splits`
|
|
254
|
+
* differs from the current config, the server redeploys the 0xSplits V2
|
|
255
|
+
* contract and stores `splitterAddress` / `splitterTxHash` on the version.
|
|
256
|
+
* Splits basis points must sum to `10000`.
|
|
186
257
|
*/
|
|
187
258
|
createWorkflowVersion(workflowId: string, updates?: {
|
|
188
259
|
graph?: {
|
|
@@ -191,12 +262,7 @@ export declare function createClient(config: ApinowConfig): {
|
|
|
191
262
|
outputMapping?: any;
|
|
192
263
|
};
|
|
193
264
|
totalPrice?: string;
|
|
194
|
-
splits?:
|
|
195
|
-
address: string;
|
|
196
|
-
basisPoints: number;
|
|
197
|
-
label?: string;
|
|
198
|
-
tokenAddress?: string;
|
|
199
|
-
}>;
|
|
265
|
+
splits?: SplitConfig[];
|
|
200
266
|
mermaidDiagram?: string;
|
|
201
267
|
executionMode?: "balanced" | "optimistic" | "settle_first";
|
|
202
268
|
changelog?: string;
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,27 @@ const APINOW_BASE = 'https://apinow.fun';
|
|
|
5
5
|
function isServerConfig(c) {
|
|
6
6
|
return 'privateKey' in c && typeof c.privateKey === 'string';
|
|
7
7
|
}
|
|
8
|
+
/**
|
|
9
|
+
* Thrown by authed writes when the backend returns a non-2xx. Exposes status
|
|
10
|
+
* code and parsed JSON body so callers can branch on e.g. 429 cooldowns
|
|
11
|
+
* without re-parsing error text.
|
|
12
|
+
*/
|
|
13
|
+
export class ApinowApiError extends Error {
|
|
14
|
+
constructor(status, body) {
|
|
15
|
+
const msg = (body && typeof body === 'object' && (body.error || body.message)) ||
|
|
16
|
+
(typeof body === 'string' ? body : JSON.stringify(body));
|
|
17
|
+
super(`APINow ${status}: ${msg}`);
|
|
18
|
+
this.name = 'ApinowApiError';
|
|
19
|
+
this.status = status;
|
|
20
|
+
this.body = body;
|
|
21
|
+
if (body && typeof body === 'object') {
|
|
22
|
+
if (typeof body.retryAfterMs === 'number')
|
|
23
|
+
this.retryAfterMs = body.retryAfterMs;
|
|
24
|
+
if (typeof body.retryAfterDays === 'number')
|
|
25
|
+
this.retryAfterDays = body.retryAfterDays;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
8
29
|
// ─── SDK ───
|
|
9
30
|
// Prevent undici (Node 20+ / Vercel) from crashing when @x402/fetch retries
|
|
10
31
|
// a POST with a cloned Request body stream and the server returns a 3xx redirect.
|
|
@@ -65,7 +86,10 @@ export function createClient(config) {
|
|
|
65
86
|
async function signAuthHeader() {
|
|
66
87
|
const issuedAt = new Date().toISOString();
|
|
67
88
|
const nonce = Math.random().toString(36).slice(2) + Date.now().toString(36);
|
|
68
|
-
|
|
89
|
+
// Single-line format: Chrome's fetch() rejects header values containing
|
|
90
|
+
// raw newlines ("Failed to execute 'fetch' on 'Window': Invalid value").
|
|
91
|
+
// Server parses via regex so space-separated works identically.
|
|
92
|
+
const message = `APINow auth | address: ${address} | issuedAt: ${issuedAt} | nonce: ${nonce}`;
|
|
69
93
|
const signature = await signMessage(message);
|
|
70
94
|
return {
|
|
71
95
|
Authorization: `Bearer ${message}||${signature}||${address}`,
|
|
@@ -92,7 +116,14 @@ export function createClient(config) {
|
|
|
92
116
|
const res = await authedFetch(url, init);
|
|
93
117
|
if (!res.ok) {
|
|
94
118
|
const text = await res.text();
|
|
95
|
-
|
|
119
|
+
let parsed = text;
|
|
120
|
+
try {
|
|
121
|
+
parsed = JSON.parse(text);
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
// leave as text
|
|
125
|
+
}
|
|
126
|
+
throw new ApinowApiError(res.status, parsed);
|
|
96
127
|
}
|
|
97
128
|
return res.json();
|
|
98
129
|
}
|
|
@@ -151,6 +182,13 @@ export function createClient(config) {
|
|
|
151
182
|
return res.json();
|
|
152
183
|
},
|
|
153
184
|
// ─── Endpoint CRUD ───
|
|
185
|
+
/**
|
|
186
|
+
* Create an endpoint. If `splits` are provided they must sum to exactly
|
|
187
|
+
* `10000` basis points; the server deploys a 0xSplits V2 splitter after
|
|
188
|
+
* creation and stores `splitterAddress` on the endpoint. Non-fatal if
|
|
189
|
+
* the splitter deploy fails — endpoint will exist without one and can be
|
|
190
|
+
* retried via `updateEndpoint({ splits })`.
|
|
191
|
+
*/
|
|
154
192
|
async createEndpoint(config) {
|
|
155
193
|
return authedJson(`${baseUrl}/api/endpoints`, {
|
|
156
194
|
method: 'POST',
|
|
@@ -163,6 +201,12 @@ export function createClient(config) {
|
|
|
163
201
|
throw new Error(`Failed to get endpoint: ${res.status}`);
|
|
164
202
|
return res.json();
|
|
165
203
|
},
|
|
204
|
+
/**
|
|
205
|
+
* Update an endpoint. Changing `splits` (structurally) redeploys the
|
|
206
|
+
* splitter contract (V2 is immutable); the old address is archived on
|
|
207
|
+
* `previousSplitters[]` and the platform drains leftover USDC from it.
|
|
208
|
+
* `splits` must sum to `10000` basis points when non-empty.
|
|
209
|
+
*/
|
|
166
210
|
async updateEndpoint(id, updates) {
|
|
167
211
|
return authedJson(`${baseUrl}/api/endpoints/${id}`, {
|
|
168
212
|
method: 'PUT',
|
|
@@ -219,6 +263,13 @@ export function createClient(config) {
|
|
|
219
263
|
body: JSON.stringify(config),
|
|
220
264
|
});
|
|
221
265
|
},
|
|
266
|
+
/**
|
|
267
|
+
* Update a workflow. Changing `graph`, `totalPrice`, or `splits`
|
|
268
|
+
* auto-creates a new `WorkflowVersion` snapshot server-side; pass
|
|
269
|
+
* `changelog` to label it. `name`/`description` are subject to a 7-day
|
|
270
|
+
* cooldown — throws `ApinowApiError` with `status=429` and `retryAfterMs`
|
|
271
|
+
* when the cooldown is active.
|
|
272
|
+
*/
|
|
222
273
|
async updateWorkflow(workflowId, updates) {
|
|
223
274
|
return authedJson(`${baseUrl}/api/workflows/${workflowId}`, {
|
|
224
275
|
method: 'PUT',
|
|
@@ -254,8 +305,11 @@ export function createClient(config) {
|
|
|
254
305
|
return res.json();
|
|
255
306
|
},
|
|
256
307
|
/**
|
|
257
|
-
* Create a new workflow version (creator only). Defaults to setting it as
|
|
258
|
-
* Omit fields to inherit from current workflow.
|
|
308
|
+
* Create a new workflow version (creator only). Defaults to setting it as
|
|
309
|
+
* default. Omit fields to inherit from current workflow. If `splits`
|
|
310
|
+
* differs from the current config, the server redeploys the 0xSplits V2
|
|
311
|
+
* contract and stores `splitterAddress` / `splitterTxHash` on the version.
|
|
312
|
+
* Splits basis points must sum to `10000`.
|
|
259
313
|
*/
|
|
260
314
|
async createWorkflowVersion(workflowId, updates = {}) {
|
|
261
315
|
return authedJson(`${baseUrl}/api/workflows/${workflowId}/versions`, {
|
package/package.json
CHANGED