@dcentralab/d402-client 0.2.7 โ†’ 0.3.2

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 ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Traia
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
package/README.md CHANGED
@@ -4,517 +4,80 @@
4
4
 
5
5
  Implementation of the D402 payment protocol for HTTP 402 (Payment Required) responses. Works in any JavaScript environment (React, Next.js, Vue, Node.js, etc.) with automatic payment signing and retry.
6
6
 
7
- Part of the iatp-js monorepo. Future packages will add MCP and A2A protocol support.
7
+ Part of the iatp-js monorepo. Built by Dcentralab.
8
8
 
9
- Built by Dcentralab.
9
+ ## ๐Ÿš€ Quick Start
10
10
 
11
- ## ๐Ÿš€ Installation
11
+ ### Installation
12
12
 
13
13
  ```bash
14
14
  npm install @dcentralab/d402-client viem wagmi
15
-
16
- # or
17
- pnpm add @dcentralab/d402-client viem wagmi
18
-
19
- # or
20
- yarn add @dcentralab/d402-client viem wagmi
21
-
22
15
  ```
23
16
 
24
- **Requirements:**
25
- - React/Next.js app
26
- - viem ^2.21.0
27
- - wagmi (for wallet connection)
28
- - User with Web3 wallet (MetaMask, WalletConnect, etc.)
29
-
30
- ## ๐Ÿ“– Quick Start (React/Next.js)
31
-
32
- ## ๐Ÿ’ก Complete React Example (Recommended Pattern)
17
+ **Requirements:** React/Next.js app with viem ^2.21.0 and wagmi for wallet connection.
33
18
 
34
- ### Custom Hook with Automatic Wallet Management
19
+ ### Your First Payment
35
20
 
