@zerocore1/sdk 0.1.0 → 0.2.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/index.cjs +70 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +34 -1
- package/dist/index.d.ts +34 -1
- package/dist/index.js +58 -5
- package/dist/index.js.map +1 -1
- package/package.json +8 -2
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
8
|
var __export = (target, all) => {
|
|
7
9
|
for (var name in all)
|
|
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
17
|
}
|
|
16
18
|
return to;
|
|
17
19
|
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
18
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
29
|
|
|
20
30
|
// src/index.ts
|
|
@@ -25,7 +35,8 @@ __export(index_exports, {
|
|
|
25
35
|
ZerocoreError: () => ZerocoreError,
|
|
26
36
|
ZerocoreNetworkError: () => ZerocoreNetworkError,
|
|
27
37
|
ZerocorePaymentError: () => ZerocorePaymentError,
|
|
28
|
-
ZerocoreRateLimitError: () => ZerocoreRateLimitError
|
|
38
|
+
ZerocoreRateLimitError: () => ZerocoreRateLimitError,
|
|
39
|
+
generateAgentKeypair: () => generateAgentKeypair
|
|
29
40
|
});
|
|
30
41
|
module.exports = __toCommonJS(index_exports);
|
|
31
42
|
|
|
@@ -72,6 +83,7 @@ var ZerocoreNetworkError = class extends ZerocoreError {
|
|
|
72
83
|
};
|
|
73
84
|
|
|
74
85
|
// src/client.ts
|
|
86
|
+
var import_tweetnacl = __toESM(require("tweetnacl"), 1);
|
|
75
87
|
var DEFAULT_BASE_URL = "https://augvmbhpuchkqqowxmrk.supabase.co/functions/v1";
|
|
76
88
|
var DEFAULT_TIMEOUT = 3e4;
|
|
77
89
|
var USER_AGENT = "zerocore-sdk-ts/0.1.0";
|
|
@@ -79,8 +91,9 @@ var Client = class {
|
|
|
79
91
|
apiKey;
|
|
80
92
|
baseUrl;
|
|
81
93
|
timeout;
|
|
94
|
+
agentKeypair;
|
|
82
95
|
constructor(options) {
|
|
83
|
-
const { apiKey, baseUrl, timeout } = options;
|
|
96
|
+
const { apiKey, baseUrl, timeout, agentPrivateKey } = options;
|
|
84
97
|
if (!apiKey || !apiKey.startsWith("zc_")) {
|
|
85
98
|
throw new ZerocoreAuthError(
|
|
86
99
|
"API key must start with 'zc_live_' or 'zc_test_'. Generate one at your ZERO.CORE dashboard \u2192 API Keys."
|
|
@@ -89,6 +102,29 @@ var Client = class {
|
|
|
89
102
|
this.apiKey = apiKey;
|
|
90
103
|
this.baseUrl = (baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
91
104
|
this.timeout = timeout ?? DEFAULT_TIMEOUT;
|
|
105
|
+
if (agentPrivateKey) {
|
|
106
|
+
const seed = hexToBytes(agentPrivateKey);
|
|
107
|
+
if (seed.length === 64) {
|
|
108
|
+
this.agentKeypair = import_tweetnacl.default.sign.keyPair.fromSecretKey(seed);
|
|
109
|
+
} else if (seed.length === 32) {
|
|
110
|
+
this.agentKeypair = import_tweetnacl.default.sign.keyPair.fromSeed(seed);
|
|
111
|
+
} else {
|
|
112
|
+
throw new Error(
|
|
113
|
+
"agentPrivateKey must be hex-encoded Ed25519 key (64 or 128 hex chars)"
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
} else {
|
|
117
|
+
this.agentKeypair = null;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Get the agent's Ed25519 public key (hex-encoded).
|
|
122
|
+
* Register this in the ZERO.CORE dashboard under the agent's settings.
|
|
123
|
+
* Returns `null` if no agent private key was provided.
|
|
124
|
+
*/
|
|
125
|
+
getAgentPublicKey() {
|
|
126
|
+
if (!this.agentKeypair) return null;
|
|
127
|
+
return bytesToHex(this.agentKeypair.publicKey);
|
|
92
128
|
}
|
|
93
129
|
// ── Public API ──────────────────────────────────────────────────────────
|
|
94
130
|
/**
|
|
@@ -128,11 +164,20 @@ var Client = class {
|
|
|
128
164
|
if (memo) {
|
|
129
165
|
payload.memo = memo;
|
|
130
166
|
}
|
|
131
|
-
const
|
|
167
|
+
const extraHeaders = {};
|
|
168
|
+
if (this.agentKeypair) {
|
|
169
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
170
|
+
const canonicalMessage = `${amountUsd}:${merchant}:${timestamp}`;
|
|
171
|
+
const msgBytes = new TextEncoder().encode(canonicalMessage);
|
|
172
|
+
const signature = import_tweetnacl.default.sign.detached(msgBytes, this.agentKeypair.secretKey);
|
|
173
|
+
extraHeaders["x-agent-signature"] = bytesToHex(signature);
|
|
174
|
+
extraHeaders["x-timestamp"] = timestamp;
|
|
175
|
+
}
|
|
176
|
+
const raw = await this.post("/authorize", payload, extraHeaders);
|
|
132
177
|
return toApprovalResult(raw);
|
|
133
178
|
}
|
|
134
179
|
// ── Internal ────────────────────────────────────────────────────────────
|
|
135
|
-
async post(path, body) {
|
|
180
|
+
async post(path, body, extraHeaders = {}) {
|
|
136
181
|
const url = `${this.baseUrl}${path}`;
|
|
137
182
|
let response;
|
|
138
183
|
try {
|
|
@@ -141,7 +186,8 @@ var Client = class {
|
|
|
141
186
|
headers: {
|
|
142
187
|
Authorization: `Bearer ${this.apiKey}`,
|
|
143
188
|
"Content-Type": "application/json",
|
|
144
|
-
"User-Agent": USER_AGENT
|
|
189
|
+
"User-Agent": USER_AGENT,
|
|
190
|
+
...extraHeaders
|
|
145
191
|
},
|
|
146
192
|
body: JSON.stringify(body),
|
|
147
193
|
signal: AbortSignal.timeout(this.timeout)
|
|
@@ -217,6 +263,23 @@ function toApprovalResult(raw) {
|
|
|
217
263
|
message: raw.message
|
|
218
264
|
};
|
|
219
265
|
}
|
|
266
|
+
function hexToBytes(hex) {
|
|
267
|
+
const bytes = new Uint8Array(hex.length / 2);
|
|
268
|
+
for (let i = 0; i < hex.length; i += 2) {
|
|
269
|
+
bytes[i / 2] = parseInt(hex.substring(i, i + 2), 16);
|
|
270
|
+
}
|
|
271
|
+
return bytes;
|
|
272
|
+
}
|
|
273
|
+
function bytesToHex(bytes) {
|
|
274
|
+
return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
275
|
+
}
|
|
276
|
+
function generateAgentKeypair() {
|
|
277
|
+
const keypair = import_tweetnacl.default.sign.keyPair();
|
|
278
|
+
return {
|
|
279
|
+
privateKey: bytesToHex(keypair.secretKey),
|
|
280
|
+
publicKey: bytesToHex(keypair.publicKey)
|
|
281
|
+
};
|
|
282
|
+
}
|
|
220
283
|
// Annotate the CommonJS export names for ESM import in node:
|
|
221
284
|
0 && (module.exports = {
|
|
222
285
|
Client,
|
|
@@ -224,6 +287,7 @@ function toApprovalResult(raw) {
|
|
|
224
287
|
ZerocoreError,
|
|
225
288
|
ZerocoreNetworkError,
|
|
226
289
|
ZerocorePaymentError,
|
|
227
|
-
ZerocoreRateLimitError
|
|
290
|
+
ZerocoreRateLimitError,
|
|
291
|
+
generateAgentKeypair
|
|
228
292
|
});
|
|
229
293
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/client.ts"],"sourcesContent":["/**\n * @zerocore1/sdk — Fiduciary Control Plane for AI Agents\n *\n * @example\n * ```ts\n * import { Client, ZerocorePaymentError } from \"@zerocore1/sdk\";\n *\n * const zc = new Client({ apiKey: \"zc_live_abc123...\" });\n *\n * try {\n * const result = await zc.authorizeSpend({\n * amountUsd: 0.03,\n * merchant: \"OpenAI\",\n * currency: \"USDC\",\n * });\n * console.log(`Approved! tx=${result.transactionId}`);\n * } catch (err) {\n * if (err instanceof ZerocorePaymentError) {\n * console.log(`Denied: ${err.reason}`);\n * }\n * }\n * ```\n *\n * @packageDocumentation\n */\n\n// Client\nexport { Client } from \"./client.js\";\n\n// Errors\nexport {\n ZerocoreError,\n ZerocoreAuthError,\n ZerocorePaymentError,\n ZerocoreRateLimitError,\n ZerocoreNetworkError,\n} from \"./errors.js\";\n\n// Types\nexport type {\n Currency,\n AuthorizeSpendParams,\n ApprovalResult,\n ClientOptions,\n DenialReason,\n} from \"./types.js\";\n","/**\n * ZERO.CORE SDK — Error Classes\n *\n * Typed exceptions for every failure mode the control plane can produce.\n */\n\nimport type { DenialReason } from \"./types.js\";\n\n// ---------------------------------------------------------------------------\n// Base\n// ---------------------------------------------------------------------------\n\n/** Base error for all ZERO.CORE SDK errors. */\nexport class ZerocoreError extends Error {\n /** HTTP status code from the API, if applicable. */\n readonly statusCode?: number;\n\n constructor(message: string, statusCode?: number) {\n super(message);\n this.name = \"ZerocoreError\";\n this.statusCode = statusCode;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Auth\n// ---------------------------------------------------------------------------\n\n/** Thrown when the API key is invalid or revoked (HTTP 401). */\nexport class ZerocoreAuthError extends ZerocoreError {\n constructor(message = \"Invalid API key\") {\n super(message, 401);\n this.name = \"ZerocoreAuthError\";\n }\n}\n\n// ---------------------------------------------------------------------------\n// Payment denied\n// ---------------------------------------------------------------------------\n\n/**\n * Thrown when the fiduciary control plane denies a transaction (HTTP 402/403).\n *\n * Inspect {@link reason} for the specific denial cause:\n * - `AGENT_INACTIVE` — Kill switch is off\n * - `EXCEEDS_PER_TX_LIMIT` — Single transaction too large\n * - `EXCEEDS_DAILY_LIMIT` — Daily budget exhausted\n * - `SETTLEMENT_FAILED: ...` — On-chain transfer failed\n */\nexport class ZerocorePaymentError extends ZerocoreError {\n /** Machine-readable denial reason from the control plane. */\n readonly reason: DenialReason;\n\n constructor(message: string, reason: DenialReason, statusCode = 403) {\n super(message, statusCode);\n this.name = \"ZerocorePaymentError\";\n this.reason = reason;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Rate limit\n// ---------------------------------------------------------------------------\n\n/** Thrown when the API rate limit is exceeded (HTTP 429). */\nexport class ZerocoreRateLimitError extends ZerocoreError {\n /** Seconds to wait before retrying, if provided by the API. */\n readonly retryAfter?: number;\n\n constructor(retryAfter?: number) {\n const msg = retryAfter\n ? `Rate limited. Retry after ${retryAfter}s.`\n : \"Rate limited.\";\n super(msg, 429);\n this.name = \"ZerocoreRateLimitError\";\n this.retryAfter = retryAfter;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Network\n// ---------------------------------------------------------------------------\n\n/** Thrown when the Edge Function is unreachable. */\nexport class ZerocoreNetworkError extends ZerocoreError {\n constructor(message = \"Cannot connect to ZERO.CORE API.\") {\n super(message);\n this.name = \"ZerocoreNetworkError\";\n }\n}\n","/**\n * ZERO.CORE SDK — Client\n *\n * The fiduciary gatekeeper for AI agents. Every paid API call your agent\n * makes should pass through {@link Client.authorizeSpend} first. If the\n * control plane says no, the call never happens.\n *\n * @example\n * ```ts\n * import { Client } from \"@zerocore1/sdk\";\n *\n * const zc = new Client({ apiKey: \"zc_live_abc123...\" });\n *\n * const result = await zc.authorizeSpend({\n * amountUsd: 0.03,\n * merchant: \"OpenAI\",\n * currency: \"USDC\",\n * });\n *\n * if (result.approved) {\n * // safe to call OpenAI\n * }\n * ```\n */\n\nimport type {\n ApprovalResult,\n AuthorizeSpendParams,\n ClientOptions,\n RawApiResponse,\n} from \"./types.js\";\n\nimport {\n ZerocoreAuthError,\n ZerocoreError,\n ZerocoreNetworkError,\n ZerocorePaymentError,\n ZerocoreRateLimitError,\n} from \"./errors.js\";\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_BASE_URL =\n \"https://augvmbhpuchkqqowxmrk.supabase.co/functions/v1\";\n\nconst DEFAULT_TIMEOUT = 30_000;\n\nconst USER_AGENT = \"zerocore-sdk-ts/0.1.0\";\n\n// ---------------------------------------------------------------------------\n// Client\n// ---------------------------------------------------------------------------\n\nexport class Client {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n private readonly timeout: number;\n\n constructor(options: ClientOptions) {\n const { apiKey, baseUrl, timeout } = options;\n\n if (!apiKey || !apiKey.startsWith(\"zc_\")) {\n throw new ZerocoreAuthError(\n \"API key must start with 'zc_live_' or 'zc_test_'. \" +\n \"Generate one at your ZERO.CORE dashboard → API Keys.\",\n );\n }\n\n this.apiKey = apiKey;\n this.baseUrl = (baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n this.timeout = timeout ?? DEFAULT_TIMEOUT;\n }\n\n // ── Public API ──────────────────────────────────────────────────────────\n\n /**\n * Request authorization for an agent payment.\n *\n * Call this **before** your agent executes any paid API call.\n * The control plane checks:\n * - Is the agent active? (kill switch)\n * - Does this exceed the per-transaction limit?\n * - Does this exceed the daily spending limit?\n *\n * If approved and `executeOnChain` is `true`, the Edge Function executes\n * a real on-chain transfer (SOL or USDC SPL token).\n *\n * @throws {ZerocorePaymentError} Transaction was denied.\n * @throws {ZerocoreAuthError} API key is invalid.\n * @throws {ZerocoreRateLimitError} Too many requests.\n * @throws {ZerocoreNetworkError} API is unreachable.\n */\n async authorizeSpend(\n params: AuthorizeSpendParams,\n ): Promise<ApprovalResult> {\n const { amountUsd, merchant, currency = \"SOL\", memo, executeOnChain = false } = params;\n\n if (amountUsd <= 0) {\n throw new Error(\"amountUsd must be positive\");\n }\n if (!merchant) {\n throw new Error(\"merchant is required\");\n }\n if (currency !== \"SOL\" && currency !== \"USDC\") {\n throw new Error(\"currency must be 'SOL' or 'USDC'\");\n }\n\n const payload: Record<string, unknown> = {\n amount_usd: amountUsd,\n merchant,\n execute_on_chain: executeOnChain,\n currency,\n };\n\n if (memo) {\n payload.memo = memo;\n }\n\n const raw = await this.post<RawApiResponse>(\"/authorize\", payload);\n\n return toApprovalResult(raw);\n }\n\n // ── Internal ────────────────────────────────────────────────────────────\n\n private async post<T>(path: string, body: Record<string, unknown>): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n\n let response: Response;\n try {\n response = await fetch(url, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n \"Content-Type\": \"application/json\",\n \"User-Agent\": USER_AGENT,\n },\n body: JSON.stringify(body),\n signal: AbortSignal.timeout(this.timeout),\n });\n } catch (err) {\n if (err instanceof DOMException && err.name === \"TimeoutError\") {\n throw new ZerocoreNetworkError(\"Request timed out.\");\n }\n throw new ZerocoreNetworkError(\n `Cannot connect to ${this.baseUrl}. Check your network or baseUrl setting.`,\n );\n }\n\n return this.handleResponse<T>(response);\n }\n\n private async handleResponse<T>(response: Response): Promise<T> {\n // 200 — success\n if (response.ok) {\n return (await response.json()) as T;\n }\n\n // 401 — auth error\n if (response.status === 401) {\n const data = await safeJson(response);\n const msg = data?.detail ?? \"Invalid API key\";\n throw new ZerocoreAuthError(typeof msg === \"string\" ? msg : \"Invalid API key\");\n }\n\n // 429 — rate limit\n if (response.status === 429) {\n const retryAfter = response.headers.get(\"Retry-After\");\n throw new ZerocoreRateLimitError(\n retryAfter ? parseFloat(retryAfter) : undefined,\n );\n }\n\n // 402 / 403 — payment denied\n if (response.status === 402 || response.status === 403) {\n const data = await safeJson(response);\n const detail = data?.detail ?? data;\n\n if (detail && typeof detail === \"object\") {\n throw new ZerocorePaymentError(\n detail.message ?? \"Payment denied\",\n detail.denial_reason ?? \"UNKNOWN\",\n response.status,\n );\n }\n\n throw new ZerocorePaymentError(\n typeof detail === \"string\" ? detail : \"Payment denied\",\n \"UNKNOWN\",\n response.status,\n );\n }\n\n // Anything else\n const data = await safeJson(response);\n const message = data?.detail ?? data?.message ?? `API error ${response.status}`;\n throw new ZerocoreError(\n typeof message === \"string\" ? message : `API error ${response.status}`,\n response.status,\n );\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Parse JSON from a response without throwing on invalid JSON. */\n// deno-lint-ignore no-explicit-any\nasync function safeJson(response: Response): Promise<any> {\n try {\n return await response.json();\n } catch {\n return null;\n }\n}\n\n/** Map a raw snake_case API response to a camelCase {@link ApprovalResult}. */\nfunction toApprovalResult(raw: RawApiResponse): ApprovalResult {\n return {\n approved: raw.approval_status === \"approved\",\n transactionId: raw.transaction_id,\n amountUsd: raw.amount_usd,\n amountSol: raw.amount_sol,\n amountUsdc: raw.amount_usdc,\n currency: raw.currency,\n merchant: raw.merchant,\n remainingDailyLimit: raw.remaining_daily_limit,\n solanaSignature: raw.solana_signature,\n denialReason: raw.denial_reason,\n message: raw.message,\n };\n}\n"],"mappings":"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","names":["data"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/client.ts"],"sourcesContent":["/**\n * @zerocore1/sdk — Fiduciary Control Plane for AI Agents\n *\n * @example\n * ```ts\n * import { Client, ZerocorePaymentError } from \"@zerocore1/sdk\";\n *\n * const zc = new Client({ apiKey: \"zc_live_abc123...\" });\n *\n * try {\n * const result = await zc.authorizeSpend({\n * amountUsd: 0.03,\n * merchant: \"OpenAI\",\n * currency: \"USDC\",\n * });\n * console.log(`Approved! tx=${result.transactionId}`);\n * } catch (err) {\n * if (err instanceof ZerocorePaymentError) {\n * console.log(`Denied: ${err.reason}`);\n * }\n * }\n * ```\n *\n * @packageDocumentation\n */\n\n// Client\nexport { Client, generateAgentKeypair } from \"./client.js\";\n\n// Errors\nexport {\n ZerocoreError,\n ZerocoreAuthError,\n ZerocorePaymentError,\n ZerocoreRateLimitError,\n ZerocoreNetworkError,\n} from \"./errors.js\";\n\n// Types\nexport type {\n Currency,\n AuthorizeSpendParams,\n ApprovalResult,\n ClientOptions,\n DenialReason,\n} from \"./types.js\";\n","/**\n * ZERO.CORE SDK — Error Classes\n *\n * Typed exceptions for every failure mode the control plane can produce.\n */\n\nimport type { DenialReason } from \"./types.js\";\n\n// ---------------------------------------------------------------------------\n// Base\n// ---------------------------------------------------------------------------\n\n/** Base error for all ZERO.CORE SDK errors. */\nexport class ZerocoreError extends Error {\n /** HTTP status code from the API, if applicable. */\n readonly statusCode?: number;\n\n constructor(message: string, statusCode?: number) {\n super(message);\n this.name = \"ZerocoreError\";\n this.statusCode = statusCode;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Auth\n// ---------------------------------------------------------------------------\n\n/** Thrown when the API key is invalid or revoked (HTTP 401). */\nexport class ZerocoreAuthError extends ZerocoreError {\n constructor(message = \"Invalid API key\") {\n super(message, 401);\n this.name = \"ZerocoreAuthError\";\n }\n}\n\n// ---------------------------------------------------------------------------\n// Payment denied\n// ---------------------------------------------------------------------------\n\n/**\n * Thrown when the fiduciary control plane denies a transaction (HTTP 402/403).\n *\n * Inspect {@link reason} for the specific denial cause:\n * - `AGENT_INACTIVE` — Kill switch is off\n * - `EXCEEDS_PER_TX_LIMIT` — Single transaction too large\n * - `EXCEEDS_DAILY_LIMIT` — Daily budget exhausted\n * - `SETTLEMENT_FAILED: ...` — On-chain transfer failed\n */\nexport class ZerocorePaymentError extends ZerocoreError {\n /** Machine-readable denial reason from the control plane. */\n readonly reason: DenialReason;\n\n constructor(message: string, reason: DenialReason, statusCode = 403) {\n super(message, statusCode);\n this.name = \"ZerocorePaymentError\";\n this.reason = reason;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Rate limit\n// ---------------------------------------------------------------------------\n\n/** Thrown when the API rate limit is exceeded (HTTP 429). */\nexport class ZerocoreRateLimitError extends ZerocoreError {\n /** Seconds to wait before retrying, if provided by the API. */\n readonly retryAfter?: number;\n\n constructor(retryAfter?: number) {\n const msg = retryAfter\n ? `Rate limited. Retry after ${retryAfter}s.`\n : \"Rate limited.\";\n super(msg, 429);\n this.name = \"ZerocoreRateLimitError\";\n this.retryAfter = retryAfter;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Network\n// ---------------------------------------------------------------------------\n\n/** Thrown when the Edge Function is unreachable. */\nexport class ZerocoreNetworkError extends ZerocoreError {\n constructor(message = \"Cannot connect to ZERO.CORE API.\") {\n super(message);\n this.name = \"ZerocoreNetworkError\";\n }\n}\n","/**\n * ZERO.CORE SDK — Client\n *\n * The fiduciary gatekeeper for AI agents. Every paid API call your agent\n * makes should pass through {@link Client.authorizeSpend} first. If the\n * control plane says no, the call never happens.\n *\n * @example\n * ```ts\n * import { Client } from \"@zerocore1/sdk\";\n *\n * const zc = new Client({ apiKey: \"zc_live_abc123...\" });\n *\n * const result = await zc.authorizeSpend({\n * amountUsd: 0.03,\n * merchant: \"OpenAI\",\n * currency: \"USDC\",\n * });\n *\n * if (result.approved) {\n * // safe to call OpenAI\n * }\n * ```\n */\n\nimport type {\n ApprovalResult,\n AuthorizeSpendParams,\n ClientOptions,\n RawApiResponse,\n} from \"./types.js\";\n\nimport {\n ZerocoreAuthError,\n ZerocoreError,\n ZerocoreNetworkError,\n ZerocorePaymentError,\n ZerocoreRateLimitError,\n} from \"./errors.js\";\n\nimport nacl from \"tweetnacl\";\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_BASE_URL =\n \"https://augvmbhpuchkqqowxmrk.supabase.co/functions/v1\";\n\nconst DEFAULT_TIMEOUT = 30_000;\n\nconst USER_AGENT = \"zerocore-sdk-ts/0.1.0\";\n\n// ---------------------------------------------------------------------------\n// Client\n// ---------------------------------------------------------------------------\n\nexport class Client {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n private readonly timeout: number;\n private readonly agentKeypair: nacl.SignKeyPair | null;\n\n constructor(options: ClientOptions) {\n const { apiKey, baseUrl, timeout, agentPrivateKey } = options;\n\n if (!apiKey || !apiKey.startsWith(\"zc_\")) {\n throw new ZerocoreAuthError(\n \"API key must start with 'zc_live_' or 'zc_test_'. \" +\n \"Generate one at your ZERO.CORE dashboard → API Keys.\",\n );\n }\n\n this.apiKey = apiKey;\n this.baseUrl = (baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n this.timeout = timeout ?? DEFAULT_TIMEOUT;\n\n // Initialize Ed25519 keypair for DID signing (optional)\n if (agentPrivateKey) {\n const seed = hexToBytes(agentPrivateKey);\n if (seed.length === 64) {\n // Full 64-byte secret key (seed + pubkey)\n this.agentKeypair = nacl.sign.keyPair.fromSecretKey(seed);\n } else if (seed.length === 32) {\n // 32-byte seed only\n this.agentKeypair = nacl.sign.keyPair.fromSeed(seed);\n } else {\n throw new Error(\n \"agentPrivateKey must be hex-encoded Ed25519 key (64 or 128 hex chars)\",\n );\n }\n } else {\n this.agentKeypair = null;\n }\n }\n\n /**\n * Get the agent's Ed25519 public key (hex-encoded).\n * Register this in the ZERO.CORE dashboard under the agent's settings.\n * Returns `null` if no agent private key was provided.\n */\n getAgentPublicKey(): string | null {\n if (!this.agentKeypair) return null;\n return bytesToHex(this.agentKeypair.publicKey);\n }\n\n // ── Public API ──────────────────────────────────────────────────────────\n\n /**\n * Request authorization for an agent payment.\n *\n * Call this **before** your agent executes any paid API call.\n * The control plane checks:\n * - Is the agent active? (kill switch)\n * - Does this exceed the per-transaction limit?\n * - Does this exceed the daily spending limit?\n *\n * If approved and `executeOnChain` is `true`, the Edge Function executes\n * a real on-chain transfer (SOL or USDC SPL token).\n *\n * @throws {ZerocorePaymentError} Transaction was denied.\n * @throws {ZerocoreAuthError} API key is invalid.\n * @throws {ZerocoreRateLimitError} Too many requests.\n * @throws {ZerocoreNetworkError} API is unreachable.\n */\n async authorizeSpend(\n params: AuthorizeSpendParams,\n ): Promise<ApprovalResult> {\n const { amountUsd, merchant, currency = \"SOL\", memo, executeOnChain = false } = params;\n\n if (amountUsd <= 0) {\n throw new Error(\"amountUsd must be positive\");\n }\n if (!merchant) {\n throw new Error(\"merchant is required\");\n }\n if (currency !== \"SOL\" && currency !== \"USDC\") {\n throw new Error(\"currency must be 'SOL' or 'USDC'\");\n }\n\n const payload: Record<string, unknown> = {\n amount_usd: amountUsd,\n merchant,\n execute_on_chain: executeOnChain,\n currency,\n };\n\n if (memo) {\n payload.memo = memo;\n }\n\n // DID signing: attach Ed25519 signature if agent keypair is configured\n const extraHeaders: Record<string, string> = {};\n if (this.agentKeypair) {\n const timestamp = new Date().toISOString();\n const canonicalMessage = `${amountUsd}:${merchant}:${timestamp}`;\n const msgBytes = new TextEncoder().encode(canonicalMessage);\n const signature = nacl.sign.detached(msgBytes, this.agentKeypair.secretKey);\n extraHeaders[\"x-agent-signature\"] = bytesToHex(signature);\n extraHeaders[\"x-timestamp\"] = timestamp;\n }\n\n const raw = await this.post<RawApiResponse>(\"/authorize\", payload, extraHeaders);\n\n return toApprovalResult(raw);\n }\n\n // ── Internal ────────────────────────────────────────────────────────────\n\n private async post<T>(\n path: string,\n body: Record<string, unknown>,\n extraHeaders: Record<string, string> = {},\n ): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n\n let response: Response;\n try {\n response = await fetch(url, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n \"Content-Type\": \"application/json\",\n \"User-Agent\": USER_AGENT,\n ...extraHeaders,\n },\n body: JSON.stringify(body),\n signal: AbortSignal.timeout(this.timeout),\n });\n } catch (err) {\n if (err instanceof DOMException && err.name === \"TimeoutError\") {\n throw new ZerocoreNetworkError(\"Request timed out.\");\n }\n throw new ZerocoreNetworkError(\n `Cannot connect to ${this.baseUrl}. Check your network or baseUrl setting.`,\n );\n }\n\n return this.handleResponse<T>(response);\n }\n\n private async handleResponse<T>(response: Response): Promise<T> {\n // 200 — success\n if (response.ok) {\n return (await response.json()) as T;\n }\n\n // 401 — auth error\n if (response.status === 401) {\n const data = await safeJson(response);\n const msg = data?.detail ?? \"Invalid API key\";\n throw new ZerocoreAuthError(typeof msg === \"string\" ? msg : \"Invalid API key\");\n }\n\n // 429 — rate limit\n if (response.status === 429) {\n const retryAfter = response.headers.get(\"Retry-After\");\n throw new ZerocoreRateLimitError(\n retryAfter ? parseFloat(retryAfter) : undefined,\n );\n }\n\n // 402 / 403 — payment denied\n if (response.status === 402 || response.status === 403) {\n const data = await safeJson(response);\n const detail = data?.detail ?? data;\n\n if (detail && typeof detail === \"object\") {\n throw new ZerocorePaymentError(\n detail.message ?? \"Payment denied\",\n detail.denial_reason ?? \"UNKNOWN\",\n response.status,\n );\n }\n\n throw new ZerocorePaymentError(\n typeof detail === \"string\" ? detail : \"Payment denied\",\n \"UNKNOWN\",\n response.status,\n );\n }\n\n // Anything else\n const data = await safeJson(response);\n const message = data?.detail ?? data?.message ?? `API error ${response.status}`;\n throw new ZerocoreError(\n typeof message === \"string\" ? message : `API error ${response.status}`,\n response.status,\n );\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Parse JSON from a response without throwing on invalid JSON. */\n// deno-lint-ignore no-explicit-any\nasync function safeJson(response: Response): Promise<any> {\n try {\n return await response.json();\n } catch {\n return null;\n }\n}\n\n/** Map a raw snake_case API response to a camelCase {@link ApprovalResult}. */\nfunction toApprovalResult(raw: RawApiResponse): ApprovalResult {\n return {\n approved: raw.approval_status === \"approved\",\n transactionId: raw.transaction_id,\n amountUsd: raw.amount_usd,\n amountSol: raw.amount_sol,\n amountUsdc: raw.amount_usdc,\n currency: raw.currency,\n merchant: raw.merchant,\n remainingDailyLimit: raw.remaining_daily_limit,\n solanaSignature: raw.solana_signature,\n denialReason: raw.denial_reason,\n message: raw.message,\n };\n}\n\n/** Convert hex string to Uint8Array. */\nfunction hexToBytes(hex: string): Uint8Array {\n const bytes = new Uint8Array(hex.length / 2);\n for (let i = 0; i < hex.length; i += 2) {\n bytes[i / 2] = parseInt(hex.substring(i, i + 2), 16);\n }\n return bytes;\n}\n\n/** Convert Uint8Array to hex string. */\nfunction bytesToHex(bytes: Uint8Array): string {\n return Array.from(bytes)\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n}\n\n/**\n * Generate a new Ed25519 keypair for agent identity (DID).\n * Returns the private key (hex) and public key (hex).\n *\n * @example\n * ```ts\n * import { generateAgentKeypair } from \"@zerocore1/sdk\";\n *\n * const { privateKey, publicKey } = generateAgentKeypair();\n * console.log(\"Register this public key:\", publicKey);\n * // Store privateKey securely — pass it as agentPrivateKey to Client\n * ```\n */\nexport function generateAgentKeypair(): { privateKey: string; publicKey: string } {\n const keypair = nacl.sign.keyPair();\n return {\n privateKey: bytesToHex(keypair.secretKey),\n publicKey: bytesToHex(keypair.publicKey),\n };\n}\n"],"mappings":"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","names":["nacl","data"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -60,6 +60,15 @@ interface ClientOptions {
|
|
|
60
60
|
baseUrl?: string;
|
|
61
61
|
/** Request timeout in milliseconds. Defaults to `30_000` (30s). */
|
|
62
62
|
timeout?: number;
|
|
63
|
+
/**
|
|
64
|
+
* Ed25519 private key (hex-encoded, 64 bytes / 128 hex chars) for agent
|
|
65
|
+
* identity verification (DID). When provided, every request is
|
|
66
|
+
* cryptographically signed with this key. The corresponding public key
|
|
67
|
+
* must be registered in the ZERO.CORE dashboard.
|
|
68
|
+
*
|
|
69
|
+
* The private key NEVER leaves the agent — only the signature is sent.
|
|
70
|
+
*/
|
|
71
|
+
agentPrivateKey?: string;
|
|
63
72
|
}
|
|
64
73
|
|
|
65
74
|
/**
|
|
@@ -91,7 +100,14 @@ declare class Client {
|
|
|
91
100
|
private readonly apiKey;
|
|
92
101
|
private readonly baseUrl;
|
|
93
102
|
private readonly timeout;
|
|
103
|
+
private readonly agentKeypair;
|
|
94
104
|
constructor(options: ClientOptions);
|
|
105
|
+
/**
|
|
106
|
+
* Get the agent's Ed25519 public key (hex-encoded).
|
|
107
|
+
* Register this in the ZERO.CORE dashboard under the agent's settings.
|
|
108
|
+
* Returns `null` if no agent private key was provided.
|
|
109
|
+
*/
|
|
110
|
+
getAgentPublicKey(): string | null;
|
|
95
111
|
/**
|
|
96
112
|
* Request authorization for an agent payment.
|
|
97
113
|
*
|
|
@@ -113,6 +129,23 @@ declare class Client {
|
|
|
113
129
|
private post;
|
|
114
130
|
private handleResponse;
|
|
115
131
|
}
|
|
132
|
+
/**
|
|
133
|
+
* Generate a new Ed25519 keypair for agent identity (DID).
|
|
134
|
+
* Returns the private key (hex) and public key (hex).
|
|
135
|
+
*
|
|
136
|
+
* @example
|
|
137
|
+
* ```ts
|
|
138
|
+
* import { generateAgentKeypair } from "@zerocore1/sdk";
|
|
139
|
+
*
|
|
140
|
+
* const { privateKey, publicKey } = generateAgentKeypair();
|
|
141
|
+
* console.log("Register this public key:", publicKey);
|
|
142
|
+
* // Store privateKey securely — pass it as agentPrivateKey to Client
|
|
143
|
+
* ```
|
|
144
|
+
*/
|
|
145
|
+
declare function generateAgentKeypair(): {
|
|
146
|
+
privateKey: string;
|
|
147
|
+
publicKey: string;
|
|
148
|
+
};
|
|
116
149
|
|
|
117
150
|
/**
|
|
118
151
|
* ZERO.CORE SDK — Error Classes
|
|
@@ -155,4 +188,4 @@ declare class ZerocoreNetworkError extends ZerocoreError {
|
|
|
155
188
|
constructor(message?: string);
|
|
156
189
|
}
|
|
157
190
|
|
|
158
|
-
export { type ApprovalResult, type AuthorizeSpendParams, Client, type ClientOptions, type Currency, type DenialReason, ZerocoreAuthError, ZerocoreError, ZerocoreNetworkError, ZerocorePaymentError, ZerocoreRateLimitError };
|
|
191
|
+
export { type ApprovalResult, type AuthorizeSpendParams, Client, type ClientOptions, type Currency, type DenialReason, ZerocoreAuthError, ZerocoreError, ZerocoreNetworkError, ZerocorePaymentError, ZerocoreRateLimitError, generateAgentKeypair };
|
package/dist/index.d.ts
CHANGED
|
@@ -60,6 +60,15 @@ interface ClientOptions {
|
|
|
60
60
|
baseUrl?: string;
|
|
61
61
|
/** Request timeout in milliseconds. Defaults to `30_000` (30s). */
|
|
62
62
|
timeout?: number;
|
|
63
|
+
/**
|
|
64
|
+
* Ed25519 private key (hex-encoded, 64 bytes / 128 hex chars) for agent
|
|
65
|
+
* identity verification (DID). When provided, every request is
|
|
66
|
+
* cryptographically signed with this key. The corresponding public key
|
|
67
|
+
* must be registered in the ZERO.CORE dashboard.
|
|
68
|
+
*
|
|
69
|
+
* The private key NEVER leaves the agent — only the signature is sent.
|
|
70
|
+
*/
|
|
71
|
+
agentPrivateKey?: string;
|
|
63
72
|
}
|
|
64
73
|
|
|
65
74
|
/**
|
|
@@ -91,7 +100,14 @@ declare class Client {
|
|
|
91
100
|
private readonly apiKey;
|
|
92
101
|
private readonly baseUrl;
|
|
93
102
|
private readonly timeout;
|
|
103
|
+
private readonly agentKeypair;
|
|
94
104
|
constructor(options: ClientOptions);
|
|
105
|
+
/**
|
|
106
|
+
* Get the agent's Ed25519 public key (hex-encoded).
|
|
107
|
+
* Register this in the ZERO.CORE dashboard under the agent's settings.
|
|
108
|
+
* Returns `null` if no agent private key was provided.
|
|
109
|
+
*/
|
|
110
|
+
getAgentPublicKey(): string | null;
|
|
95
111
|
/**
|
|
96
112
|
* Request authorization for an agent payment.
|
|
97
113
|
*
|
|
@@ -113,6 +129,23 @@ declare class Client {
|
|
|
113
129
|
private post;
|
|
114
130
|
private handleResponse;
|
|
115
131
|
}
|
|
132
|
+
/**
|
|
133
|
+
* Generate a new Ed25519 keypair for agent identity (DID).
|
|
134
|
+
* Returns the private key (hex) and public key (hex).
|
|
135
|
+
*
|
|
136
|
+
* @example
|
|
137
|
+
* ```ts
|
|
138
|
+
* import { generateAgentKeypair } from "@zerocore1/sdk";
|
|
139
|
+
*
|
|
140
|
+
* const { privateKey, publicKey } = generateAgentKeypair();
|
|
141
|
+
* console.log("Register this public key:", publicKey);
|
|
142
|
+
* // Store privateKey securely — pass it as agentPrivateKey to Client
|
|
143
|
+
* ```
|
|
144
|
+
*/
|
|
145
|
+
declare function generateAgentKeypair(): {
|
|
146
|
+
privateKey: string;
|
|
147
|
+
publicKey: string;
|
|
148
|
+
};
|
|
116
149
|
|
|
117
150
|
/**
|
|
118
151
|
* ZERO.CORE SDK — Error Classes
|
|
@@ -155,4 +188,4 @@ declare class ZerocoreNetworkError extends ZerocoreError {
|
|
|
155
188
|
constructor(message?: string);
|
|
156
189
|
}
|
|
157
190
|
|
|
158
|
-
export { type ApprovalResult, type AuthorizeSpendParams, Client, type ClientOptions, type Currency, type DenialReason, ZerocoreAuthError, ZerocoreError, ZerocoreNetworkError, ZerocorePaymentError, ZerocoreRateLimitError };
|
|
191
|
+
export { type ApprovalResult, type AuthorizeSpendParams, Client, type ClientOptions, type Currency, type DenialReason, ZerocoreAuthError, ZerocoreError, ZerocoreNetworkError, ZerocorePaymentError, ZerocoreRateLimitError, generateAgentKeypair };
|
package/dist/index.js
CHANGED
|
@@ -41,6 +41,7 @@ var ZerocoreNetworkError = class extends ZerocoreError {
|
|
|
41
41
|
};
|
|
42
42
|
|
|
43
43
|
// src/client.ts
|
|
44
|
+
import nacl from "tweetnacl";
|
|
44
45
|
var DEFAULT_BASE_URL = "https://augvmbhpuchkqqowxmrk.supabase.co/functions/v1";
|
|
45
46
|
var DEFAULT_TIMEOUT = 3e4;
|
|
46
47
|
var USER_AGENT = "zerocore-sdk-ts/0.1.0";
|
|
@@ -48,8 +49,9 @@ var Client = class {
|
|
|
48
49
|
apiKey;
|
|
49
50
|
baseUrl;
|
|
50
51
|
timeout;
|
|
52
|
+
agentKeypair;
|
|
51
53
|
constructor(options) {
|
|
52
|
-
const { apiKey, baseUrl, timeout } = options;
|
|
54
|
+
const { apiKey, baseUrl, timeout, agentPrivateKey } = options;
|
|
53
55
|
if (!apiKey || !apiKey.startsWith("zc_")) {
|
|
54
56
|
throw new ZerocoreAuthError(
|
|
55
57
|
"API key must start with 'zc_live_' or 'zc_test_'. Generate one at your ZERO.CORE dashboard \u2192 API Keys."
|
|
@@ -58,6 +60,29 @@ var Client = class {
|
|
|
58
60
|
this.apiKey = apiKey;
|
|
59
61
|
this.baseUrl = (baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
60
62
|
this.timeout = timeout ?? DEFAULT_TIMEOUT;
|
|
63
|
+
if (agentPrivateKey) {
|
|
64
|
+
const seed = hexToBytes(agentPrivateKey);
|
|
65
|
+
if (seed.length === 64) {
|
|
66
|
+
this.agentKeypair = nacl.sign.keyPair.fromSecretKey(seed);
|
|
67
|
+
} else if (seed.length === 32) {
|
|
68
|
+
this.agentKeypair = nacl.sign.keyPair.fromSeed(seed);
|
|
69
|
+
} else {
|
|
70
|
+
throw new Error(
|
|
71
|
+
"agentPrivateKey must be hex-encoded Ed25519 key (64 or 128 hex chars)"
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
} else {
|
|
75
|
+
this.agentKeypair = null;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Get the agent's Ed25519 public key (hex-encoded).
|
|
80
|
+
* Register this in the ZERO.CORE dashboard under the agent's settings.
|
|
81
|
+
* Returns `null` if no agent private key was provided.
|
|
82
|
+
*/
|
|
83
|
+
getAgentPublicKey() {
|
|
84
|
+
if (!this.agentKeypair) return null;
|
|
85
|
+
return bytesToHex(this.agentKeypair.publicKey);
|
|
61
86
|
}
|
|
62
87
|
// ── Public API ──────────────────────────────────────────────────────────
|
|
63
88
|
/**
|
|
@@ -97,11 +122,20 @@ var Client = class {
|
|
|
97
122
|
if (memo) {
|
|
98
123
|
payload.memo = memo;
|
|
99
124
|
}
|
|
100
|
-
const
|
|
125
|
+
const extraHeaders = {};
|
|
126
|
+
if (this.agentKeypair) {
|
|
127
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
128
|
+
const canonicalMessage = `${amountUsd}:${merchant}:${timestamp}`;
|
|
129
|
+
const msgBytes = new TextEncoder().encode(canonicalMessage);
|
|
130
|
+
const signature = nacl.sign.detached(msgBytes, this.agentKeypair.secretKey);
|
|
131
|
+
extraHeaders["x-agent-signature"] = bytesToHex(signature);
|
|
132
|
+
extraHeaders["x-timestamp"] = timestamp;
|
|
133
|
+
}
|
|
134
|
+
const raw = await this.post("/authorize", payload, extraHeaders);
|
|
101
135
|
return toApprovalResult(raw);
|
|
102
136
|
}
|
|
103
137
|
// ── Internal ────────────────────────────────────────────────────────────
|
|
104
|
-
async post(path, body) {
|
|
138
|
+
async post(path, body, extraHeaders = {}) {
|
|
105
139
|
const url = `${this.baseUrl}${path}`;
|
|
106
140
|
let response;
|
|
107
141
|
try {
|
|
@@ -110,7 +144,8 @@ var Client = class {
|
|
|
110
144
|
headers: {
|
|
111
145
|
Authorization: `Bearer ${this.apiKey}`,
|
|
112
146
|
"Content-Type": "application/json",
|
|
113
|
-
"User-Agent": USER_AGENT
|
|
147
|
+
"User-Agent": USER_AGENT,
|
|
148
|
+
...extraHeaders
|
|
114
149
|
},
|
|
115
150
|
body: JSON.stringify(body),
|
|
116
151
|
signal: AbortSignal.timeout(this.timeout)
|
|
@@ -186,12 +221,30 @@ function toApprovalResult(raw) {
|
|
|
186
221
|
message: raw.message
|
|
187
222
|
};
|
|
188
223
|
}
|
|
224
|
+
function hexToBytes(hex) {
|
|
225
|
+
const bytes = new Uint8Array(hex.length / 2);
|
|
226
|
+
for (let i = 0; i < hex.length; i += 2) {
|
|
227
|
+
bytes[i / 2] = parseInt(hex.substring(i, i + 2), 16);
|
|
228
|
+
}
|
|
229
|
+
return bytes;
|
|
230
|
+
}
|
|
231
|
+
function bytesToHex(bytes) {
|
|
232
|
+
return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
233
|
+
}
|
|
234
|
+
function generateAgentKeypair() {
|
|
235
|
+
const keypair = nacl.sign.keyPair();
|
|
236
|
+
return {
|
|
237
|
+
privateKey: bytesToHex(keypair.secretKey),
|
|
238
|
+
publicKey: bytesToHex(keypair.publicKey)
|
|
239
|
+
};
|
|
240
|
+
}
|
|
189
241
|
export {
|
|
190
242
|
Client,
|
|
191
243
|
ZerocoreAuthError,
|
|
192
244
|
ZerocoreError,
|
|
193
245
|
ZerocoreNetworkError,
|
|
194
246
|
ZerocorePaymentError,
|
|
195
|
-
ZerocoreRateLimitError
|
|
247
|
+
ZerocoreRateLimitError,
|
|
248
|
+
generateAgentKeypair
|
|
196
249
|
};
|
|
197
250
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts","../src/client.ts"],"sourcesContent":["/**\n * ZERO.CORE SDK — Error Classes\n *\n * Typed exceptions for every failure mode the control plane can produce.\n */\n\nimport type { DenialReason } from \"./types.js\";\n\n// ---------------------------------------------------------------------------\n// Base\n// ---------------------------------------------------------------------------\n\n/** Base error for all ZERO.CORE SDK errors. */\nexport class ZerocoreError extends Error {\n /** HTTP status code from the API, if applicable. */\n readonly statusCode?: number;\n\n constructor(message: string, statusCode?: number) {\n super(message);\n this.name = \"ZerocoreError\";\n this.statusCode = statusCode;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Auth\n// ---------------------------------------------------------------------------\n\n/** Thrown when the API key is invalid or revoked (HTTP 401). */\nexport class ZerocoreAuthError extends ZerocoreError {\n constructor(message = \"Invalid API key\") {\n super(message, 401);\n this.name = \"ZerocoreAuthError\";\n }\n}\n\n// ---------------------------------------------------------------------------\n// Payment denied\n// ---------------------------------------------------------------------------\n\n/**\n * Thrown when the fiduciary control plane denies a transaction (HTTP 402/403).\n *\n * Inspect {@link reason} for the specific denial cause:\n * - `AGENT_INACTIVE` — Kill switch is off\n * - `EXCEEDS_PER_TX_LIMIT` — Single transaction too large\n * - `EXCEEDS_DAILY_LIMIT` — Daily budget exhausted\n * - `SETTLEMENT_FAILED: ...` — On-chain transfer failed\n */\nexport class ZerocorePaymentError extends ZerocoreError {\n /** Machine-readable denial reason from the control plane. */\n readonly reason: DenialReason;\n\n constructor(message: string, reason: DenialReason, statusCode = 403) {\n super(message, statusCode);\n this.name = \"ZerocorePaymentError\";\n this.reason = reason;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Rate limit\n// ---------------------------------------------------------------------------\n\n/** Thrown when the API rate limit is exceeded (HTTP 429). */\nexport class ZerocoreRateLimitError extends ZerocoreError {\n /** Seconds to wait before retrying, if provided by the API. */\n readonly retryAfter?: number;\n\n constructor(retryAfter?: number) {\n const msg = retryAfter\n ? `Rate limited. Retry after ${retryAfter}s.`\n : \"Rate limited.\";\n super(msg, 429);\n this.name = \"ZerocoreRateLimitError\";\n this.retryAfter = retryAfter;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Network\n// ---------------------------------------------------------------------------\n\n/** Thrown when the Edge Function is unreachable. */\nexport class ZerocoreNetworkError extends ZerocoreError {\n constructor(message = \"Cannot connect to ZERO.CORE API.\") {\n super(message);\n this.name = \"ZerocoreNetworkError\";\n }\n}\n","/**\n * ZERO.CORE SDK — Client\n *\n * The fiduciary gatekeeper for AI agents. Every paid API call your agent\n * makes should pass through {@link Client.authorizeSpend} first. If the\n * control plane says no, the call never happens.\n *\n * @example\n * ```ts\n * import { Client } from \"@zerocore1/sdk\";\n *\n * const zc = new Client({ apiKey: \"zc_live_abc123...\" });\n *\n * const result = await zc.authorizeSpend({\n * amountUsd: 0.03,\n * merchant: \"OpenAI\",\n * currency: \"USDC\",\n * });\n *\n * if (result.approved) {\n * // safe to call OpenAI\n * }\n * ```\n */\n\nimport type {\n ApprovalResult,\n AuthorizeSpendParams,\n ClientOptions,\n RawApiResponse,\n} from \"./types.js\";\n\nimport {\n ZerocoreAuthError,\n ZerocoreError,\n ZerocoreNetworkError,\n ZerocorePaymentError,\n ZerocoreRateLimitError,\n} from \"./errors.js\";\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_BASE_URL =\n \"https://augvmbhpuchkqqowxmrk.supabase.co/functions/v1\";\n\nconst DEFAULT_TIMEOUT = 30_000;\n\nconst USER_AGENT = \"zerocore-sdk-ts/0.1.0\";\n\n// ---------------------------------------------------------------------------\n// Client\n// ---------------------------------------------------------------------------\n\nexport class Client {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n private readonly timeout: number;\n\n constructor(options: ClientOptions) {\n const { apiKey, baseUrl, timeout } = options;\n\n if (!apiKey || !apiKey.startsWith(\"zc_\")) {\n throw new ZerocoreAuthError(\n \"API key must start with 'zc_live_' or 'zc_test_'. \" +\n \"Generate one at your ZERO.CORE dashboard → API Keys.\",\n );\n }\n\n this.apiKey = apiKey;\n this.baseUrl = (baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n this.timeout = timeout ?? DEFAULT_TIMEOUT;\n }\n\n // ── Public API ──────────────────────────────────────────────────────────\n\n /**\n * Request authorization for an agent payment.\n *\n * Call this **before** your agent executes any paid API call.\n * The control plane checks:\n * - Is the agent active? (kill switch)\n * - Does this exceed the per-transaction limit?\n * - Does this exceed the daily spending limit?\n *\n * If approved and `executeOnChain` is `true`, the Edge Function executes\n * a real on-chain transfer (SOL or USDC SPL token).\n *\n * @throws {ZerocorePaymentError} Transaction was denied.\n * @throws {ZerocoreAuthError} API key is invalid.\n * @throws {ZerocoreRateLimitError} Too many requests.\n * @throws {ZerocoreNetworkError} API is unreachable.\n */\n async authorizeSpend(\n params: AuthorizeSpendParams,\n ): Promise<ApprovalResult> {\n const { amountUsd, merchant, currency = \"SOL\", memo, executeOnChain = false } = params;\n\n if (amountUsd <= 0) {\n throw new Error(\"amountUsd must be positive\");\n }\n if (!merchant) {\n throw new Error(\"merchant is required\");\n }\n if (currency !== \"SOL\" && currency !== \"USDC\") {\n throw new Error(\"currency must be 'SOL' or 'USDC'\");\n }\n\n const payload: Record<string, unknown> = {\n amount_usd: amountUsd,\n merchant,\n execute_on_chain: executeOnChain,\n currency,\n };\n\n if (memo) {\n payload.memo = memo;\n }\n\n const raw = await this.post<RawApiResponse>(\"/authorize\", payload);\n\n return toApprovalResult(raw);\n }\n\n // ── Internal ────────────────────────────────────────────────────────────\n\n private async post<T>(path: string, body: Record<string, unknown>): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n\n let response: Response;\n try {\n response = await fetch(url, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n \"Content-Type\": \"application/json\",\n \"User-Agent\": USER_AGENT,\n },\n body: JSON.stringify(body),\n signal: AbortSignal.timeout(this.timeout),\n });\n } catch (err) {\n if (err instanceof DOMException && err.name === \"TimeoutError\") {\n throw new ZerocoreNetworkError(\"Request timed out.\");\n }\n throw new ZerocoreNetworkError(\n `Cannot connect to ${this.baseUrl}. Check your network or baseUrl setting.`,\n );\n }\n\n return this.handleResponse<T>(response);\n }\n\n private async handleResponse<T>(response: Response): Promise<T> {\n // 200 — success\n if (response.ok) {\n return (await response.json()) as T;\n }\n\n // 401 — auth error\n if (response.status === 401) {\n const data = await safeJson(response);\n const msg = data?.detail ?? \"Invalid API key\";\n throw new ZerocoreAuthError(typeof msg === \"string\" ? msg : \"Invalid API key\");\n }\n\n // 429 — rate limit\n if (response.status === 429) {\n const retryAfter = response.headers.get(\"Retry-After\");\n throw new ZerocoreRateLimitError(\n retryAfter ? parseFloat(retryAfter) : undefined,\n );\n }\n\n // 402 / 403 — payment denied\n if (response.status === 402 || response.status === 403) {\n const data = await safeJson(response);\n const detail = data?.detail ?? data;\n\n if (detail && typeof detail === \"object\") {\n throw new ZerocorePaymentError(\n detail.message ?? \"Payment denied\",\n detail.denial_reason ?? \"UNKNOWN\",\n response.status,\n );\n }\n\n throw new ZerocorePaymentError(\n typeof detail === \"string\" ? detail : \"Payment denied\",\n \"UNKNOWN\",\n response.status,\n );\n }\n\n // Anything else\n const data = await safeJson(response);\n const message = data?.detail ?? data?.message ?? `API error ${response.status}`;\n throw new ZerocoreError(\n typeof message === \"string\" ? message : `API error ${response.status}`,\n response.status,\n );\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Parse JSON from a response without throwing on invalid JSON. */\n// deno-lint-ignore no-explicit-any\nasync function safeJson(response: Response): Promise<any> {\n try {\n return await response.json();\n } catch {\n return null;\n }\n}\n\n/** Map a raw snake_case API response to a camelCase {@link ApprovalResult}. */\nfunction toApprovalResult(raw: RawApiResponse): ApprovalResult {\n return {\n approved: raw.approval_status === \"approved\",\n transactionId: raw.transaction_id,\n amountUsd: raw.amount_usd,\n amountSol: raw.amount_sol,\n amountUsdc: raw.amount_usdc,\n currency: raw.currency,\n merchant: raw.merchant,\n remainingDailyLimit: raw.remaining_daily_limit,\n solanaSignature: raw.solana_signature,\n denialReason: raw.denial_reason,\n message: raw.message,\n };\n}\n"],"mappings":";AAaO,IAAM,gBAAN,cAA4B,MAAM;AAAA;AAAA,EAE9B;AAAA,EAET,YAAY,SAAiB,YAAqB;AAChD,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,aAAa;AAAA,EACpB;AACF;AAOO,IAAM,oBAAN,cAAgC,cAAc;AAAA,EACnD,YAAY,UAAU,mBAAmB;AACvC,UAAM,SAAS,GAAG;AAClB,SAAK,OAAO;AAAA,EACd;AACF;AAeO,IAAM,uBAAN,cAAmC,cAAc;AAAA;AAAA,EAE7C;AAAA,EAET,YAAY,SAAiB,QAAsB,aAAa,KAAK;AACnE,UAAM,SAAS,UAAU;AACzB,SAAK,OAAO;AACZ,SAAK,SAAS;AAAA,EAChB;AACF;AAOO,IAAM,yBAAN,cAAqC,cAAc;AAAA;AAAA,EAE/C;AAAA,EAET,YAAY,YAAqB;AAC/B,UAAM,MAAM,aACR,6BAA6B,UAAU,OACvC;AACJ,UAAM,KAAK,GAAG;AACd,SAAK,OAAO;AACZ,SAAK,aAAa;AAAA,EACpB;AACF;AAOO,IAAM,uBAAN,cAAmC,cAAc;AAAA,EACtD,YAAY,UAAU,oCAAoC;AACxD,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;;;AC7CA,IAAM,mBACJ;AAEF,IAAM,kBAAkB;AAExB,IAAM,aAAa;AAMZ,IAAM,SAAN,MAAa;AAAA,EACD;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,SAAwB;AAClC,UAAM,EAAE,QAAQ,SAAS,QAAQ,IAAI;AAErC,QAAI,CAAC,UAAU,CAAC,OAAO,WAAW,KAAK,GAAG;AACxC,YAAM,IAAI;AAAA,QACR;AAAA,MAEF;AAAA,IACF;AAEA,SAAK,SAAS;AACd,SAAK,WAAW,WAAW,kBAAkB,QAAQ,QAAQ,EAAE;AAC/D,SAAK,UAAU,WAAW;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAqBA,MAAM,eACJ,QACyB;AACzB,UAAM,EAAE,WAAW,UAAU,WAAW,OAAO,MAAM,iBAAiB,MAAM,IAAI;AAEhF,QAAI,aAAa,GAAG;AAClB,YAAM,IAAI,MAAM,4BAA4B;AAAA,IAC9C;AACA,QAAI,CAAC,UAAU;AACb,YAAM,IAAI,MAAM,sBAAsB;AAAA,IACxC;AACA,QAAI,aAAa,SAAS,aAAa,QAAQ;AAC7C,YAAM,IAAI,MAAM,kCAAkC;AAAA,IACpD;AAEA,UAAM,UAAmC;AAAA,MACvC,YAAY;AAAA,MACZ;AAAA,MACA,kBAAkB;AAAA,MAClB;AAAA,IACF;AAEA,QAAI,MAAM;AACR,cAAQ,OAAO;AAAA,IACjB;AAEA,UAAM,MAAM,MAAM,KAAK,KAAqB,cAAc,OAAO;AAEjE,WAAO,iBAAiB,GAAG;AAAA,EAC7B;AAAA;AAAA,EAIA,MAAc,KAAQ,MAAc,MAA2C;AAC7E,UAAM,MAAM,GAAG,KAAK,OAAO,GAAG,IAAI;AAElC,QAAI;AACJ,QAAI;AACF,iBAAW,MAAM,MAAM,KAAK;AAAA,QAC1B,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,eAAe,UAAU,KAAK,MAAM;AAAA,UACpC,gBAAgB;AAAA,UAChB,cAAc;AAAA,QAChB;AAAA,QACA,MAAM,KAAK,UAAU,IAAI;AAAA,QACzB,QAAQ,YAAY,QAAQ,KAAK,OAAO;AAAA,MAC1C,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,UAAI,eAAe,gBAAgB,IAAI,SAAS,gBAAgB;AAC9D,cAAM,IAAI,qBAAqB,oBAAoB;AAAA,MACrD;AACA,YAAM,IAAI;AAAA,QACR,qBAAqB,KAAK,OAAO;AAAA,MACnC;AAAA,IACF;AAEA,WAAO,KAAK,eAAkB,QAAQ;AAAA,EACxC;AAAA,EAEA,MAAc,eAAkB,UAAgC;AAE9D,QAAI,SAAS,IAAI;AACf,aAAQ,MAAM,SAAS,KAAK;AAAA,IAC9B;AAGA,QAAI,SAAS,WAAW,KAAK;AAC3B,YAAMA,QAAO,MAAM,SAAS,QAAQ;AACpC,YAAM,MAAMA,OAAM,UAAU;AAC5B,YAAM,IAAI,kBAAkB,OAAO,QAAQ,WAAW,MAAM,iBAAiB;AAAA,IAC/E;AAGA,QAAI,SAAS,WAAW,KAAK;AAC3B,YAAM,aAAa,SAAS,QAAQ,IAAI,aAAa;AACrD,YAAM,IAAI;AAAA,QACR,aAAa,WAAW,UAAU,IAAI;AAAA,MACxC;AAAA,IACF;AAGA,QAAI,SAAS,WAAW,OAAO,SAAS,WAAW,KAAK;AACtD,YAAMA,QAAO,MAAM,SAAS,QAAQ;AACpC,YAAM,SAASA,OAAM,UAAUA;AAE/B,UAAI,UAAU,OAAO,WAAW,UAAU;AACxC,cAAM,IAAI;AAAA,UACR,OAAO,WAAW;AAAA,UAClB,OAAO,iBAAiB;AAAA,UACxB,SAAS;AAAA,QACX;AAAA,MACF;AAEA,YAAM,IAAI;AAAA,QACR,OAAO,WAAW,WAAW,SAAS;AAAA,QACtC;AAAA,QACA,SAAS;AAAA,MACX;AAAA,IACF;AAGA,UAAM,OAAO,MAAM,SAAS,QAAQ;AACpC,UAAM,UAAU,MAAM,UAAU,MAAM,WAAW,aAAa,SAAS,MAAM;AAC7E,UAAM,IAAI;AAAA,MACR,OAAO,YAAY,WAAW,UAAU,aAAa,SAAS,MAAM;AAAA,MACpE,SAAS;AAAA,IACX;AAAA,EACF;AACF;AAQA,eAAe,SAAS,UAAkC;AACxD,MAAI;AACF,WAAO,MAAM,SAAS,KAAK;AAAA,EAC7B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGA,SAAS,iBAAiB,KAAqC;AAC7D,SAAO;AAAA,IACL,UAAU,IAAI,oBAAoB;AAAA,IAClC,eAAe,IAAI;AAAA,IACnB,WAAW,IAAI;AAAA,IACf,WAAW,IAAI;AAAA,IACf,YAAY,IAAI;AAAA,IAChB,UAAU,IAAI;AAAA,IACd,UAAU,IAAI;AAAA,IACd,qBAAqB,IAAI;AAAA,IACzB,iBAAiB,IAAI;AAAA,IACrB,cAAc,IAAI;AAAA,IAClB,SAAS,IAAI;AAAA,EACf;AACF;","names":["data"]}
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/client.ts"],"sourcesContent":["/**\n * ZERO.CORE SDK — Error Classes\n *\n * Typed exceptions for every failure mode the control plane can produce.\n */\n\nimport type { DenialReason } from \"./types.js\";\n\n// ---------------------------------------------------------------------------\n// Base\n// ---------------------------------------------------------------------------\n\n/** Base error for all ZERO.CORE SDK errors. */\nexport class ZerocoreError extends Error {\n /** HTTP status code from the API, if applicable. */\n readonly statusCode?: number;\n\n constructor(message: string, statusCode?: number) {\n super(message);\n this.name = \"ZerocoreError\";\n this.statusCode = statusCode;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Auth\n// ---------------------------------------------------------------------------\n\n/** Thrown when the API key is invalid or revoked (HTTP 401). */\nexport class ZerocoreAuthError extends ZerocoreError {\n constructor(message = \"Invalid API key\") {\n super(message, 401);\n this.name = \"ZerocoreAuthError\";\n }\n}\n\n// ---------------------------------------------------------------------------\n// Payment denied\n// ---------------------------------------------------------------------------\n\n/**\n * Thrown when the fiduciary control plane denies a transaction (HTTP 402/403).\n *\n * Inspect {@link reason} for the specific denial cause:\n * - `AGENT_INACTIVE` — Kill switch is off\n * - `EXCEEDS_PER_TX_LIMIT` — Single transaction too large\n * - `EXCEEDS_DAILY_LIMIT` — Daily budget exhausted\n * - `SETTLEMENT_FAILED: ...` — On-chain transfer failed\n */\nexport class ZerocorePaymentError extends ZerocoreError {\n /** Machine-readable denial reason from the control plane. */\n readonly reason: DenialReason;\n\n constructor(message: string, reason: DenialReason, statusCode = 403) {\n super(message, statusCode);\n this.name = \"ZerocorePaymentError\";\n this.reason = reason;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Rate limit\n// ---------------------------------------------------------------------------\n\n/** Thrown when the API rate limit is exceeded (HTTP 429). */\nexport class ZerocoreRateLimitError extends ZerocoreError {\n /** Seconds to wait before retrying, if provided by the API. */\n readonly retryAfter?: number;\n\n constructor(retryAfter?: number) {\n const msg = retryAfter\n ? `Rate limited. Retry after ${retryAfter}s.`\n : \"Rate limited.\";\n super(msg, 429);\n this.name = \"ZerocoreRateLimitError\";\n this.retryAfter = retryAfter;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Network\n// ---------------------------------------------------------------------------\n\n/** Thrown when the Edge Function is unreachable. */\nexport class ZerocoreNetworkError extends ZerocoreError {\n constructor(message = \"Cannot connect to ZERO.CORE API.\") {\n super(message);\n this.name = \"ZerocoreNetworkError\";\n }\n}\n","/**\n * ZERO.CORE SDK — Client\n *\n * The fiduciary gatekeeper for AI agents. Every paid API call your agent\n * makes should pass through {@link Client.authorizeSpend} first. If the\n * control plane says no, the call never happens.\n *\n * @example\n * ```ts\n * import { Client } from \"@zerocore1/sdk\";\n *\n * const zc = new Client({ apiKey: \"zc_live_abc123...\" });\n *\n * const result = await zc.authorizeSpend({\n * amountUsd: 0.03,\n * merchant: \"OpenAI\",\n * currency: \"USDC\",\n * });\n *\n * if (result.approved) {\n * // safe to call OpenAI\n * }\n * ```\n */\n\nimport type {\n ApprovalResult,\n AuthorizeSpendParams,\n ClientOptions,\n RawApiResponse,\n} from \"./types.js\";\n\nimport {\n ZerocoreAuthError,\n ZerocoreError,\n ZerocoreNetworkError,\n ZerocorePaymentError,\n ZerocoreRateLimitError,\n} from \"./errors.js\";\n\nimport nacl from \"tweetnacl\";\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_BASE_URL =\n \"https://augvmbhpuchkqqowxmrk.supabase.co/functions/v1\";\n\nconst DEFAULT_TIMEOUT = 30_000;\n\nconst USER_AGENT = \"zerocore-sdk-ts/0.1.0\";\n\n// ---------------------------------------------------------------------------\n// Client\n// ---------------------------------------------------------------------------\n\nexport class Client {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n private readonly timeout: number;\n private readonly agentKeypair: nacl.SignKeyPair | null;\n\n constructor(options: ClientOptions) {\n const { apiKey, baseUrl, timeout, agentPrivateKey } = options;\n\n if (!apiKey || !apiKey.startsWith(\"zc_\")) {\n throw new ZerocoreAuthError(\n \"API key must start with 'zc_live_' or 'zc_test_'. \" +\n \"Generate one at your ZERO.CORE dashboard → API Keys.\",\n );\n }\n\n this.apiKey = apiKey;\n this.baseUrl = (baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n this.timeout = timeout ?? DEFAULT_TIMEOUT;\n\n // Initialize Ed25519 keypair for DID signing (optional)\n if (agentPrivateKey) {\n const seed = hexToBytes(agentPrivateKey);\n if (seed.length === 64) {\n // Full 64-byte secret key (seed + pubkey)\n this.agentKeypair = nacl.sign.keyPair.fromSecretKey(seed);\n } else if (seed.length === 32) {\n // 32-byte seed only\n this.agentKeypair = nacl.sign.keyPair.fromSeed(seed);\n } else {\n throw new Error(\n \"agentPrivateKey must be hex-encoded Ed25519 key (64 or 128 hex chars)\",\n );\n }\n } else {\n this.agentKeypair = null;\n }\n }\n\n /**\n * Get the agent's Ed25519 public key (hex-encoded).\n * Register this in the ZERO.CORE dashboard under the agent's settings.\n * Returns `null` if no agent private key was provided.\n */\n getAgentPublicKey(): string | null {\n if (!this.agentKeypair) return null;\n return bytesToHex(this.agentKeypair.publicKey);\n }\n\n // ── Public API ──────────────────────────────────────────────────────────\n\n /**\n * Request authorization for an agent payment.\n *\n * Call this **before** your agent executes any paid API call.\n * The control plane checks:\n * - Is the agent active? (kill switch)\n * - Does this exceed the per-transaction limit?\n * - Does this exceed the daily spending limit?\n *\n * If approved and `executeOnChain` is `true`, the Edge Function executes\n * a real on-chain transfer (SOL or USDC SPL token).\n *\n * @throws {ZerocorePaymentError} Transaction was denied.\n * @throws {ZerocoreAuthError} API key is invalid.\n * @throws {ZerocoreRateLimitError} Too many requests.\n * @throws {ZerocoreNetworkError} API is unreachable.\n */\n async authorizeSpend(\n params: AuthorizeSpendParams,\n ): Promise<ApprovalResult> {\n const { amountUsd, merchant, currency = \"SOL\", memo, executeOnChain = false } = params;\n\n if (amountUsd <= 0) {\n throw new Error(\"amountUsd must be positive\");\n }\n if (!merchant) {\n throw new Error(\"merchant is required\");\n }\n if (currency !== \"SOL\" && currency !== \"USDC\") {\n throw new Error(\"currency must be 'SOL' or 'USDC'\");\n }\n\n const payload: Record<string, unknown> = {\n amount_usd: amountUsd,\n merchant,\n execute_on_chain: executeOnChain,\n currency,\n };\n\n if (memo) {\n payload.memo = memo;\n }\n\n // DID signing: attach Ed25519 signature if agent keypair is configured\n const extraHeaders: Record<string, string> = {};\n if (this.agentKeypair) {\n const timestamp = new Date().toISOString();\n const canonicalMessage = `${amountUsd}:${merchant}:${timestamp}`;\n const msgBytes = new TextEncoder().encode(canonicalMessage);\n const signature = nacl.sign.detached(msgBytes, this.agentKeypair.secretKey);\n extraHeaders[\"x-agent-signature\"] = bytesToHex(signature);\n extraHeaders[\"x-timestamp\"] = timestamp;\n }\n\n const raw = await this.post<RawApiResponse>(\"/authorize\", payload, extraHeaders);\n\n return toApprovalResult(raw);\n }\n\n // ── Internal ────────────────────────────────────────────────────────────\n\n private async post<T>(\n path: string,\n body: Record<string, unknown>,\n extraHeaders: Record<string, string> = {},\n ): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n\n let response: Response;\n try {\n response = await fetch(url, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n \"Content-Type\": \"application/json\",\n \"User-Agent\": USER_AGENT,\n ...extraHeaders,\n },\n body: JSON.stringify(body),\n signal: AbortSignal.timeout(this.timeout),\n });\n } catch (err) {\n if (err instanceof DOMException && err.name === \"TimeoutError\") {\n throw new ZerocoreNetworkError(\"Request timed out.\");\n }\n throw new ZerocoreNetworkError(\n `Cannot connect to ${this.baseUrl}. Check your network or baseUrl setting.`,\n );\n }\n\n return this.handleResponse<T>(response);\n }\n\n private async handleResponse<T>(response: Response): Promise<T> {\n // 200 — success\n if (response.ok) {\n return (await response.json()) as T;\n }\n\n // 401 — auth error\n if (response.status === 401) {\n const data = await safeJson(response);\n const msg = data?.detail ?? \"Invalid API key\";\n throw new ZerocoreAuthError(typeof msg === \"string\" ? msg : \"Invalid API key\");\n }\n\n // 429 — rate limit\n if (response.status === 429) {\n const retryAfter = response.headers.get(\"Retry-After\");\n throw new ZerocoreRateLimitError(\n retryAfter ? parseFloat(retryAfter) : undefined,\n );\n }\n\n // 402 / 403 — payment denied\n if (response.status === 402 || response.status === 403) {\n const data = await safeJson(response);\n const detail = data?.detail ?? data;\n\n if (detail && typeof detail === \"object\") {\n throw new ZerocorePaymentError(\n detail.message ?? \"Payment denied\",\n detail.denial_reason ?? \"UNKNOWN\",\n response.status,\n );\n }\n\n throw new ZerocorePaymentError(\n typeof detail === \"string\" ? detail : \"Payment denied\",\n \"UNKNOWN\",\n response.status,\n );\n }\n\n // Anything else\n const data = await safeJson(response);\n const message = data?.detail ?? data?.message ?? `API error ${response.status}`;\n throw new ZerocoreError(\n typeof message === \"string\" ? message : `API error ${response.status}`,\n response.status,\n );\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Parse JSON from a response without throwing on invalid JSON. */\n// deno-lint-ignore no-explicit-any\nasync function safeJson(response: Response): Promise<any> {\n try {\n return await response.json();\n } catch {\n return null;\n }\n}\n\n/** Map a raw snake_case API response to a camelCase {@link ApprovalResult}. */\nfunction toApprovalResult(raw: RawApiResponse): ApprovalResult {\n return {\n approved: raw.approval_status === \"approved\",\n transactionId: raw.transaction_id,\n amountUsd: raw.amount_usd,\n amountSol: raw.amount_sol,\n amountUsdc: raw.amount_usdc,\n currency: raw.currency,\n merchant: raw.merchant,\n remainingDailyLimit: raw.remaining_daily_limit,\n solanaSignature: raw.solana_signature,\n denialReason: raw.denial_reason,\n message: raw.message,\n };\n}\n\n/** Convert hex string to Uint8Array. */\nfunction hexToBytes(hex: string): Uint8Array {\n const bytes = new Uint8Array(hex.length / 2);\n for (let i = 0; i < hex.length; i += 2) {\n bytes[i / 2] = parseInt(hex.substring(i, i + 2), 16);\n }\n return bytes;\n}\n\n/** Convert Uint8Array to hex string. */\nfunction bytesToHex(bytes: Uint8Array): string {\n return Array.from(bytes)\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n}\n\n/**\n * Generate a new Ed25519 keypair for agent identity (DID).\n * Returns the private key (hex) and public key (hex).\n *\n * @example\n * ```ts\n * import { generateAgentKeypair } from \"@zerocore1/sdk\";\n *\n * const { privateKey, publicKey } = generateAgentKeypair();\n * console.log(\"Register this public key:\", publicKey);\n * // Store privateKey securely — pass it as agentPrivateKey to Client\n * ```\n */\nexport function generateAgentKeypair(): { privateKey: string; publicKey: string } {\n const keypair = nacl.sign.keyPair();\n return {\n privateKey: bytesToHex(keypair.secretKey),\n publicKey: bytesToHex(keypair.publicKey),\n };\n}\n"],"mappings":"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","names":["data"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zerocore1/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "TypeScript SDK for ZERO.CORE — the Fiduciary Control Plane for AI Agents",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "ZERO.CORE <dev@zerocore.io>",
|
|
@@ -17,7 +17,10 @@
|
|
|
17
17
|
"solana",
|
|
18
18
|
"fintech",
|
|
19
19
|
"usdc",
|
|
20
|
-
"settlement"
|
|
20
|
+
"settlement",
|
|
21
|
+
"did",
|
|
22
|
+
"zero-trust",
|
|
23
|
+
"ed25519"
|
|
21
24
|
],
|
|
22
25
|
"type": "module",
|
|
23
26
|
"main": "./dist/index.cjs",
|
|
@@ -51,5 +54,8 @@
|
|
|
51
54
|
},
|
|
52
55
|
"engines": {
|
|
53
56
|
"node": ">=18.0.0"
|
|
57
|
+
},
|
|
58
|
+
"dependencies": {
|
|
59
|
+
"tweetnacl": "^1.0.3"
|
|
54
60
|
}
|
|
55
61
|
}
|