@hauska-sdk/core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +29 -0
- package/README.md +263 -0
- package/dist/CNSSDK.d.ts +115 -0
- package/dist/CNSSDK.d.ts.map +1 -0
- package/dist/CNSSDK.js +389 -0
- package/dist/CNSSDK.js.map +1 -0
- package/dist/EventAnchoringService.d.ts +58 -0
- package/dist/EventAnchoringService.d.ts.map +1 -0
- package/dist/EventAnchoringService.js +84 -0
- package/dist/EventAnchoringService.js.map +1 -0
- package/dist/errors.d.ts +160 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +202 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/types/index.d.ts +39 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +5 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types.d.ts +181 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/docs/api-reference.md +433 -0
- package/docs/examples.md +362 -0
- package/docs/getting-started.md +265 -0
- package/docs/troubleshooting.md +398 -0
- package/package.json +74 -0
package/docs/examples.md
ADDED
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
# Examples
|
|
2
|
+
|
|
3
|
+
Real-world usage examples for the CNS Protocol Core SDK.
|
|
4
|
+
|
|
5
|
+
## Complete Flow Examples
|
|
6
|
+
|
|
7
|
+
The SDK includes complete flow examples demonstrating end-to-end usage:
|
|
8
|
+
|
|
9
|
+
### Architect Invoice Flow
|
|
10
|
+
|
|
11
|
+
Complete flow for an architect invoicing scenario: invoice creation → payment → blueprint transfer.
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { architectInvoiceFlow } from "@hauska-sdk/core/examples/architect-invoice-flow";
|
|
15
|
+
|
|
16
|
+
const result = await architectInvoiceFlow();
|
|
17
|
+
// Returns: { architectWallet, clientWallet, blueprintVDA, invoiceVDA, blueprintCID }
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
**Flow:**
|
|
21
|
+
1. Architect creates invoice and uploads blueprint
|
|
22
|
+
2. Client makes payment
|
|
23
|
+
3. Payment is verified
|
|
24
|
+
4. Blueprint VDA is transferred to client
|
|
25
|
+
5. Client retrieves blueprint
|
|
26
|
+
|
|
27
|
+
### Data Room Flow
|
|
28
|
+
|
|
29
|
+
Complete flow for creating a data room with access control.
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
import { dataRoomFlow } from "@hauska-sdk/core/examples/data-room-flow";
|
|
33
|
+
|
|
34
|
+
const result = await dataRoomFlow();
|
|
35
|
+
// Returns: { ownerWallet, buyerWallet, dataRoomVDA, accessPass, documentCID, titleReportCID }
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
**Flow:**
|
|
39
|
+
1. Property owner creates data room VDA
|
|
40
|
+
2. Uploads property documents to IPFS
|
|
41
|
+
3. Creates access pass for potential buyer
|
|
42
|
+
4. Buyer accesses documents with access pass
|
|
43
|
+
5. Owner can revoke access pass
|
|
44
|
+
|
|
45
|
+
### Healthcare Patient Flow
|
|
46
|
+
|
|
47
|
+
Complete flow for healthcare patient record management.
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
import { healthcarePatientFlow } from "@hauska-sdk/core/examples/healthcare-patient-flow";
|
|
51
|
+
|
|
52
|
+
const result = await healthcarePatientFlow();
|
|
53
|
+
// Returns: { patientWallet, doctorWallet, healthRecordVDA, accessPass, recordsCID, totalRecords }
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
**Flow:**
|
|
57
|
+
1. Patient creates health record VDA
|
|
58
|
+
2. Uploads encrypted medical records
|
|
59
|
+
3. Grants doctor temporary access (24 hours)
|
|
60
|
+
4. Doctor accesses records with access pass
|
|
61
|
+
5. Search all records for patient
|
|
62
|
+
|
|
63
|
+
### Real Estate Property Flow
|
|
64
|
+
|
|
65
|
+
Complete flow for a real estate property transaction.
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
import { realEstatePropertyFlow } from "@hauska-sdk/core/examples/real-estate-property-flow";
|
|
69
|
+
|
|
70
|
+
const result = await realEstatePropertyFlow();
|
|
71
|
+
// Returns: { ownerWallet, buyerWallet, propertyVDA, viewingAccessPass, purchasePayment, transferredProperty, documentCID, searchResults }
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**Flow:**
|
|
75
|
+
1. Property owner lists property
|
|
76
|
+
2. Buyer views property (creates data room access)
|
|
77
|
+
3. Buyer makes payment
|
|
78
|
+
4. Property VDA is transferred to buyer
|
|
79
|
+
5. Buyer now owns the property VDA
|
|
80
|
+
6. Search property by address
|
|
81
|
+
|
|
82
|
+
## Common Patterns
|
|
83
|
+
|
|
84
|
+
### Pattern 1: Create and Share Document
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
// 1. Create data room with document
|
|
88
|
+
const dataRoom = await sdk.createDataRoom({
|
|
89
|
+
ownerWallet: { userId: "owner", password: "pass" },
|
|
90
|
+
vdaParams: {
|
|
91
|
+
assetType: "deed",
|
|
92
|
+
address: "123 Main St",
|
|
93
|
+
spoke: "real-estate",
|
|
94
|
+
},
|
|
95
|
+
document: {
|
|
96
|
+
content: Buffer.from("Property documents..."),
|
|
97
|
+
name: "property-deed.pdf",
|
|
98
|
+
encrypt: true,
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
// 2. Create access pass for recipient
|
|
103
|
+
const accessPass = await sdk.getVDASDK().createAccessPass({
|
|
104
|
+
grantorWallet: ownerWallet.address,
|
|
105
|
+
recipientWallet: recipientWallet.address,
|
|
106
|
+
accessibleVDAs: [dataRoom.vda.id],
|
|
107
|
+
permissions: ["view", "download"],
|
|
108
|
+
expiry: Date.now() + 30 * 24 * 3600000, // 30 days
|
|
109
|
+
spoke: "real-estate",
|
|
110
|
+
address: "123 Main St",
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
// 3. Recipient retrieves document
|
|
114
|
+
const document = await sdk.retrieveDocument({
|
|
115
|
+
wallet: { userId: "recipient", password: "pass" },
|
|
116
|
+
cid: dataRoom.document!.cid,
|
|
117
|
+
requiredPermissions: ["view"],
|
|
118
|
+
decrypt: true,
|
|
119
|
+
watermark: true, // Watermarked for access pass viewer
|
|
120
|
+
});
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Pattern 2: Purchase and Transfer
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
// 1. Purchase and mint VDA
|
|
127
|
+
const purchase = await sdk.purchaseAndMintVDA({
|
|
128
|
+
wallet: { userId: "buyer", password: "pass" },
|
|
129
|
+
amount: "5000",
|
|
130
|
+
currency: "USDC",
|
|
131
|
+
method: "crypto",
|
|
132
|
+
vdaParams: {
|
|
133
|
+
assetType: "blueprint",
|
|
134
|
+
address: "123 Main St",
|
|
135
|
+
spoke: "architect",
|
|
136
|
+
},
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
// 2. Transfer VDA to buyer
|
|
140
|
+
await sdk.getVDASDK().transferOwnership({
|
|
141
|
+
vdaId: originalVDA.id,
|
|
142
|
+
currentOwner: sellerWallet.address,
|
|
143
|
+
newOwner: buyerWallet.address,
|
|
144
|
+
});
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Pattern 3: Search and Filter
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
// Search by address
|
|
151
|
+
const results = await sdk.getVDASDK().searchByAddress("Main St", {
|
|
152
|
+
limit: 10,
|
|
153
|
+
offset: 0,
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
// Search by patient ID
|
|
157
|
+
const patientRecords = await sdk.getVDASDK().searchByPatientId("PATIENT-12345");
|
|
158
|
+
|
|
159
|
+
// Search by API14
|
|
160
|
+
const oilRecords = await sdk.getVDASDK().searchByAPI14("42-123-45678-00-00");
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### Pattern 4: Access Control
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
// Verify access before retrieving
|
|
167
|
+
const accessVerification = await sdk.getRetrievalSDK().verifyAccess(
|
|
168
|
+
documentCID,
|
|
169
|
+
wallet.address,
|
|
170
|
+
["view", "download"]
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
if (accessVerification.hasAccess) {
|
|
174
|
+
console.log(`Access granted via: ${accessVerification.accessType}`);
|
|
175
|
+
const document = await sdk.retrieveDocument({
|
|
176
|
+
wallet: { userId: "user", password: "pass" },
|
|
177
|
+
cid: documentCID,
|
|
178
|
+
requiredPermissions: ["view"],
|
|
179
|
+
decrypt: true,
|
|
180
|
+
});
|
|
181
|
+
} else {
|
|
182
|
+
console.log(`Access denied: ${accessVerification.reason}`);
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Pattern 5: Error Handling
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
import {
|
|
190
|
+
SDKError,
|
|
191
|
+
PaymentError,
|
|
192
|
+
VDAError,
|
|
193
|
+
RetrievalError,
|
|
194
|
+
isSDKError,
|
|
195
|
+
} from "@hauska-sdk/core";
|
|
196
|
+
|
|
197
|
+
try {
|
|
198
|
+
await sdk.purchaseAndMintVDA({ /* ... */ });
|
|
199
|
+
} catch (error) {
|
|
200
|
+
if (isSDKError(error)) {
|
|
201
|
+
switch (error.code) {
|
|
202
|
+
case "PAYMENT_VERIFICATION_FAILED":
|
|
203
|
+
// Handle payment verification failure
|
|
204
|
+
break;
|
|
205
|
+
case "VDA_NOT_FOUND":
|
|
206
|
+
// Handle VDA not found
|
|
207
|
+
break;
|
|
208
|
+
default:
|
|
209
|
+
console.error("SDK error:", error.message, error.context);
|
|
210
|
+
}
|
|
211
|
+
} else {
|
|
212
|
+
console.error("Unexpected error:", error);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### Pattern 6: Logging and Monitoring
|
|
218
|
+
|
|
219
|
+
```typescript
|
|
220
|
+
const sdk = new CNSSDK({
|
|
221
|
+
// ... config
|
|
222
|
+
logHook: (level, message, data) => {
|
|
223
|
+
// Send to your logging service
|
|
224
|
+
logger[level](message, data);
|
|
225
|
+
},
|
|
226
|
+
metricsHook: (event, data) => {
|
|
227
|
+
// Send to your analytics service
|
|
228
|
+
analytics.track(event, {
|
|
229
|
+
...data,
|
|
230
|
+
timestamp: Date.now(),
|
|
231
|
+
});
|
|
232
|
+
},
|
|
233
|
+
});
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
## Integration Examples
|
|
237
|
+
|
|
238
|
+
### Express.js Integration
|
|
239
|
+
|
|
240
|
+
```typescript
|
|
241
|
+
import express from "express";
|
|
242
|
+
import { CNSSDK } from "@hauska-sdk/core";
|
|
243
|
+
|
|
244
|
+
const app = express();
|
|
245
|
+
const sdk = new CNSSDK({ /* ... config */ });
|
|
246
|
+
|
|
247
|
+
// Create data room endpoint
|
|
248
|
+
app.post("/api/data-rooms", async (req, res) => {
|
|
249
|
+
try {
|
|
250
|
+
const dataRoom = await sdk.createDataRoom({
|
|
251
|
+
ownerWallet: {
|
|
252
|
+
userId: req.user.id,
|
|
253
|
+
password: req.body.password,
|
|
254
|
+
},
|
|
255
|
+
vdaParams: {
|
|
256
|
+
assetType: "deed",
|
|
257
|
+
address: req.body.address,
|
|
258
|
+
spoke: "real-estate",
|
|
259
|
+
},
|
|
260
|
+
document: {
|
|
261
|
+
content: Buffer.from(req.body.document),
|
|
262
|
+
encrypt: true,
|
|
263
|
+
},
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
res.json({ dataRoom });
|
|
267
|
+
} catch (error) {
|
|
268
|
+
if (isSDKError(error)) {
|
|
269
|
+
res.status(error.statusCode || 500).json({ error: error.message });
|
|
270
|
+
} else {
|
|
271
|
+
res.status(500).json({ error: "Internal server error" });
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
// Retrieve document endpoint
|
|
277
|
+
app.get("/api/documents/:cid", async (req, res) => {
|
|
278
|
+
try {
|
|
279
|
+
const document = await sdk.retrieveDocument({
|
|
280
|
+
wallet: {
|
|
281
|
+
userId: req.user.id,
|
|
282
|
+
password: req.body.password,
|
|
283
|
+
},
|
|
284
|
+
cid: req.params.cid,
|
|
285
|
+
requiredPermissions: ["view"],
|
|
286
|
+
decrypt: true,
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
res.setHeader("Content-Type", "application/pdf");
|
|
290
|
+
res.send(document);
|
|
291
|
+
} catch (error) {
|
|
292
|
+
if (error instanceof RetrievalError) {
|
|
293
|
+
res.status(error.statusCode || 404).json({ error: error.message });
|
|
294
|
+
} else {
|
|
295
|
+
res.status(500).json({ error: "Internal server error" });
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### Next.js API Route
|
|
302
|
+
|
|
303
|
+
```typescript
|
|
304
|
+
// pages/api/vdas/mint.ts
|
|
305
|
+
import { CNSSDK } from "@hauska-sdk/core";
|
|
306
|
+
import type { NextApiRequest, NextApiResponse } from "next";
|
|
307
|
+
|
|
308
|
+
const sdk = new CNSSDK({ /* ... config */ });
|
|
309
|
+
|
|
310
|
+
export default async function handler(
|
|
311
|
+
req: NextApiRequest,
|
|
312
|
+
res: NextApiResponse
|
|
313
|
+
) {
|
|
314
|
+
if (req.method !== "POST") {
|
|
315
|
+
return res.status(405).json({ error: "Method not allowed" });
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
try {
|
|
319
|
+
const vda = await sdk.getVDASDK().mint({
|
|
320
|
+
assetType: req.body.assetType,
|
|
321
|
+
ownerWallet: req.body.ownerWallet,
|
|
322
|
+
spoke: req.body.spoke,
|
|
323
|
+
address: req.body.address,
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
res.status(200).json({ vda });
|
|
327
|
+
} catch (error) {
|
|
328
|
+
if (isSDKError(error)) {
|
|
329
|
+
res.status(error.statusCode || 500).json({ error: error.message });
|
|
330
|
+
} else {
|
|
331
|
+
res.status(500).json({ error: "Internal server error" });
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
## Running Examples
|
|
338
|
+
|
|
339
|
+
To run the complete flow examples:
|
|
340
|
+
|
|
341
|
+
```bash
|
|
342
|
+
# Install dependencies
|
|
343
|
+
npm install
|
|
344
|
+
|
|
345
|
+
# Run architect invoice flow
|
|
346
|
+
npx ts-node packages/core/examples/architect-invoice-flow.ts
|
|
347
|
+
|
|
348
|
+
# Run data room flow
|
|
349
|
+
npx ts-node packages/core/examples/data-room-flow.ts
|
|
350
|
+
|
|
351
|
+
# Run healthcare patient flow
|
|
352
|
+
npx ts-node packages/core/examples/healthcare-patient-flow.ts
|
|
353
|
+
|
|
354
|
+
# Run real estate property flow
|
|
355
|
+
npx ts-node packages/core/examples/real-estate-property-flow.ts
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
## Next Steps
|
|
359
|
+
|
|
360
|
+
- Read the [API Reference](./api-reference.md) for complete API documentation
|
|
361
|
+
- Check the [Getting Started Guide](./getting-started.md) for setup instructions
|
|
362
|
+
- See [Troubleshooting](./troubleshooting.md) for common issues
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
# Getting Started with CNS Protocol Core SDK
|
|
2
|
+
|
|
3
|
+
This guide will help you get started with the CNS Protocol Core SDK in minutes.
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
- Node.js 18+ installed
|
|
8
|
+
- TypeScript 5.3+ (recommended)
|
|
9
|
+
- A Pinata account (for IPFS storage)
|
|
10
|
+
- PostgreSQL database (or use Mock adapter for testing)
|
|
11
|
+
- Base L2 RPC endpoint (for blockchain operations)
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install @hauska-sdk/core
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Basic Setup
|
|
20
|
+
|
|
21
|
+
### 1. Install Required Adapters
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
# For production (PostgreSQL)
|
|
25
|
+
npm install @hauska-sdk/adapters-storage-postgres
|
|
26
|
+
|
|
27
|
+
# For testing (Mock)
|
|
28
|
+
npm install @hauska-sdk/adapters-storage-mock
|
|
29
|
+
|
|
30
|
+
# For blockchain operations
|
|
31
|
+
npm install @hauska-sdk/adapters-blockchain-ethers
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### 2. Initialize the SDK
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
import { CNSSDK } from "@hauska-sdk/core";
|
|
38
|
+
import { PostgreSQLStorageAdapter } from "@hauska-sdk/adapters-storage-postgres";
|
|
39
|
+
|
|
40
|
+
const sdk = new CNSSDK({
|
|
41
|
+
vda: {
|
|
42
|
+
storageAdapter: new PostgreSQLStorageAdapter({
|
|
43
|
+
connectionString: process.env.DATABASE_URL!,
|
|
44
|
+
}),
|
|
45
|
+
},
|
|
46
|
+
payment: {
|
|
47
|
+
storage: new PostgreSQLStorageAdapter({
|
|
48
|
+
connectionString: process.env.DATABASE_URL!,
|
|
49
|
+
}),
|
|
50
|
+
blockchain: {
|
|
51
|
+
chain: "base",
|
|
52
|
+
token: "USDC",
|
|
53
|
+
facilitatorWallet: process.env.FACILITATOR_WALLET!,
|
|
54
|
+
baseRpcUrl: process.env.BASE_RPC_URL!,
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
retrieval: {
|
|
58
|
+
pinata: {
|
|
59
|
+
pinataJwt: process.env.PINATA_JWT!,
|
|
60
|
+
pinataGateway: "https://gateway.pinata.cloud",
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### 3. Environment Variables
|
|
67
|
+
|
|
68
|
+
Create a `.env` file:
|
|
69
|
+
|
|
70
|
+
```env
|
|
71
|
+
# Database
|
|
72
|
+
DATABASE_URL=postgresql://user:password@localhost:5432/cns_protocol
|
|
73
|
+
|
|
74
|
+
# Pinata (IPFS)
|
|
75
|
+
PINATA_JWT=your_pinata_jwt_token
|
|
76
|
+
|
|
77
|
+
# Blockchain
|
|
78
|
+
FACILITATOR_WALLET=0xYourFacilitatorWalletAddress
|
|
79
|
+
BASE_RPC_URL=https://mainnet.base.org
|
|
80
|
+
|
|
81
|
+
# Optional: Logging
|
|
82
|
+
LOG_LEVEL=info
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Your First VDA
|
|
86
|
+
|
|
87
|
+
Let's create your first Verified Digital Asset:
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
// Get or create a wallet for the user
|
|
91
|
+
const wallet = await sdk.getOrCreateWallet({
|
|
92
|
+
userId: "user-123",
|
|
93
|
+
password: "secure-password",
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
// Mint a VDA
|
|
97
|
+
const vda = await sdk.getVDASDK().mint({
|
|
98
|
+
assetType: "deed",
|
|
99
|
+
ownerWallet: wallet.address,
|
|
100
|
+
address: "123 Main St, Schertz, TX 78154",
|
|
101
|
+
legalDesc: "Lot 5, Block 3",
|
|
102
|
+
spoke: "real-estate",
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
console.log(`VDA created: ${vda.id}`);
|
|
106
|
+
console.log(`Owner: ${vda.metadata.ownerWallet}`);
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Your First Data Room
|
|
110
|
+
|
|
111
|
+
Create a data room with an encrypted document:
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
const dataRoom = await sdk.createDataRoom({
|
|
115
|
+
ownerWallet: {
|
|
116
|
+
userId: "owner-123",
|
|
117
|
+
password: "owner-password",
|
|
118
|
+
},
|
|
119
|
+
vdaParams: {
|
|
120
|
+
assetType: "deed",
|
|
121
|
+
address: "123 Main St, Schertz, TX 78154",
|
|
122
|
+
legalDesc: "Lot 5, Block 3",
|
|
123
|
+
spoke: "real-estate",
|
|
124
|
+
},
|
|
125
|
+
document: {
|
|
126
|
+
content: Buffer.from("Property deed content..."),
|
|
127
|
+
name: "property-deed.pdf",
|
|
128
|
+
encrypt: true, // Encrypt before uploading to IPFS
|
|
129
|
+
},
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
console.log(`Data room VDA: ${dataRoom.vda.id}`);
|
|
133
|
+
console.log(`Document CID: ${dataRoom.document?.cid}`);
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## Grant Access with Access Pass
|
|
137
|
+
|
|
138
|
+
Create an access pass to grant temporary access:
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
const accessPass = await sdk.getVDASDK().createAccessPass({
|
|
142
|
+
grantorWallet: ownerWallet.address,
|
|
143
|
+
recipientWallet: buyerWallet.address,
|
|
144
|
+
accessibleVDAs: [dataRoom.vda.id],
|
|
145
|
+
permissions: ["view", "download"],
|
|
146
|
+
expiry: Date.now() + 30 * 24 * 3600000, // 30 days
|
|
147
|
+
spoke: "real-estate",
|
|
148
|
+
address: "123 Main St, Schertz, TX 78154",
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
console.log(`Access pass created: ${accessPass.id}`);
|
|
152
|
+
console.log(`Expires: ${new Date(accessPass.metadata.expiry!)}`);
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## Retrieve a Document
|
|
156
|
+
|
|
157
|
+
Retrieve a document with access control:
|
|
158
|
+
|
|
159
|
+
```typescript
|
|
160
|
+
const document = await sdk.retrieveDocument({
|
|
161
|
+
wallet: {
|
|
162
|
+
userId: "buyer-456",
|
|
163
|
+
password: "buyer-password",
|
|
164
|
+
},
|
|
165
|
+
cid: dataRoom.document!.cid,
|
|
166
|
+
requiredPermissions: ["view"],
|
|
167
|
+
decrypt: true,
|
|
168
|
+
watermark: true, // Watermark for access pass viewers
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
console.log(`Document retrieved: ${document.length} bytes`);
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## Complete Example: Real Estate Flow
|
|
175
|
+
|
|
176
|
+
Here's a complete example of a real estate property flow:
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
import { CNSSDK } from "@hauska-sdk/core";
|
|
180
|
+
import { PostgreSQLStorageAdapter } from "@hauska-sdk/adapters-storage-postgres";
|
|
181
|
+
|
|
182
|
+
const sdk = new CNSSDK({
|
|
183
|
+
// ... config
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
// 1. Property owner creates data room
|
|
187
|
+
const dataRoom = await sdk.createDataRoom({
|
|
188
|
+
ownerWallet: { userId: "owner", password: "pass" },
|
|
189
|
+
vdaParams: {
|
|
190
|
+
assetType: "deed",
|
|
191
|
+
address: "123 Main St",
|
|
192
|
+
spoke: "real-estate",
|
|
193
|
+
},
|
|
194
|
+
document: {
|
|
195
|
+
content: Buffer.from("Property documents..."),
|
|
196
|
+
encrypt: true,
|
|
197
|
+
},
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
// 2. Create access pass for buyer
|
|
201
|
+
await sdk.getVDASDK().createAccessPass({
|
|
202
|
+
grantorWallet: ownerWallet.address,
|
|
203
|
+
recipientWallet: buyerWallet.address,
|
|
204
|
+
accessibleVDAs: [dataRoom.vda.id],
|
|
205
|
+
permissions: ["view"],
|
|
206
|
+
expiry: Date.now() + 7 * 24 * 3600000, // 7 days
|
|
207
|
+
spoke: "real-estate",
|
|
208
|
+
address: "123 Main St",
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
// 3. Buyer makes payment
|
|
212
|
+
const purchase = await sdk.purchaseAndMintVDA({
|
|
213
|
+
wallet: { userId: "buyer", password: "pass" },
|
|
214
|
+
amount: "250000",
|
|
215
|
+
currency: "USDC",
|
|
216
|
+
method: "crypto",
|
|
217
|
+
vdaParams: {
|
|
218
|
+
assetType: "invoice",
|
|
219
|
+
address: "123 Main St",
|
|
220
|
+
spoke: "real-estate",
|
|
221
|
+
},
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
// 4. Transfer property to buyer
|
|
225
|
+
await sdk.getVDASDK().transferOwnership({
|
|
226
|
+
vdaId: dataRoom.vda.id,
|
|
227
|
+
currentOwner: ownerWallet.address,
|
|
228
|
+
newOwner: buyerWallet.address,
|
|
229
|
+
});
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## Next Steps
|
|
233
|
+
|
|
234
|
+
- Read the [API Reference](./api-reference.md) for complete API documentation
|
|
235
|
+
- Check out [Examples](./examples.md) for more use cases
|
|
236
|
+
- See [Troubleshooting](./troubleshooting.md) for common issues
|
|
237
|
+
|
|
238
|
+
## Testing
|
|
239
|
+
|
|
240
|
+
For testing, use the Mock storage adapter:
|
|
241
|
+
|
|
242
|
+
```typescript
|
|
243
|
+
import { MockStorageAdapter } from "@hauska-sdk/adapters-storage-mock";
|
|
244
|
+
|
|
245
|
+
const sdk = new CNSSDK({
|
|
246
|
+
vda: {
|
|
247
|
+
storageAdapter: new MockStorageAdapter(),
|
|
248
|
+
},
|
|
249
|
+
payment: {
|
|
250
|
+
storage: new MockStorageAdapter(),
|
|
251
|
+
},
|
|
252
|
+
retrieval: {
|
|
253
|
+
pinata: {
|
|
254
|
+
pinataJwt: "test-jwt",
|
|
255
|
+
pinataGateway: "https://gateway.pinata.cloud",
|
|
256
|
+
},
|
|
257
|
+
},
|
|
258
|
+
});
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
## Need Help?
|
|
262
|
+
|
|
263
|
+
- Check the [Troubleshooting Guide](./troubleshooting.md)
|
|
264
|
+
- Review the [API Reference](./api-reference.md)
|
|
265
|
+
- Open an issue on GitHub
|