36
21
  ```typescript
37
- 'use client'
38
-
39
- import { useMutation } from '@tanstack/react-query'
22
+ import { D402Client, createIATPWallet, getWalletsByOwner } from '@dcentralab/d402-client'
40
23
  import { useWalletClient } from 'wagmi'
41
- import {
42
- createIATPWallet,
43
- D402Client,
44
- getWalletsByOwner
45
- } from '@dcentralab/d402-client'
46
-
47
- interface PaymentParams {
48
- endpoint: string
49
- payload: Record<string, unknown>
50
- maxValue: bigint
51
- network?: 'sepolia'
52
- }
53
-
54
- export function useD402Payment() {
55
- const { data: walletClient } = useWalletClient()
56
-
57
- const mutation = useMutation({
58
- mutationFn: async ({
59
- endpoint,
60
- payload,
61
- maxValue,
62
- network = 'sepolia'
63
- }: PaymentParams) => {
64
- if (!walletClient) {
65
- throw new Error('Please connect your wallet first')
66
- }
67
-
68
- // Check if user already has IATP wallet
69
- const existingWallets = await getWalletsByOwner({
70
- ownerAddress: walletClient.account.address,
71
- network
72
- })
73
-
74
- // Get or create wallet
75
- let iatpWalletAddress: `0x${string}`
76
-
77
- if (existingWallets.length === 0) {
78
- // Create new wallet (one-time)
79
- const newWallet = await createIATPWallet({
80
- ownerAccount: walletClient.account,
81
- network
82
- })
83
- iatpWalletAddress = newWallet.walletAddress
84
- } else {
85
- // Use existing wallet
86
- iatpWalletAddress = existingWallets[0]
87
- }
88
-
89
- // Create D402 client
90
- const client = new D402Client({
91
- operatorAccount: walletClient.account,
92
- iatpWalletAddress,
93
- maxValue
94
- })
95
-
96
- // Call 402-protected API
97
- const response = await client.fetch(endpoint, {
98
- method: 'POST',
99
- headers: { 'Content-Type': 'application/json' },
100
- body: JSON.stringify(payload)
101
- })
102
-
103
- return await response.json()
104
- }
105
- })
106
-
107
- return {
108
- execute: mutation.mutateAsync,
109
- isLoading: mutation.isPending,
110
- result: mutation.data,
111
- error: mutation.error,
112
- isWalletConnected: !!walletClient
113
- }
114
- }
115
- ```
116
-
117
- ### Use in Component
118
-
119
- ```typescript
120
- 'use client'
121
-
122
- import { useD402Payment } from '@/hooks/useD402Payment'
123
-
124
- export default function AnalyzeButton() {
125
- const { execute, isLoading, result, error, isWalletConnected } = useD402Payment()
126
-
127
- async function handleAnalyze() {
128
- await execute({
129
- endpoint: 'https://sentiment-api.com/analyze',
130
- payload: { text: 'Bitcoin looks bullish today' },
131
- maxValue: 1000000n // 1 USDC max
132
- })
133
- }
134
-
135
- if (!isWalletConnected) {
136
- return <button disabled>Connect Wallet First</button>
137
- }
138
-
139
- return (
140
- <div>
141
- <button onClick={handleAnalyze} disabled={isLoading}>
142
- {isLoading ? 'Processing...' : 'Analyze Sentiment (โ‰ˆ0.01 USDC)'}
143
- </button>
144
-
145
- {error && (
146
- <div className="error">
147
- Error: {error.message}
148
- </div>
149
- )}
150
-
151
- {result && (
152
- <div className="success">
153
- <pre>{JSON.stringify(result, null, 2)}</pre>
154
- </div>
155
- )}
156
- </div>
157
- )
158
- }
159
- ```
160
-
161
- **This pattern:**
162
- - โœ… Automatically checks for existing wallet
163
- - โœ… Creates wallet only if needed (one-time)
164
- - โœ… Reuses wallet for future calls
165
- - โœ… Handles loading and error states
166
- - โœ… Works with React Query for caching
167
-
168
- ---
169
-
170
- ## ๐Ÿ—๏ธ Features
171
-
172
- ### 1. IATPWallet Creation
173
-
174
- Create on-chain wallet with owner/operator separation:
175
-
176
- ```typescript
177
- import { createIATPWallet } from '@dcentralab/d402-client'
178
- import { privateKeyToAccount } from 'viem/accounts'
179
24
 
180
- // Owner creates wallet (one-time setup)
181
- const ownerAccount = privateKeyToAccount('0x...')
25
+ // In your React component
26
+ const { data: walletClient } = useWalletClient()
182
27
 
183
- const result = await createIATPWallet({
184
- ownerAccount,
185
- network: 'sepolia',
186
- rpcUrl: 'https://ethereum-sepolia-rpc.publicnode.com'
28
+ // 1. Check if user has an IATP wallet
29
+ const existingWallets = await getWalletsByOwner({
30
+ ownerAddress: walletClient.account.address,
31
+ network: 'sepolia'
187
32
  })
188
33
 
189
- console.log('Wallet:', result.walletAddress)
190
- console.log('Owner:', result.ownerAddress)
191
- ```
192
-
193
- **Returns:**
194
- - `walletAddress` - IATPWallet contract address
195
- - `ownerAddress` - Owner's address (also the operator)
196
- - `transactionHash` - Creation transaction
197
- - `blockNumber` - Block where wallet was created
198
- - `network` - Network where deployed
199
- - `chainId` - Chain ID
200
-
201
- ### 2. Automatic 402 Payment Handling
202
-
203
- ```typescript
204
- import { D402Client } from '@dcentralab/d402-client'
34
+ // 2. Create wallet if needed (one-time)
35
+ const walletAddress = existingWallets.length === 0
36
+ ? (await createIATPWallet({ ownerAccount: walletClient.account })).walletAddress
37
+ : existingWallets[0]
205
38
 
39
+ // 3. Create D402 client
206
40
  const client = new D402Client({
207
- operatorAccount,
208
- iatpWalletAddress: '0xYourWallet...',
209
- maxValue: 1000000n,
210
- networkFilter: 'sepolia', // Only Sepolia network
211
- schemeFilter: 'exact' // Only exact payments
41
+ operatorAccount: walletClient.account,
42
+ iatpWalletAddress: walletAddress,
43
+ maxValue: 1000000n // 1 USDC max
212
44
  })
213
45
 
214
- // Client automatically:
215
- // 1. Detects 402 responses
216
- // 2. Parses payment requirements
217
- // 3. Signs with EIP-712
218
- // 4. Retries with payment
219
- const response = await client.fetch('https://paid-api.com/endpoint')
220
- ```
221
-
222
- ### 3. Manual Payment Flow (Low-Level)
223
-
224
- ```typescript
225
- import {
226
- parsePaymentRequirement,
227
- signD402Payment,
228
- encodePayment
229
- } from '@dcentralab/d402-client'
230
-
231
- // 1. Make request
232
- const response = await fetch('https://api.example.com')
233
-
234
- if (response.status === 402) {
235
- // 2. Parse payment requirement
236
- const requirement = await parsePaymentRequirement(response)
237
-
238
- // 3. Sign payment
239
- const signedPayment = await signD402Payment({
240
- operatorAccount,
241
- paymentRequirement: requirement,
242
- iatpWalletAddress: '0xYourWallet...'
243
- })
244
-
245
- // 4. Encode for header
246
- const paymentHeader = encodePayment(signedPayment)
247
-
248
- // 5. Retry with payment
249
- const paidResponse = await fetch('https://api.example.com', {
250
- headers: { 'X-Payment': paymentHeader }
251
- })
252
- }
253
- ```
254
-
255
- ## ๐Ÿ”ง API Reference
256
-
257
- ### D402Client
258
-
259
- Main class for automatic 402 payment handling.
260
-
261
- #### Constructor
262
-
263
- ```typescript
264
- new D402Client(config: D402ClientConfig)
265
- ```
266
-
267
- **Config Options:**
268
-
269
- | Option | Type | Required | Description |
270
- |--------|------|----------|-------------|
271
- | `operatorAccount` | `Account` | โœ… | Viem account for signing payments (EOA) |
272
- | `iatpWalletAddress` | `0x${string}` | โŒ | IATPWallet contract address (uses operator address if not provided) |
273
- | `maxValue` | `bigint` | โŒ | Max payment in base units (wei). Safety limit to prevent overpaying. |
274
- | `networkFilter` | `string` | โŒ | Only select requirements matching this network |
275
- | `schemeFilter` | `string` | โŒ | Payment scheme filter (default: "exact") |
276
- | `paymentRequirementsSelector` | `PaymentSelector` | โŒ | Custom payment selection logic |
277
-
278
- #### Methods
279
-
280
- **`fetch(url, init?): Promise<Response>`**
281
-
282
- Fetch with automatic 402 payment handling. Same API as native fetch.
283
-
284
- ```typescript
285
- const response = await client.fetch(url, {
46
+ // 4. Call 402-protected API (automatic payment handling!)
47
+ const response = await client.fetch('https://paid-api.com/analyze', {
286
48
  method: 'POST',
287
- headers: { 'Content-Type': 'application/json' },
288
- body: JSON.stringify(data)
49
+ body: JSON.stringify({ text: 'Bitcoin looks bullish' })
289
50
  })
290
51
  ```
