tether-name 1.0.5 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +48 -30
- package/dist/index.d.mts +32 -11
- package/dist/index.d.ts +32 -11
- package/dist/index.js +50 -15
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +50 -15
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -16,8 +16,8 @@ Requires Node.js 20+ (uses native `fetch` and `crypto` modules).
|
|
|
16
16
|
import { TetherClient } from 'tether-name';
|
|
17
17
|
|
|
18
18
|
const client = new TetherClient({
|
|
19
|
-
|
|
20
|
-
privateKeyPath: '/path/to/your/private-key.
|
|
19
|
+
agentId: 'your-agent-id',
|
|
20
|
+
privateKeyPath: '/path/to/your/private-key.pem'
|
|
21
21
|
});
|
|
22
22
|
|
|
23
23
|
// One-call verification
|
|
@@ -35,7 +35,7 @@ For more control over the verification process:
|
|
|
35
35
|
import { TetherClient } from 'tether-name';
|
|
36
36
|
|
|
37
37
|
const client = new TetherClient({
|
|
38
|
-
|
|
38
|
+
agentId: 'your-agent-id',
|
|
39
39
|
privateKeyPem: `-----BEGIN RSA PRIVATE KEY-----
|
|
40
40
|
MIIEpAIBAAKCAQEA...
|
|
41
41
|
-----END RSA PRIVATE KEY-----`
|
|
@@ -71,8 +71,8 @@ interface TetherClientConfig {
|
|
|
71
71
|
// API key (for agent management — no private key needed)
|
|
72
72
|
apiKey?: string; // Or use TETHER_API_KEY env var
|
|
73
73
|
|
|
74
|
-
//
|
|
75
|
-
|
|
74
|
+
// Agent ID (required for verify/sign, optional with apiKey)
|
|
75
|
+
agentId?: string; // Or use TETHER_AGENT_ID env var
|
|
76
76
|
|
|
77
77
|
// Private key (required for verify/sign, choose one)
|
|
78
78
|
privateKeyPath?: string; // Path to DER or PEM file
|
|
@@ -95,46 +95,46 @@ const client = new TetherClient({
|
|
|
95
95
|
const agent = await client.createAgent('my-bot');
|
|
96
96
|
```
|
|
97
97
|
|
|
98
|
-
**API key +
|
|
98
|
+
**API key + agent + private key** — full access (management and verification):
|
|
99
99
|
|
|
100
100
|
```typescript
|
|
101
101
|
const client = new TetherClient({
|
|
102
102
|
apiKey: 'sk-tether-name-...',
|
|
103
|
-
|
|
104
|
-
privateKeyPath: '/path/to/key.
|
|
103
|
+
agentId: 'your-agent-id',
|
|
104
|
+
privateKeyPath: '/path/to/key.pem'
|
|
105
105
|
});
|
|
106
106
|
```
|
|
107
107
|
|
|
108
|
-
**
|
|
108
|
+
**Agent + private key only** — verification without agent management (original behavior):
|
|
109
109
|
|
|
110
110
|
```typescript
|
|
111
111
|
const client = new TetherClient({
|
|
112
|
-
|
|
113
|
-
privateKeyPath: '/path/to/key.
|
|
112
|
+
agentId: 'your-agent-id',
|
|
113
|
+
privateKeyPath: '/path/to/key.pem'
|
|
114
114
|
});
|
|
115
115
|
```
|
|
116
116
|
|
|
117
117
|
### Key Format Support
|
|
118
118
|
|
|
119
|
-
The SDK supports both
|
|
119
|
+
The SDK supports both PEM and DER private key formats:
|
|
120
120
|
|
|
121
121
|
```typescript
|
|
122
122
|
// From file path (auto-detects format)
|
|
123
123
|
const client1 = new TetherClient({
|
|
124
|
-
|
|
125
|
-
privateKeyPath: '/path/to/key.
|
|
124
|
+
agentId: 'your-id',
|
|
125
|
+
privateKeyPath: '/path/to/key.pem' // or .der
|
|
126
126
|
});
|
|
127
127
|
|
|
128
128
|
// From PEM string
|
|
129
129
|
const client2 = new TetherClient({
|
|
130
|
-
|
|
130
|
+
agentId: 'your-id',
|
|
131
131
|
privateKeyPem: '-----BEGIN RSA PRIVATE KEY-----\n...'
|
|
132
132
|
});
|
|
133
133
|
|
|
134
134
|
// From DER buffer
|
|
135
135
|
const derBuffer = fs.readFileSync('/path/to/key.der');
|
|
136
136
|
const client3 = new TetherClient({
|
|
137
|
-
|
|
137
|
+
agentId: 'your-id',
|
|
138
138
|
privateKeyBuffer: derBuffer
|
|
139
139
|
});
|
|
140
140
|
```
|
|
@@ -147,26 +147,29 @@ Create and manage agents programmatically with an API key:
|
|
|
147
147
|
const client = new TetherClient({ apiKey: 'sk-tether-name-...' });
|
|
148
148
|
|
|
149
149
|
// Create an agent
|
|
150
|
-
const agent = await client.createAgent('my-bot', 'Does helpful things');
|
|
150
|
+
const agent = await client.createAgent('my-bot', 'Does helpful things', 'verified-domain-id');
|
|
151
151
|
console.log(agent.id); // "abc123"
|
|
152
152
|
console.log(agent.agentName); // "my-bot"
|
|
153
|
-
console.log(agent.registrationToken); // Use to register
|
|
153
|
+
console.log(agent.registrationToken); // Use to register the agent
|
|
154
154
|
|
|
155
155
|
// List all agents
|
|
156
156
|
const agents = await client.listAgents();
|
|
157
157
|
|
|
158
|
+
// List registered domains
|
|
159
|
+
const domains = await client.listDomains();
|
|
160
|
+
|
|
158
161
|
// Delete an agent
|
|
159
162
|
await client.deleteAgent(agent.id);
|
|
160
163
|
```
|
|
161
164
|
|
|
162
165
|
## Environment Variables
|
|
163
166
|
|
|
164
|
-
Set these environment variables to avoid hardcoding
|
|
167
|
+
Set these environment variables to avoid hardcoding secrets:
|
|
165
168
|
|
|
166
169
|
```bash
|
|
167
170
|
export TETHER_API_KEY="sk-tether-name-..." # API key for agent management
|
|
168
|
-
export
|
|
169
|
-
export TETHER_PRIVATE_KEY_PATH="/path/to/your/private-key.
|
|
171
|
+
export TETHER_AGENT_ID="your-agent-id"
|
|
172
|
+
export TETHER_PRIVATE_KEY_PATH="/path/to/your/private-key.pem"
|
|
170
173
|
```
|
|
171
174
|
|
|
172
175
|
Then initialize without parameters:
|
|
@@ -205,14 +208,18 @@ Signs a challenge using the configured private key.
|
|
|
205
208
|
|
|
206
209
|
Submits signed proof to verify the challenge.
|
|
207
210
|
|
|
208
|
-
#### `async createAgent(agentName: string, description?: string): Promise<Agent>`
|
|
211
|
+
#### `async createAgent(agentName: string, description?: string, domainId?: string): Promise<Agent>`
|
|
209
212
|
|
|
210
|
-
Creates a new agent. Requires API key authentication.
|
|
213
|
+
Creates a new agent. Requires API key authentication. `domainId` is optional and links this agent to a verified domain.
|
|
211
214
|
|
|
212
215
|
#### `async listAgents(): Promise<Agent[]>`
|
|
213
216
|
|
|
214
217
|
Lists all agents for the authenticated account. Requires API key authentication.
|
|
215
218
|
|
|
219
|
+
#### `async listDomains(): Promise<Domain[]>`
|
|
220
|
+
|
|
221
|
+
Lists all registered domains for the authenticated account. Requires API key authentication.
|
|
222
|
+
|
|
216
223
|
#### `async deleteAgent(agentId: string): Promise<boolean>`
|
|
217
224
|
|
|
218
225
|
Deletes an agent by ID. Requires API key authentication. Returns `true` on success.
|
|
@@ -225,6 +232,7 @@ interface VerificationResult {
|
|
|
225
232
|
agentName?: string; // Registered agent name
|
|
226
233
|
verifyUrl?: string; // Public verification URL
|
|
227
234
|
email?: string; // Registered email
|
|
235
|
+
domain?: string; // Verified domain (if assigned)
|
|
228
236
|
registeredSince?: string; // ISO date of registration
|
|
229
237
|
error?: string; // Error message if failed
|
|
230
238
|
challenge?: string; // The verified challenge
|
|
@@ -236,30 +244,40 @@ interface Agent {
|
|
|
236
244
|
id: string; // Unique agent ID
|
|
237
245
|
agentName: string; // Agent display name
|
|
238
246
|
description: string; // Agent description
|
|
247
|
+
domainId?: string; // Optional assigned domain ID
|
|
248
|
+
domain?: string | null; // Resolved assigned domain name
|
|
239
249
|
createdAt: number; // Creation time (epoch ms)
|
|
240
250
|
registrationToken?: string; // Token for key registration (returned on create)
|
|
241
251
|
lastVerifiedAt?: number; // Last verification time (epoch ms)
|
|
242
252
|
}
|
|
243
253
|
```
|
|
244
254
|
|
|
255
|
+
```typescript
|
|
256
|
+
interface Domain {
|
|
257
|
+
id: string;
|
|
258
|
+
domain: string;
|
|
259
|
+
verified: boolean;
|
|
260
|
+
verifiedAt: number;
|
|
261
|
+
lastCheckedAt: number;
|
|
262
|
+
createdAt: number;
|
|
263
|
+
}
|
|
264
|
+
```
|
|
265
|
+
|
|
245
266
|
### Errors
|
|
246
267
|
|
|
247
268
|
- `TetherError` - Base error class
|
|
248
269
|
- `TetherVerificationError` - Verification failed
|
|
249
270
|
- `TetherAPIError` - API request failed
|
|
250
271
|
|
|
251
|
-
## Getting Your
|
|
272
|
+
## Getting Your Agent Identity
|
|
252
273
|
|
|
253
274
|
1. Visit [tether.name](https://tether.name)
|
|
254
|
-
2. Register your agent and get
|
|
275
|
+
2. Register your agent and get an agent ID
|
|
255
276
|
3. Generate an RSA-2048 private key:
|
|
256
277
|
|
|
257
278
|
```bash
|
|
258
|
-
# Generate private key
|
|
259
|
-
openssl
|
|
260
|
-
|
|
261
|
-
# Convert to DER format (optional)
|
|
262
|
-
openssl rsa -in private-key.pem -outform DER -out private-key.der
|
|
279
|
+
# Generate private key (PEM format)
|
|
280
|
+
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out private-key.pem
|
|
263
281
|
```
|
|
264
282
|
|
|
265
283
|
## Requirements
|
package/dist/index.d.mts
CHANGED
|
@@ -4,15 +4,15 @@ import { KeyObject } from 'crypto';
|
|
|
4
4
|
* Configuration options for TetherClient
|
|
5
5
|
*/
|
|
6
6
|
interface TetherClientConfig {
|
|
7
|
-
/** The
|
|
8
|
-
|
|
7
|
+
/** The agent ID */
|
|
8
|
+
agentId?: string;
|
|
9
9
|
/** Path to the private key file (DER or PEM format) */
|
|
10
10
|
privateKeyPath?: string;
|
|
11
11
|
/** Private key as a string (PEM format) */
|
|
12
12
|
privateKeyPem?: string;
|
|
13
13
|
/** Private key as a Buffer (DER format) */
|
|
14
14
|
privateKeyBuffer?: Buffer;
|
|
15
|
-
/** API key for management operations (alternative to
|
|
15
|
+
/** API key for management operations (alternative to agent auth) */
|
|
16
16
|
apiKey?: string;
|
|
17
17
|
}
|
|
18
18
|
/**
|
|
@@ -27,7 +27,7 @@ interface ChallengeResponse {
|
|
|
27
27
|
interface VerificationRequest {
|
|
28
28
|
challenge: string;
|
|
29
29
|
proof: string;
|
|
30
|
-
|
|
30
|
+
agentId: string;
|
|
31
31
|
}
|
|
32
32
|
/**
|
|
33
33
|
* Response from the challenge verification endpoint
|
|
@@ -37,6 +37,7 @@ interface VerificationResponse {
|
|
|
37
37
|
verifyUrl?: string;
|
|
38
38
|
agentName?: string;
|
|
39
39
|
email?: string;
|
|
40
|
+
domain?: string;
|
|
40
41
|
/** Raw API value (epoch ms from service; older services may return ISO strings) */
|
|
41
42
|
registeredSince?: number | string;
|
|
42
43
|
error?: string;
|
|
@@ -53,6 +54,8 @@ interface VerificationResult {
|
|
|
53
54
|
verifyUrl?: string;
|
|
54
55
|
/** The agent's registered email */
|
|
55
56
|
email?: string;
|
|
57
|
+
/** Verified domain (if this agent has a domain assigned) */
|
|
58
|
+
domain?: string;
|
|
56
59
|
/** ISO date string of when the agent was registered */
|
|
57
60
|
registeredSince?: string;
|
|
58
61
|
/** Error message if verification failed */
|
|
@@ -71,17 +74,31 @@ interface Agent {
|
|
|
71
74
|
id: string;
|
|
72
75
|
agentName: string;
|
|
73
76
|
description: string;
|
|
77
|
+
domainId?: string;
|
|
78
|
+
domain?: string | null;
|
|
74
79
|
createdAt: number;
|
|
75
80
|
registrationToken?: string;
|
|
76
81
|
lastVerifiedAt?: number;
|
|
77
82
|
}
|
|
78
83
|
/**
|
|
79
|
-
*
|
|
84
|
+
* A domain registered to the authenticated account
|
|
80
85
|
*/
|
|
81
|
-
interface
|
|
86
|
+
interface Domain {
|
|
87
|
+
id: string;
|
|
88
|
+
domain: string;
|
|
89
|
+
verified: boolean;
|
|
90
|
+
verifiedAt: number;
|
|
91
|
+
lastCheckedAt: number;
|
|
92
|
+
createdAt: number;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Response from the issue agent endpoint
|
|
96
|
+
*/
|
|
97
|
+
interface IssueAgentResponse {
|
|
82
98
|
id: string;
|
|
83
99
|
agentName: string;
|
|
84
100
|
description: string;
|
|
101
|
+
domainId?: string;
|
|
85
102
|
createdAt: number;
|
|
86
103
|
registrationToken: string;
|
|
87
104
|
}
|
|
@@ -90,7 +107,7 @@ interface IssueCredentialResponse {
|
|
|
90
107
|
* TetherClient - Official SDK for tether.name agent identity verification
|
|
91
108
|
*/
|
|
92
109
|
declare class TetherClient {
|
|
93
|
-
private readonly
|
|
110
|
+
private readonly agentId;
|
|
94
111
|
private readonly privateKey;
|
|
95
112
|
private readonly baseUrl;
|
|
96
113
|
private readonly apiKey?;
|
|
@@ -108,9 +125,9 @@ declare class TetherClient {
|
|
|
108
125
|
*/
|
|
109
126
|
private _requireApiKey;
|
|
110
127
|
/**
|
|
111
|
-
* Ensures
|
|
128
|
+
* Ensures an agent ID is available, throwing if not
|
|
112
129
|
*/
|
|
113
|
-
private
|
|
130
|
+
private _requireAgentId;
|
|
114
131
|
/**
|
|
115
132
|
* Request a challenge from the Tether API
|
|
116
133
|
*/
|
|
@@ -130,11 +147,15 @@ declare class TetherClient {
|
|
|
130
147
|
/**
|
|
131
148
|
* Create a new agent
|
|
132
149
|
*/
|
|
133
|
-
createAgent(agentName: string, description?: string): Promise<Agent>;
|
|
150
|
+
createAgent(agentName: string, description?: string, domainId?: string): Promise<Agent>;
|
|
134
151
|
/**
|
|
135
152
|
* List all agents
|
|
136
153
|
*/
|
|
137
154
|
listAgents(): Promise<Agent[]>;
|
|
155
|
+
/**
|
|
156
|
+
* List all registered domains
|
|
157
|
+
*/
|
|
158
|
+
listDomains(): Promise<Domain[]>;
|
|
138
159
|
/**
|
|
139
160
|
* Delete an agent by ID
|
|
140
161
|
*/
|
|
@@ -181,4 +202,4 @@ declare function signChallenge(privateKey: KeyObject, challenge: string): string
|
|
|
181
202
|
*/
|
|
182
203
|
declare function detectKeyFormat(keyPath: string): KeyFormat;
|
|
183
204
|
|
|
184
|
-
export { type Agent, type ChallengeResponse, type
|
|
205
|
+
export { type Agent, type ChallengeResponse, type Domain, type IssueAgentResponse, type KeyFormat, TetherAPIError, TetherClient, type TetherClientConfig, TetherError, TetherVerificationError, type VerificationRequest, type VerificationResponse, type VerificationResult, detectKeyFormat, loadPrivateKey, signChallenge };
|
package/dist/index.d.ts
CHANGED
|
@@ -4,15 +4,15 @@ import { KeyObject } from 'crypto';
|
|
|
4
4
|
* Configuration options for TetherClient
|
|
5
5
|
*/
|
|
6
6
|
interface TetherClientConfig {
|
|
7
|
-
/** The
|
|
8
|
-
|
|
7
|
+
/** The agent ID */
|
|
8
|
+
agentId?: string;
|
|
9
9
|
/** Path to the private key file (DER or PEM format) */
|
|
10
10
|
privateKeyPath?: string;
|
|
11
11
|
/** Private key as a string (PEM format) */
|
|
12
12
|
privateKeyPem?: string;
|
|
13
13
|
/** Private key as a Buffer (DER format) */
|
|
14
14
|
privateKeyBuffer?: Buffer;
|
|
15
|
-
/** API key for management operations (alternative to
|
|
15
|
+
/** API key for management operations (alternative to agent auth) */
|
|
16
16
|
apiKey?: string;
|
|
17
17
|
}
|
|
18
18
|
/**
|
|
@@ -27,7 +27,7 @@ interface ChallengeResponse {
|
|
|
27
27
|
interface VerificationRequest {
|
|
28
28
|
challenge: string;
|
|
29
29
|
proof: string;
|
|
30
|
-
|
|
30
|
+
agentId: string;
|
|
31
31
|
}
|
|
32
32
|
/**
|
|
33
33
|
* Response from the challenge verification endpoint
|
|
@@ -37,6 +37,7 @@ interface VerificationResponse {
|
|
|
37
37
|
verifyUrl?: string;
|
|
38
38
|
agentName?: string;
|
|
39
39
|
email?: string;
|
|
40
|
+
domain?: string;
|
|
40
41
|
/** Raw API value (epoch ms from service; older services may return ISO strings) */
|
|
41
42
|
registeredSince?: number | string;
|
|
42
43
|
error?: string;
|
|
@@ -53,6 +54,8 @@ interface VerificationResult {
|
|
|
53
54
|
verifyUrl?: string;
|
|
54
55
|
/** The agent's registered email */
|
|
55
56
|
email?: string;
|
|
57
|
+
/** Verified domain (if this agent has a domain assigned) */
|
|
58
|
+
domain?: string;
|
|
56
59
|
/** ISO date string of when the agent was registered */
|
|
57
60
|
registeredSince?: string;
|
|
58
61
|
/** Error message if verification failed */
|
|
@@ -71,17 +74,31 @@ interface Agent {
|
|
|
71
74
|
id: string;
|
|
72
75
|
agentName: string;
|
|
73
76
|
description: string;
|
|
77
|
+
domainId?: string;
|
|
78
|
+
domain?: string | null;
|
|
74
79
|
createdAt: number;
|
|
75
80
|
registrationToken?: string;
|
|
76
81
|
lastVerifiedAt?: number;
|
|
77
82
|
}
|
|
78
83
|
/**
|
|
79
|
-
*
|
|
84
|
+
* A domain registered to the authenticated account
|
|
80
85
|
*/
|
|
81
|
-
interface
|
|
86
|
+
interface Domain {
|
|
87
|
+
id: string;
|
|
88
|
+
domain: string;
|
|
89
|
+
verified: boolean;
|
|
90
|
+
verifiedAt: number;
|
|
91
|
+
lastCheckedAt: number;
|
|
92
|
+
createdAt: number;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Response from the issue agent endpoint
|
|
96
|
+
*/
|
|
97
|
+
interface IssueAgentResponse {
|
|
82
98
|
id: string;
|
|
83
99
|
agentName: string;
|
|
84
100
|
description: string;
|
|
101
|
+
domainId?: string;
|
|
85
102
|
createdAt: number;
|
|
86
103
|
registrationToken: string;
|
|
87
104
|
}
|
|
@@ -90,7 +107,7 @@ interface IssueCredentialResponse {
|
|
|
90
107
|
* TetherClient - Official SDK for tether.name agent identity verification
|
|
91
108
|
*/
|
|
92
109
|
declare class TetherClient {
|
|
93
|
-
private readonly
|
|
110
|
+
private readonly agentId;
|
|
94
111
|
private readonly privateKey;
|
|
95
112
|
private readonly baseUrl;
|
|
96
113
|
private readonly apiKey?;
|
|
@@ -108,9 +125,9 @@ declare class TetherClient {
|
|
|
108
125
|
*/
|
|
109
126
|
private _requireApiKey;
|
|
110
127
|
/**
|
|
111
|
-
* Ensures
|
|
128
|
+
* Ensures an agent ID is available, throwing if not
|
|
112
129
|
*/
|
|
113
|
-
private
|
|
130
|
+
private _requireAgentId;
|
|
114
131
|
/**
|
|
115
132
|
* Request a challenge from the Tether API
|
|
116
133
|
*/
|
|
@@ -130,11 +147,15 @@ declare class TetherClient {
|
|
|
130
147
|
/**
|
|
131
148
|
* Create a new agent
|
|
132
149
|
*/
|
|
133
|
-
createAgent(agentName: string, description?: string): Promise<Agent>;
|
|
150
|
+
createAgent(agentName: string, description?: string, domainId?: string): Promise<Agent>;
|
|
134
151
|
/**
|
|
135
152
|
* List all agents
|
|
136
153
|
*/
|
|
137
154
|
listAgents(): Promise<Agent[]>;
|
|
155
|
+
/**
|
|
156
|
+
* List all registered domains
|
|
157
|
+
*/
|
|
158
|
+
listDomains(): Promise<Domain[]>;
|
|
138
159
|
/**
|
|
139
160
|
* Delete an agent by ID
|
|
140
161
|
*/
|
|
@@ -181,4 +202,4 @@ declare function signChallenge(privateKey: KeyObject, challenge: string): string
|
|
|
181
202
|
*/
|
|
182
203
|
declare function detectKeyFormat(keyPath: string): KeyFormat;
|
|
183
204
|
|
|
184
|
-
export { type Agent, type ChallengeResponse, type
|
|
205
|
+
export { type Agent, type ChallengeResponse, type Domain, type IssueAgentResponse, type KeyFormat, TetherAPIError, TetherClient, type TetherClientConfig, TetherError, TetherVerificationError, type VerificationRequest, type VerificationResponse, type VerificationResult, detectKeyFormat, loadPrivateKey, signChallenge };
|
package/dist/index.js
CHANGED
|
@@ -133,14 +133,14 @@ function detectKeyFormat(keyPath) {
|
|
|
133
133
|
|
|
134
134
|
// src/client.ts
|
|
135
135
|
var TetherClient = class {
|
|
136
|
-
|
|
136
|
+
agentId;
|
|
137
137
|
privateKey;
|
|
138
138
|
baseUrl;
|
|
139
139
|
apiKey;
|
|
140
140
|
constructor(config) {
|
|
141
141
|
this.baseUrl = "https://api.tether.name";
|
|
142
142
|
this.apiKey = config.apiKey || process.env.TETHER_API_KEY;
|
|
143
|
-
this.
|
|
143
|
+
this.agentId = config.agentId || process.env.TETHER_AGENT_ID || "";
|
|
144
144
|
const keyPath = config.privateKeyPath || process.env.TETHER_PRIVATE_KEY_PATH;
|
|
145
145
|
const hasKeyMaterial = keyPath || config.privateKeyPem || config.privateKeyBuffer;
|
|
146
146
|
if (hasKeyMaterial) {
|
|
@@ -154,7 +154,7 @@ var TetherClient = class {
|
|
|
154
154
|
}
|
|
155
155
|
if (!this.apiKey && !this.privateKey) {
|
|
156
156
|
}
|
|
157
|
-
if (!this.apiKey && !this.
|
|
157
|
+
if (!this.apiKey && !this.agentId) {
|
|
158
158
|
}
|
|
159
159
|
}
|
|
160
160
|
/**
|
|
@@ -188,15 +188,15 @@ var TetherClient = class {
|
|
|
188
188
|
}
|
|
189
189
|
}
|
|
190
190
|
/**
|
|
191
|
-
* Ensures
|
|
191
|
+
* Ensures an agent ID is available, throwing if not
|
|
192
192
|
*/
|
|
193
|
-
|
|
194
|
-
if (!this.
|
|
193
|
+
_requireAgentId() {
|
|
194
|
+
if (!this.agentId) {
|
|
195
195
|
throw new TetherError(
|
|
196
|
-
"
|
|
196
|
+
"Agent ID is required for this operation. Provide it in config or set TETHER_AGENT_ID environment variable."
|
|
197
197
|
);
|
|
198
198
|
}
|
|
199
|
-
return this.
|
|
199
|
+
return this.agentId;
|
|
200
200
|
}
|
|
201
201
|
/**
|
|
202
202
|
* Request a challenge from the Tether API
|
|
@@ -245,12 +245,12 @@ var TetherClient = class {
|
|
|
245
245
|
* Submit proof for a challenge
|
|
246
246
|
*/
|
|
247
247
|
async submitProof(challenge, proof) {
|
|
248
|
-
const
|
|
248
|
+
const agentId = this._requireAgentId();
|
|
249
249
|
try {
|
|
250
250
|
const payload = {
|
|
251
251
|
challenge,
|
|
252
252
|
proof,
|
|
253
|
-
|
|
253
|
+
agentId
|
|
254
254
|
};
|
|
255
255
|
const response = await fetch(`${this.baseUrl}/challenge/verify`, {
|
|
256
256
|
method: "POST",
|
|
@@ -274,6 +274,7 @@ var TetherClient = class {
|
|
|
274
274
|
agentName: data.agentName,
|
|
275
275
|
verifyUrl: data.verifyUrl,
|
|
276
276
|
email: data.email,
|
|
277
|
+
domain: data.domain,
|
|
277
278
|
registeredSince,
|
|
278
279
|
error: data.error,
|
|
279
280
|
challenge
|
|
@@ -317,16 +318,16 @@ var TetherClient = class {
|
|
|
317
318
|
/**
|
|
318
319
|
* Create a new agent
|
|
319
320
|
*/
|
|
320
|
-
async createAgent(agentName, description = "") {
|
|
321
|
+
async createAgent(agentName, description = "", domainId) {
|
|
321
322
|
this._requireApiKey();
|
|
322
323
|
try {
|
|
323
|
-
const response = await fetch(`${this.baseUrl}/
|
|
324
|
+
const response = await fetch(`${this.baseUrl}/agents/issue`, {
|
|
324
325
|
method: "POST",
|
|
325
326
|
headers: {
|
|
326
327
|
"Content-Type": "application/json",
|
|
327
328
|
...this._authHeaders()
|
|
328
329
|
},
|
|
329
|
-
body: JSON.stringify({ agentName, description })
|
|
330
|
+
body: JSON.stringify({ agentName, description, ...domainId ? { domainId } : {} })
|
|
330
331
|
});
|
|
331
332
|
if (!response.ok) {
|
|
332
333
|
const errorText = await response.text().catch(() => "Unknown error");
|
|
@@ -356,7 +357,7 @@ var TetherClient = class {
|
|
|
356
357
|
async listAgents() {
|
|
357
358
|
this._requireApiKey();
|
|
358
359
|
try {
|
|
359
|
-
const response = await fetch(`${this.baseUrl}/
|
|
360
|
+
const response = await fetch(`${this.baseUrl}/agents`, {
|
|
360
361
|
method: "GET",
|
|
361
362
|
headers: {
|
|
362
363
|
...this._authHeaders()
|
|
@@ -384,13 +385,47 @@ var TetherClient = class {
|
|
|
384
385
|
);
|
|
385
386
|
}
|
|
386
387
|
}
|
|
388
|
+
/**
|
|
389
|
+
* List all registered domains
|
|
390
|
+
*/
|
|
391
|
+
async listDomains() {
|
|
392
|
+
this._requireApiKey();
|
|
393
|
+
try {
|
|
394
|
+
const response = await fetch(`${this.baseUrl}/domains`, {
|
|
395
|
+
method: "GET",
|
|
396
|
+
headers: {
|
|
397
|
+
...this._authHeaders()
|
|
398
|
+
}
|
|
399
|
+
});
|
|
400
|
+
if (!response.ok) {
|
|
401
|
+
const errorText = await response.text().catch(() => "Unknown error");
|
|
402
|
+
throw new TetherAPIError(
|
|
403
|
+
`List domains failed: ${response.status} ${response.statusText}`,
|
|
404
|
+
response.status,
|
|
405
|
+
errorText
|
|
406
|
+
);
|
|
407
|
+
}
|
|
408
|
+
const data = await response.json();
|
|
409
|
+
return data;
|
|
410
|
+
} catch (error) {
|
|
411
|
+
if (error instanceof TetherError) {
|
|
412
|
+
throw error;
|
|
413
|
+
}
|
|
414
|
+
throw new TetherAPIError(
|
|
415
|
+
`Failed to list domains: ${error instanceof Error ? error.message : String(error)}`,
|
|
416
|
+
void 0,
|
|
417
|
+
void 0,
|
|
418
|
+
error instanceof Error ? error : void 0
|
|
419
|
+
);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
387
422
|
/**
|
|
388
423
|
* Delete an agent by ID
|
|
389
424
|
*/
|
|
390
425
|
async deleteAgent(agentId) {
|
|
391
426
|
this._requireApiKey();
|
|
392
427
|
try {
|
|
393
|
-
const response = await fetch(`${this.baseUrl}/
|
|
428
|
+
const response = await fetch(`${this.baseUrl}/agents/${agentId}`, {
|
|
394
429
|
method: "DELETE",
|
|
395
430
|
headers: {
|
|
396
431
|
...this._authHeaders()
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/crypto.ts","../src/client.ts"],"sourcesContent":["/**\n * Tether Name SDK - Official Node.js library for tether.name agent identity verification\n * \n * @example\n * ```typescript\n * import { TetherClient } from 'tether-name';\n * \n * const client = new TetherClient({\n * credentialId: 'your-credential-id',\n * privateKeyPath: '/path/to/key.der'\n * });\n * \n * const result = await client.verify();\n * console.log(result.verified, result.agentName);\n * ```\n */\n\n// Main exports\nexport { TetherClient } from './client.js';\n\n// Types\nexport type {\n TetherClientConfig,\n ChallengeResponse,\n Agent,\n IssueCredentialResponse,\n VerificationRequest,\n VerificationResponse,\n VerificationResult,\n KeyFormat\n} from './types.js';\n\n// Errors\nexport {\n TetherError,\n TetherAPIError,\n TetherVerificationError\n} from './errors.js';\n\n// Crypto utilities (for advanced use cases)\nexport {\n loadPrivateKey,\n signChallenge,\n detectKeyFormat\n} from './crypto.js';","/**\n * Base error class for all Tether-related errors\n */\nexport class TetherError extends Error {\n constructor(message: string, public readonly cause?: Error) {\n super(message);\n this.name = 'TetherError';\n \n // Maintain proper stack trace for where our error was thrown (only available on V8)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, TetherError);\n }\n }\n}\n\n/**\n * Error thrown when verification fails\n */\nexport class TetherVerificationError extends TetherError {\n constructor(message: string, cause?: Error) {\n super(message, cause);\n this.name = 'TetherVerificationError';\n }\n}\n\n/**\n * Error thrown when API requests fail\n */\nexport class TetherAPIError extends TetherError {\n constructor(\n message: string,\n public readonly status?: number,\n public readonly response?: string,\n cause?: Error\n ) {\n super(message, cause);\n this.name = 'TetherAPIError';\n }\n}","import { createSign, createPrivateKey, KeyObject } from 'crypto';\nimport { readFileSync } from 'fs';\nimport { TetherError } from './errors.js';\nimport type { KeyFormat } from './types.js';\n\n/**\n * Imports a DER-encoded private key, trying PKCS#8 first then PKCS#1.\n */\nfunction importDerKey(derData: Buffer): KeyObject {\n try {\n return createPrivateKey({ key: derData, format: 'der', type: 'pkcs8' });\n } catch {\n // PKCS#8 failed — try PKCS#1\n }\n try {\n return createPrivateKey({ key: derData, format: 'der', type: 'pkcs1' });\n } catch {\n // PKCS#1 also failed\n }\n throw new TetherError(\n 'Failed to load DER private key: data is not valid PKCS#8 or PKCS#1. ' +\n 'Ensure the file is an RSA private key in DER format.'\n );\n}\n\n/**\n * Loads a private key from various sources\n */\nexport function loadPrivateKey(options: {\n keyPath?: string;\n keyPem?: string;\n keyBuffer?: Buffer;\n}): KeyObject {\n const { keyPath, keyPem, keyBuffer } = options;\n\n try {\n if (keyPem) {\n // PEM string provided directly\n return createPrivateKey(keyPem);\n }\n\n if (keyBuffer) {\n // DER buffer provided directly\n return importDerKey(keyBuffer);\n }\n\n if (keyPath) {\n // Read from file - detect format by extension or content\n const keyData = readFileSync(keyPath);\n\n // Try to detect format\n if (keyPath.endsWith('.pem') || keyData.toString().includes('-----BEGIN')) {\n // PEM format\n return createPrivateKey(keyData);\n } else {\n // Assume DER format\n return importDerKey(keyData);\n }\n }\n\n throw new TetherError('No private key provided');\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherError(\n `Failed to load private key: ${error instanceof Error ? error.message : String(error)}`,\n error instanceof Error ? error : undefined\n );\n }\n}\n\n/**\n * Signs a challenge string using RSA-SHA256\n * Returns URL-safe base64 encoded signature (no padding)\n */\nexport function signChallenge(privateKey: KeyObject, challenge: string): string {\n try {\n const sign = createSign('SHA256');\n sign.update(challenge);\n sign.end();\n \n const signature = sign.sign(privateKey);\n \n // Convert to URL-safe base64 without padding\n return signature\n .toString('base64')\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=/g, '');\n } catch (error) {\n throw new TetherError(\n `Failed to sign challenge: ${error instanceof Error ? error.message : String(error)}`,\n error instanceof Error ? error : undefined\n );\n }\n}\n\n/**\n * Utility function to detect key format from file extension or content\n */\nexport function detectKeyFormat(keyPath: string): KeyFormat {\n if (keyPath.endsWith('.pem')) {\n return 'pem';\n }\n if (keyPath.endsWith('.der')) {\n return 'der';\n }\n \n // Try to read a small portion to detect format\n try {\n const keyData = readFileSync(keyPath, { encoding: 'utf8', flag: 'r' });\n if (keyData.includes('-----BEGIN')) {\n return 'pem';\n }\n } catch {\n // If we can't read as text, it's probably DER\n }\n \n return 'der';\n}","import { KeyObject } from 'crypto';\nimport { TetherError, TetherAPIError, TetherVerificationError } from './errors.js';\nimport { loadPrivateKey, signChallenge } from './crypto.js';\nimport type {\n TetherClientConfig,\n ChallengeResponse,\n Agent,\n IssueCredentialResponse,\n VerificationRequest,\n VerificationResponse,\n VerificationResult\n} from './types.js';\n\n/**\n * TetherClient - Official SDK for tether.name agent identity verification\n */\nexport class TetherClient {\n private readonly credentialId: string;\n private readonly privateKey: KeyObject | null;\n private readonly baseUrl: string;\n private readonly apiKey?: string;\n\n constructor(config: TetherClientConfig) {\n // Set base URL\n this.baseUrl = 'https://api.tether.name';\n\n // Get API key from config or environment\n this.apiKey = config.apiKey || process.env.TETHER_API_KEY;\n\n // Get credential ID from config or environment\n this.credentialId = config.credentialId || process.env.TETHER_CREDENTIAL_ID || '';\n\n // Load private key if key material is provided\n const keyPath = config.privateKeyPath || process.env.TETHER_PRIVATE_KEY_PATH;\n const hasKeyMaterial = keyPath || config.privateKeyPem || config.privateKeyBuffer;\n\n if (hasKeyMaterial) {\n this.privateKey = loadPrivateKey({\n keyPath,\n keyPem: config.privateKeyPem,\n keyBuffer: config.privateKeyBuffer\n });\n } else {\n this.privateKey = null;\n }\n\n // If no API key and no private key, credential ID and key are still needed for verify/sign\n // but we defer the error to when those methods are called\n if (!this.apiKey && !this.privateKey) {\n // Allow construction — errors thrown at method call time\n }\n\n if (!this.apiKey && !this.credentialId) {\n // Allow construction — errors thrown at method call time\n }\n }\n\n /**\n * Returns authorization headers when an API key is configured\n */\n private _authHeaders(): Record<string, string> {\n if (this.apiKey) {\n return { 'Authorization': `Bearer ${this.apiKey}` };\n }\n return {};\n }\n\n /**\n * Ensures a private key is available, throwing if not\n */\n private _requirePrivateKey(): KeyObject {\n if (!this.privateKey) {\n throw new TetherError(\n 'Private key is required for this operation. Provide privateKeyPath, privateKeyPem, or privateKeyBuffer in config, or set TETHER_PRIVATE_KEY_PATH environment variable.'\n );\n }\n return this.privateKey;\n }\n\n /**\n * Ensures an API key is available, throwing if not\n */\n private _requireApiKey(): void {\n if (!this.apiKey) {\n throw new TetherError(\n 'API key is required for agent management operations. Provide apiKey in config or set TETHER_API_KEY environment variable.'\n );\n }\n }\n\n /**\n * Ensures a credential ID is available, throwing if not\n */\n private _requireCredentialId(): string {\n if (!this.credentialId) {\n throw new TetherError(\n 'Credential ID is required for this operation. Provide it in config or set TETHER_CREDENTIAL_ID environment variable.'\n );\n }\n return this.credentialId;\n }\n\n /**\n * Request a challenge from the Tether API\n */\n async requestChallenge(): Promise<string> {\n try {\n const response = await fetch(`${this.baseUrl}/challenge`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n }\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new TetherAPIError(\n `Challenge request failed: ${response.status} ${response.statusText}`,\n response.status,\n errorText\n );\n }\n\n const data = await response.json() as ChallengeResponse;\n\n if (!data.code) {\n throw new TetherAPIError('Invalid challenge response: missing code');\n }\n\n return data.code;\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherAPIError(\n `Failed to request challenge: ${error instanceof Error ? error.message : String(error)}`,\n undefined,\n undefined,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * Sign a challenge string\n */\n sign(challenge: string): string {\n const key = this._requirePrivateKey();\n return signChallenge(key, challenge);\n }\n\n /**\n * Submit proof for a challenge\n */\n async submitProof(challenge: string, proof: string): Promise<VerificationResult> {\n const credentialId = this._requireCredentialId();\n\n try {\n const payload: VerificationRequest = {\n challenge,\n proof,\n credentialId\n };\n\n const response = await fetch(`${this.baseUrl}/challenge/verify`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify(payload)\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new TetherAPIError(\n `Verification failed: ${response.status} ${response.statusText}`,\n response.status,\n errorText\n );\n }\n\n const data = await response.json() as VerificationResponse;\n\n // Convert API response to our result format\n const registeredSince = typeof data.registeredSince === 'number'\n ? new Date(data.registeredSince).toISOString()\n : data.registeredSince;\n\n return {\n verified: data.valid,\n agentName: data.agentName,\n verifyUrl: data.verifyUrl,\n email: data.email,\n registeredSince,\n error: data.error,\n challenge\n };\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherAPIError(\n `Failed to submit proof: ${error instanceof Error ? error.message : String(error)}`,\n undefined,\n undefined,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * Perform complete verification in one call\n */\n async verify(): Promise<VerificationResult> {\n try {\n const challenge = await this.requestChallenge();\n const proof = this.sign(challenge);\n const result = await this.submitProof(challenge, proof);\n\n if (!result.verified) {\n throw new TetherVerificationError(\n result.error || 'Verification failed for unknown reason'\n );\n }\n\n return result;\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherVerificationError(\n `Verification failed: ${error instanceof Error ? error.message : String(error)}`,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * Create a new agent\n */\n async createAgent(agentName: string, description: string = ''): Promise<Agent> {\n this._requireApiKey();\n try {\n const response = await fetch(`${this.baseUrl}/credentials/issue`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...this._authHeaders()\n },\n body: JSON.stringify({ agentName, description })\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new TetherAPIError(\n `Create agent failed: ${response.status} ${response.statusText}`,\n response.status,\n errorText\n );\n }\n\n const data = await response.json() as IssueCredentialResponse;\n return data;\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherAPIError(\n `Failed to create agent: ${error instanceof Error ? error.message : String(error)}`,\n undefined,\n undefined,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * List all agents\n */\n async listAgents(): Promise<Agent[]> {\n this._requireApiKey();\n try {\n const response = await fetch(`${this.baseUrl}/credentials`, {\n method: 'GET',\n headers: {\n ...this._authHeaders()\n }\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new TetherAPIError(\n `List agents failed: ${response.status} ${response.statusText}`,\n response.status,\n errorText\n );\n }\n\n const data = await response.json() as Agent[];\n return data;\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherAPIError(\n `Failed to list agents: ${error instanceof Error ? error.message : String(error)}`,\n undefined,\n undefined,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * Delete an agent by ID\n */\n async deleteAgent(agentId: string): Promise<boolean> {\n this._requireApiKey();\n try {\n const response = await fetch(`${this.baseUrl}/credentials/${agentId}`, {\n method: 'DELETE',\n headers: {\n ...this._authHeaders()\n }\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new TetherAPIError(\n `Delete agent failed: ${response.status} ${response.statusText}`,\n response.status,\n errorText\n );\n }\n\n return true;\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherAPIError(\n `Failed to delete agent: ${error instanceof Error ? error.message : String(error)}`,\n undefined,\n undefined,\n error instanceof Error ? error : undefined\n );\n }\n }\n}"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/crypto.ts","../src/client.ts"],"sourcesContent":["/**\n * Tether Name SDK - Official Node.js library for tether.name agent identity verification\n * \n * @example\n * ```typescript\n * import { TetherClient } from 'tether-name';\n * \n * const client = new TetherClient({\n * agentId: 'your-agent-id',\n * privateKeyPath: '/path/to/key.pem'\n * });\n * \n * const result = await client.verify();\n * console.log(result.verified, result.agentName);\n * ```\n */\n\n// Main exports\nexport { TetherClient } from './client.js';\n\n// Types\nexport type {\n TetherClientConfig,\n ChallengeResponse,\n Agent,\n Domain,\n IssueAgentResponse,\n VerificationRequest,\n VerificationResponse,\n VerificationResult,\n KeyFormat\n} from './types.js';\n\n// Errors\nexport {\n TetherError,\n TetherAPIError,\n TetherVerificationError\n} from './errors.js';\n\n// Crypto utilities (for advanced use cases)\nexport {\n loadPrivateKey,\n signChallenge,\n detectKeyFormat\n} from './crypto.js';","/**\n * Base error class for all Tether-related errors\n */\nexport class TetherError extends Error {\n constructor(message: string, public readonly cause?: Error) {\n super(message);\n this.name = 'TetherError';\n \n // Maintain proper stack trace for where our error was thrown (only available on V8)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, TetherError);\n }\n }\n}\n\n/**\n * Error thrown when verification fails\n */\nexport class TetherVerificationError extends TetherError {\n constructor(message: string, cause?: Error) {\n super(message, cause);\n this.name = 'TetherVerificationError';\n }\n}\n\n/**\n * Error thrown when API requests fail\n */\nexport class TetherAPIError extends TetherError {\n constructor(\n message: string,\n public readonly status?: number,\n public readonly response?: string,\n cause?: Error\n ) {\n super(message, cause);\n this.name = 'TetherAPIError';\n }\n}","import { createSign, createPrivateKey, KeyObject } from 'crypto';\nimport { readFileSync } from 'fs';\nimport { TetherError } from './errors.js';\nimport type { KeyFormat } from './types.js';\n\n/**\n * Imports a DER-encoded private key, trying PKCS#8 first then PKCS#1.\n */\nfunction importDerKey(derData: Buffer): KeyObject {\n try {\n return createPrivateKey({ key: derData, format: 'der', type: 'pkcs8' });\n } catch {\n // PKCS#8 failed — try PKCS#1\n }\n try {\n return createPrivateKey({ key: derData, format: 'der', type: 'pkcs1' });\n } catch {\n // PKCS#1 also failed\n }\n throw new TetherError(\n 'Failed to load DER private key: data is not valid PKCS#8 or PKCS#1. ' +\n 'Ensure the file is an RSA private key in DER format.'\n );\n}\n\n/**\n * Loads a private key from various sources\n */\nexport function loadPrivateKey(options: {\n keyPath?: string;\n keyPem?: string;\n keyBuffer?: Buffer;\n}): KeyObject {\n const { keyPath, keyPem, keyBuffer } = options;\n\n try {\n if (keyPem) {\n // PEM string provided directly\n return createPrivateKey(keyPem);\n }\n\n if (keyBuffer) {\n // DER buffer provided directly\n return importDerKey(keyBuffer);\n }\n\n if (keyPath) {\n // Read from file - detect format by extension or content\n const keyData = readFileSync(keyPath);\n\n // Try to detect format\n if (keyPath.endsWith('.pem') || keyData.toString().includes('-----BEGIN')) {\n // PEM format\n return createPrivateKey(keyData);\n } else {\n // Assume DER format\n return importDerKey(keyData);\n }\n }\n\n throw new TetherError('No private key provided');\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherError(\n `Failed to load private key: ${error instanceof Error ? error.message : String(error)}`,\n error instanceof Error ? error : undefined\n );\n }\n}\n\n/**\n * Signs a challenge string using RSA-SHA256\n * Returns URL-safe base64 encoded signature (no padding)\n */\nexport function signChallenge(privateKey: KeyObject, challenge: string): string {\n try {\n const sign = createSign('SHA256');\n sign.update(challenge);\n sign.end();\n \n const signature = sign.sign(privateKey);\n \n // Convert to URL-safe base64 without padding\n return signature\n .toString('base64')\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=/g, '');\n } catch (error) {\n throw new TetherError(\n `Failed to sign challenge: ${error instanceof Error ? error.message : String(error)}`,\n error instanceof Error ? error : undefined\n );\n }\n}\n\n/**\n * Utility function to detect key format from file extension or content\n */\nexport function detectKeyFormat(keyPath: string): KeyFormat {\n if (keyPath.endsWith('.pem')) {\n return 'pem';\n }\n if (keyPath.endsWith('.der')) {\n return 'der';\n }\n \n // Try to read a small portion to detect format\n try {\n const keyData = readFileSync(keyPath, { encoding: 'utf8', flag: 'r' });\n if (keyData.includes('-----BEGIN')) {\n return 'pem';\n }\n } catch {\n // If we can't read as text, it's probably DER\n }\n \n return 'der';\n}","import { KeyObject } from 'crypto';\nimport { TetherError, TetherAPIError, TetherVerificationError } from './errors.js';\nimport { loadPrivateKey, signChallenge } from './crypto.js';\nimport type {\n TetherClientConfig,\n ChallengeResponse,\n Agent,\n Domain,\n IssueAgentResponse,\n VerificationRequest,\n VerificationResponse,\n VerificationResult\n} from './types.js';\n\n/**\n * TetherClient - Official SDK for tether.name agent identity verification\n */\nexport class TetherClient {\n private readonly agentId: string;\n private readonly privateKey: KeyObject | null;\n private readonly baseUrl: string;\n private readonly apiKey?: string;\n\n constructor(config: TetherClientConfig) {\n // Set base URL\n this.baseUrl = 'https://api.tether.name';\n\n // Get API key from config or environment\n this.apiKey = config.apiKey || process.env.TETHER_API_KEY;\n\n // Get agent ID from config or environment\n this.agentId = config.agentId || process.env.TETHER_AGENT_ID || '';\n\n // Load private key if key material is provided\n const keyPath = config.privateKeyPath || process.env.TETHER_PRIVATE_KEY_PATH;\n const hasKeyMaterial = keyPath || config.privateKeyPem || config.privateKeyBuffer;\n\n if (hasKeyMaterial) {\n this.privateKey = loadPrivateKey({\n keyPath,\n keyPem: config.privateKeyPem,\n keyBuffer: config.privateKeyBuffer\n });\n } else {\n this.privateKey = null;\n }\n\n // If no API key and no private key, agent ID and key are still needed for verify/sign\n // but we defer the error to when those methods are called\n if (!this.apiKey && !this.privateKey) {\n // Allow construction — errors thrown at method call time\n }\n\n if (!this.apiKey && !this.agentId) {\n // Allow construction — errors thrown at method call time\n }\n }\n\n /**\n * Returns authorization headers when an API key is configured\n */\n private _authHeaders(): Record<string, string> {\n if (this.apiKey) {\n return { 'Authorization': `Bearer ${this.apiKey}` };\n }\n return {};\n }\n\n /**\n * Ensures a private key is available, throwing if not\n */\n private _requirePrivateKey(): KeyObject {\n if (!this.privateKey) {\n throw new TetherError(\n 'Private key is required for this operation. Provide privateKeyPath, privateKeyPem, or privateKeyBuffer in config, or set TETHER_PRIVATE_KEY_PATH environment variable.'\n );\n }\n return this.privateKey;\n }\n\n /**\n * Ensures an API key is available, throwing if not\n */\n private _requireApiKey(): void {\n if (!this.apiKey) {\n throw new TetherError(\n 'API key is required for agent management operations. Provide apiKey in config or set TETHER_API_KEY environment variable.'\n );\n }\n }\n\n /**\n * Ensures an agent ID is available, throwing if not\n */\n private _requireAgentId(): string {\n if (!this.agentId) {\n throw new TetherError(\n 'Agent ID is required for this operation. Provide it in config or set TETHER_AGENT_ID environment variable.'\n );\n }\n return this.agentId;\n }\n\n /**\n * Request a challenge from the Tether API\n */\n async requestChallenge(): Promise<string> {\n try {\n const response = await fetch(`${this.baseUrl}/challenge`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n }\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new TetherAPIError(\n `Challenge request failed: ${response.status} ${response.statusText}`,\n response.status,\n errorText\n );\n }\n\n const data = await response.json() as ChallengeResponse;\n\n if (!data.code) {\n throw new TetherAPIError('Invalid challenge response: missing code');\n }\n\n return data.code;\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherAPIError(\n `Failed to request challenge: ${error instanceof Error ? error.message : String(error)}`,\n undefined,\n undefined,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * Sign a challenge string\n */\n sign(challenge: string): string {\n const key = this._requirePrivateKey();\n return signChallenge(key, challenge);\n }\n\n /**\n * Submit proof for a challenge\n */\n async submitProof(challenge: string, proof: string): Promise<VerificationResult> {\n const agentId = this._requireAgentId();\n\n try {\n const payload: VerificationRequest = {\n challenge,\n proof,\n agentId\n };\n\n const response = await fetch(`${this.baseUrl}/challenge/verify`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify(payload)\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new TetherAPIError(\n `Verification failed: ${response.status} ${response.statusText}`,\n response.status,\n errorText\n );\n }\n\n const data = await response.json() as VerificationResponse;\n\n // Convert API response to our result format\n const registeredSince = typeof data.registeredSince === 'number'\n ? new Date(data.registeredSince).toISOString()\n : data.registeredSince;\n\n return {\n verified: data.valid,\n agentName: data.agentName,\n verifyUrl: data.verifyUrl,\n email: data.email,\n domain: data.domain,\n registeredSince,\n error: data.error,\n challenge\n };\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherAPIError(\n `Failed to submit proof: ${error instanceof Error ? error.message : String(error)}`,\n undefined,\n undefined,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * Perform complete verification in one call\n */\n async verify(): Promise<VerificationResult> {\n try {\n const challenge = await this.requestChallenge();\n const proof = this.sign(challenge);\n const result = await this.submitProof(challenge, proof);\n\n if (!result.verified) {\n throw new TetherVerificationError(\n result.error || 'Verification failed for unknown reason'\n );\n }\n\n return result;\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherVerificationError(\n `Verification failed: ${error instanceof Error ? error.message : String(error)}`,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * Create a new agent\n */\n async createAgent(agentName: string, description: string = '', domainId?: string): Promise<Agent> {\n this._requireApiKey();\n try {\n const response = await fetch(`${this.baseUrl}/agents/issue`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...this._authHeaders()\n },\n body: JSON.stringify({ agentName, description, ...(domainId ? { domainId } : {}) })\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new TetherAPIError(\n `Create agent failed: ${response.status} ${response.statusText}`,\n response.status,\n errorText\n );\n }\n\n const data = await response.json() as IssueAgentResponse;\n return data;\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherAPIError(\n `Failed to create agent: ${error instanceof Error ? error.message : String(error)}`,\n undefined,\n undefined,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * List all agents\n */\n async listAgents(): Promise<Agent[]> {\n this._requireApiKey();\n try {\n const response = await fetch(`${this.baseUrl}/agents`, {\n method: 'GET',\n headers: {\n ...this._authHeaders()\n }\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new TetherAPIError(\n `List agents failed: ${response.status} ${response.statusText}`,\n response.status,\n errorText\n );\n }\n\n const data = await response.json() as Agent[];\n return data;\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherAPIError(\n `Failed to list agents: ${error instanceof Error ? error.message : String(error)}`,\n undefined,\n undefined,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * List all registered domains\n */\n async listDomains(): Promise<Domain[]> {\n this._requireApiKey();\n try {\n const response = await fetch(`${this.baseUrl}/domains`, {\n method: 'GET',\n headers: {\n ...this._authHeaders()\n }\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new TetherAPIError(\n `List domains failed: ${response.status} ${response.statusText}`,\n response.status,\n errorText\n );\n }\n\n const data = await response.json() as Domain[];\n return data;\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherAPIError(\n `Failed to list domains: ${error instanceof Error ? error.message : String(error)}`,\n undefined,\n undefined,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * Delete an agent by ID\n */\n async deleteAgent(agentId: string): Promise<boolean> {\n this._requireApiKey();\n try {\n const response = await fetch(`${this.baseUrl}/agents/${agentId}`, {\n method: 'DELETE',\n headers: {\n ...this._authHeaders()\n }\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new TetherAPIError(\n `Delete agent failed: ${response.status} ${response.statusText}`,\n response.status,\n errorText\n );\n }\n\n return true;\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherAPIError(\n `Failed to delete agent: ${error instanceof Error ? error.message : String(error)}`,\n undefined,\n undefined,\n error instanceof Error ? error : undefined\n );\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACGO,IAAM,cAAN,MAAM,qBAAoB,MAAM;AAAA,EACrC,YAAY,SAAiC,OAAe;AAC1D,UAAM,OAAO;AAD8B;AAE3C,SAAK,OAAO;AAGZ,QAAI,MAAM,mBAAmB;AAC3B,YAAM,kBAAkB,MAAM,YAAW;AAAA,IAC3C;AAAA,EACF;AACF;AAKO,IAAM,0BAAN,cAAsC,YAAY;AAAA,EACvD,YAAY,SAAiB,OAAe;AAC1C,UAAM,SAAS,KAAK;AACpB,SAAK,OAAO;AAAA,EACd;AACF;AAKO,IAAM,iBAAN,cAA6B,YAAY;AAAA,EAC9C,YACE,SACgB,QACA,UAChB,OACA;AACA,UAAM,SAAS,KAAK;AAJJ;AACA;AAIhB,SAAK,OAAO;AAAA,EACd;AACF;;;ACtCA,oBAAwD;AACxD,gBAA6B;AAO7B,SAAS,aAAa,SAA4B;AAChD,MAAI;AACF,eAAO,gCAAiB,EAAE,KAAK,SAAS,QAAQ,OAAO,MAAM,QAAQ,CAAC;AAAA,EACxE,QAAQ;AAAA,EAER;AACA,MAAI;AACF,eAAO,gCAAiB,EAAE,KAAK,SAAS,QAAQ,OAAO,MAAM,QAAQ,CAAC;AAAA,EACxE,QAAQ;AAAA,EAER;AACA,QAAM,IAAI;AAAA,IACR;AAAA,EAEF;AACF;AAKO,SAAS,eAAe,SAIjB;AACZ,QAAM,EAAE,SAAS,QAAQ,UAAU,IAAI;AAEvC,MAAI;AACF,QAAI,QAAQ;AAEV,iBAAO,gCAAiB,MAAM;AAAA,IAChC;AAEA,QAAI,WAAW;AAEb,aAAO,aAAa,SAAS;AAAA,IAC/B;AAEA,QAAI,SAAS;AAEX,YAAM,cAAU,wBAAa,OAAO;AAGpC,UAAI,QAAQ,SAAS,MAAM,KAAK,QAAQ,SAAS,EAAE,SAAS,YAAY,GAAG;AAEzE,mBAAO,gCAAiB,OAAO;AAAA,MACjC,OAAO;AAEL,eAAO,aAAa,OAAO;AAAA,MAC7B;AAAA,IACF;AAEA,UAAM,IAAI,YAAY,yBAAyB;AAAA,EACjD,SAAS,OAAO;AACd,QAAI,iBAAiB,aAAa;AAChC,YAAM;AAAA,IACR;AACA,UAAM,IAAI;AAAA,MACR,+BAA+B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,MACrF,iBAAiB,QAAQ,QAAQ;AAAA,IACnC;AAAA,EACF;AACF;AAMO,SAAS,cAAc,YAAuB,WAA2B;AAC9E,MAAI;AACF,UAAM,WAAO,0BAAW,QAAQ;AAChC,SAAK,OAAO,SAAS;AACrB,SAAK,IAAI;AAET,UAAM,YAAY,KAAK,KAAK,UAAU;AAGtC,WAAO,UACJ,SAAS,QAAQ,EACjB,QAAQ,OAAO,GAAG,EAClB,QAAQ,OAAO,GAAG,EAClB,QAAQ,MAAM,EAAE;AAAA,EACrB,SAAS,OAAO;AACd,UAAM,IAAI;AAAA,MACR,6BAA6B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,MACnF,iBAAiB,QAAQ,QAAQ;AAAA,IACnC;AAAA,EACF;AACF;AAKO,SAAS,gBAAgB,SAA4B;AAC1D,MAAI,QAAQ,SAAS,MAAM,GAAG;AAC5B,WAAO;AAAA,EACT;AACA,MAAI,QAAQ,SAAS,MAAM,GAAG;AAC5B,WAAO;AAAA,EACT;AAGA,MAAI;AACF,UAAM,cAAU,wBAAa,SAAS,EAAE,UAAU,QAAQ,MAAM,IAAI,CAAC;AACrE,QAAI,QAAQ,SAAS,YAAY,GAAG;AAClC,aAAO;AAAA,IACT;AAAA,EACF,QAAQ;AAAA,EAER;AAEA,SAAO;AACT;;;ACvGO,IAAM,eAAN,MAAmB;AAAA,EACP;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,QAA4B;AAEtC,SAAK,UAAU;AAGf,SAAK,SAAS,OAAO,UAAU,QAAQ,IAAI;AAG3C,SAAK,UAAU,OAAO,WAAW,QAAQ,IAAI,mBAAmB;AAGhE,UAAM,UAAU,OAAO,kBAAkB,QAAQ,IAAI;AACrD,UAAM,iBAAiB,WAAW,OAAO,iBAAiB,OAAO;AAEjE,QAAI,gBAAgB;AAClB,WAAK,aAAa,eAAe;AAAA,QAC/B;AAAA,QACA,QAAQ,OAAO;AAAA,QACf,WAAW,OAAO;AAAA,MACpB,CAAC;AAAA,IACH,OAAO;AACL,WAAK,aAAa;AAAA,IACpB;AAIA,QAAI,CAAC,KAAK,UAAU,CAAC,KAAK,YAAY;AAAA,IAEtC;AAEA,QAAI,CAAC,KAAK,UAAU,CAAC,KAAK,SAAS;AAAA,IAEnC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,eAAuC;AAC7C,QAAI,KAAK,QAAQ;AACf,aAAO,EAAE,iBAAiB,UAAU,KAAK,MAAM,GAAG;AAAA,IACpD;AACA,WAAO,CAAC;AAAA,EACV;AAAA;AAAA;AAAA;AAAA,EAKQ,qBAAgC;AACtC,QAAI,CAAC,KAAK,YAAY;AACpB,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AACA,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKQ,iBAAuB;AAC7B,QAAI,CAAC,KAAK,QAAQ;AAChB,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,kBAA0B;AAChC,QAAI,CAAC,KAAK,SAAS;AACjB,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AACA,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,mBAAoC;AACxC,QAAI;AACF,YAAM,WAAW,MAAM,MAAM,GAAG,KAAK,OAAO,cAAc;AAAA,QACxD,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,gBAAgB;AAAA,QAClB;AAAA,MACF,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,YAAY,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,eAAe;AACnE,cAAM,IAAI;AAAA,UACR,6BAA6B,SAAS,MAAM,IAAI,SAAS,UAAU;AAAA,UACnE,SAAS;AAAA,UACT;AAAA,QACF;AAAA,MACF;AAEA,YAAM,OAAO,MAAM,SAAS,KAAK;AAEjC,UAAI,CAAC,KAAK,MAAM;AACd,cAAM,IAAI,eAAe,0CAA0C;AAAA,MACrE;AAEA,aAAO,KAAK;AAAA,IACd,SAAS,OAAO;AACd,UAAI,iBAAiB,aAAa;AAChC,cAAM;AAAA,MACR;AACA,YAAM,IAAI;AAAA,QACR,gCAAgC,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,QACtF;AAAA,QACA;AAAA,QACA,iBAAiB,QAAQ,QAAQ;AAAA,MACnC;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,KAAK,WAA2B;AAC9B,UAAM,MAAM,KAAK,mBAAmB;AACpC,WAAO,cAAc,KAAK,SAAS;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YAAY,WAAmB,OAA4C;AAC/E,UAAM,UAAU,KAAK,gBAAgB;AAErC,QAAI;AACF,YAAM,UAA+B;AAAA,QACnC;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAEA,YAAM,WAAW,MAAM,MAAM,GAAG,KAAK,OAAO,qBAAqB;AAAA,QAC/D,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,gBAAgB;AAAA,QAClB;AAAA,QACA,MAAM,KAAK,UAAU,OAAO;AAAA,MAC9B,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,YAAY,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,eAAe;AACnE,cAAM,IAAI;AAAA,UACR,wBAAwB,SAAS,MAAM,IAAI,SAAS,UAAU;AAAA,UAC9D,SAAS;AAAA,UACT;AAAA,QACF;AAAA,MACF;AAEA,YAAM,OAAO,MAAM,SAAS,KAAK;AAGjC,YAAM,kBAAkB,OAAO,KAAK,oBAAoB,WACpD,IAAI,KAAK,KAAK,eAAe,EAAE,YAAY,IAC3C,KAAK;AAET,aAAO;AAAA,QACL,UAAU,KAAK;AAAA,QACf,WAAW,KAAK;AAAA,QAChB,WAAW,KAAK;AAAA,QAChB,OAAO,KAAK;AAAA,QACZ,QAAQ,KAAK;AAAA,QACb;AAAA,QACA,OAAO,KAAK;AAAA,QACZ;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AACd,UAAI,iBAAiB,aAAa;AAChC,cAAM;AAAA,MACR;AACA,YAAM,IAAI;AAAA,QACR,2BAA2B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,QACjF;AAAA,QACA;AAAA,QACA,iBAAiB,QAAQ,QAAQ;AAAA,MACnC;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,SAAsC;AAC1C,QAAI;AACF,YAAM,YAAY,MAAM,KAAK,iBAAiB;AAC9C,YAAM,QAAQ,KAAK,KAAK,SAAS;AACjC,YAAM,SAAS,MAAM,KAAK,YAAY,WAAW,KAAK;AAEtD,UAAI,CAAC,OAAO,UAAU;AACpB,cAAM,IAAI;AAAA,UACR,OAAO,SAAS;AAAA,QAClB;AAAA,MACF;AAEA,aAAO;AAAA,IACT,SAAS,OAAO;AACd,UAAI,iBAAiB,aAAa;AAChC,cAAM;AAAA,MACR;AACA,YAAM,IAAI;AAAA,QACR,wBAAwB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,QAC9E,iBAAiB,QAAQ,QAAQ;AAAA,MACnC;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YAAY,WAAmB,cAAsB,IAAI,UAAmC;AAChG,SAAK,eAAe;AACpB,QAAI;AACF,YAAM,WAAW,MAAM,MAAM,GAAG,KAAK,OAAO,iBAAiB;AAAA,QAC3D,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,gBAAgB;AAAA,UAChB,GAAG,KAAK,aAAa;AAAA,QACvB;AAAA,QACA,MAAM,KAAK,UAAU,EAAE,WAAW,aAAa,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC,EAAG,CAAC;AAAA,MACpF,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,YAAY,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,eAAe;AACnE,cAAM,IAAI;AAAA,UACR,wBAAwB,SAAS,MAAM,IAAI,SAAS,UAAU;AAAA,UAC9D,SAAS;AAAA,UACT;AAAA,QACF;AAAA,MACF;AAEA,YAAM,OAAO,MAAM,SAAS,KAAK;AACjC,aAAO;AAAA,IACT,SAAS,OAAO;AACd,UAAI,iBAAiB,aAAa;AAChC,cAAM;AAAA,MACR;AACA,YAAM,IAAI;AAAA,QACR,2BAA2B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,QACjF;AAAA,QACA;AAAA,QACA,iBAAiB,QAAQ,QAAQ;AAAA,MACnC;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aAA+B;AACnC,SAAK,eAAe;AACpB,QAAI;AACF,YAAM,WAAW,MAAM,MAAM,GAAG,KAAK,OAAO,WAAW;AAAA,QACrD,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,GAAG,KAAK,aAAa;AAAA,QACvB;AAAA,MACF,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,YAAY,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,eAAe;AACnE,cAAM,IAAI;AAAA,UACR,uBAAuB,SAAS,MAAM,IAAI,SAAS,UAAU;AAAA,UAC7D,SAAS;AAAA,UACT;AAAA,QACF;AAAA,MACF;AAEA,YAAM,OAAO,MAAM,SAAS,KAAK;AACjC,aAAO;AAAA,IACT,SAAS,OAAO;AACd,UAAI,iBAAiB,aAAa;AAChC,cAAM;AAAA,MACR;AACA,YAAM,IAAI;AAAA,QACR,0BAA0B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,QAChF;AAAA,QACA;AAAA,QACA,iBAAiB,QAAQ,QAAQ;AAAA,MACnC;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cAAiC;AACrC,SAAK,eAAe;AACpB,QAAI;AACF,YAAM,WAAW,MAAM,MAAM,GAAG,KAAK,OAAO,YAAY;AAAA,QACtD,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,GAAG,KAAK,aAAa;AAAA,QACvB;AAAA,MACF,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,YAAY,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,eAAe;AACnE,cAAM,IAAI;AAAA,UACR,wBAAwB,SAAS,MAAM,IAAI,SAAS,UAAU;AAAA,UAC9D,SAAS;AAAA,UACT;AAAA,QACF;AAAA,MACF;AAEA,YAAM,OAAO,MAAM,SAAS,KAAK;AACjC,aAAO;AAAA,IACT,SAAS,OAAO;AACd,UAAI,iBAAiB,aAAa;AAChC,cAAM;AAAA,MACR;AACA,YAAM,IAAI;AAAA,QACR,2BAA2B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,QACjF;AAAA,QACA;AAAA,QACA,iBAAiB,QAAQ,QAAQ;AAAA,MACnC;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YAAY,SAAmC;AACnD,SAAK,eAAe;AACpB,QAAI;AACF,YAAM,WAAW,MAAM,MAAM,GAAG,KAAK,OAAO,WAAW,OAAO,IAAI;AAAA,QAChE,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,GAAG,KAAK,aAAa;AAAA,QACvB;AAAA,MACF,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,YAAY,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,eAAe;AACnE,cAAM,IAAI;AAAA,UACR,wBAAwB,SAAS,MAAM,IAAI,SAAS,UAAU;AAAA,UAC9D,SAAS;AAAA,UACT;AAAA,QACF;AAAA,MACF;AAEA,aAAO;AAAA,IACT,SAAS,OAAO;AACd,UAAI,iBAAiB,aAAa;AAChC,cAAM;AAAA,MACR;AACA,YAAM,IAAI;AAAA,QACR,2BAA2B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,QACjF;AAAA,QACA;AAAA,QACA,iBAAiB,QAAQ,QAAQ;AAAA,MACnC;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
|
package/dist/index.mjs
CHANGED
|
@@ -101,14 +101,14 @@ function detectKeyFormat(keyPath) {
|
|
|
101
101
|
|
|
102
102
|
// src/client.ts
|
|
103
103
|
var TetherClient = class {
|
|
104
|
-
|
|
104
|
+
agentId;
|
|
105
105
|
privateKey;
|
|
106
106
|
baseUrl;
|
|
107
107
|
apiKey;
|
|
108
108
|
constructor(config) {
|
|
109
109
|
this.baseUrl = "https://api.tether.name";
|
|
110
110
|
this.apiKey = config.apiKey || process.env.TETHER_API_KEY;
|
|
111
|
-
this.
|
|
111
|
+
this.agentId = config.agentId || process.env.TETHER_AGENT_ID || "";
|
|
112
112
|
const keyPath = config.privateKeyPath || process.env.TETHER_PRIVATE_KEY_PATH;
|
|
113
113
|
const hasKeyMaterial = keyPath || config.privateKeyPem || config.privateKeyBuffer;
|
|
114
114
|
if (hasKeyMaterial) {
|
|
@@ -122,7 +122,7 @@ var TetherClient = class {
|
|
|
122
122
|
}
|
|
123
123
|
if (!this.apiKey && !this.privateKey) {
|
|
124
124
|
}
|
|
125
|
-
if (!this.apiKey && !this.
|
|
125
|
+
if (!this.apiKey && !this.agentId) {
|
|
126
126
|
}
|
|
127
127
|
}
|
|
128
128
|
/**
|
|
@@ -156,15 +156,15 @@ var TetherClient = class {
|
|
|
156
156
|
}
|
|
157
157
|
}
|
|
158
158
|
/**
|
|
159
|
-
* Ensures
|
|
159
|
+
* Ensures an agent ID is available, throwing if not
|
|
160
160
|
*/
|
|
161
|
-
|
|
162
|
-
if (!this.
|
|
161
|
+
_requireAgentId() {
|
|
162
|
+
if (!this.agentId) {
|
|
163
163
|
throw new TetherError(
|
|
164
|
-
"
|
|
164
|
+
"Agent ID is required for this operation. Provide it in config or set TETHER_AGENT_ID environment variable."
|
|
165
165
|
);
|
|
166
166
|
}
|
|
167
|
-
return this.
|
|
167
|
+
return this.agentId;
|
|
168
168
|
}
|
|
169
169
|
/**
|
|
170
170
|
* Request a challenge from the Tether API
|
|
@@ -213,12 +213,12 @@ var TetherClient = class {
|
|
|
213
213
|
* Submit proof for a challenge
|
|
214
214
|
*/
|
|
215
215
|
async submitProof(challenge, proof) {
|
|
216
|
-
const
|
|
216
|
+
const agentId = this._requireAgentId();
|
|
217
217
|
try {
|
|
218
218
|
const payload = {
|
|
219
219
|
challenge,
|
|
220
220
|
proof,
|
|
221
|
-
|
|
221
|
+
agentId
|
|
222
222
|
};
|
|
223
223
|
const response = await fetch(`${this.baseUrl}/challenge/verify`, {
|
|
224
224
|
method: "POST",
|
|
@@ -242,6 +242,7 @@ var TetherClient = class {
|
|
|
242
242
|
agentName: data.agentName,
|
|
243
243
|
verifyUrl: data.verifyUrl,
|
|
244
244
|
email: data.email,
|
|
245
|
+
domain: data.domain,
|
|
245
246
|
registeredSince,
|
|
246
247
|
error: data.error,
|
|
247
248
|
challenge
|
|
@@ -285,16 +286,16 @@ var TetherClient = class {
|
|
|
285
286
|
/**
|
|
286
287
|
* Create a new agent
|
|
287
288
|
*/
|
|
288
|
-
async createAgent(agentName, description = "") {
|
|
289
|
+
async createAgent(agentName, description = "", domainId) {
|
|
289
290
|
this._requireApiKey();
|
|
290
291
|
try {
|
|
291
|
-
const response = await fetch(`${this.baseUrl}/
|
|
292
|
+
const response = await fetch(`${this.baseUrl}/agents/issue`, {
|
|
292
293
|
method: "POST",
|
|
293
294
|
headers: {
|
|
294
295
|
"Content-Type": "application/json",
|
|
295
296
|
...this._authHeaders()
|
|
296
297
|
},
|
|
297
|
-
body: JSON.stringify({ agentName, description })
|
|
298
|
+
body: JSON.stringify({ agentName, description, ...domainId ? { domainId } : {} })
|
|
298
299
|
});
|
|
299
300
|
if (!response.ok) {
|
|
300
301
|
const errorText = await response.text().catch(() => "Unknown error");
|
|
@@ -324,7 +325,7 @@ var TetherClient = class {
|
|
|
324
325
|
async listAgents() {
|
|
325
326
|
this._requireApiKey();
|
|
326
327
|
try {
|
|
327
|
-
const response = await fetch(`${this.baseUrl}/
|
|
328
|
+
const response = await fetch(`${this.baseUrl}/agents`, {
|
|
328
329
|
method: "GET",
|
|
329
330
|
headers: {
|
|
330
331
|
...this._authHeaders()
|
|
@@ -352,13 +353,47 @@ var TetherClient = class {
|
|
|
352
353
|
);
|
|
353
354
|
}
|
|
354
355
|
}
|
|
356
|
+
/**
|
|
357
|
+
* List all registered domains
|
|
358
|
+
*/
|
|
359
|
+
async listDomains() {
|
|
360
|
+
this._requireApiKey();
|
|
361
|
+
try {
|
|
362
|
+
const response = await fetch(`${this.baseUrl}/domains`, {
|
|
363
|
+
method: "GET",
|
|
364
|
+
headers: {
|
|
365
|
+
...this._authHeaders()
|
|
366
|
+
}
|
|
367
|
+
});
|
|
368
|
+
if (!response.ok) {
|
|
369
|
+
const errorText = await response.text().catch(() => "Unknown error");
|
|
370
|
+
throw new TetherAPIError(
|
|
371
|
+
`List domains failed: ${response.status} ${response.statusText}`,
|
|
372
|
+
response.status,
|
|
373
|
+
errorText
|
|
374
|
+
);
|
|
375
|
+
}
|
|
376
|
+
const data = await response.json();
|
|
377
|
+
return data;
|
|
378
|
+
} catch (error) {
|
|
379
|
+
if (error instanceof TetherError) {
|
|
380
|
+
throw error;
|
|
381
|
+
}
|
|
382
|
+
throw new TetherAPIError(
|
|
383
|
+
`Failed to list domains: ${error instanceof Error ? error.message : String(error)}`,
|
|
384
|
+
void 0,
|
|
385
|
+
void 0,
|
|
386
|
+
error instanceof Error ? error : void 0
|
|
387
|
+
);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
355
390
|
/**
|
|
356
391
|
* Delete an agent by ID
|
|
357
392
|
*/
|
|
358
393
|
async deleteAgent(agentId) {
|
|
359
394
|
this._requireApiKey();
|
|
360
395
|
try {
|
|
361
|
-
const response = await fetch(`${this.baseUrl}/
|
|
396
|
+
const response = await fetch(`${this.baseUrl}/agents/${agentId}`, {
|
|
362
397
|
method: "DELETE",
|
|
363
398
|
headers: {
|
|
364
399
|
...this._authHeaders()
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts","../src/crypto.ts","../src/client.ts"],"sourcesContent":["/**\n * Base error class for all Tether-related errors\n */\nexport class TetherError extends Error {\n constructor(message: string, public readonly cause?: Error) {\n super(message);\n this.name = 'TetherError';\n \n // Maintain proper stack trace for where our error was thrown (only available on V8)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, TetherError);\n }\n }\n}\n\n/**\n * Error thrown when verification fails\n */\nexport class TetherVerificationError extends TetherError {\n constructor(message: string, cause?: Error) {\n super(message, cause);\n this.name = 'TetherVerificationError';\n }\n}\n\n/**\n * Error thrown when API requests fail\n */\nexport class TetherAPIError extends TetherError {\n constructor(\n message: string,\n public readonly status?: number,\n public readonly response?: string,\n cause?: Error\n ) {\n super(message, cause);\n this.name = 'TetherAPIError';\n }\n}","import { createSign, createPrivateKey, KeyObject } from 'crypto';\nimport { readFileSync } from 'fs';\nimport { TetherError } from './errors.js';\nimport type { KeyFormat } from './types.js';\n\n/**\n * Imports a DER-encoded private key, trying PKCS#8 first then PKCS#1.\n */\nfunction importDerKey(derData: Buffer): KeyObject {\n try {\n return createPrivateKey({ key: derData, format: 'der', type: 'pkcs8' });\n } catch {\n // PKCS#8 failed — try PKCS#1\n }\n try {\n return createPrivateKey({ key: derData, format: 'der', type: 'pkcs1' });\n } catch {\n // PKCS#1 also failed\n }\n throw new TetherError(\n 'Failed to load DER private key: data is not valid PKCS#8 or PKCS#1. ' +\n 'Ensure the file is an RSA private key in DER format.'\n );\n}\n\n/**\n * Loads a private key from various sources\n */\nexport function loadPrivateKey(options: {\n keyPath?: string;\n keyPem?: string;\n keyBuffer?: Buffer;\n}): KeyObject {\n const { keyPath, keyPem, keyBuffer } = options;\n\n try {\n if (keyPem) {\n // PEM string provided directly\n return createPrivateKey(keyPem);\n }\n\n if (keyBuffer) {\n // DER buffer provided directly\n return importDerKey(keyBuffer);\n }\n\n if (keyPath) {\n // Read from file - detect format by extension or content\n const keyData = readFileSync(keyPath);\n\n // Try to detect format\n if (keyPath.endsWith('.pem') || keyData.toString().includes('-----BEGIN')) {\n // PEM format\n return createPrivateKey(keyData);\n } else {\n // Assume DER format\n return importDerKey(keyData);\n }\n }\n\n throw new TetherError('No private key provided');\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherError(\n `Failed to load private key: ${error instanceof Error ? error.message : String(error)}`,\n error instanceof Error ? error : undefined\n );\n }\n}\n\n/**\n * Signs a challenge string using RSA-SHA256\n * Returns URL-safe base64 encoded signature (no padding)\n */\nexport function signChallenge(privateKey: KeyObject, challenge: string): string {\n try {\n const sign = createSign('SHA256');\n sign.update(challenge);\n sign.end();\n \n const signature = sign.sign(privateKey);\n \n // Convert to URL-safe base64 without padding\n return signature\n .toString('base64')\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=/g, '');\n } catch (error) {\n throw new TetherError(\n `Failed to sign challenge: ${error instanceof Error ? error.message : String(error)}`,\n error instanceof Error ? error : undefined\n );\n }\n}\n\n/**\n * Utility function to detect key format from file extension or content\n */\nexport function detectKeyFormat(keyPath: string): KeyFormat {\n if (keyPath.endsWith('.pem')) {\n return 'pem';\n }\n if (keyPath.endsWith('.der')) {\n return 'der';\n }\n \n // Try to read a small portion to detect format\n try {\n const keyData = readFileSync(keyPath, { encoding: 'utf8', flag: 'r' });\n if (keyData.includes('-----BEGIN')) {\n return 'pem';\n }\n } catch {\n // If we can't read as text, it's probably DER\n }\n \n return 'der';\n}","import { KeyObject } from 'crypto';\nimport { TetherError, TetherAPIError, TetherVerificationError } from './errors.js';\nimport { loadPrivateKey, signChallenge } from './crypto.js';\nimport type {\n TetherClientConfig,\n ChallengeResponse,\n Agent,\n IssueCredentialResponse,\n VerificationRequest,\n VerificationResponse,\n VerificationResult\n} from './types.js';\n\n/**\n * TetherClient - Official SDK for tether.name agent identity verification\n */\nexport class TetherClient {\n private readonly credentialId: string;\n private readonly privateKey: KeyObject | null;\n private readonly baseUrl: string;\n private readonly apiKey?: string;\n\n constructor(config: TetherClientConfig) {\n // Set base URL\n this.baseUrl = 'https://api.tether.name';\n\n // Get API key from config or environment\n this.apiKey = config.apiKey || process.env.TETHER_API_KEY;\n\n // Get credential ID from config or environment\n this.credentialId = config.credentialId || process.env.TETHER_CREDENTIAL_ID || '';\n\n // Load private key if key material is provided\n const keyPath = config.privateKeyPath || process.env.TETHER_PRIVATE_KEY_PATH;\n const hasKeyMaterial = keyPath || config.privateKeyPem || config.privateKeyBuffer;\n\n if (hasKeyMaterial) {\n this.privateKey = loadPrivateKey({\n keyPath,\n keyPem: config.privateKeyPem,\n keyBuffer: config.privateKeyBuffer\n });\n } else {\n this.privateKey = null;\n }\n\n // If no API key and no private key, credential ID and key are still needed for verify/sign\n // but we defer the error to when those methods are called\n if (!this.apiKey && !this.privateKey) {\n // Allow construction — errors thrown at method call time\n }\n\n if (!this.apiKey && !this.credentialId) {\n // Allow construction — errors thrown at method call time\n }\n }\n\n /**\n * Returns authorization headers when an API key is configured\n */\n private _authHeaders(): Record<string, string> {\n if (this.apiKey) {\n return { 'Authorization': `Bearer ${this.apiKey}` };\n }\n return {};\n }\n\n /**\n * Ensures a private key is available, throwing if not\n */\n private _requirePrivateKey(): KeyObject {\n if (!this.privateKey) {\n throw new TetherError(\n 'Private key is required for this operation. Provide privateKeyPath, privateKeyPem, or privateKeyBuffer in config, or set TETHER_PRIVATE_KEY_PATH environment variable.'\n );\n }\n return this.privateKey;\n }\n\n /**\n * Ensures an API key is available, throwing if not\n */\n private _requireApiKey(): void {\n if (!this.apiKey) {\n throw new TetherError(\n 'API key is required for agent management operations. Provide apiKey in config or set TETHER_API_KEY environment variable.'\n );\n }\n }\n\n /**\n * Ensures a credential ID is available, throwing if not\n */\n private _requireCredentialId(): string {\n if (!this.credentialId) {\n throw new TetherError(\n 'Credential ID is required for this operation. Provide it in config or set TETHER_CREDENTIAL_ID environment variable.'\n );\n }\n return this.credentialId;\n }\n\n /**\n * Request a challenge from the Tether API\n */\n async requestChallenge(): Promise<string> {\n try {\n const response = await fetch(`${this.baseUrl}/challenge`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n }\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new TetherAPIError(\n `Challenge request failed: ${response.status} ${response.statusText}`,\n response.status,\n errorText\n );\n }\n\n const data = await response.json() as ChallengeResponse;\n\n if (!data.code) {\n throw new TetherAPIError('Invalid challenge response: missing code');\n }\n\n return data.code;\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherAPIError(\n `Failed to request challenge: ${error instanceof Error ? error.message : String(error)}`,\n undefined,\n undefined,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * Sign a challenge string\n */\n sign(challenge: string): string {\n const key = this._requirePrivateKey();\n return signChallenge(key, challenge);\n }\n\n /**\n * Submit proof for a challenge\n */\n async submitProof(challenge: string, proof: string): Promise<VerificationResult> {\n const credentialId = this._requireCredentialId();\n\n try {\n const payload: VerificationRequest = {\n challenge,\n proof,\n credentialId\n };\n\n const response = await fetch(`${this.baseUrl}/challenge/verify`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify(payload)\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new TetherAPIError(\n `Verification failed: ${response.status} ${response.statusText}`,\n response.status,\n errorText\n );\n }\n\n const data = await response.json() as VerificationResponse;\n\n // Convert API response to our result format\n const registeredSince = typeof data.registeredSince === 'number'\n ? new Date(data.registeredSince).toISOString()\n : data.registeredSince;\n\n return {\n verified: data.valid,\n agentName: data.agentName,\n verifyUrl: data.verifyUrl,\n email: data.email,\n registeredSince,\n error: data.error,\n challenge\n };\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherAPIError(\n `Failed to submit proof: ${error instanceof Error ? error.message : String(error)}`,\n undefined,\n undefined,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * Perform complete verification in one call\n */\n async verify(): Promise<VerificationResult> {\n try {\n const challenge = await this.requestChallenge();\n const proof = this.sign(challenge);\n const result = await this.submitProof(challenge, proof);\n\n if (!result.verified) {\n throw new TetherVerificationError(\n result.error || 'Verification failed for unknown reason'\n );\n }\n\n return result;\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherVerificationError(\n `Verification failed: ${error instanceof Error ? error.message : String(error)}`,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * Create a new agent\n */\n async createAgent(agentName: string, description: string = ''): Promise<Agent> {\n this._requireApiKey();\n try {\n const response = await fetch(`${this.baseUrl}/credentials/issue`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...this._authHeaders()\n },\n body: JSON.stringify({ agentName, description })\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new TetherAPIError(\n `Create agent failed: ${response.status} ${response.statusText}`,\n response.status,\n errorText\n );\n }\n\n const data = await response.json() as IssueCredentialResponse;\n return data;\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherAPIError(\n `Failed to create agent: ${error instanceof Error ? error.message : String(error)}`,\n undefined,\n undefined,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * List all agents\n */\n async listAgents(): Promise<Agent[]> {\n this._requireApiKey();\n try {\n const response = await fetch(`${this.baseUrl}/credentials`, {\n method: 'GET',\n headers: {\n ...this._authHeaders()\n }\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new TetherAPIError(\n `List agents failed: ${response.status} ${response.statusText}`,\n response.status,\n errorText\n );\n }\n\n const data = await response.json() as Agent[];\n return data;\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherAPIError(\n `Failed to list agents: ${error instanceof Error ? error.message : String(error)}`,\n undefined,\n undefined,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * Delete an agent by ID\n */\n async deleteAgent(agentId: string): Promise<boolean> {\n this._requireApiKey();\n try {\n const response = await fetch(`${this.baseUrl}/credentials/${agentId}`, {\n method: 'DELETE',\n headers: {\n ...this._authHeaders()\n }\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new TetherAPIError(\n `Delete agent failed: ${response.status} ${response.statusText}`,\n response.status,\n errorText\n );\n }\n\n return true;\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherAPIError(\n `Failed to delete agent: ${error instanceof Error ? error.message : String(error)}`,\n undefined,\n undefined,\n error instanceof Error ? error : undefined\n );\n }\n }\n}"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/crypto.ts","../src/client.ts"],"sourcesContent":["/**\n * Base error class for all Tether-related errors\n */\nexport class TetherError extends Error {\n constructor(message: string, public readonly cause?: Error) {\n super(message);\n this.name = 'TetherError';\n \n // Maintain proper stack trace for where our error was thrown (only available on V8)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, TetherError);\n }\n }\n}\n\n/**\n * Error thrown when verification fails\n */\nexport class TetherVerificationError extends TetherError {\n constructor(message: string, cause?: Error) {\n super(message, cause);\n this.name = 'TetherVerificationError';\n }\n}\n\n/**\n * Error thrown when API requests fail\n */\nexport class TetherAPIError extends TetherError {\n constructor(\n message: string,\n public readonly status?: number,\n public readonly response?: string,\n cause?: Error\n ) {\n super(message, cause);\n this.name = 'TetherAPIError';\n }\n}","import { createSign, createPrivateKey, KeyObject } from 'crypto';\nimport { readFileSync } from 'fs';\nimport { TetherError } from './errors.js';\nimport type { KeyFormat } from './types.js';\n\n/**\n * Imports a DER-encoded private key, trying PKCS#8 first then PKCS#1.\n */\nfunction importDerKey(derData: Buffer): KeyObject {\n try {\n return createPrivateKey({ key: derData, format: 'der', type: 'pkcs8' });\n } catch {\n // PKCS#8 failed — try PKCS#1\n }\n try {\n return createPrivateKey({ key: derData, format: 'der', type: 'pkcs1' });\n } catch {\n // PKCS#1 also failed\n }\n throw new TetherError(\n 'Failed to load DER private key: data is not valid PKCS#8 or PKCS#1. ' +\n 'Ensure the file is an RSA private key in DER format.'\n );\n}\n\n/**\n * Loads a private key from various sources\n */\nexport function loadPrivateKey(options: {\n keyPath?: string;\n keyPem?: string;\n keyBuffer?: Buffer;\n}): KeyObject {\n const { keyPath, keyPem, keyBuffer } = options;\n\n try {\n if (keyPem) {\n // PEM string provided directly\n return createPrivateKey(keyPem);\n }\n\n if (keyBuffer) {\n // DER buffer provided directly\n return importDerKey(keyBuffer);\n }\n\n if (keyPath) {\n // Read from file - detect format by extension or content\n const keyData = readFileSync(keyPath);\n\n // Try to detect format\n if (keyPath.endsWith('.pem') || keyData.toString().includes('-----BEGIN')) {\n // PEM format\n return createPrivateKey(keyData);\n } else {\n // Assume DER format\n return importDerKey(keyData);\n }\n }\n\n throw new TetherError('No private key provided');\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherError(\n `Failed to load private key: ${error instanceof Error ? error.message : String(error)}`,\n error instanceof Error ? error : undefined\n );\n }\n}\n\n/**\n * Signs a challenge string using RSA-SHA256\n * Returns URL-safe base64 encoded signature (no padding)\n */\nexport function signChallenge(privateKey: KeyObject, challenge: string): string {\n try {\n const sign = createSign('SHA256');\n sign.update(challenge);\n sign.end();\n \n const signature = sign.sign(privateKey);\n \n // Convert to URL-safe base64 without padding\n return signature\n .toString('base64')\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=/g, '');\n } catch (error) {\n throw new TetherError(\n `Failed to sign challenge: ${error instanceof Error ? error.message : String(error)}`,\n error instanceof Error ? error : undefined\n );\n }\n}\n\n/**\n * Utility function to detect key format from file extension or content\n */\nexport function detectKeyFormat(keyPath: string): KeyFormat {\n if (keyPath.endsWith('.pem')) {\n return 'pem';\n }\n if (keyPath.endsWith('.der')) {\n return 'der';\n }\n \n // Try to read a small portion to detect format\n try {\n const keyData = readFileSync(keyPath, { encoding: 'utf8', flag: 'r' });\n if (keyData.includes('-----BEGIN')) {\n return 'pem';\n }\n } catch {\n // If we can't read as text, it's probably DER\n }\n \n return 'der';\n}","import { KeyObject } from 'crypto';\nimport { TetherError, TetherAPIError, TetherVerificationError } from './errors.js';\nimport { loadPrivateKey, signChallenge } from './crypto.js';\nimport type {\n TetherClientConfig,\n ChallengeResponse,\n Agent,\n Domain,\n IssueAgentResponse,\n VerificationRequest,\n VerificationResponse,\n VerificationResult\n} from './types.js';\n\n/**\n * TetherClient - Official SDK for tether.name agent identity verification\n */\nexport class TetherClient {\n private readonly agentId: string;\n private readonly privateKey: KeyObject | null;\n private readonly baseUrl: string;\n private readonly apiKey?: string;\n\n constructor(config: TetherClientConfig) {\n // Set base URL\n this.baseUrl = 'https://api.tether.name';\n\n // Get API key from config or environment\n this.apiKey = config.apiKey || process.env.TETHER_API_KEY;\n\n // Get agent ID from config or environment\n this.agentId = config.agentId || process.env.TETHER_AGENT_ID || '';\n\n // Load private key if key material is provided\n const keyPath = config.privateKeyPath || process.env.TETHER_PRIVATE_KEY_PATH;\n const hasKeyMaterial = keyPath || config.privateKeyPem || config.privateKeyBuffer;\n\n if (hasKeyMaterial) {\n this.privateKey = loadPrivateKey({\n keyPath,\n keyPem: config.privateKeyPem,\n keyBuffer: config.privateKeyBuffer\n });\n } else {\n this.privateKey = null;\n }\n\n // If no API key and no private key, agent ID and key are still needed for verify/sign\n // but we defer the error to when those methods are called\n if (!this.apiKey && !this.privateKey) {\n // Allow construction — errors thrown at method call time\n }\n\n if (!this.apiKey && !this.agentId) {\n // Allow construction — errors thrown at method call time\n }\n }\n\n /**\n * Returns authorization headers when an API key is configured\n */\n private _authHeaders(): Record<string, string> {\n if (this.apiKey) {\n return { 'Authorization': `Bearer ${this.apiKey}` };\n }\n return {};\n }\n\n /**\n * Ensures a private key is available, throwing if not\n */\n private _requirePrivateKey(): KeyObject {\n if (!this.privateKey) {\n throw new TetherError(\n 'Private key is required for this operation. Provide privateKeyPath, privateKeyPem, or privateKeyBuffer in config, or set TETHER_PRIVATE_KEY_PATH environment variable.'\n );\n }\n return this.privateKey;\n }\n\n /**\n * Ensures an API key is available, throwing if not\n */\n private _requireApiKey(): void {\n if (!this.apiKey) {\n throw new TetherError(\n 'API key is required for agent management operations. Provide apiKey in config or set TETHER_API_KEY environment variable.'\n );\n }\n }\n\n /**\n * Ensures an agent ID is available, throwing if not\n */\n private _requireAgentId(): string {\n if (!this.agentId) {\n throw new TetherError(\n 'Agent ID is required for this operation. Provide it in config or set TETHER_AGENT_ID environment variable.'\n );\n }\n return this.agentId;\n }\n\n /**\n * Request a challenge from the Tether API\n */\n async requestChallenge(): Promise<string> {\n try {\n const response = await fetch(`${this.baseUrl}/challenge`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n }\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new TetherAPIError(\n `Challenge request failed: ${response.status} ${response.statusText}`,\n response.status,\n errorText\n );\n }\n\n const data = await response.json() as ChallengeResponse;\n\n if (!data.code) {\n throw new TetherAPIError('Invalid challenge response: missing code');\n }\n\n return data.code;\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherAPIError(\n `Failed to request challenge: ${error instanceof Error ? error.message : String(error)}`,\n undefined,\n undefined,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * Sign a challenge string\n */\n sign(challenge: string): string {\n const key = this._requirePrivateKey();\n return signChallenge(key, challenge);\n }\n\n /**\n * Submit proof for a challenge\n */\n async submitProof(challenge: string, proof: string): Promise<VerificationResult> {\n const agentId = this._requireAgentId();\n\n try {\n const payload: VerificationRequest = {\n challenge,\n proof,\n agentId\n };\n\n const response = await fetch(`${this.baseUrl}/challenge/verify`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify(payload)\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new TetherAPIError(\n `Verification failed: ${response.status} ${response.statusText}`,\n response.status,\n errorText\n );\n }\n\n const data = await response.json() as VerificationResponse;\n\n // Convert API response to our result format\n const registeredSince = typeof data.registeredSince === 'number'\n ? new Date(data.registeredSince).toISOString()\n : data.registeredSince;\n\n return {\n verified: data.valid,\n agentName: data.agentName,\n verifyUrl: data.verifyUrl,\n email: data.email,\n domain: data.domain,\n registeredSince,\n error: data.error,\n challenge\n };\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherAPIError(\n `Failed to submit proof: ${error instanceof Error ? error.message : String(error)}`,\n undefined,\n undefined,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * Perform complete verification in one call\n */\n async verify(): Promise<VerificationResult> {\n try {\n const challenge = await this.requestChallenge();\n const proof = this.sign(challenge);\n const result = await this.submitProof(challenge, proof);\n\n if (!result.verified) {\n throw new TetherVerificationError(\n result.error || 'Verification failed for unknown reason'\n );\n }\n\n return result;\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherVerificationError(\n `Verification failed: ${error instanceof Error ? error.message : String(error)}`,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * Create a new agent\n */\n async createAgent(agentName: string, description: string = '', domainId?: string): Promise<Agent> {\n this._requireApiKey();\n try {\n const response = await fetch(`${this.baseUrl}/agents/issue`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...this._authHeaders()\n },\n body: JSON.stringify({ agentName, description, ...(domainId ? { domainId } : {}) })\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new TetherAPIError(\n `Create agent failed: ${response.status} ${response.statusText}`,\n response.status,\n errorText\n );\n }\n\n const data = await response.json() as IssueAgentResponse;\n return data;\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherAPIError(\n `Failed to create agent: ${error instanceof Error ? error.message : String(error)}`,\n undefined,\n undefined,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * List all agents\n */\n async listAgents(): Promise<Agent[]> {\n this._requireApiKey();\n try {\n const response = await fetch(`${this.baseUrl}/agents`, {\n method: 'GET',\n headers: {\n ...this._authHeaders()\n }\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new TetherAPIError(\n `List agents failed: ${response.status} ${response.statusText}`,\n response.status,\n errorText\n );\n }\n\n const data = await response.json() as Agent[];\n return data;\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherAPIError(\n `Failed to list agents: ${error instanceof Error ? error.message : String(error)}`,\n undefined,\n undefined,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * List all registered domains\n */\n async listDomains(): Promise<Domain[]> {\n this._requireApiKey();\n try {\n const response = await fetch(`${this.baseUrl}/domains`, {\n method: 'GET',\n headers: {\n ...this._authHeaders()\n }\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new TetherAPIError(\n `List domains failed: ${response.status} ${response.statusText}`,\n response.status,\n errorText\n );\n }\n\n const data = await response.json() as Domain[];\n return data;\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherAPIError(\n `Failed to list domains: ${error instanceof Error ? error.message : String(error)}`,\n undefined,\n undefined,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * Delete an agent by ID\n */\n async deleteAgent(agentId: string): Promise<boolean> {\n this._requireApiKey();\n try {\n const response = await fetch(`${this.baseUrl}/agents/${agentId}`, {\n method: 'DELETE',\n headers: {\n ...this._authHeaders()\n }\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new TetherAPIError(\n `Delete agent failed: ${response.status} ${response.statusText}`,\n response.status,\n errorText\n );\n }\n\n return true;\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherAPIError(\n `Failed to delete agent: ${error instanceof Error ? error.message : String(error)}`,\n undefined,\n undefined,\n error instanceof Error ? error : undefined\n );\n }\n }\n}\n"],"mappings":";AAGO,IAAM,cAAN,MAAM,qBAAoB,MAAM;AAAA,EACrC,YAAY,SAAiC,OAAe;AAC1D,UAAM,OAAO;AAD8B;AAE3C,SAAK,OAAO;AAGZ,QAAI,MAAM,mBAAmB;AAC3B,YAAM,kBAAkB,MAAM,YAAW;AAAA,IAC3C;AAAA,EACF;AACF;AAKO,IAAM,0BAAN,cAAsC,YAAY;AAAA,EACvD,YAAY,SAAiB,OAAe;AAC1C,UAAM,SAAS,KAAK;AACpB,SAAK,OAAO;AAAA,EACd;AACF;AAKO,IAAM,iBAAN,cAA6B,YAAY;AAAA,EAC9C,YACE,SACgB,QACA,UAChB,OACA;AACA,UAAM,SAAS,KAAK;AAJJ;AACA;AAIhB,SAAK,OAAO;AAAA,EACd;AACF;;;ACtCA,SAAS,YAAY,wBAAmC;AACxD,SAAS,oBAAoB;AAO7B,SAAS,aAAa,SAA4B;AAChD,MAAI;AACF,WAAO,iBAAiB,EAAE,KAAK,SAAS,QAAQ,OAAO,MAAM,QAAQ,CAAC;AAAA,EACxE,QAAQ;AAAA,EAER;AACA,MAAI;AACF,WAAO,iBAAiB,EAAE,KAAK,SAAS,QAAQ,OAAO,MAAM,QAAQ,CAAC;AAAA,EACxE,QAAQ;AAAA,EAER;AACA,QAAM,IAAI;AAAA,IACR;AAAA,EAEF;AACF;AAKO,SAAS,eAAe,SAIjB;AACZ,QAAM,EAAE,SAAS,QAAQ,UAAU,IAAI;AAEvC,MAAI;AACF,QAAI,QAAQ;AAEV,aAAO,iBAAiB,MAAM;AAAA,IAChC;AAEA,QAAI,WAAW;AAEb,aAAO,aAAa,SAAS;AAAA,IAC/B;AAEA,QAAI,SAAS;AAEX,YAAM,UAAU,aAAa,OAAO;AAGpC,UAAI,QAAQ,SAAS,MAAM,KAAK,QAAQ,SAAS,EAAE,SAAS,YAAY,GAAG;AAEzE,eAAO,iBAAiB,OAAO;AAAA,MACjC,OAAO;AAEL,eAAO,aAAa,OAAO;AAAA,MAC7B;AAAA,IACF;AAEA,UAAM,IAAI,YAAY,yBAAyB;AAAA,EACjD,SAAS,OAAO;AACd,QAAI,iBAAiB,aAAa;AAChC,YAAM;AAAA,IACR;AACA,UAAM,IAAI;AAAA,MACR,+BAA+B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,MACrF,iBAAiB,QAAQ,QAAQ;AAAA,IACnC;AAAA,EACF;AACF;AAMO,SAAS,cAAc,YAAuB,WAA2B;AAC9E,MAAI;AACF,UAAM,OAAO,WAAW,QAAQ;AAChC,SAAK,OAAO,SAAS;AACrB,SAAK,IAAI;AAET,UAAM,YAAY,KAAK,KAAK,UAAU;AAGtC,WAAO,UACJ,SAAS,QAAQ,EACjB,QAAQ,OAAO,GAAG,EAClB,QAAQ,OAAO,GAAG,EAClB,QAAQ,MAAM,EAAE;AAAA,EACrB,SAAS,OAAO;AACd,UAAM,IAAI;AAAA,MACR,6BAA6B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,MACnF,iBAAiB,QAAQ,QAAQ;AAAA,IACnC;AAAA,EACF;AACF;AAKO,SAAS,gBAAgB,SAA4B;AAC1D,MAAI,QAAQ,SAAS,MAAM,GAAG;AAC5B,WAAO;AAAA,EACT;AACA,MAAI,QAAQ,SAAS,MAAM,GAAG;AAC5B,WAAO;AAAA,EACT;AAGA,MAAI;AACF,UAAM,UAAU,aAAa,SAAS,EAAE,UAAU,QAAQ,MAAM,IAAI,CAAC;AACrE,QAAI,QAAQ,SAAS,YAAY,GAAG;AAClC,aAAO;AAAA,IACT;AAAA,EACF,QAAQ;AAAA,EAER;AAEA,SAAO;AACT;;;ACvGO,IAAM,eAAN,MAAmB;AAAA,EACP;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,QAA4B;AAEtC,SAAK,UAAU;AAGf,SAAK,SAAS,OAAO,UAAU,QAAQ,IAAI;AAG3C,SAAK,UAAU,OAAO,WAAW,QAAQ,IAAI,mBAAmB;AAGhE,UAAM,UAAU,OAAO,kBAAkB,QAAQ,IAAI;AACrD,UAAM,iBAAiB,WAAW,OAAO,iBAAiB,OAAO;AAEjE,QAAI,gBAAgB;AAClB,WAAK,aAAa,eAAe;AAAA,QAC/B;AAAA,QACA,QAAQ,OAAO;AAAA,QACf,WAAW,OAAO;AAAA,MACpB,CAAC;AAAA,IACH,OAAO;AACL,WAAK,aAAa;AAAA,IACpB;AAIA,QAAI,CAAC,KAAK,UAAU,CAAC,KAAK,YAAY;AAAA,IAEtC;AAEA,QAAI,CAAC,KAAK,UAAU,CAAC,KAAK,SAAS;AAAA,IAEnC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,eAAuC;AAC7C,QAAI,KAAK,QAAQ;AACf,aAAO,EAAE,iBAAiB,UAAU,KAAK,MAAM,GAAG;AAAA,IACpD;AACA,WAAO,CAAC;AAAA,EACV;AAAA;AAAA;AAAA;AAAA,EAKQ,qBAAgC;AACtC,QAAI,CAAC,KAAK,YAAY;AACpB,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AACA,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKQ,iBAAuB;AAC7B,QAAI,CAAC,KAAK,QAAQ;AAChB,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,kBAA0B;AAChC,QAAI,CAAC,KAAK,SAAS;AACjB,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AACA,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,mBAAoC;AACxC,QAAI;AACF,YAAM,WAAW,MAAM,MAAM,GAAG,KAAK,OAAO,cAAc;AAAA,QACxD,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,gBAAgB;AAAA,QAClB;AAAA,MACF,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,YAAY,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,eAAe;AACnE,cAAM,IAAI;AAAA,UACR,6BAA6B,SAAS,MAAM,IAAI,SAAS,UAAU;AAAA,UACnE,SAAS;AAAA,UACT;AAAA,QACF;AAAA,MACF;AAEA,YAAM,OAAO,MAAM,SAAS,KAAK;AAEjC,UAAI,CAAC,KAAK,MAAM;AACd,cAAM,IAAI,eAAe,0CAA0C;AAAA,MACrE;AAEA,aAAO,KAAK;AAAA,IACd,SAAS,OAAO;AACd,UAAI,iBAAiB,aAAa;AAChC,cAAM;AAAA,MACR;AACA,YAAM,IAAI;AAAA,QACR,gCAAgC,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,QACtF;AAAA,QACA;AAAA,QACA,iBAAiB,QAAQ,QAAQ;AAAA,MACnC;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,KAAK,WAA2B;AAC9B,UAAM,MAAM,KAAK,mBAAmB;AACpC,WAAO,cAAc,KAAK,SAAS;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YAAY,WAAmB,OAA4C;AAC/E,UAAM,UAAU,KAAK,gBAAgB;AAErC,QAAI;AACF,YAAM,UAA+B;AAAA,QACnC;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAEA,YAAM,WAAW,MAAM,MAAM,GAAG,KAAK,OAAO,qBAAqB;AAAA,QAC/D,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,gBAAgB;AAAA,QAClB;AAAA,QACA,MAAM,KAAK,UAAU,OAAO;AAAA,MAC9B,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,YAAY,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,eAAe;AACnE,cAAM,IAAI;AAAA,UACR,wBAAwB,SAAS,MAAM,IAAI,SAAS,UAAU;AAAA,UAC9D,SAAS;AAAA,UACT;AAAA,QACF;AAAA,MACF;AAEA,YAAM,OAAO,MAAM,SAAS,KAAK;AAGjC,YAAM,kBAAkB,OAAO,KAAK,oBAAoB,WACpD,IAAI,KAAK,KAAK,eAAe,EAAE,YAAY,IAC3C,KAAK;AAET,aAAO;AAAA,QACL,UAAU,KAAK;AAAA,QACf,WAAW,KAAK;AAAA,QAChB,WAAW,KAAK;AAAA,QAChB,OAAO,KAAK;AAAA,QACZ,QAAQ,KAAK;AAAA,QACb;AAAA,QACA,OAAO,KAAK;AAAA,QACZ;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AACd,UAAI,iBAAiB,aAAa;AAChC,cAAM;AAAA,MACR;AACA,YAAM,IAAI;AAAA,QACR,2BAA2B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,QACjF;AAAA,QACA;AAAA,QACA,iBAAiB,QAAQ,QAAQ;AAAA,MACnC;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,SAAsC;AAC1C,QAAI;AACF,YAAM,YAAY,MAAM,KAAK,iBAAiB;AAC9C,YAAM,QAAQ,KAAK,KAAK,SAAS;AACjC,YAAM,SAAS,MAAM,KAAK,YAAY,WAAW,KAAK;AAEtD,UAAI,CAAC,OAAO,UAAU;AACpB,cAAM,IAAI;AAAA,UACR,OAAO,SAAS;AAAA,QAClB;AAAA,MACF;AAEA,aAAO;AAAA,IACT,SAAS,OAAO;AACd,UAAI,iBAAiB,aAAa;AAChC,cAAM;AAAA,MACR;AACA,YAAM,IAAI;AAAA,QACR,wBAAwB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,QAC9E,iBAAiB,QAAQ,QAAQ;AAAA,MACnC;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YAAY,WAAmB,cAAsB,IAAI,UAAmC;AAChG,SAAK,eAAe;AACpB,QAAI;AACF,YAAM,WAAW,MAAM,MAAM,GAAG,KAAK,OAAO,iBAAiB;AAAA,QAC3D,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,gBAAgB;AAAA,UAChB,GAAG,KAAK,aAAa;AAAA,QACvB;AAAA,QACA,MAAM,KAAK,UAAU,EAAE,WAAW,aAAa,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC,EAAG,CAAC;AAAA,MACpF,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,YAAY,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,eAAe;AACnE,cAAM,IAAI;AAAA,UACR,wBAAwB,SAAS,MAAM,IAAI,SAAS,UAAU;AAAA,UAC9D,SAAS;AAAA,UACT;AAAA,QACF;AAAA,MACF;AAEA,YAAM,OAAO,MAAM,SAAS,KAAK;AACjC,aAAO;AAAA,IACT,SAAS,OAAO;AACd,UAAI,iBAAiB,aAAa;AAChC,cAAM;AAAA,MACR;AACA,YAAM,IAAI;AAAA,QACR,2BAA2B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,QACjF;AAAA,QACA;AAAA,QACA,iBAAiB,QAAQ,QAAQ;AAAA,MACnC;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aAA+B;AACnC,SAAK,eAAe;AACpB,QAAI;AACF,YAAM,WAAW,MAAM,MAAM,GAAG,KAAK,OAAO,WAAW;AAAA,QACrD,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,GAAG,KAAK,aAAa;AAAA,QACvB;AAAA,MACF,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,YAAY,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,eAAe;AACnE,cAAM,IAAI;AAAA,UACR,uBAAuB,SAAS,MAAM,IAAI,SAAS,UAAU;AAAA,UAC7D,SAAS;AAAA,UACT;AAAA,QACF;AAAA,MACF;AAEA,YAAM,OAAO,MAAM,SAAS,KAAK;AACjC,aAAO;AAAA,IACT,SAAS,OAAO;AACd,UAAI,iBAAiB,aAAa;AAChC,cAAM;AAAA,MACR;AACA,YAAM,IAAI;AAAA,QACR,0BAA0B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,QAChF;AAAA,QACA;AAAA,QACA,iBAAiB,QAAQ,QAAQ;AAAA,MACnC;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cAAiC;AACrC,SAAK,eAAe;AACpB,QAAI;AACF,YAAM,WAAW,MAAM,MAAM,GAAG,KAAK,OAAO,YAAY;AAAA,QACtD,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,GAAG,KAAK,aAAa;AAAA,QACvB;AAAA,MACF,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,YAAY,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,eAAe;AACnE,cAAM,IAAI;AAAA,UACR,wBAAwB,SAAS,MAAM,IAAI,SAAS,UAAU;AAAA,UAC9D,SAAS;AAAA,UACT;AAAA,QACF;AAAA,MACF;AAEA,YAAM,OAAO,MAAM,SAAS,KAAK;AACjC,aAAO;AAAA,IACT,SAAS,OAAO;AACd,UAAI,iBAAiB,aAAa;AAChC,cAAM;AAAA,MACR;AACA,YAAM,IAAI;AAAA,QACR,2BAA2B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,QACjF;AAAA,QACA;AAAA,QACA,iBAAiB,QAAQ,QAAQ;AAAA,MACnC;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YAAY,SAAmC;AACnD,SAAK,eAAe;AACpB,QAAI;AACF,YAAM,WAAW,MAAM,MAAM,GAAG,KAAK,OAAO,WAAW,OAAO,IAAI;AAAA,QAChE,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,GAAG,KAAK,aAAa;AAAA,QACvB;AAAA,MACF,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,YAAY,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,eAAe;AACnE,cAAM,IAAI;AAAA,UACR,wBAAwB,SAAS,MAAM,IAAI,SAAS,UAAU;AAAA,UAC9D,SAAS;AAAA,UACT;AAAA,QACF;AAAA,MACF;AAEA,aAAO;AAAA,IACT,SAAS,OAAO;AACd,UAAI,iBAAiB,aAAa;AAChC,cAAM;AAAA,MACR;AACA,YAAM,IAAI;AAAA,QACR,2BAA2B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,QACjF;AAAA,QACA;AAAA,QACA,iBAAiB,QAAQ,QAAQ;AAAA,MACnC;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tether-name",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "Official Node.js SDK for tether.name - AI agent identity verification",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"homepage": "https://tether.name",
|
|
35
35
|
"repository": {
|
|
36
36
|
"type": "git",
|
|
37
|
-
"url": "https://github.com/tether-name/tether-name-node.git"
|
|
37
|
+
"url": "git+https://github.com/tether-name/tether-name-node.git"
|
|
38
38
|
},
|
|
39
39
|
"bugs": {
|
|
40
40
|
"url": "https://github.com/tether-name/tether-name-node/issues"
|