budgent-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.
@@ -0,0 +1,56 @@
1
+ export interface BudgentConfig {
2
+ baseUrl: string;
3
+ keyId?: string;
4
+ hmacSecret?: string;
5
+ bearer?: string;
6
+ }
7
+ export interface PayInput {
8
+ amount: number;
9
+ domain?: string;
10
+ recipient?: string;
11
+ url?: string;
12
+ resource?: string;
13
+ taskId?: string;
14
+ idempotencyKey?: string;
15
+ metadata?: Record<string, any>;
16
+ model?: 'PUSH' | 'INVOICE';
17
+ }
18
+ export interface PaymentResult {
19
+ id: string;
20
+ status: 'SETTLED' | 'APPROVED' | 'REVERTED' | 'HELD' | 'DENIED' | 'FAILED' | 'CREATED';
21
+ reason: string;
22
+ amount: number;
23
+ asset: string;
24
+ recipient: string;
25
+ context: {
26
+ domain: string;
27
+ url: string;
28
+ resource: string;
29
+ taskId: string;
30
+ };
31
+ contextHash: string;
32
+ signature: string | null;
33
+ explorer: string | null;
34
+ ruleResults?: {
35
+ rule: string;
36
+ status: string;
37
+ detail: string;
38
+ }[];
39
+ }
40
+ /**
41
+ * Budgent agent SDK. The agent pays through explicit REST calls — no x402, no transport
42
+ * games — and the on-chain program enforces the budget. The agent never holds the wallet's
43
+ * keys, only a scoped API key.
44
+ */
45
+ export declare class BudgentClient {
46
+ private cfg;
47
+ constructor(cfg: BudgentConfig);
48
+ private sign;
49
+ private req;
50
+ /** Create + execute a payment (push model). Returns the on-chain verdict. */
51
+ pay(input: PayInput): Promise<PaymentResult>;
52
+ getPayment(id: string): Promise<PaymentResult>;
53
+ /** The agent's own budget snapshot (policy + balance + spend). */
54
+ me(): Promise<any>;
55
+ }
56
+ export default BudgentClient;
package/dist/index.js ADDED
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BudgentClient = void 0;
4
+ const crypto_1 = require("crypto");
5
+ /**
6
+ * Budgent agent SDK. The agent pays through explicit REST calls — no x402, no transport
7
+ * games — and the on-chain program enforces the budget. The agent never holds the wallet's
8
+ * keys, only a scoped API key.
9
+ */
10
+ class BudgentClient {
11
+ constructor(cfg) {
12
+ this.cfg = cfg;
13
+ if (!cfg.baseUrl)
14
+ throw new Error('baseUrl required');
15
+ }
16
+ sign(method, path, body) {
17
+ if (this.cfg.keyId && this.cfg.hmacSecret) {
18
+ const ts = Math.floor(Date.now() / 1000).toString();
19
+ const base = `${ts}.${method}.${path}.${body}`;
20
+ const sig = (0, crypto_1.createHmac)('sha256', this.cfg.hmacSecret).update(base).digest('hex');
21
+ return {
22
+ 'X-Budgent-Key': this.cfg.keyId,
23
+ 'X-Budgent-Timestamp': ts,
24
+ 'X-Budgent-Signature': sig,
25
+ };
26
+ }
27
+ if (this.cfg.bearer)
28
+ return { Authorization: `Bearer ${this.cfg.bearer}` };
29
+ throw new Error('provide keyId+hmacSecret or bearer');
30
+ }
31
+ async req(method, path, payload) {
32
+ const body = payload != null ? JSON.stringify(payload) : '';
33
+ const res = await fetch(this.cfg.baseUrl + path, {
34
+ method,
35
+ headers: { 'Content-Type': 'application/json', ...this.sign(method, path, body) },
36
+ body: method === 'GET' ? undefined : body,
37
+ });
38
+ const text = await res.text();
39
+ const json = text ? JSON.parse(text) : {};
40
+ if (!res.ok)
41
+ throw new Error(`${res.status} ${json.message || text}`);
42
+ return json;
43
+ }
44
+ /** Create + execute a payment (push model). Returns the on-chain verdict. */
45
+ pay(input) {
46
+ return this.req('POST', '/v1/payments', input);
47
+ }
48
+ getPayment(id) {
49
+ return this.req('GET', `/v1/payments/${id}`);
50
+ }
51
+ /** The agent's own budget snapshot (policy + balance + spend). */
52
+ me() {
53
+ return this.req('GET', '/v1/me');
54
+ }
55
+ }
56
+ exports.BudgentClient = BudgentClient;
57
+ exports.default = BudgentClient;
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "budgent-sdk",
3
+ "version": "0.1.0",
4
+ "description": "Budgent agent SDK — pay autonomously through a REST API, bounded by a non-custodial on-chain program (per-tx cap, daily limit, allow/block lists, co-sign).",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "files": [
8
+ "dist",
9
+ "src"
10
+ ],
11
+ "scripts": {
12
+ "build": "tsc -p tsconfig.json",
13
+ "prepublishOnly": "tsc -p tsconfig.json"
14
+ },
15
+ "keywords": [
16
+ "budgent",
17
+ "solana",
18
+ "ai-agents",
19
+ "agents",
20
+ "payments",
21
+ "wallet",
22
+ "x402"
23
+ ],
24
+ "engines": {
25
+ "node": ">=18"
26
+ },
27
+ "devDependencies": {
28
+ "@types/node": "^20.0.0",
29
+ "typescript": "^5.4.0"
30
+ },
31
+ "license": "MIT"
32
+ }
package/src/index.ts ADDED
@@ -0,0 +1,89 @@
1
+ import { createHmac } from 'crypto';
2
+
3
+ export interface BudgentConfig {
4
+ baseUrl: string;
5
+ keyId?: string;
6
+ hmacSecret?: string;
7
+ bearer?: string; // alternative simple auth
8
+ }
9
+
10
+ export interface PayInput {
11
+ amount: number;
12
+ domain?: string; // resolved via the vault's resource registry
13
+ recipient?: string; // or a direct pubkey
14
+ url?: string;
15
+ resource?: string;
16
+ taskId?: string;
17
+ idempotencyKey?: string;
18
+ metadata?: Record<string, any>;
19
+ model?: 'PUSH' | 'INVOICE';
20
+ }
21
+
22
+ export interface PaymentResult {
23
+ id: string;
24
+ status: 'SETTLED' | 'APPROVED' | 'REVERTED' | 'HELD' | 'DENIED' | 'FAILED' | 'CREATED';
25
+ reason: string;
26
+ amount: number;
27
+ asset: string;
28
+ recipient: string;
29
+ context: { domain: string; url: string; resource: string; taskId: string };
30
+ contextHash: string;
31
+ signature: string | null;
32
+ explorer: string | null;
33
+ ruleResults?: { rule: string; status: string; detail: string }[];
34
+ }
35
+
36
+ /**
37
+ * Budgent agent SDK. The agent pays through explicit REST calls — no x402, no transport
38
+ * games — and the on-chain program enforces the budget. The agent never holds the wallet's
39
+ * keys, only a scoped API key.
40
+ */
41
+ export class BudgentClient {
42
+ constructor(private cfg: BudgentConfig) {
43
+ if (!cfg.baseUrl) throw new Error('baseUrl required');
44
+ }
45
+
46
+ private sign(method: string, path: string, body: string): Record<string, string> {
47
+ if (this.cfg.keyId && this.cfg.hmacSecret) {
48
+ const ts = Math.floor(Date.now() / 1000).toString();
49
+ const base = `${ts}.${method}.${path}.${body}`;
50
+ const sig = createHmac('sha256', this.cfg.hmacSecret).update(base).digest('hex');
51
+ return {
52
+ 'X-Budgent-Key': this.cfg.keyId,
53
+ 'X-Budgent-Timestamp': ts,
54
+ 'X-Budgent-Signature': sig,
55
+ };
56
+ }
57
+ if (this.cfg.bearer) return { Authorization: `Bearer ${this.cfg.bearer}` };
58
+ throw new Error('provide keyId+hmacSecret or bearer');
59
+ }
60
+
61
+ private async req(method: string, path: string, payload?: any): Promise<any> {
62
+ const body = payload != null ? JSON.stringify(payload) : '';
63
+ const res = await fetch(this.cfg.baseUrl + path, {
64
+ method,
65
+ headers: { 'Content-Type': 'application/json', ...this.sign(method, path, body) },
66
+ body: method === 'GET' ? undefined : body,
67
+ });
68
+ const text = await res.text();
69
+ const json = text ? JSON.parse(text) : {};
70
+ if (!res.ok) throw new Error(`${res.status} ${json.message || text}`);
71
+ return json;
72
+ }
73
+
74
+ /** Create + execute a payment (push model). Returns the on-chain verdict. */
75
+ pay(input: PayInput): Promise<PaymentResult> {
76
+ return this.req('POST', '/v1/payments', input);
77
+ }
78
+
79
+ getPayment(id: string): Promise<PaymentResult> {
80
+ return this.req('GET', `/v1/payments/${id}`);
81
+ }
82
+
83
+ /** The agent's own budget snapshot (policy + balance + spend). */
84
+ me(): Promise<any> {
85
+ return this.req('GET', '/v1/me');
86
+ }
87
+ }
88
+
89
+ export default BudgentClient;