291
52
 
292
- **`selectPaymentRequirement(requirements): PaymentRequirement`**
293
-
294
- Select payment requirement from list based on filters.
295
-
296
- **`getWalletAddress(): 0x${string}`**
297
-
298
- Get configured wallet address.
299
-
300
- **`getOperatorAccount(): Account`**
301
-
302
- Get operator account.
303
-
304
- **`getMaxValue(): bigint | undefined`**
305
-
306
- Get maximum payment limit.
307
-
308
- ### Functions
309
-
310
- **`createIATPWallet(params): Promise<WalletCreationResult>`**
311
-
312
- Create new IATPWallet contract on-chain.
313
-
314
- **Parameters:**
315
- - `ownerAccount: Account` - Owner's viem account (will also be the operator)
316
- - `network?: 'sepolia'` - Network (default: sepolia)
317
- - `rpcUrl?: string` - Custom RPC URL
318
-
319
- **`parsePaymentRequirement(response): Promise<PaymentRequirement>`**
320
-
321
- Parse first payment requirement from 402 response.
322
-
323
- **`parseAllPaymentRequirements(response): Promise<PaymentRequirement[]>`**
324
-
325
- Parse all payment requirements from 402 response.
326
-
327
- **`signD402Payment(params): Promise<SignedPayment>`**
328
-
329
- Sign payment with EIP-712.
330
-
331
- **`encodePayment(payment): string`**
332
-
333
- Encode signed payment to base64 for X-Payment header.
334
-
335
- **`decodePayment(encoded): SignedPayment`**
336
-
337
- Decode base64 payment header.
338
-
339
- ### Contract Functions
340
-
341
- **`getContractAddress(name, network): string | null`**
342
-
343
- Get contract address for network.
344
-
345
- **`getContractAbi(name, network): any[] | null`**
346
-
347
- Get contract ABI for network.
348
-
349
- **`getContractConfig(name, network): { address, abi } | null`**
350
-
351
- Get both address and ABI.
352
-
353
- ### Utility Functions
354
-
355
- **`parseMoney(amount, decimals): bigint`**
53
+ That's it! The client automatically handles 402 responses, payment signing, and retry.
356
54
 
