@terminal3/t3n-sdk 0.2.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/LICENSE +21 -0
- package/README.OIDC.md +216 -0
- package/README.md +639 -0
- package/dist/demo.d.ts +25 -0
- package/dist/index.d.ts +819 -0
- package/dist/index.esm.js +2 -0
- package/dist/index.js +2 -0
- package/dist/src/client/actions.d.ts +17 -0
- package/dist/src/client/config.d.ts +35 -0
- package/dist/src/client/encryption.d.ts +30 -0
- package/dist/src/client/handlers.d.ts +45 -0
- package/dist/src/client/index.d.ts +10 -0
- package/dist/src/client/request-parser.d.ts +48 -0
- package/dist/src/client/t3n-client.d.ts +70 -0
- package/dist/src/client/transport.d.ts +107 -0
- package/dist/src/config/index.d.ts +67 -0
- package/dist/src/config/loader.d.ts +11 -0
- package/dist/src/config/types.d.ts +25 -0
- package/dist/src/index.d.ts +23 -0
- package/dist/src/types/auth.d.ts +54 -0
- package/dist/src/types/index.d.ts +35 -0
- package/dist/src/types/session.d.ts +24 -0
- package/dist/src/utils/contract-version.d.ts +5 -0
- package/dist/src/utils/crypto.d.ts +52 -0
- package/dist/src/utils/errors.d.ts +61 -0
- package/dist/src/utils/index.d.ts +9 -0
- package/dist/src/utils/logger.d.ts +102 -0
- package/dist/src/utils/redaction.d.ts +13 -0
- package/dist/src/utils/session.d.ts +37 -0
- package/dist/src/wasm/index.d.ts +5 -0
- package/dist/src/wasm/interface.d.ts +105 -0
- package/dist/src/wasm/loader.d.ts +43 -0
- package/dist/wasm/generated/interfaces/component-session-client-auth.d.ts +12 -0
- package/dist/wasm/generated/interfaces/component-session-client-handshake.d.ts +12 -0
- package/dist/wasm/generated/interfaces/component-session-server-auth.d.ts +12 -0
- package/dist/wasm/generated/interfaces/component-session-server-handshake.d.ts +12 -0
- package/dist/wasm/generated/interfaces/component-session-session.d.ts +8 -0
- package/dist/wasm/generated/interfaces/wasi-cli-environment.d.ts +2 -0
- package/dist/wasm/generated/interfaces/wasi-cli-exit.d.ts +3 -0
- package/dist/wasm/generated/interfaces/wasi-cli-stderr.d.ts +3 -0
- package/dist/wasm/generated/interfaces/wasi-cli-stdin.d.ts +3 -0
- package/dist/wasm/generated/interfaces/wasi-cli-stdout.d.ts +3 -0
- package/dist/wasm/generated/interfaces/wasi-clocks-wall-clock.d.ts +5 -0
- package/dist/wasm/generated/interfaces/wasi-filesystem-preopens.d.ts +3 -0
- package/dist/wasm/generated/interfaces/wasi-filesystem-types.d.ts +124 -0
- package/dist/wasm/generated/interfaces/wasi-io-error.d.ts +8 -0
- package/dist/wasm/generated/interfaces/wasi-io-streams.d.ts +28 -0
- package/dist/wasm/generated/session.core.wasm +0 -0
- package/dist/wasm/generated/session.core2.wasm +0 -0
- package/dist/wasm/generated/session.d.ts +16 -0
- package/dist/wasm/generated/session.js +3437 -0
- package/package.json +104 -0
package/README.md
ADDED
|
@@ -0,0 +1,639 @@
|
|
|
1
|
+
# T3n TypeScript SDK
|
|
2
|
+
|
|
3
|
+
A minimal TypeScript SDK that mirrors the server's RPC handler approach, keeping all state machine logic hidden in WASM and providing a clean, agnostic wrapper that doesn't expose authentication methods or internal states.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Simple API**: Clean, minimal interface that's easy to use
|
|
8
|
+
- **Method Agnostic**: Supports multiple authentication methods (Ethereum, OIDC) without exposing implementation details
|
|
9
|
+
- **WASM-Powered**: All cryptographic complexity and state machine logic isolated in WASM components
|
|
10
|
+
- **Type Safe**: Full TypeScript support with comprehensive type definitions
|
|
11
|
+
- **Secure**: Encrypted communication with T3n nodes
|
|
12
|
+
- **Extensible**: Easy to add new authentication methods without changing TypeScript code
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pnpm add @terminal3/t3n-sdk
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Quick Start
|
|
21
|
+
|
|
22
|
+
### Basic Usage
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
import {
|
|
26
|
+
T3nClient,
|
|
27
|
+
loadWasmComponent,
|
|
28
|
+
createEthAuthInput,
|
|
29
|
+
eth_get_address,
|
|
30
|
+
eth_sign,
|
|
31
|
+
} from "@terminal3/t3n-sdk";
|
|
32
|
+
|
|
33
|
+
const wasmComponent = await loadWasmComponent();
|
|
34
|
+
const privateKey = process.env.T3N_DEMO_KEY!;
|
|
35
|
+
|
|
36
|
+
const client = new T3nClient({
|
|
37
|
+
baseUrl: "https://t3n-node.example.com",
|
|
38
|
+
wasmComponent,
|
|
39
|
+
handlers: {
|
|
40
|
+
EthSign: eth_sign(privateKey),
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
await client.startHandshake();
|
|
45
|
+
|
|
46
|
+
const did = await client.authenticate(
|
|
47
|
+
createEthAuthInput(eth_get_address(privateKey))
|
|
48
|
+
);
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Ethereum Authentication
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
import {
|
|
55
|
+
T3nClient,
|
|
56
|
+
createEthAuthInput,
|
|
57
|
+
eth_get_address,
|
|
58
|
+
eth_sign,
|
|
59
|
+
} from "@terminal3/t3n-sdk";
|
|
60
|
+
|
|
61
|
+
const privateKey = "0x...";
|
|
62
|
+
|
|
63
|
+
const client = new T3nClient({
|
|
64
|
+
wasmComponent: await loadWasmComponent(),
|
|
65
|
+
handlers: {
|
|
66
|
+
EthSign: eth_sign(privateKey),
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
await client.startHandshake();
|
|
71
|
+
const did = await client.authenticate(
|
|
72
|
+
createEthAuthInput(eth_get_address(privateKey))
|
|
73
|
+
);
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### OIDC Authentication
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
import { createOidcAuthInput } from "@terminal3/t3n-sdk";
|
|
80
|
+
|
|
81
|
+
const oidcCredentials = {
|
|
82
|
+
provider: "google",
|
|
83
|
+
idToken: "jwt_token_here",
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const did = await client.authenticate(createOidcAuthInput(oidcCredentials));
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Architecture
|
|
90
|
+
|
|
91
|
+
The T3n SDK follows the same architectural principles as the server's `rpc.rs`:
|
|
92
|
+
|
|
93
|
+
- **Completely agnostic** about authentication methods (Ethereum, OIDC, etc.)
|
|
94
|
+
- **No knowledge** of internal state machine phases or details
|
|
95
|
+
- **Simply calls** WASM `next()` and eagerly tries to `finish()`
|
|
96
|
+
- **Lets WASM handle** all the complexity internally
|
|
97
|
+
- **Works with** completely opaque byte arrays (just like the WIT interface)
|
|
98
|
+
|
|
99
|
+
### What's Hidden in WASM (Everything Important)
|
|
100
|
+
|
|
101
|
+
- All state machine phases and transitions
|
|
102
|
+
- Authentication method-specific logic (challenge/response, OIDC flows, signature verification)
|
|
103
|
+
- Cryptographic operations and key derivation
|
|
104
|
+
- Protocol-specific message formatting and parsing
|
|
105
|
+
- Error handling and retry logic
|
|
106
|
+
- Internal state representations (all states are opaque byte arrays)
|
|
107
|
+
|
|
108
|
+
### What's Exposed in TypeScript (Minimal Surface)
|
|
109
|
+
|
|
110
|
+
- Input helpers only: `createEthAuthInput`, `createOidcAuthInput`, and signer handlers
|
|
111
|
+
- High-level status: Just mirrors server's `SessionStatus` enum
|
|
112
|
+
- Simple API methods: `startHandshake()`, `authenticate()`
|
|
113
|
+
- Basic configuration: `baseUrl`, `sessionId`
|
|
114
|
+
- Opaque state management: Byte arrays we never interpret
|
|
115
|
+
|
|
116
|
+
## API Reference
|
|
117
|
+
|
|
118
|
+
### T3nClient
|
|
119
|
+
|
|
120
|
+
The main client class for interacting with T3n nodes.
|
|
121
|
+
|
|
122
|
+
#### Constructor
|
|
123
|
+
|
|
124
|
+
```typescript
|
|
125
|
+
new T3nClient(config: T3nClientConfig)
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
#### Methods
|
|
129
|
+
|
|
130
|
+
- `startHandshake(): Promise<void>` - Establish secure session with the node
|
|
131
|
+
- `authenticate(authInput: AuthInput): Promise<Did>` - Authenticate using provided credentials
|
|
132
|
+
- `getSessionId(): SessionId` - Get current session ID
|
|
133
|
+
- `getStatus(): SessionStatus` - Get current session status
|
|
134
|
+
- `getDid(): Did | null` - Get authenticated DID (null if not authenticated)
|
|
135
|
+
- `isAuthenticated(): boolean` - Check if client is authenticated
|
|
136
|
+
|
|
137
|
+
### Types
|
|
138
|
+
|
|
139
|
+
#### SessionStatus
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
enum SessionStatus {
|
|
143
|
+
Init = 0,
|
|
144
|
+
Encrypted = 1,
|
|
145
|
+
Authenticated = 2,
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
#### AuthInput
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
enum AuthMethod {
|
|
153
|
+
Ethereum = "eth",
|
|
154
|
+
OIDC = "oidc",
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
interface EthAuthInput {
|
|
158
|
+
method: AuthMethod.Ethereum;
|
|
159
|
+
address: string;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
interface OidcCredentials {
|
|
163
|
+
provider: string;
|
|
164
|
+
idToken: string;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
interface OidcAuthInput {
|
|
168
|
+
method: AuthMethod.OIDC;
|
|
169
|
+
credentials: OidcCredentials;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
type AuthInput = EthAuthInput | OidcAuthInput;
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Helper utilities:
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
createEthAuthInput(address: string): EthAuthInput;
|
|
179
|
+
createOidcAuthInput(credentials: OidcCredentials): OidcAuthInput;
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## Error Handling
|
|
183
|
+
|
|
184
|
+
The SDK provides specific error types for different failure scenarios:
|
|
185
|
+
|
|
186
|
+
```typescript
|
|
187
|
+
import {
|
|
188
|
+
T3nError,
|
|
189
|
+
SessionStateError,
|
|
190
|
+
AuthenticationError,
|
|
191
|
+
HandshakeError,
|
|
192
|
+
RpcError
|
|
193
|
+
} from '@terminal3/t3n-sdk';
|
|
194
|
+
|
|
195
|
+
try {
|
|
196
|
+
await client.authenticate(signer);
|
|
197
|
+
} catch (error) {
|
|
198
|
+
if (error instanceof AuthenticationError) {
|
|
199
|
+
console.log('Authentication failed:', error.message);
|
|
200
|
+
} else if (error instanceof SessionStateError) {
|
|
201
|
+
console.log('Invalid session state:', error.currentState);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
## Configuration
|
|
207
|
+
|
|
208
|
+
### T3nClientConfig
|
|
209
|
+
|
|
210
|
+
```typescript
|
|
211
|
+
interface T3nClientConfig {
|
|
212
|
+
baseUrl?: string; // T3n node URL (defaults to "http://localhost:3000" if not provided)
|
|
213
|
+
wasmComponent: WasmComponent; // WASM component instance
|
|
214
|
+
transport?: Transport; // Optional transport layer (uses HttpTransport with baseUrl if not provided)
|
|
215
|
+
sessionId?: SessionId; // Optional custom session ID
|
|
216
|
+
timeout?: number; // Request timeout (default: 30000ms)
|
|
217
|
+
headers?: Record<string, string>; // Custom headers
|
|
218
|
+
logLevel?: LogLevel; // Log level for this client (defaults to global log level, which is LogLevel.ERROR)
|
|
219
|
+
logger?: Logger; // Optional custom logger (overrides logLevel if provided)
|
|
220
|
+
handlers?: GuestToHostHandlers; // Optional guest-to-host request handlers
|
|
221
|
+
}
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Example with Custom Configuration
|
|
225
|
+
|
|
226
|
+
```typescript
|
|
227
|
+
import { T3nClient, LogLevel } from '@terminal3/t3n-sdk';
|
|
228
|
+
|
|
229
|
+
const client = new T3nClient({
|
|
230
|
+
baseUrl: "https://t3n-node.example.com",
|
|
231
|
+
wasmComponent: await loadWasmComponent(),
|
|
232
|
+
timeout: 60000, // 60 second timeout
|
|
233
|
+
logLevel: LogLevel.DEBUG, // Enable debug logging
|
|
234
|
+
headers: {
|
|
235
|
+
'User-Agent': 'MyApp/1.0.0',
|
|
236
|
+
'X-Custom-Header': 'custom-value'
|
|
237
|
+
},
|
|
238
|
+
handlers: {
|
|
239
|
+
EthSign: eth_sign(privateKey),
|
|
240
|
+
MlKemPublicKey: ml_kem_public_key(),
|
|
241
|
+
Random: random(),
|
|
242
|
+
}
|
|
243
|
+
});
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
## Logging
|
|
247
|
+
|
|
248
|
+
The T3n SDK provides flexible logging capabilities with hierarchical log levels, allowing you to control verbosity for debugging and monitoring purposes.
|
|
249
|
+
|
|
250
|
+
### Log Levels
|
|
251
|
+
|
|
252
|
+
The SDK supports four log levels in hierarchical order (from most to least verbose):
|
|
253
|
+
|
|
254
|
+
- **`LogLevel.DEBUG`** (0) - Most verbose, includes all log messages
|
|
255
|
+
- **`LogLevel.INFO`** (1) - Informational messages, warnings, and errors
|
|
256
|
+
- **`LogLevel.WARN`** (2) - Warnings and errors only
|
|
257
|
+
- **`LogLevel.ERROR`** (3) - Errors only (default)
|
|
258
|
+
|
|
259
|
+
Log levels are hierarchical: setting a level includes all higher-priority levels. For example, setting `LogLevel.INFO` will log INFO, WARN, and ERROR messages, but not DEBUG messages.
|
|
260
|
+
|
|
261
|
+
### Default Behavior
|
|
262
|
+
|
|
263
|
+
By default, the SDK uses `LogLevel.ERROR`, which means only error messages are logged. This ensures minimal console output in production environments.
|
|
264
|
+
|
|
265
|
+
### Global Log Level Control
|
|
266
|
+
|
|
267
|
+
The SDK provides a global log level that serves as the default for all loggers created without an explicit level. Use `setGlobalLogLevel()` to configure this default, typically at application startup.
|
|
268
|
+
|
|
269
|
+
**How it works:**
|
|
270
|
+
|
|
271
|
+
- `setGlobalLogLevel()` affects all loggers created via `getLogger()` or `createLogger()` without an explicit level
|
|
272
|
+
- Only loggers created *after* calling `setGlobalLogLevel()` will use the new level
|
|
273
|
+
- Existing logger instances retain their original log level
|
|
274
|
+
|
|
275
|
+
**Interaction with per-component overrides:**
|
|
276
|
+
|
|
277
|
+
- When creating a `T3nClient`, you can override the global level by providing `logLevel` in the config
|
|
278
|
+
- Per-component `logLevel` takes precedence over the global setting
|
|
279
|
+
- If neither is provided, the global default (`LogLevel.ERROR`) is used
|
|
280
|
+
|
|
281
|
+
```typescript
|
|
282
|
+
import { setGlobalLogLevel, LogLevel, T3nClient } from '@terminal3/t3n-sdk';
|
|
283
|
+
|
|
284
|
+
// Set global level at application startup
|
|
285
|
+
setGlobalLogLevel(LogLevel.DEBUG);
|
|
286
|
+
|
|
287
|
+
// This client will use DEBUG level (from global)
|
|
288
|
+
const client1 = new T3nClient({
|
|
289
|
+
wasmComponent: await loadWasmComponent(),
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
// This client overrides global level with INFO
|
|
293
|
+
const client2 = new T3nClient({
|
|
294
|
+
wasmComponent: await loadWasmComponent(),
|
|
295
|
+
logLevel: LogLevel.INFO, // Overrides global DEBUG
|
|
296
|
+
});
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
### Creating Logger Instances
|
|
300
|
+
|
|
301
|
+
You can create logger instances programmatically:
|
|
302
|
+
|
|
303
|
+
```typescript
|
|
304
|
+
import { createLogger, getLogger, LogLevel } from '@terminal3/t3n-sdk';
|
|
305
|
+
|
|
306
|
+
// Create a logger with a specific level
|
|
307
|
+
const debugLogger = createLogger(LogLevel.DEBUG);
|
|
308
|
+
|
|
309
|
+
// Get a logger using the global log level
|
|
310
|
+
const globalLogger = getLogger();
|
|
311
|
+
|
|
312
|
+
// Use logger in handlers
|
|
313
|
+
const handlers = {
|
|
314
|
+
EthSign: metamask_sign(address, debugLogger),
|
|
315
|
+
};
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
### Best Practices
|
|
319
|
+
|
|
320
|
+
- **Production**: Use `LogLevel.ERROR` (default) to minimize console output
|
|
321
|
+
- **Development**: Use `LogLevel.DEBUG` for detailed debugging information
|
|
322
|
+
- **Staging**: Use `LogLevel.INFO` for monitoring without excessive verbosity
|
|
323
|
+
- **Custom Logging**: Implement a custom logger to integrate with your logging infrastructure (e.g., Winston, Pino, or cloud logging services)
|
|
324
|
+
|
|
325
|
+
### Example: Environment-Based Logging
|
|
326
|
+
|
|
327
|
+
```typescript
|
|
328
|
+
import { setGlobalLogLevel, LogLevel } from '@terminal3/t3n-sdk';
|
|
329
|
+
|
|
330
|
+
// Set log level based on environment
|
|
331
|
+
const logLevel = process.env.NODE_ENV === 'production'
|
|
332
|
+
? LogLevel.ERROR
|
|
333
|
+
: LogLevel.DEBUG;
|
|
334
|
+
|
|
335
|
+
setGlobalLogLevel(logLevel);
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
## Development
|
|
339
|
+
|
|
340
|
+
### Building
|
|
341
|
+
|
|
342
|
+
```bash
|
|
343
|
+
pnpm build
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
### Testing
|
|
347
|
+
|
|
348
|
+
```bash
|
|
349
|
+
pnpm test
|
|
350
|
+
pnpm run test:coverage
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
### Linting
|
|
354
|
+
|
|
355
|
+
```bash
|
|
356
|
+
pnpm lint
|
|
357
|
+
pnpm run lint:fix
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
### Demo
|
|
361
|
+
|
|
362
|
+
```bash
|
|
363
|
+
# Run the demo (builds first)
|
|
364
|
+
pnpm demo
|
|
365
|
+
|
|
366
|
+
# Run demo in development mode
|
|
367
|
+
pnpm demo:dev
|
|
368
|
+
|
|
369
|
+
# Run demo with real WASM component
|
|
370
|
+
pnpm demo:real-wasm
|
|
371
|
+
|
|
372
|
+
# Run demo with real WASM component and upsert profile
|
|
373
|
+
pnpm demo:real-wasm --upsert
|
|
374
|
+
|
|
375
|
+
# Run demo with real WASM component and upsert profile from file
|
|
376
|
+
pnpm demo:real-wasm --upsert path/to/profile.json
|
|
377
|
+
|
|
378
|
+
# Run demo with real WASM component, upsert profile, and specify email
|
|
379
|
+
pnpm demo:real-wasm --upsert --email user@example.com
|
|
380
|
+
|
|
381
|
+
# Run demo with real WASM component, upsert profile from file, and specify email
|
|
382
|
+
pnpm demo:real-wasm --upsert path/to/profile.json --email user@example.com
|
|
383
|
+
|
|
384
|
+
# Provider webhook (default: user update only; no OID4VP present)
|
|
385
|
+
pnpm demo:real-wasm --provider
|
|
386
|
+
|
|
387
|
+
# Provider webhook: user update then OID4VP present (add --oid4vp or --oid4vp-json)
|
|
388
|
+
pnpm demo:real-wasm --provider --oid4vp
|
|
389
|
+
|
|
390
|
+
# Provider webhook with custom user-update payload from file
|
|
391
|
+
pnpm demo:real-wasm --provider --user-update-json path/to/user-update.json
|
|
392
|
+
|
|
393
|
+
# Provider with custom OID4VP payload (runs user update then OID4VP with this file)
|
|
394
|
+
pnpm demo:real-wasm --provider --oid4vp-json path/to/oid4vp.json
|
|
395
|
+
|
|
396
|
+
# OID4VP present only (skip user update; use existing DID)
|
|
397
|
+
pnpm demo:real-wasm --provider --oid4vp-only --did did:t3n:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
|
398
|
+
|
|
399
|
+
# Provider with custom signing key (must match TEE provider config public_key)
|
|
400
|
+
pnpm demo:real-wasm --provider --provider-signing-key 0x0123...your32bytehex
|
|
401
|
+
|
|
402
|
+
# Provider webhook call with custom email
|
|
403
|
+
pnpm demo:real-wasm --provider --email test@example.com
|
|
404
|
+
|
|
405
|
+
# Provider webhook call with custom provider ID
|
|
406
|
+
pnpm demo:real-wasm --provider --provider-id t3 --email test@example.com
|
|
407
|
+
|
|
408
|
+
# Get profile after authentication (requires session authentication)
|
|
409
|
+
pnpm demo:real-wasm --get-profile --email test@example.com
|
|
410
|
+
|
|
411
|
+
# Get profile with JSON path filters
|
|
412
|
+
pnpm demo:real-wasm --get-profile --email test@example.com --filter "$.first_name" --filter "$.email_address"
|
|
413
|
+
|
|
414
|
+
# Provider webhook + Get profile (email automatically passed from provider call)
|
|
415
|
+
pnpm demo:real-wasm --provider --get-profile
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
#### Provider and OID4VP
|
|
419
|
+
|
|
420
|
+
With `--provider`, the demo runs a **user update** (create/update profile) by default. No OID4VP present request is sent unless you pass an OID4VP-related flag:
|
|
421
|
+
|
|
422
|
+
1. **User update only (default)** – POST a configurable payload (`profile`, `attestations`, `credentials`) to the provider webhook. The TEE creates or updates the profile and returns a `did` and optional `tx_hash`.
|
|
423
|
+
|
|
424
|
+
2. **User update then OID4VP present** – When you pass **`--oid4vp`** or **`--oid4vp-json <path>`**, after step 1 the demo also sends an `oid4vp_present` request with `profile.did` from step 1, plus `dcql_query`, `response_uri`, `nonce`, and `client_id`.
|
|
425
|
+
|
|
426
|
+
3. **OID4VP present only** – When you pass **`--oid4vp-only --did <did>`**, the demo skips user update and sends only the OID4VP present request for the given DID.
|
|
427
|
+
|
|
428
|
+
Payloads are configurable via **defaults** or **JSON files** (`--user-update-json`, `--oid4vp-json`). The request body is signed with EIP-191 using the provider’s EOA key. The key must match the TEE’s provider config (see `tests/integration/provider_configs/provider_configs.json`: `auth_method.public_key` for the provider). By default the demo uses the test key (`0x01`×32); override with `--provider-signing-key` or `PROVIDER_SIGNING_KEY` for other environments.
|
|
429
|
+
|
|
430
|
+
```bash
|
|
431
|
+
# User update only (default)
|
|
432
|
+
pnpm demo:real-wasm --provider
|
|
433
|
+
|
|
434
|
+
# User update then OID4VP present (default OID4VP payload)
|
|
435
|
+
pnpm demo:real-wasm --provider --oid4vp
|
|
436
|
+
|
|
437
|
+
# User update then OID4VP present (custom OID4VP JSON)
|
|
438
|
+
pnpm demo:real-wasm --provider --oid4vp-json ./my-oid4vp.json
|
|
439
|
+
|
|
440
|
+
# OID4VP only for an existing DID
|
|
441
|
+
pnpm demo:real-wasm --provider --oid4vp-only --did did:t3n:your-uuid-here
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
#### Demo Command-Line Arguments
|
|
445
|
+
|
|
446
|
+
The demo supports the following command-line arguments:
|
|
447
|
+
|
|
448
|
+
- `--upsert` or `-u`: Enable upsert profile action after authentication. Optionally provide a JSON file path to load profile data from.
|
|
449
|
+
|
|
450
|
+
- `--email` or `-e`: Specify email address for profile operations. If not provided, the demo will prompt you interactively.
|
|
451
|
+
|
|
452
|
+
- `--provider` or `-p`: Call the provider webhook endpoint. This simulates a third-party provider (e.g., KYC service) sending user data to T3n. The webhook call:
|
|
453
|
+
- Signs the payload with an EOA signature using a test private key (or `--provider-signing-key` / `PROVIDER_SIGNING_KEY`)
|
|
454
|
+
- Sends profile data to `/api/{provider_id}` endpoint
|
|
455
|
+
- Returns a DID and transaction hash
|
|
456
|
+
- Does not require session authentication
|
|
457
|
+
- **Default flow:** With `--provider` only, the demo runs **user update only** (create/update profile). No OID4VP present request is sent.
|
|
458
|
+
- To also run **OID4VP present** after user update, pass **`--oid4vp`** (default OID4VP payload) or **`--oid4vp-json <path>`** (custom payload).
|
|
459
|
+
- To run **only** OID4VP present (no user update), use **`--oid4vp-only`** with **`--did <did>`**.
|
|
460
|
+
|
|
461
|
+
- `--provider-id`: Specify the provider ID for webhook calls (default: "t3"). Used with `--provider` flag.
|
|
462
|
+
|
|
463
|
+
- `--user-update-json`: Path to a JSON file for the user-update (create profile) payload. Shape: `{ "profile": { ... }, "attestations": [ ... ], "credentials": [ ... ] }`. If omitted, default payload is used (includes a test SD-JWT so OID4VP with default DCQL can be satisfied).
|
|
464
|
+
|
|
465
|
+
- `--oid4vp-json`: Path to a JSON file for the OID4VP present payload. When running the full two-step flow, `profile.did` is always set from step 1. If omitted, default payload is used (dcql_query, response_uri from `VP_VERIFIER_URL`, nonce, client_id). **Presence of this flag (with a path) also enables the OID4VP present step** after user update.
|
|
466
|
+
|
|
467
|
+
- `--oid4vp`: With `--provider`, run user update then OID4VP present using the default OID4VP payload. Use this to trigger the full two-step flow without providing `--oid4vp-json`.
|
|
468
|
+
|
|
469
|
+
- `--oid4vp-only`: With `--provider`, skip step 1 and run only OID4VP present. Requires `--did <did>`.
|
|
470
|
+
|
|
471
|
+
- `--did`: DID to use for OID4VP when `--oid4vp-only` is set (e.g. `did:t3n:uuid`).
|
|
472
|
+
|
|
473
|
+
- `--wait-tx`: After step 1 (user update), wait for transaction confirmation before step 2. Can also set env `WAIT_FOR_TX=true`. (Tx wait is not implemented; flag is accepted for future use.)
|
|
474
|
+
|
|
475
|
+
- `--provider-signing-key`: EOA private key (32-byte hex, e.g. `0x01...01`) for signing provider webhooks. Must match the TEE’s provider config `auth_method.public_key` for the provider. Default is the test key used in integration (see `tests/integration/provider_configs/provider_configs.json`). Can also set env `PROVIDER_SIGNING_KEY`.
|
|
476
|
+
|
|
477
|
+
- `--script-version`: Optional override for contract script version used by session-based actions (`--upsert`, `--get-profile`, `--agent-auth`). If omitted, the demo resolves the latest version dynamically from `/api/contracts/current` for `tee:user/contracts`.
|
|
478
|
+
|
|
479
|
+
- `--get-profile` or `-g`: Retrieve user profile using the session client. This command:
|
|
480
|
+
- Requires authentication (handled automatically)
|
|
481
|
+
- Uses email from provider webhook call or `--email` argument
|
|
482
|
+
- Supports optional JSON path filtering
|
|
483
|
+
|
|
484
|
+
- `--filter` or `-f`: Specify JSON path filters for get-profile command. Can be used multiple times to filter specific profile fields. Example: `--filter "$.first_name" --filter "$.email_address"`.
|
|
485
|
+
|
|
486
|
+
**Combining Commands:**
|
|
487
|
+
|
|
488
|
+
You can combine multiple flags for more complex workflows:
|
|
489
|
+
|
|
490
|
+
```bash
|
|
491
|
+
# Provider webhook call followed by get-profile (email automatically passed)
|
|
492
|
+
pnpm demo:real-wasm --provider --get-profile
|
|
493
|
+
|
|
494
|
+
# Provider webhook with custom email, then get-profile with filters
|
|
495
|
+
pnpm demo:real-wasm --provider --email test@example.com --get-profile --filter "$.first_name"
|
|
496
|
+
|
|
497
|
+
# Upsert profile, then get-profile
|
|
498
|
+
pnpm demo:real-wasm --upsert --email user@example.com --get-profile
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
#### Demo Environment Variables
|
|
502
|
+
|
|
503
|
+
The demo supports the following environment variables:
|
|
504
|
+
|
|
505
|
+
- `CRYPTO_NODE_URL`: The base URL of the T3n crypto node API (defaults to `http://localhost:3000`).
|
|
506
|
+
- `TEE_API_URL`: The base URL of the T3n TEE API endpoint (defaults to `http://localhost:3000/api`). Used by the `--provider` flag for webhook calls.
|
|
507
|
+
- `VP_VERIFIER_URL`: Base URL for the OID4VP response endpoint (defaults to `http://localhost:8100`). The demo sets `response_uri` to `{VP_VERIFIER_URL}/post` in the default OID4VP payload.
|
|
508
|
+
- `PROVIDER_SIGNING_KEY`: EOA private key (32-byte hex) for signing provider webhooks. Overrides the default test key when set.
|
|
509
|
+
- `WAIT_FOR_TX`: When set to `"true"` or `"1"`, enables waiting for tx confirmation before OID4VP (same as `--wait-tx`).
|
|
510
|
+
- `SCRIPT_VERSION`: Optional script version override for session-based demo actions. Priority is `--script-version` > `SCRIPT_VERSION` > dynamic latest lookup from `/api/contracts/current`.
|
|
511
|
+
- `DEBUG`: Enable debug logging when set to `"true"` (defaults to disabled).
|
|
512
|
+
|
|
513
|
+
Example usage:
|
|
514
|
+
|
|
515
|
+
```bash
|
|
516
|
+
# With custom crypto node URL
|
|
517
|
+
CRYPTO_NODE_URL=http://localhost:3000 pnpm demo:real-wasm
|
|
518
|
+
|
|
519
|
+
# With custom TEE API URL for provider webhook calls
|
|
520
|
+
TEE_API_URL=http://localhost:3000/api pnpm demo:real-wasm --provider
|
|
521
|
+
|
|
522
|
+
# With custom VP verifier URL for OID4VP response_uri
|
|
523
|
+
VP_VERIFIER_URL=http://localhost:8100 pnpm demo:real-wasm --provider
|
|
524
|
+
|
|
525
|
+
# With custom provider signing key (must match TEE provider config)
|
|
526
|
+
PROVIDER_SIGNING_KEY=0x0123... pnpm demo:real-wasm --provider
|
|
527
|
+
|
|
528
|
+
# Override script version explicitly (otherwise latest is resolved dynamically)
|
|
529
|
+
pnpm demo:real-wasm --get-profile --script-version 1.0.0
|
|
530
|
+
|
|
531
|
+
# With debug logging enabled
|
|
532
|
+
DEBUG=true pnpm demo:real-wasm
|
|
533
|
+
|
|
534
|
+
# With both custom URLs and debug logging
|
|
535
|
+
CRYPTO_NODE_URL=http://localhost:3000 TEE_API_URL=http://localhost:3000/api DEBUG=true pnpm demo:real-wasm --provider --get-profile
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
#### Email Verification (OTP Flow)
|
|
539
|
+
|
|
540
|
+
When upserting a profile with an email address (either for a new profile or when changing an existing email), the system requires email verification via OTP (One-Time Password):
|
|
541
|
+
|
|
542
|
+
1. **Initial Upsert**: When you run `--upsert` with an email, the system sends a 6-digit OTP code to the specified email address.
|
|
543
|
+
|
|
544
|
+
2. **OTP Prompt**: The demo will automatically detect that OTP verification is needed and prompt you:
|
|
545
|
+
|
|
546
|
+
```text
|
|
547
|
+
📧 Email verification required
|
|
548
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ address. The demo will prompt you to enter the 6-digit OTP code sent to your email.
|
|
549
|
+
|
|
550
|
+
3. **Enter OTP Code**: When prompted, enter the 6-digit code you received in your email.
|
|
551
|
+
|
|
552
|
+
4. **Verification**: The demo will automatically retry the upsert with your OTP code and complete the profile upsert.
|
|
553
|
+
|
|
554
|
+
**Note**: In debug/mock mode (`DEBUG=true` or `MOCK_MODE=true`), the OTP code will be displayed in the console for testing purposes.
|
|
555
|
+
|
|
556
|
+
**Note**: The demo supports interactive OIDC authentication. When you select OIDC authentication, the demo will:
|
|
557
|
+
|
|
558
|
+
1. Start a local web server on port 8081
|
|
559
|
+
2. Open your browser automatically
|
|
560
|
+
3. Guide you through the Google OAuth flow
|
|
561
|
+
4. Allow you to paste the ID token back into the terminal
|
|
562
|
+
|
|
563
|
+
## WASM Integration
|
|
564
|
+
|
|
565
|
+
The SDK can work with both real T3n WASM components and mock components for testing.
|
|
566
|
+
|
|
567
|
+
### Automatic WASM Loading
|
|
568
|
+
|
|
569
|
+
```typescript
|
|
570
|
+
import { loadWasmComponent } from '@terminal3/t3n-sdk';
|
|
571
|
+
|
|
572
|
+
// Automatically loads real WASM if available, falls back to mock
|
|
573
|
+
const wasmComponent = await loadWasmComponent();
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
The loader will automatically:
|
|
577
|
+
|
|
578
|
+
1. Try to load the real T3n WASM component (if available)
|
|
579
|
+
2. Fall back to a mock component for testing
|
|
580
|
+
|
|
581
|
+
### Real WASM Component
|
|
582
|
+
|
|
583
|
+
To use the real WASM component:
|
|
584
|
+
|
|
585
|
+
1. **Build the WASM component** (from T3n project root):
|
|
586
|
+
|
|
587
|
+
```bash
|
|
588
|
+
cd node
|
|
589
|
+
cargo build -p session --target wasm32-wasip2 --release
|
|
590
|
+
```
|
|
591
|
+
|
|
592
|
+
2. **Copy the WASM file** to the SDK directory:
|
|
593
|
+
|
|
594
|
+
```bash
|
|
595
|
+
cp target/debug/build/cn-api-*/out/session.wasm t3n-sdk/
|
|
596
|
+
```
|
|
597
|
+
|
|
598
|
+
3. **The SDK will automatically detect and use it**:
|
|
599
|
+
|
|
600
|
+
```bash
|
|
601
|
+
pnpm demo:real-wasm
|
|
602
|
+
```
|
|
603
|
+
|
|
604
|
+
### Mock Component for Testing
|
|
605
|
+
|
|
606
|
+
```typescript
|
|
607
|
+
import { createMockWasmComponent } from '@terminal3/t3n-sdk';
|
|
608
|
+
|
|
609
|
+
// Use mock component for testing
|
|
610
|
+
const mockComponent = createMockWasmComponent();
|
|
611
|
+
```
|
|
612
|
+
|
|
613
|
+
### WASM Component Features
|
|
614
|
+
|
|
615
|
+
When using the real WASM component, you get:
|
|
616
|
+
|
|
617
|
+
- **Actual cryptographic operations** from the T3n session module
|
|
618
|
+
- **Real state machine logic** for handshake and authentication
|
|
619
|
+
- **Production-grade security** for session establishment
|
|
620
|
+
- **Full protocol compatibility** with T3n nodes
|
|
621
|
+
|
|
622
|
+
## Examples
|
|
623
|
+
|
|
624
|
+
See the [examples](src/examples/) directory for more comprehensive usage examples:
|
|
625
|
+
|
|
626
|
+
- [Basic Usage](src/examples/basic-usage.ts) - Simple session establishment and RPC
|
|
627
|
+
- [Advanced Usage](src/examples/advanced-usage.ts) - Error handling, custom configuration, and integration patterns
|
|
628
|
+
|
|
629
|
+
## License
|
|
630
|
+
|
|
631
|
+
MIT
|
|
632
|
+
|
|
633
|
+
## Contributing
|
|
634
|
+
|
|
635
|
+
Please read our contributing guidelines and submit pull requests to our repository.
|
|
636
|
+
|
|
637
|
+
## Support
|
|
638
|
+
|
|
639
|
+
For support, please open an issue on our GitHub repository or contact the T3n team.
|