@conto_finance/sdk 0.1.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/README.md +107 -0
- package/dist/index.d.mts +753 -0
- package/dist/index.d.ts +753 -0
- package/dist/index.js +697 -0
- package/dist/index.mjs +683 -0
- package/package.json +60 -0
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,683 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __commonJS = (cb, mod) => function __require() {
|
|
8
|
+
try {
|
|
9
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
10
|
+
} catch (e) {
|
|
11
|
+
throw mod = 0, e;
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
var __copyProps = (to, from, except, desc) => {
|
|
15
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
16
|
+
for (let key of __getOwnPropNames(from))
|
|
17
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
18
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
19
|
+
}
|
|
20
|
+
return to;
|
|
21
|
+
};
|
|
22
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
23
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
24
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
25
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
26
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
27
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
28
|
+
mod
|
|
29
|
+
));
|
|
30
|
+
|
|
31
|
+
// package.json
|
|
32
|
+
var require_package = __commonJS({
|
|
33
|
+
"package.json"(exports, module) {
|
|
34
|
+
module.exports = {
|
|
35
|
+
name: "@conto_finance/sdk",
|
|
36
|
+
version: "0.1.0",
|
|
37
|
+
description: "Conto SDK for AI agent payment authorization",
|
|
38
|
+
main: "./dist/index.js",
|
|
39
|
+
module: "./dist/index.mjs",
|
|
40
|
+
types: "./dist/index.d.ts",
|
|
41
|
+
exports: {
|
|
42
|
+
".": {
|
|
43
|
+
types: "./dist/index.d.ts",
|
|
44
|
+
import: "./dist/index.mjs",
|
|
45
|
+
require: "./dist/index.js"
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
publishConfig: {
|
|
49
|
+
access: "public"
|
|
50
|
+
},
|
|
51
|
+
engines: {
|
|
52
|
+
node: ">=18"
|
|
53
|
+
},
|
|
54
|
+
files: [
|
|
55
|
+
"dist"
|
|
56
|
+
],
|
|
57
|
+
scripts: {
|
|
58
|
+
build: "tsup src/index.ts --format cjs,esm --dts",
|
|
59
|
+
dev: "tsup src/index.ts --format cjs,esm --dts --watch",
|
|
60
|
+
lint: "tsc --noEmit",
|
|
61
|
+
prepublishOnly: "npm run build"
|
|
62
|
+
},
|
|
63
|
+
keywords: [
|
|
64
|
+
"conto",
|
|
65
|
+
"ai",
|
|
66
|
+
"agent",
|
|
67
|
+
"payments",
|
|
68
|
+
"authorization",
|
|
69
|
+
"sdk"
|
|
70
|
+
],
|
|
71
|
+
author: "Conto",
|
|
72
|
+
license: "MIT",
|
|
73
|
+
repository: {
|
|
74
|
+
type: "git",
|
|
75
|
+
url: "https://github.com/conto-finance/conto.git",
|
|
76
|
+
directory: "packages/sdk"
|
|
77
|
+
},
|
|
78
|
+
homepage: "https://conto.finance/docs/sdk",
|
|
79
|
+
bugs: {
|
|
80
|
+
url: "https://github.com/conto-finance/conto/issues"
|
|
81
|
+
},
|
|
82
|
+
dependencies: {
|
|
83
|
+
"@sentry/node": "^10.56.0"
|
|
84
|
+
},
|
|
85
|
+
overrides: {
|
|
86
|
+
esbuild: "0.28.1"
|
|
87
|
+
},
|
|
88
|
+
devDependencies: {
|
|
89
|
+
"@types/node": "^22.19.18",
|
|
90
|
+
tsup: "^8.5.1",
|
|
91
|
+
typescript: "^5.9.3"
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
// src/package-version.js
|
|
98
|
+
var require_package_version = __commonJS({
|
|
99
|
+
"src/package-version.js"(exports, module) {
|
|
100
|
+
"use strict";
|
|
101
|
+
var packageJson = require_package();
|
|
102
|
+
var SDK_PACKAGE_VERSION3 = packageJson.version || "0.0.0";
|
|
103
|
+
module.exports = {
|
|
104
|
+
SDK_PACKAGE_VERSION: SDK_PACKAGE_VERSION3
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
// src/index.ts
|
|
110
|
+
var import_package_version2 = __toESM(require_package_version());
|
|
111
|
+
import * as Sentry2 from "@sentry/node";
|
|
112
|
+
|
|
113
|
+
// src/admin.ts
|
|
114
|
+
var import_package_version = __toESM(require_package_version());
|
|
115
|
+
import * as Sentry from "@sentry/node";
|
|
116
|
+
var ContoAdmin = class {
|
|
117
|
+
constructor(config) {
|
|
118
|
+
if (!config.orgApiKey) {
|
|
119
|
+
throw new Error("Organization API key is required");
|
|
120
|
+
}
|
|
121
|
+
if (config.orgApiKey.startsWith("conto_agent_")) {
|
|
122
|
+
throw new Error(
|
|
123
|
+
"ContoAdmin requires an organization API key (conto_xxx...), not an agent SDK key (conto_agent_xxx...). Use the Conto class for agent operations."
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
if (!config.orgApiKey.startsWith("conto_")) {
|
|
127
|
+
throw new Error(
|
|
128
|
+
"Invalid API key format. Expected organization API key starting with conto_xxx..."
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
this.orgApiKey = config.orgApiKey;
|
|
132
|
+
this.baseUrl = (config.baseUrl || "https://conto.finance").replace(/\/$/, "");
|
|
133
|
+
this.timeout = config.timeout || 3e4;
|
|
134
|
+
this.agents = new AgentsClient(this);
|
|
135
|
+
this.wallets = new WalletsClient(this);
|
|
136
|
+
this.policies = new PoliciesClient(this);
|
|
137
|
+
this.team = new TeamClient(this);
|
|
138
|
+
}
|
|
139
|
+
async fetchWithRetry(url, options, maxRetries = 3) {
|
|
140
|
+
let lastError = null;
|
|
141
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
142
|
+
try {
|
|
143
|
+
const response = await fetch(url, options);
|
|
144
|
+
if (response.status === 429 || response.status >= 500 && attempt < maxRetries) {
|
|
145
|
+
const retryAfter = response.headers.get("retry-after");
|
|
146
|
+
const delay = retryAfter ? parseInt(retryAfter, 10) * 1e3 : Math.min(1e3 * 2 ** attempt, 1e4);
|
|
147
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
return response;
|
|
151
|
+
} catch (err) {
|
|
152
|
+
lastError = err instanceof Error ? err : new Error(String(err));
|
|
153
|
+
if (attempt < maxRetries) {
|
|
154
|
+
const delay = Math.min(1e3 * 2 ** attempt, 1e4);
|
|
155
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
throw lastError || new Error("Request failed after retries");
|
|
161
|
+
}
|
|
162
|
+
/** Make an authenticated request to the Conto API */
|
|
163
|
+
async request(method, path, body) {
|
|
164
|
+
const url = `${this.baseUrl}${path}`;
|
|
165
|
+
const controller = new AbortController();
|
|
166
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
167
|
+
try {
|
|
168
|
+
const response = await this.fetchWithRetry(url, {
|
|
169
|
+
method,
|
|
170
|
+
headers: {
|
|
171
|
+
Authorization: `Bearer ${this.orgApiKey}`,
|
|
172
|
+
"Content-Type": "application/json",
|
|
173
|
+
"User-Agent": `@conto_finance/sdk-admin/${import_package_version.SDK_PACKAGE_VERSION}`
|
|
174
|
+
},
|
|
175
|
+
body: body ? JSON.stringify(body) : void 0,
|
|
176
|
+
signal: controller.signal
|
|
177
|
+
});
|
|
178
|
+
clearTimeout(timeoutId);
|
|
179
|
+
const data = await response.json();
|
|
180
|
+
if (!response.ok) {
|
|
181
|
+
const errorMessage = typeof data.error === "string" ? data.error : "Request failed";
|
|
182
|
+
const error = new Error(errorMessage);
|
|
183
|
+
error.code = typeof data.code === "string" ? data.code : "UNKNOWN_ERROR";
|
|
184
|
+
error.status = response.status;
|
|
185
|
+
throw error;
|
|
186
|
+
}
|
|
187
|
+
return data;
|
|
188
|
+
} catch (error) {
|
|
189
|
+
clearTimeout(timeoutId);
|
|
190
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
191
|
+
const timeoutError = new Error("Request timeout");
|
|
192
|
+
timeoutError.code = "TIMEOUT";
|
|
193
|
+
timeoutError.status = 0;
|
|
194
|
+
Sentry.captureException(timeoutError, { extra: { method, path } });
|
|
195
|
+
throw timeoutError;
|
|
196
|
+
}
|
|
197
|
+
if (error instanceof Error) {
|
|
198
|
+
Sentry.captureException(error, { extra: { method, path } });
|
|
199
|
+
}
|
|
200
|
+
throw error;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
var AgentsClient = class {
|
|
205
|
+
constructor(client) {
|
|
206
|
+
this.client = client;
|
|
207
|
+
}
|
|
208
|
+
/** List agents in the organization */
|
|
209
|
+
async list(params) {
|
|
210
|
+
const query = new URLSearchParams();
|
|
211
|
+
if (params?.status) query.set("status", params.status);
|
|
212
|
+
if (params?.search) query.set("search", params.search);
|
|
213
|
+
if (params?.limit) query.set("limit", String(params.limit));
|
|
214
|
+
if (params?.offset) query.set("offset", String(params.offset));
|
|
215
|
+
const qs = query.toString() ? `?${query.toString()}` : "";
|
|
216
|
+
return this.client.request("GET", `/api/agents${qs}`);
|
|
217
|
+
}
|
|
218
|
+
/** Create a new agent */
|
|
219
|
+
async create(input) {
|
|
220
|
+
return this.client.request(
|
|
221
|
+
"POST",
|
|
222
|
+
"/api/agents",
|
|
223
|
+
input
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
/** Get a single agent by ID */
|
|
227
|
+
async get(agentId) {
|
|
228
|
+
return this.client.request("GET", `/api/agents/${agentId}`);
|
|
229
|
+
}
|
|
230
|
+
/** Update an agent */
|
|
231
|
+
async update(agentId, input) {
|
|
232
|
+
return this.client.request(
|
|
233
|
+
"PATCH",
|
|
234
|
+
`/api/agents/${agentId}`,
|
|
235
|
+
input
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
/** Delete an agent (soft delete) */
|
|
239
|
+
async delete(agentId) {
|
|
240
|
+
return this.client.request("DELETE", `/api/agents/${agentId}`);
|
|
241
|
+
}
|
|
242
|
+
/** Freeze an agent, blocking all transactions */
|
|
243
|
+
async freeze(agentId, input) {
|
|
244
|
+
return this.client.request(
|
|
245
|
+
"POST",
|
|
246
|
+
`/api/agents/${agentId}/freeze`,
|
|
247
|
+
input
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
/** Unfreeze an agent, restoring transaction ability */
|
|
251
|
+
async unfreeze(agentId, input) {
|
|
252
|
+
return this.client.request(
|
|
253
|
+
"POST",
|
|
254
|
+
`/api/agents/${agentId}/unfreeze`,
|
|
255
|
+
input
|
|
256
|
+
);
|
|
257
|
+
}
|
|
258
|
+
/** List wallets linked to an agent */
|
|
259
|
+
async listWallets(agentId) {
|
|
260
|
+
return this.client.request(
|
|
261
|
+
"GET",
|
|
262
|
+
`/api/agents/${agentId}/wallets`
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
/** Link a wallet to an agent with spending limits */
|
|
266
|
+
async linkWallet(agentId, input) {
|
|
267
|
+
return this.client.request(
|
|
268
|
+
"POST",
|
|
269
|
+
`/api/agents/${agentId}/wallets`,
|
|
270
|
+
input
|
|
271
|
+
);
|
|
272
|
+
}
|
|
273
|
+
/** Unlink a wallet from an agent */
|
|
274
|
+
async unlinkWallet(agentId, walletId) {
|
|
275
|
+
return this.client.request(
|
|
276
|
+
"DELETE",
|
|
277
|
+
`/api/agents/${agentId}/wallets/${walletId}`
|
|
278
|
+
);
|
|
279
|
+
}
|
|
280
|
+
/** List policies assigned to an agent */
|
|
281
|
+
async listPolicies(agentId) {
|
|
282
|
+
return this.client.request(
|
|
283
|
+
"GET",
|
|
284
|
+
`/api/agents/${agentId}/policies`
|
|
285
|
+
);
|
|
286
|
+
}
|
|
287
|
+
/** Assign a policy to an agent */
|
|
288
|
+
async assignPolicy(agentId, policyId, overrides) {
|
|
289
|
+
return this.client.request("POST", `/api/agents/${agentId}/policies`, {
|
|
290
|
+
policyId,
|
|
291
|
+
...overrides && { overrides }
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
/** Unassign a policy from an agent */
|
|
295
|
+
async unassignPolicy(agentId, policyId) {
|
|
296
|
+
return this.client.request(
|
|
297
|
+
"DELETE",
|
|
298
|
+
`/api/agents/${agentId}/policies?policyId=${policyId}`
|
|
299
|
+
);
|
|
300
|
+
}
|
|
301
|
+
/** List SDK keys for an agent */
|
|
302
|
+
async listSdkKeys(agentId) {
|
|
303
|
+
return this.client.request("GET", `/api/agents/${agentId}/sdk-keys`);
|
|
304
|
+
}
|
|
305
|
+
/** Create an SDK key for an agent (key value is returned only once) */
|
|
306
|
+
async createSdkKey(agentId, input) {
|
|
307
|
+
return this.client.request(
|
|
308
|
+
"POST",
|
|
309
|
+
`/api/agents/${agentId}/sdk-keys`,
|
|
310
|
+
input
|
|
311
|
+
);
|
|
312
|
+
}
|
|
313
|
+
/** Revoke an SDK key */
|
|
314
|
+
async revokeSdkKey(agentId, keyId) {
|
|
315
|
+
return this.client.request(
|
|
316
|
+
"DELETE",
|
|
317
|
+
`/api/agents/${agentId}/sdk-keys?keyId=${keyId}`
|
|
318
|
+
);
|
|
319
|
+
}
|
|
320
|
+
};
|
|
321
|
+
var WalletsClient = class {
|
|
322
|
+
constructor(client) {
|
|
323
|
+
this.client = client;
|
|
324
|
+
}
|
|
325
|
+
/** List wallets in the organization */
|
|
326
|
+
async list(params) {
|
|
327
|
+
const query = new URLSearchParams();
|
|
328
|
+
if (params?.status) query.set("status", params.status);
|
|
329
|
+
if (params?.chainType) query.set("chainType", params.chainType);
|
|
330
|
+
if (params?.chainId) query.set("chainId", params.chainId);
|
|
331
|
+
if (params?.limit) query.set("limit", String(params.limit));
|
|
332
|
+
if (params?.offset) query.set("offset", String(params.offset));
|
|
333
|
+
const qs = query.toString() ? `?${query.toString()}` : "";
|
|
334
|
+
return this.client.request("GET", `/api/wallets${qs}`);
|
|
335
|
+
}
|
|
336
|
+
/** Create a new wallet or attach an existing provider/self-custodied wallet */
|
|
337
|
+
async create(input) {
|
|
338
|
+
return this.client.request(
|
|
339
|
+
"POST",
|
|
340
|
+
"/api/wallets",
|
|
341
|
+
input
|
|
342
|
+
);
|
|
343
|
+
}
|
|
344
|
+
/** Get a single wallet by ID */
|
|
345
|
+
async get(walletId) {
|
|
346
|
+
return this.client.request("GET", `/api/wallets/${walletId}`);
|
|
347
|
+
}
|
|
348
|
+
/** Update a wallet */
|
|
349
|
+
async update(walletId, input) {
|
|
350
|
+
return this.client.request(
|
|
351
|
+
"PATCH",
|
|
352
|
+
`/api/wallets/${walletId}`,
|
|
353
|
+
input
|
|
354
|
+
);
|
|
355
|
+
}
|
|
356
|
+
/** Delete a wallet (cannot delete if linked to agents) */
|
|
357
|
+
async delete(walletId) {
|
|
358
|
+
return this.client.request("DELETE", `/api/wallets/${walletId}`);
|
|
359
|
+
}
|
|
360
|
+
/** Provision a wallet for onchain transactions */
|
|
361
|
+
async provision(walletId) {
|
|
362
|
+
return this.client.request(
|
|
363
|
+
"POST",
|
|
364
|
+
`/api/wallets/${walletId}/provision`,
|
|
365
|
+
{}
|
|
366
|
+
);
|
|
367
|
+
}
|
|
368
|
+
/** Refresh a wallet's balance from the chain */
|
|
369
|
+
async refreshBalance(walletId) {
|
|
370
|
+
return this.client.request(
|
|
371
|
+
"POST",
|
|
372
|
+
`/api/wallets/${walletId}/refresh-balance`,
|
|
373
|
+
{}
|
|
374
|
+
);
|
|
375
|
+
}
|
|
376
|
+
};
|
|
377
|
+
var PoliciesClient = class {
|
|
378
|
+
constructor(client) {
|
|
379
|
+
this.client = client;
|
|
380
|
+
}
|
|
381
|
+
/** List policies in the organization */
|
|
382
|
+
async list(params) {
|
|
383
|
+
const query = new URLSearchParams();
|
|
384
|
+
if (params?.limit) query.set("limit", String(params.limit));
|
|
385
|
+
if (params?.offset) query.set("offset", String(params.offset));
|
|
386
|
+
const qs = query.toString() ? `?${query.toString()}` : "";
|
|
387
|
+
return this.client.request("GET", `/api/policies${qs}`);
|
|
388
|
+
}
|
|
389
|
+
/** Create a new policy (optionally with rules and agent assignments) */
|
|
390
|
+
async create(input) {
|
|
391
|
+
return this.client.request(
|
|
392
|
+
"POST",
|
|
393
|
+
"/api/policies",
|
|
394
|
+
input
|
|
395
|
+
);
|
|
396
|
+
}
|
|
397
|
+
/** Get a single policy by ID */
|
|
398
|
+
async get(policyId) {
|
|
399
|
+
return this.client.request("GET", `/api/policies/${policyId}`);
|
|
400
|
+
}
|
|
401
|
+
/** Update a policy */
|
|
402
|
+
async update(policyId, input) {
|
|
403
|
+
return this.client.request(
|
|
404
|
+
"PATCH",
|
|
405
|
+
`/api/policies/${policyId}`,
|
|
406
|
+
input
|
|
407
|
+
);
|
|
408
|
+
}
|
|
409
|
+
/** Delete a policy */
|
|
410
|
+
async delete(policyId) {
|
|
411
|
+
return this.client.request("DELETE", `/api/policies/${policyId}`);
|
|
412
|
+
}
|
|
413
|
+
/** List rules for a policy */
|
|
414
|
+
async listRules(policyId) {
|
|
415
|
+
return this.client.request("GET", `/api/policies/${policyId}/rules`);
|
|
416
|
+
}
|
|
417
|
+
/** Add a single rule to a policy */
|
|
418
|
+
async addRule(policyId, rule) {
|
|
419
|
+
return this.client.request(
|
|
420
|
+
"POST",
|
|
421
|
+
`/api/policies/${policyId}/rules`,
|
|
422
|
+
rule
|
|
423
|
+
);
|
|
424
|
+
}
|
|
425
|
+
/** Add multiple rules to a policy */
|
|
426
|
+
async addRules(policyId, rules) {
|
|
427
|
+
return this.client.request("POST", `/api/policies/${policyId}/rules`, {
|
|
428
|
+
rules
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
/** Update a single rule */
|
|
432
|
+
async updateRule(policyId, ruleId, input) {
|
|
433
|
+
return this.client.request(
|
|
434
|
+
"PATCH",
|
|
435
|
+
`/api/policies/${policyId}/rules/${ruleId}`,
|
|
436
|
+
input
|
|
437
|
+
);
|
|
438
|
+
}
|
|
439
|
+
/** Delete a single rule */
|
|
440
|
+
async deleteRule(policyId, ruleId) {
|
|
441
|
+
return this.client.request(
|
|
442
|
+
"DELETE",
|
|
443
|
+
`/api/policies/${policyId}/rules/${ruleId}`
|
|
444
|
+
);
|
|
445
|
+
}
|
|
446
|
+
/** Delete all rules for a policy */
|
|
447
|
+
async deleteAllRules(policyId) {
|
|
448
|
+
return this.client.request(
|
|
449
|
+
"DELETE",
|
|
450
|
+
`/api/policies/${policyId}/rules`
|
|
451
|
+
);
|
|
452
|
+
}
|
|
453
|
+
};
|
|
454
|
+
var TeamClient = class {
|
|
455
|
+
constructor(client) {
|
|
456
|
+
this.client = client;
|
|
457
|
+
}
|
|
458
|
+
/** List organization memberships for the authenticated organization */
|
|
459
|
+
async listMembers() {
|
|
460
|
+
return this.client.request(
|
|
461
|
+
"GET",
|
|
462
|
+
"/api/organizations/me/members"
|
|
463
|
+
);
|
|
464
|
+
}
|
|
465
|
+
};
|
|
466
|
+
|
|
467
|
+
// src/index.ts
|
|
468
|
+
if (process.env.SENTRY_DSN) {
|
|
469
|
+
Sentry2.init({
|
|
470
|
+
dsn: process.env.SENTRY_DSN,
|
|
471
|
+
environment: process.env.NODE_ENV || "production",
|
|
472
|
+
tracesSampleRate: 0.05,
|
|
473
|
+
enableLogs: true
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
var Conto = class {
|
|
477
|
+
constructor(config) {
|
|
478
|
+
if (!config.apiKey) {
|
|
479
|
+
throw new Error("API key is required");
|
|
480
|
+
}
|
|
481
|
+
if (!config.apiKey.startsWith("conto_agent_")) {
|
|
482
|
+
throw new Error("Invalid API key format. Expected conto_agent_xxx...");
|
|
483
|
+
}
|
|
484
|
+
this.apiKey = config.apiKey;
|
|
485
|
+
this.baseUrl = (config.baseUrl || "https://conto.finance").replace(/\/$/, "");
|
|
486
|
+
this.timeout = config.timeout || 3e4;
|
|
487
|
+
this.payments = new PaymentsClient(this);
|
|
488
|
+
}
|
|
489
|
+
async fetchWithRetry(url, options, maxRetries = 3) {
|
|
490
|
+
let lastError = null;
|
|
491
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
492
|
+
try {
|
|
493
|
+
const response = await fetch(url, options);
|
|
494
|
+
if (response.status === 429 || response.status >= 500 && attempt < maxRetries) {
|
|
495
|
+
const retryAfter = response.headers.get("retry-after");
|
|
496
|
+
const delay = retryAfter ? parseInt(retryAfter, 10) * 1e3 : Math.min(1e3 * 2 ** attempt, 1e4);
|
|
497
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
498
|
+
continue;
|
|
499
|
+
}
|
|
500
|
+
return response;
|
|
501
|
+
} catch (err) {
|
|
502
|
+
lastError = err instanceof Error ? err : new Error(String(err));
|
|
503
|
+
if (attempt < maxRetries) {
|
|
504
|
+
const delay = Math.min(1e3 * 2 ** attempt, 1e4);
|
|
505
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
506
|
+
continue;
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
throw lastError || new Error("Request failed after retries");
|
|
511
|
+
}
|
|
512
|
+
/** Make an authenticated request to the Giro API */
|
|
513
|
+
async request(method, path, body) {
|
|
514
|
+
const url = `${this.baseUrl}${path}`;
|
|
515
|
+
const controller = new AbortController();
|
|
516
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
517
|
+
try {
|
|
518
|
+
const response = await this.fetchWithRetry(url, {
|
|
519
|
+
method,
|
|
520
|
+
headers: {
|
|
521
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
522
|
+
"Content-Type": "application/json",
|
|
523
|
+
"User-Agent": `@conto_finance/sdk/${import_package_version2.SDK_PACKAGE_VERSION}`
|
|
524
|
+
},
|
|
525
|
+
body: body ? JSON.stringify(body) : void 0,
|
|
526
|
+
signal: controller.signal
|
|
527
|
+
});
|
|
528
|
+
clearTimeout(timeoutId);
|
|
529
|
+
const data = await response.json();
|
|
530
|
+
if (!response.ok) {
|
|
531
|
+
const errorMessage = typeof data.error === "string" ? data.error : "Request failed";
|
|
532
|
+
const error = new Error(errorMessage);
|
|
533
|
+
error.code = typeof data.code === "string" ? data.code : "UNKNOWN_ERROR";
|
|
534
|
+
error.status = response.status;
|
|
535
|
+
throw error;
|
|
536
|
+
}
|
|
537
|
+
return data;
|
|
538
|
+
} catch (error) {
|
|
539
|
+
clearTimeout(timeoutId);
|
|
540
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
541
|
+
const timeoutError = new Error("Request timeout");
|
|
542
|
+
timeoutError.code = "TIMEOUT";
|
|
543
|
+
timeoutError.status = 0;
|
|
544
|
+
Sentry2.captureException(timeoutError, { extra: { method, path } });
|
|
545
|
+
throw timeoutError;
|
|
546
|
+
}
|
|
547
|
+
if (error instanceof Error) {
|
|
548
|
+
Sentry2.captureException(error, { extra: { method, path } });
|
|
549
|
+
}
|
|
550
|
+
throw error;
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
};
|
|
554
|
+
var PaymentsClient = class {
|
|
555
|
+
constructor(client) {
|
|
556
|
+
this.client = client;
|
|
557
|
+
}
|
|
558
|
+
/**
|
|
559
|
+
* Request authorization for a payment.
|
|
560
|
+
*
|
|
561
|
+
* This evaluates spending policies and returns whether the payment
|
|
562
|
+
* is approved, denied, or requires manual approval.
|
|
563
|
+
*
|
|
564
|
+
* @example
|
|
565
|
+
* ```typescript
|
|
566
|
+
* const request = await conto.payments.request({
|
|
567
|
+
* amount: 25.00,
|
|
568
|
+
* recipientAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f...',
|
|
569
|
+
* recipientName: 'OpenAI',
|
|
570
|
+
* purpose: 'GPT-4 API credits',
|
|
571
|
+
* category: 'API_PROVIDER'
|
|
572
|
+
* });
|
|
573
|
+
*
|
|
574
|
+
* if (request.status === 'APPROVED') {
|
|
575
|
+
* // Payment is pre-authorized, execute it
|
|
576
|
+
* const result = await conto.payments.execute(request.requestId);
|
|
577
|
+
* } else if (request.status === 'REQUIRES_APPROVAL') {
|
|
578
|
+
* // Wait for human approval
|
|
579
|
+
* console.log('Payment requires manual approval');
|
|
580
|
+
* } else {
|
|
581
|
+
* // Payment was denied
|
|
582
|
+
* console.log('Denied:', request.reasons.join(', '));
|
|
583
|
+
* }
|
|
584
|
+
* ```
|
|
585
|
+
*/
|
|
586
|
+
async request(input) {
|
|
587
|
+
return this.client.request(
|
|
588
|
+
"POST",
|
|
589
|
+
"/api/sdk/payments/request",
|
|
590
|
+
input
|
|
591
|
+
);
|
|
592
|
+
}
|
|
593
|
+
/**
|
|
594
|
+
* Execute an approved payment.
|
|
595
|
+
*
|
|
596
|
+
* This sends the onchain transaction. Only works for payments
|
|
597
|
+
* with status 'APPROVED'.
|
|
598
|
+
*
|
|
599
|
+
* @param requestId - The requestId from a successful payment request
|
|
600
|
+
*
|
|
601
|
+
* @example
|
|
602
|
+
* ```typescript
|
|
603
|
+
* const result = await conto.payments.execute(request.requestId);
|
|
604
|
+
* console.log(`Transaction: ${result.txHash}`);
|
|
605
|
+
* console.log(`Explorer: ${result.explorerUrl}`);
|
|
606
|
+
* ```
|
|
607
|
+
*/
|
|
608
|
+
async execute(requestId) {
|
|
609
|
+
return this.client.request(
|
|
610
|
+
"POST",
|
|
611
|
+
`/api/sdk/payments/${requestId}/execute`,
|
|
612
|
+
{}
|
|
613
|
+
);
|
|
614
|
+
}
|
|
615
|
+
/**
|
|
616
|
+
* Get the status of a payment request.
|
|
617
|
+
*
|
|
618
|
+
* @param requestId - The requestId to check
|
|
619
|
+
*
|
|
620
|
+
* @example
|
|
621
|
+
* ```typescript
|
|
622
|
+
* const status = await conto.payments.status(requestId);
|
|
623
|
+
* if (status.transaction?.status === 'CONFIRMED') {
|
|
624
|
+
* console.log('Payment confirmed at block', status.transaction.blockNumber);
|
|
625
|
+
* }
|
|
626
|
+
* ```
|
|
627
|
+
*/
|
|
628
|
+
async status(requestId) {
|
|
629
|
+
return this.client.request(
|
|
630
|
+
"GET",
|
|
631
|
+
`/api/sdk/payments/${requestId}`,
|
|
632
|
+
void 0
|
|
633
|
+
);
|
|
634
|
+
}
|
|
635
|
+
/**
|
|
636
|
+
* Request and execute a payment in one call.
|
|
637
|
+
*
|
|
638
|
+
* Convenience method that requests authorization and immediately
|
|
639
|
+
* executes if approved. Throws if denied or requires approval.
|
|
640
|
+
*
|
|
641
|
+
* @example
|
|
642
|
+
* ```typescript
|
|
643
|
+
* try {
|
|
644
|
+
* const result = await conto.payments.pay({
|
|
645
|
+
* amount: 10.00,
|
|
646
|
+
* recipientAddress: '0x...',
|
|
647
|
+
* purpose: 'Service fee'
|
|
648
|
+
* });
|
|
649
|
+
* console.log(`Paid! TX: ${result.txHash}`);
|
|
650
|
+
* } catch (error) {
|
|
651
|
+
* if (error.code === 'REQUIRES_APPROVAL') {
|
|
652
|
+
* console.log('Payment needs human approval');
|
|
653
|
+
* } else {
|
|
654
|
+
* console.log('Payment denied:', error.message);
|
|
655
|
+
* }
|
|
656
|
+
* }
|
|
657
|
+
* ```
|
|
658
|
+
*/
|
|
659
|
+
async pay(input) {
|
|
660
|
+
const { autoExecute: _autoExecute, ...requestInput } = input;
|
|
661
|
+
const request = await this.request(requestInput);
|
|
662
|
+
if (request.status === "DENIED") {
|
|
663
|
+
const error = new Error(`Payment denied: ${request.reasons.join(", ")}`);
|
|
664
|
+
error.code = "PAYMENT_DENIED";
|
|
665
|
+
error.status = 403;
|
|
666
|
+
throw error;
|
|
667
|
+
}
|
|
668
|
+
if (request.status === "REQUIRES_APPROVAL") {
|
|
669
|
+
const error = new Error("Payment requires manual approval");
|
|
670
|
+
error.code = "REQUIRES_APPROVAL";
|
|
671
|
+
error.status = 202;
|
|
672
|
+
throw error;
|
|
673
|
+
}
|
|
674
|
+
return this.execute(request.requestId);
|
|
675
|
+
}
|
|
676
|
+
};
|
|
677
|
+
var index_default = Conto;
|
|
678
|
+
export {
|
|
679
|
+
Conto,
|
|
680
|
+
ContoAdmin,
|
|
681
|
+
Conto as Giro,
|
|
682
|
+
index_default as default
|
|
683
|
+
};
|