357
- Convert money string to atomic units.
55
+ ## ๐Ÿ“– Documentation
358
56
 
359
- **`usdToUsdc(amount): bigint`**
57
+ - **[Getting Started Guide](./docs/getting-started.md)** - Installation, setup, and first payment
58
+ - **[API Reference](./docs/api-reference.md)** - Complete API documentation
59
+ - **[Wallet Management](./docs/wallet-management.md)** - Creating and managing IATP wallets
60
+ - **[Usage Patterns](./docs/usage-patterns.md)** - Frontend vs backend patterns
61
+ - **[Examples](./docs/examples.md)** - Complete code examples
62
+ - **[Security Guide](./docs/security.md)** - Best practices and security considerations
360
63
 
361
- Convert USD to USDC wei (6 decimals).
64
+ ## ๐Ÿ—๏ธ Key Features
362
65
 
363
- **`generateNonce(): 0x${string}`**
364
-
365
- Generate random 32-byte nonce.
366
-
367
- **`getChainId(network): number`**
368
-
369
- Get chain ID for network name.
370
-
371
- ## ๐Ÿ’ก Usage Patterns
372
-
373
- ### Pattern 1: Frontend Direct (Recommended for Web3 Apps)
374
-
375
- **React component calls 402 API directly:**
376
-
377
- ```typescript
378
- 'use client'
379
-
380
- import { D402Client } from '@dcentralab/d402-client'
381
- import { useWalletClient } from 'wagmi'
382
-
383
- export default function PaymentComponent() {
384
- const { data: walletClient } = useWalletClient()
385
-
386
- async function callPaidAPI() {
387
- if (!walletClient) return
388
-
389
- // User's wallet signs payments
390
- const client = new D402Client({
391
- operatorAccount: walletClient.account,
392
- iatpWalletAddress: '0xUserIATPWallet...',
393
- maxValue: 1000000n
394
- })
395
-
396
- // Calls external 402 API directly
397
- const response = await client.fetch('https://sentiment-api.com/analyze', {
398
- method: 'POST',
399
- body: JSON.stringify({ text: 'Bitcoin sentiment' })
400
- })
401
-
402
- return await response.json()
403
- }
404
- }
405
- ```
406
-
407
- **Flow:** Browser โ†’ D402Client โ†’ External 402 API
408
-
409
- **Pros:**
410
- - โœ… User pays from their wallet
411
- - โœ… Fully decentralized
412
- - โœ… No backend needed
413
-
414
- **Cons:**
415
- - โš ๏ธ Requires wallet connection
416
- - โš ๏ธ User approves each payment
417
-
418
- ### Pattern 2: Backend Proxy (Alternative)
419
-
420
- **Backend handles 402 calls, frontend just calls your API:**
421
-
422
- **Backend (Node.js):**
423
- ```typescript
424
- import { D402Client } from '@dcentralab/d402-client'
425
- import { privateKeyToAccount } from 'viem/accounts'
426
-
427
- const operatorAccount = privateKeyToAccount(process.env.OPERATOR_KEY!)
428
-
429
- app.post('/api/analyze', async (req, res) => {
430
- const client = new D402Client({
431
- operatorAccount,
432
- iatpWalletAddress: req.user.iatpWallet,
433
- maxValue: 1000000n
434
- })
435
-
436
- const response = await client.fetch('https://sentiment-api.com/analyze', {
437
- method: 'POST',
438
- body: JSON.stringify(req.body)
439
- })
440
-
441
- res.json(await response.json())
442
- })
443
- ```
444
-
445
- **Frontend (simpler):**
446
- ```typescript
447
- // Just call YOUR backend
448
- const response = await fetch('/api/analyze', {
449
- method: 'POST',
450
- body: JSON.stringify({ text: 'Analyze this' })
451
- })
452
- ```
453
-
454
- **Cons:**
455
- - โš ๏ธ Backend controls payments
456
- - โš ๏ธ More centralized
66
+ - โœ… **Automatic 402 handling** - Detects, signs, and retries with payment
67
+ - โœ… **EIP-712 signatures** - Secure, typed message signing
68
+ - โœ… **Universal** - Works in browsers and Node.js
69
+ - โœ… **Type-safe** - Full TypeScript support
70
+ - โœ… **Well-tested** - 166 tests covering all functionality
457
71
 
