@leashmarket/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 ADDED
@@ -0,0 +1,125 @@
1
+ # @leashmarket/sdk
2
+
3
+ Typed TypeScript client for the public Leash API. Use it from any
4
+ JavaScript runtime — browsers, Bun, Deno, Node, edge — to:
5
+
6
+ - Search the agent marketplace (`leash.discover`)
7
+ - Vet a counterparty's reputation (`leash.reputation`)
8
+ - Record a client-minted agent on the platform (`leash.recordAgent`)
9
+ - Manage agent-scoped webhooks signed with X-Leash-Sig
10
+ - Pull receipts for an agent (legacy API-key auth)
11
+ - Create + manage payment links (legacy API-key auth)
12
+
13
+ > Provisioning agents (generating keypairs, minting MPL Core assets,
14
+ > setting USDC delegation) is **not** in the SDK — use
15
+ > [`@leashmarket/mcp`](../mcp/README.md) (`mintAgentLocally()`) or the
16
+ > `leash agent create` CLI for that. The SDK is for "remote control"
17
+ > of agents that already exist; the MCP is the engine that creates
18
+ > them.
19
+
20
+ ## Install
21
+
22
+ ```bash
23
+ pnpm add @leashmarket/sdk
24
+ # or
25
+ npm install @leashmarket/sdk
26
+ ```
27
+
28
+ ## Quickstart
29
+
30
+ ```ts
31
+ import { LeashClient } from '@leashmarket/sdk';
32
+
33
+ const leash = new LeashClient({ baseUrl: 'https://api.leash.market' });
34
+
35
+ // 1. Marketplace browse — public, no auth.
36
+ const services = await leash.discover({ capability: 'ocr', max_price_usdc: 0.1 });
37
+
38
+ // 2. Reputation lookup before paying — public, no auth.
39
+ const rep = await leash.reputation({
40
+ agentMint: services.items[0].seller_agent_mint!,
41
+ });
42
+ if (rep.rating < 0.5) throw new Error('seller has too low a rating');
43
+
44
+ // 3. Record a client-minted agent — public, no auth (idempotent on
45
+ // `mint`). Mint + delegate the asset locally with `@leashmarket/mcp`'s
46
+ // `mintAgentLocally` first, then hand the result here.
47
+ const recorded = await leash.recordAgent({
48
+ mint: 'BcN4ToBs8jE3dbYNhYqDJqGnKPjH3zRX8gsDUDH72JQp',
49
+ executive_pubkey: '947dU4Nk8HsdkFcrVip5Zt9XLnfFF5iJSvepEArdr5Ma',
50
+ name: 'my-experimental-bot',
51
+ network: 'solana-devnet',
52
+ });
53
+ console.log('recorded', recorded.mint, 'treasury', recorded.treasury);
54
+ ```
55
+
56
+ ## Authenticated calls
57
+
58
+ The webhook endpoints are agent-scoped — they verify a
59
+ `X-Leash-Sig` header signed with the agent's executive ed25519
60
+ keypair. Pass the keypair and mint to the constructor; the SDK
61
+ stamps a fresh signature per request.
62
+
63
+ ```ts
64
+ import { LeashClient } from '@leashmarket/sdk';
65
+
66
+ const leash = new LeashClient({
67
+ agentMint: 'AjfeyP...',
68
+ executiveSecretBase58: process.env.LEASH_EXECUTIVE_KEY!,
69
+ });
70
+
71
+ const sub = await leash.createWebhook({
72
+ url: 'https://my-app.example/leash-webhook',
73
+ events: ['receipt.published', 'agent.treasury.withdraw'],
74
+ });
75
+ console.log('SAVE THIS SECRET:', sub.secret); // returned ONCE.
76
+
77
+ const subs = await leash.listWebhooks();
78
+ await leash.deleteWebhook(sub.id);
79
+ ```
80
+
81
+ ## Reputation cheat sheet
82
+
83
+ `reputation.rating` is a normalised score in `[0, 1]`:
84
+
85
+ ```text
86
+ rating = (1 - dispute_rate) * weight
87
+ weight = min(1, log10(settled_calls + 1) / 3)
88
+ ```
89
+
90
+ - A new agent with `settled_calls: 0` has `rating: 0` regardless of
91
+ dispute rate. That's intentional — you don't have data yet.
92
+ - An established agent with no disputes saturates at `1.0` around
93
+ ~1000 settled calls.
94
+ - `dispute_rate = denied_calls / (settled_calls + denied_calls)`.
95
+
96
+ ## Errors
97
+
98
+ Network / non-2xx responses throw `LeashError`:
99
+
100
+ ```ts
101
+ import { LeashError } from '@leashmarket/sdk';
102
+
103
+ try {
104
+ await leash.discover();
105
+ } catch (err) {
106
+ if (err instanceof LeashError) {
107
+ console.log('status:', err.status, 'body:', err.body);
108
+ }
109
+ }
110
+ ```
111
+
112
+ ## OpenAPI
113
+
114
+ The full set of endpoints is documented at
115
+ `https://api.leash.market/openapi.json`. The SDK is hand-rolled
116
+ against that surface so the runtime stays dep-free; type drift is
117
+ caught by integration tests.
118
+
119
+ ## Develop
120
+
121
+ ```bash
122
+ pnpm --filter @leashmarket/sdk typecheck
123
+ pnpm --filter @leashmarket/sdk test
124
+ pnpm --filter @leashmarket/sdk build
125
+ ```
@@ -0,0 +1,167 @@
1
+ /**
2
+ * `LeashClient` — typed wrapper over the public Leash API.
3
+ *
4
+ * Two modes of authentication:
5
+ *
6
+ * 1. **Anonymous** — `new LeashClient({ baseUrl })`. Public reads
7
+ * (`discover`, `reputation`) work without credentials.
8
+ *
9
+ * 2. **Agent-signed** — pass `{ agentMint, executiveSecretBase58 }`.
10
+ * Authenticated calls (e.g. webhook management) get a fresh
11
+ * `X-Leash-Sig` header per request, signed with the executive
12
+ * keypair.
13
+ *
14
+ * 3. **Legacy API key** — pass `{ apiKey }`. Used until every
15
+ * endpoint accepts X-Leash-Sig; today this is what the chat
16
+ * product issues per user.
17
+ *
18
+ * Each method returns parsed JSON typed against `./types.ts`.
19
+ * Network failures throw `LeashError` so callers can branch on the
20
+ * `status` and `body` properties.
21
+ */
22
+ import type { AgentWebhook, AgentWebhookWithSecret, DailyTransactionsResponse, DiscoverResponse, PaymentLink, PaymentLinkCreateInput, PaymentLinkPatchInput, PaymentLinksListResponse, PaySkillsProvider, Receipt, RecordAgentInput, RecordAgentResponse, ReceiptsResponse, ReputationSnapshot, SvmNetwork, TransactionHistoryResponse } from './types.js';
23
+ export type LeashClientOptions = {
24
+ baseUrl?: string;
25
+ /**
26
+ * Optional agent-signed auth bundle. When set, the client signs
27
+ * every request that targets `/v1/agents/{mint}/...` with the
28
+ * executive keypair (X-Leash-Sig). Public reads stay unsigned.
29
+ */
30
+ agentMint?: string;
31
+ executiveSecretBase58?: string;
32
+ /**
33
+ * Legacy bearer-token auth. Used for endpoints that haven't
34
+ * migrated to X-Leash-Sig yet (e.g. /v1/payment-links).
35
+ */
36
+ apiKey?: string;
37
+ /** Hook for tests. Defaults to the global `fetch`. */
38
+ fetchImpl?: typeof globalThis.fetch;
39
+ };
40
+ export declare class LeashError extends Error {
41
+ readonly status: number;
42
+ readonly body: unknown;
43
+ constructor(status: number, message: string, body: unknown);
44
+ }
45
+ export declare class LeashClient {
46
+ readonly baseUrl: string;
47
+ private readonly agentMint?;
48
+ private readonly executiveSecretBase58?;
49
+ private readonly apiKey?;
50
+ private readonly fetchImpl;
51
+ constructor(opts?: LeashClientOptions);
52
+ discover(query?: {
53
+ capability?: string;
54
+ max_price_usdc?: number;
55
+ pricing_type?: 'free' | 'per_call' | 'variable';
56
+ /**
57
+ * Restrict to a single catalogue:
58
+ * - `'leash'`: agents on the Leash marketplace.
59
+ * - `'pay-skills'`: providers in the Solana Foundation
60
+ * `pay-skills` registry.
61
+ * - `'all'` (default): merged.
62
+ */
63
+ source?: 'leash' | 'pay-skills' | 'all';
64
+ limit?: number;
65
+ }): Promise<DiscoverResponse>;
66
+ /**
67
+ * Expand a `pay-skills` provider into its endpoint list.
68
+ *
69
+ * Use after {@link discover}: an item with `source === 'pay-skills'`
70
+ * carries an `slug` equal to the provider FQN
71
+ * (e.g. `agentmail/email`). Pass that here to get the absolute
72
+ * endpoint URLs, methods, pricing, and supported stablecoins so the
73
+ * agent can hand a URL to `buyer.fetch()` or `host.pay()`.
74
+ *
75
+ * Mirrors `pay skills endpoints <fqn>` from the pay.sh CLI.
76
+ */
77
+ paySkillsProvider(fqn: string): Promise<PaySkillsProvider>;
78
+ reputation(args: {
79
+ agentMint: string;
80
+ network?: SvmNetwork;
81
+ }): Promise<ReputationSnapshot>;
82
+ recordAgent(input: RecordAgentInput): Promise<RecordAgentResponse>;
83
+ receipts(args: {
84
+ agentMint: string;
85
+ direction?: 'spend' | 'earn';
86
+ limit?: number;
87
+ }): Promise<ReceiptsResponse>;
88
+ /**
89
+ * `GET /v1/receipts/by-hash/{hash}` — direct lookup of a single
90
+ * receipt by its deterministic `receipt_hash`. Network is bound to
91
+ * the API key prefix; cross-network hashes return 404.
92
+ *
93
+ * The response is the same row shape `receipts()` emits, with the
94
+ * full canonical ReceiptV1 in `raw`.
95
+ */
96
+ getReceipt(hash: string): Promise<Receipt>;
97
+ /**
98
+ * Walk the paginated `/v1/receipts/{agent}` feed and return every
99
+ * receipt within the rolling `now - days` window. Stops early when
100
+ * `limit` is hit (default 200, max 1000) or when a row falls out of
101
+ * the window. Mirrors the `leash_transaction_history` MCP tool.
102
+ *
103
+ * Stables (USDC/USDG/USDT) are summed as USD 1:1 in the returned
104
+ * totals; non-stable receipts get counted but excluded from the USD
105
+ * math (`non_usd_count`).
106
+ */
107
+ transactionHistory(args: {
108
+ agentMint: string;
109
+ days?: number;
110
+ direction?: 'both' | 'outgoing' | 'incoming';
111
+ limit?: number;
112
+ }): Promise<TransactionHistoryResponse>;
113
+ /**
114
+ * Same window as {@link transactionHistory} but folds the receipts
115
+ * into per-day buckets keyed on UTC ingest date. Days with no
116
+ * activity are emitted with zeros so the timeline is continuous.
117
+ * Mirrors the `leash_daily_transactions` MCP tool.
118
+ */
119
+ dailyTransactions(args: {
120
+ agentMint: string;
121
+ days?: number;
122
+ }): Promise<DailyTransactionsResponse>;
123
+ /**
124
+ * Walk the agent's receipts feed newest-first and stop once a row
125
+ * falls before `cutoffMs`, the cap is hit, or the feed is
126
+ * exhausted. Used by {@link transactionHistory} +
127
+ * {@link dailyTransactions}.
128
+ */
129
+ private fetchReceiptWindow;
130
+ /**
131
+ * `POST /v1/agents/{mint}/webhooks` — subscribe the active agent.
132
+ * Returns the secret ONCE; persist it now or you'll have to upsert
133
+ * to rotate. Called transparently with X-Leash-Sig auth.
134
+ */
135
+ createWebhook(args: {
136
+ url: string;
137
+ events?: string[];
138
+ }): Promise<AgentWebhookWithSecret>;
139
+ listWebhooks(): Promise<{
140
+ items: AgentWebhook[];
141
+ }>;
142
+ deleteWebhook(id: string): Promise<{
143
+ ok: true;
144
+ }>;
145
+ createPaymentLink(input: PaymentLinkCreateInput): Promise<PaymentLink>;
146
+ listPaymentLinks(query?: {
147
+ ownerAgent?: string;
148
+ includeDisabled?: boolean;
149
+ cursor?: string;
150
+ limit?: number;
151
+ }): Promise<PaymentLinksListResponse>;
152
+ getPaymentLink(id: string): Promise<PaymentLink>;
153
+ updatePaymentLink(id: string, patch: PaymentLinkPatchInput): Promise<PaymentLink>;
154
+ deletePaymentLink(id: string): Promise<{
155
+ ok: true;
156
+ }>;
157
+ private requireApiKey;
158
+ private requireAgentAuth;
159
+ /**
160
+ * Fire one HTTP request, signing it with X-Leash-Sig when the
161
+ * caller provided an agent identity AND the path is one of the
162
+ * agent-scoped endpoints. Public/legacy paths skip signing and
163
+ * fall back to the API-key bearer if available.
164
+ */
165
+ private requestJson;
166
+ }
167
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}