458
72
  ## ๐ŸŒ Supported Networks
459
73
 
460
74
  IATP contracts are currently deployed on:
461
75
 
462
- | Network | Type | Chain ID | USDC Address | RPC URL |
463
- |----------------------|---------|------------|----------------------------------------------|---------------------------------------------------|
464
- | **Sepolia Testnet** | Testnet | `11155111` | `0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238` | [Chainlist](https://chainlist.org/chain/11155111) |
465
-
466
- > **Note:** Additional networks (mainnet, Base, Polygon, etc.) will be supported once IATP contracts are deployed on those chains.
467
-
468
- ## ๐Ÿ“ฆ Package Exports
469
-
470
- ```typescript
471
- // Main client
472
- export { D402Client } from '@dcentralab/d402-client'
76
+ | Network | Chain ID | USDC Address |
77
+ |----------------------|------------|----------------------------------------------|
78
+ | **Sepolia Testnet** | `11155111` | `0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238` |
473
79
 
474
- // Wallet management
475
- export { createIATPWallet } from '@dcentralab/d402-client'
476
-
477
- // Payment functions
478
- export {
479
- parsePaymentRequirement,
480
- parseAllPaymentRequirements,
481
- signD402Payment,
482
- encodePayment,
483
- decodePayment
484
- } from '@dcentralab/d402-client'
485
-
486
- // Contract access
487
- export {
488
- ContractName,
489
- getContractAddress,
490
- getContractAbi,
491
- getContractConfig
492
- } from '@dcentralab/d402-client'
493
-
494
- // Utilities
495
- export {
496
- parseMoney,
497
- usdToUsdc,
498
- generateNonce,
499
- getChainId
500
- } from '@dcentralab/d402-client'
501
-
502
- // Error classes
503
- export {
504
- PaymentError,
505
- PaymentAmountExceededError,
506
- UnsupportedSchemeError,
507
- Invalid402ResponseError
508
- } from '@dcentralab/d402-client'
509
-
510
- // Types
511
- export type {
512
- D402ClientConfig,
513
- PaymentRequirement,
514
- SignedPayment,
515
- WalletCreationResult
516
- } from '@dcentralab/d402-client'
517
- ```
80
+ > Additional networks (mainnet, Base, Polygon, etc.) will be supported once IATP contracts are deployed.
518
81
 
519
82
  ## ๐Ÿงช Testing
520
83
 
@@ -522,102 +85,44 @@ export type {
522
85
  # Run all tests
523
86
  pnpm test
524
87
 
525
- # Run specific test file
526
- pnpm test client.test.ts
527
-
528
88
  # Run with coverage
529
89
  pnpm test --coverage
530
90
 
531
- # Watch mode
532
- pnpm test --watch
91
+ # Type check
92
+ pnpm typecheck
533
93
  ```
534
94
 
535
- **Test Coverage:**
536
- - โœ… 17 encoder/decoder tests
537
- - โœ… 19 parser tests
538
- - โœ… 29 contracts tests
539
- - โœ… 24 signer tests
540
- - โœ… 14 wallet tests
541
- - โœ… 19 client constructor tests
542
- - โœ… 22 integration tests
543
-
544
- **Total: 144 tests**
545
-
546
- ## ๐Ÿ”’ Security
95
+ **Test Coverage:** 166 tests covering client, wallet, payment, settlement, and integration scenarios.
547
96
 
548
- ### Private Key Handling
549
-
550
- **โœ… Safe (Backend):**
551
- ```typescript
552
- // Store operator key in environment variable
553
- const operatorAccount = privateKeyToAccount(process.env.OPERATOR_KEY!)
554
- ```
555
-
556
- **โŒ Unsafe (Frontend):**
557
- ```typescript
558
- // Never hardcode private keys in frontend code
559
- const account = privateKeyToAccount('0xHARDCODED') // DON'T DO THIS!
560
- ```
97
+ ## ๐Ÿ“ฆ Package Exports
561
98
 
562
- **โœ… Safe (Frontend with Wallet):**
563
99
  ```typescript
564
- // Use wallet client from wagmi/viem
565
- const { data: walletClient } = useWalletClient()
566
- const client = new D402Client({
567
- operatorAccount: walletClient.account
568
- })
569
- ```
570
-
571
- ### Payment Security
572
-
573
- - โœ… EIP-712 typed signatures prevent tampering
574
- - โœ… Nonce prevents replay attacks
575
- - โœ… Timestamp bounds (validAfter/validBefore)
576
- - โœ… Amount verification
577
- - โœ… Destination address verification
578
- - โœ… maxValue safety limit
579
-
580
- ## ๐Ÿ› ๏ธ Development
581
-
582
- ### Build
583
-
584
- ```bash
585
- pnpm build
586
- ```
100
+ // Main client
101
+ import { D402Client } from '@dcentralab/d402-client'
587
102
 
588
- Outputs:
589
- - `dist/index.js` - CommonJS
590
- - `dist/index.mjs` - ES Module
591
- - `dist/index.d.ts` - TypeScript types
103
+ // Wallet management
104
+ import { createIATPWallet, getWalletsByOwner, getAvailableBalance } from '@dcentralab/d402-client'
592
105
 
593
- ### Type Checking
106
+ // Payment functions
107
+ import { signD402Payment, encodePayment, parsePaymentRequirement } from '@dcentralab/d402-client'
594
108
 
595
- ```bash
596
- pnpm typecheck
109
+ // All exports documented in API Reference
597
110
  ```
598
111
 
599
- ## ๐Ÿ“ Related Packages
600
-
601
- Part of the IATP-JS monorepo:
602
- - `@dcentralab/d402-client` - D402 payment protocol (this package)
603
- - `@dcentralab/mcp-client` - MCP integration (planned)
604
- - `@dcentralab/a2a-client` - A2A protocol (planned)
112
+ ## ๐Ÿค Contributing
605
113
 
606
- ## ๐Ÿ”— Related Projects
607
-
608
- - [Viem](https://viem.sh) - TypeScript Web3 library
609
- - [D402 Protocol](https://docs.cdp.coinbase.com/x402) - HTTP 402 specification
114
+ We welcome contributions! See the [main Contributing Guide](../../docs/CONTRIBUTING.md).
610
115
 
611
116
  ## ๐Ÿ“„ License
612
117
 
613
- MIT
118
+ MIT License - see [LICENSE](../../LICENSE) file.
614
119
 
615
120
  ## ๐Ÿ’ฌ Support
616
121
 
617
- - GitHub Issues: [iatp-js/issues](https://github.com/DcentraLab/iatp-js/issues)
618
- - Email: dev.support@d402.net
122
+ - ๐Ÿ“ง Email: dev.support@d402.net
123
+ - ๐Ÿ› Issues: [GitHub Issues](https://github.com/DcentraLab/iatp-js/issues)
124
+ - ๐Ÿ“š Docs: [Complete Documentation](./docs/)
619
125
 
620
126
  ---
621
127
 
622
128
  **Made with โค๏ธ by the DcentraLab Team**
623
-