@cmdoss/memwal-sdk 0.6.2 → 0.8.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/ARCHITECTURE.md +547 -547
- package/BENCHMARKS.md +238 -238
- package/README.md +310 -181
- package/dist/ai-sdk/tools.d.ts +2 -2
- package/dist/ai-sdk/tools.js +2 -2
- package/dist/client/ClientMemoryManager.js +2 -2
- package/dist/client/ClientMemoryManager.js.map +1 -1
- package/dist/client/PersonalDataWallet.d.ts.map +1 -1
- package/dist/client/SimplePDWClient.d.ts +29 -1
- package/dist/client/SimplePDWClient.d.ts.map +1 -1
- package/dist/client/SimplePDWClient.js +45 -13
- package/dist/client/SimplePDWClient.js.map +1 -1
- package/dist/client/namespaces/EmbeddingsNamespace.d.ts +1 -1
- package/dist/client/namespaces/EmbeddingsNamespace.js +1 -1
- package/dist/client/namespaces/MemoryNamespace.d.ts +31 -0
- package/dist/client/namespaces/MemoryNamespace.d.ts.map +1 -1
- package/dist/client/namespaces/MemoryNamespace.js +272 -39
- package/dist/client/namespaces/MemoryNamespace.js.map +1 -1
- package/dist/client/namespaces/consolidated/AINamespace.d.ts +2 -2
- package/dist/client/namespaces/consolidated/AINamespace.js +2 -2
- package/dist/client/namespaces/consolidated/BlockchainNamespace.d.ts +12 -2
- package/dist/client/namespaces/consolidated/BlockchainNamespace.d.ts.map +1 -1
- package/dist/client/namespaces/consolidated/BlockchainNamespace.js +62 -4
- package/dist/client/namespaces/consolidated/BlockchainNamespace.js.map +1 -1
- package/dist/client/namespaces/consolidated/StorageNamespace.d.ts +67 -2
- package/dist/client/namespaces/consolidated/StorageNamespace.d.ts.map +1 -1
- package/dist/client/namespaces/consolidated/StorageNamespace.js +549 -16
- package/dist/client/namespaces/consolidated/StorageNamespace.js.map +1 -1
- package/dist/config/ConfigurationHelper.js +61 -61
- package/dist/config/defaults.js +2 -2
- package/dist/config/defaults.js.map +1 -1
- package/dist/graph/GraphService.js +21 -21
- package/dist/graph/GraphService.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/seal/EncryptionService.d.ts +9 -5
- package/dist/infrastructure/seal/EncryptionService.d.ts.map +1 -1
- package/dist/infrastructure/seal/EncryptionService.js +37 -15
- package/dist/infrastructure/seal/EncryptionService.js.map +1 -1
- package/dist/infrastructure/seal/SealService.d.ts +13 -5
- package/dist/infrastructure/seal/SealService.d.ts.map +1 -1
- package/dist/infrastructure/seal/SealService.js +36 -34
- package/dist/infrastructure/seal/SealService.js.map +1 -1
- package/dist/langchain/createPDWRAG.js +30 -30
- package/dist/retrieval/MemoryDecryptionPipeline.d.ts.map +1 -1
- package/dist/retrieval/MemoryDecryptionPipeline.js +2 -1
- package/dist/retrieval/MemoryDecryptionPipeline.js.map +1 -1
- package/dist/retrieval/MemoryRetrievalService.d.ts +31 -0
- package/dist/retrieval/MemoryRetrievalService.d.ts.map +1 -1
- package/dist/retrieval/MemoryRetrievalService.js +44 -4
- package/dist/retrieval/MemoryRetrievalService.js.map +1 -1
- package/dist/services/CapabilityService.d.ts.map +1 -1
- package/dist/services/CapabilityService.js +30 -14
- package/dist/services/CapabilityService.js.map +1 -1
- package/dist/services/CrossContextPermissionService.d.ts.map +1 -1
- package/dist/services/CrossContextPermissionService.js +9 -7
- package/dist/services/CrossContextPermissionService.js.map +1 -1
- package/dist/services/EmbeddingService.d.ts +28 -1
- package/dist/services/EmbeddingService.d.ts.map +1 -1
- package/dist/services/EmbeddingService.js +54 -0
- package/dist/services/EmbeddingService.js.map +1 -1
- package/dist/services/EncryptionService.d.ts.map +1 -1
- package/dist/services/EncryptionService.js +6 -5
- package/dist/services/EncryptionService.js.map +1 -1
- package/dist/services/GeminiAIService.js +309 -309
- package/dist/services/IndexManager.d.ts +5 -1
- package/dist/services/IndexManager.d.ts.map +1 -1
- package/dist/services/IndexManager.js +17 -40
- package/dist/services/IndexManager.js.map +1 -1
- package/dist/services/QueryService.js +1 -1
- package/dist/services/QueryService.js.map +1 -1
- package/dist/services/StorageService.d.ts +11 -0
- package/dist/services/StorageService.d.ts.map +1 -1
- package/dist/services/StorageService.js +73 -10
- package/dist/services/StorageService.js.map +1 -1
- package/dist/services/TransactionService.d.ts +20 -0
- package/dist/services/TransactionService.d.ts.map +1 -1
- package/dist/services/TransactionService.js +43 -0
- package/dist/services/TransactionService.js.map +1 -1
- package/dist/services/ViewService.js +2 -2
- package/dist/services/ViewService.js.map +1 -1
- package/dist/services/storage/QuiltBatchManager.d.ts +101 -1
- package/dist/services/storage/QuiltBatchManager.d.ts.map +1 -1
- package/dist/services/storage/QuiltBatchManager.js +410 -20
- package/dist/services/storage/QuiltBatchManager.js.map +1 -1
- package/dist/services/storage/index.d.ts +1 -1
- package/dist/services/storage/index.d.ts.map +1 -1
- package/dist/services/storage/index.js.map +1 -1
- package/dist/utils/LRUCache.d.ts +106 -0
- package/dist/utils/LRUCache.d.ts.map +1 -0
- package/dist/utils/LRUCache.js +281 -0
- package/dist/utils/LRUCache.js.map +1 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +2 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/memoryIndexOnChain.d.ts +212 -0
- package/dist/utils/memoryIndexOnChain.d.ts.map +1 -0
- package/dist/utils/memoryIndexOnChain.js +312 -0
- package/dist/utils/memoryIndexOnChain.js.map +1 -0
- package/dist/utils/rebuildIndexNode.d.ts +29 -0
- package/dist/utils/rebuildIndexNode.d.ts.map +1 -1
- package/dist/utils/rebuildIndexNode.js +366 -98
- package/dist/utils/rebuildIndexNode.js.map +1 -1
- package/dist/vector/HnswWasmService.d.ts +20 -5
- package/dist/vector/HnswWasmService.d.ts.map +1 -1
- package/dist/vector/HnswWasmService.js +73 -40
- package/dist/vector/HnswWasmService.js.map +1 -1
- package/dist/vector/IHnswService.d.ts +10 -1
- package/dist/vector/IHnswService.d.ts.map +1 -1
- package/dist/vector/IHnswService.js.map +1 -1
- package/dist/vector/NodeHnswService.d.ts +16 -0
- package/dist/vector/NodeHnswService.d.ts.map +1 -1
- package/dist/vector/NodeHnswService.js +84 -5
- package/dist/vector/NodeHnswService.js.map +1 -1
- package/dist/vector/createHnswService.d.ts +1 -1
- package/dist/vector/createHnswService.js +1 -1
- package/dist/vector/index.d.ts +1 -1
- package/dist/vector/index.js +1 -1
- package/package.json +157 -157
- package/src/access/PermissionService.ts +635 -635
- package/src/aggregation/AggregationService.ts +389 -389
- package/src/ai-sdk/PDWVectorStore.ts +715 -715
- package/src/ai-sdk/index.ts +65 -65
- package/src/ai-sdk/tools.ts +460 -460
- package/src/ai-sdk/types.ts +404 -404
- package/src/batch/BatchManager.ts +597 -597
- package/src/batch/BatchingService.ts +429 -429
- package/src/batch/MemoryProcessingCache.ts +492 -492
- package/src/batch/index.ts +30 -30
- package/src/browser.ts +200 -200
- package/src/client/ClientMemoryManager.ts +987 -987
- package/src/client/PersonalDataWallet.ts +345 -345
- package/src/client/SimplePDWClient.ts +1289 -1222
- package/src/client/factory.ts +154 -154
- package/src/client/namespaces/AnalyticsNamespace.ts +377 -377
- package/src/client/namespaces/BatchNamespace.ts +356 -356
- package/src/client/namespaces/CacheNamespace.ts +123 -123
- package/src/client/namespaces/CapabilityNamespace.ts +217 -217
- package/src/client/namespaces/ClassifyNamespace.ts +169 -169
- package/src/client/namespaces/ContextNamespace.ts +297 -297
- package/src/client/namespaces/EmbeddingsNamespace.ts +99 -99
- package/src/client/namespaces/EncryptionNamespace.ts +221 -221
- package/src/client/namespaces/GraphNamespace.ts +468 -468
- package/src/client/namespaces/IndexNamespace.ts +361 -361
- package/src/client/namespaces/MemoryNamespace.ts +1422 -1135
- package/src/client/namespaces/PermissionsNamespace.ts +254 -254
- package/src/client/namespaces/PipelineNamespace.ts +220 -220
- package/src/client/namespaces/SearchNamespace.ts +1049 -1049
- package/src/client/namespaces/StorageNamespace.ts +458 -458
- package/src/client/namespaces/TxNamespace.ts +260 -260
- package/src/client/namespaces/WalletNamespace.ts +243 -243
- package/src/client/namespaces/consolidated/AINamespace.ts +449 -449
- package/src/client/namespaces/consolidated/BlockchainNamespace.ts +607 -546
- package/src/client/namespaces/consolidated/SecurityNamespace.ts +648 -648
- package/src/client/namespaces/consolidated/StorageNamespace.ts +1141 -497
- package/src/client/namespaces/consolidated/index.ts +39 -39
- package/src/client/signers/KeypairSigner.ts +108 -108
- package/src/client/signers/UnifiedSigner.ts +110 -110
- package/src/client/signers/WalletAdapterSigner.ts +159 -159
- package/src/client/signers/index.ts +26 -26
- package/src/config/ConfigurationHelper.ts +412 -412
- package/src/config/defaults.ts +51 -51
- package/src/config/index.ts +8 -8
- package/src/config/validation.ts +70 -70
- package/src/core/index.ts +14 -14
- package/src/core/interfaces/IService.ts +307 -307
- package/src/core/interfaces/index.ts +8 -8
- package/src/core/types/capability.ts +297 -297
- package/src/core/types/index.ts +870 -870
- package/src/core/types/wallet.ts +270 -270
- package/src/core/types.ts +9 -9
- package/src/core/wallet.ts +222 -222
- package/src/embedding/index.ts +19 -19
- package/src/embedding/types.ts +357 -357
- package/src/errors/index.ts +602 -602
- package/src/errors/recovery.ts +461 -461
- package/src/errors/validation.ts +567 -567
- package/src/generated/pdw/capability.ts +319 -319
- package/src/graph/GraphService.ts +887 -887
- package/src/graph/KnowledgeGraphManager.ts +728 -728
- package/src/graph/index.ts +25 -25
- package/src/index.ts +498 -474
- package/src/infrastructure/index.ts +22 -22
- package/src/infrastructure/seal/EncryptionService.ts +628 -603
- package/src/infrastructure/seal/SealService.ts +613 -615
- package/src/infrastructure/seal/index.ts +9 -9
- package/src/infrastructure/sui/BlockchainManager.ts +627 -627
- package/src/infrastructure/sui/SuiService.ts +888 -888
- package/src/infrastructure/sui/index.ts +9 -9
- package/src/infrastructure/walrus/StorageManager.ts +604 -604
- package/src/infrastructure/walrus/WalrusStorageService.ts +612 -612
- package/src/infrastructure/walrus/index.ts +9 -9
- package/src/langchain/PDWEmbeddings.ts +145 -145
- package/src/langchain/PDWVectorStore.ts +456 -456
- package/src/langchain/createPDWRAG.ts +303 -303
- package/src/langchain/index.ts +47 -47
- package/src/permissions/ConsentRepository.browser.ts +249 -249
- package/src/permissions/ConsentRepository.ts +364 -364
- package/src/pipeline/MemoryPipeline.ts +862 -862
- package/src/pipeline/PipelineManager.ts +683 -683
- package/src/pipeline/index.ts +26 -26
- package/src/retrieval/AdvancedSearchService.ts +629 -629
- package/src/retrieval/MemoryAnalyticsService.ts +711 -711
- package/src/retrieval/MemoryDecryptionPipeline.ts +825 -824
- package/src/retrieval/MemoryRetrievalService.ts +904 -830
- package/src/retrieval/index.ts +42 -42
- package/src/services/BatchService.ts +352 -352
- package/src/services/CapabilityService.ts +464 -448
- package/src/services/ClassifierService.ts +465 -465
- package/src/services/CrossContextPermissionService.ts +486 -484
- package/src/services/EmbeddingService.ts +771 -706
- package/src/services/EncryptionService.ts +712 -711
- package/src/services/GeminiAIService.ts +753 -753
- package/src/services/IndexManager.ts +977 -1004
- package/src/services/MemoryIndexService.ts +1003 -1003
- package/src/services/MemoryService.ts +369 -369
- package/src/services/QueryService.ts +890 -890
- package/src/services/StorageService.ts +1182 -1111
- package/src/services/TransactionService.ts +838 -790
- package/src/services/VectorService.ts +462 -462
- package/src/services/ViewService.ts +484 -484
- package/src/services/index.ts +25 -25
- package/src/services/storage/BlobAttributesManager.ts +333 -333
- package/src/services/storage/KnowledgeGraphManager.ts +425 -425
- package/src/services/storage/MemorySearchManager.ts +387 -387
- package/src/services/storage/QuiltBatchManager.ts +1130 -660
- package/src/services/storage/WalrusMetadataManager.ts +268 -268
- package/src/services/storage/WalrusStorageManager.ts +287 -287
- package/src/services/storage/index.ts +57 -52
- package/src/types/index.ts +13 -13
- package/src/utils/LRUCache.ts +378 -0
- package/src/utils/index.ts +76 -68
- package/src/utils/memoryIndexOnChain.ts +507 -0
- package/src/utils/rebuildIndex.ts +290 -290
- package/src/utils/rebuildIndexNode.ts +771 -424
- package/src/vector/BrowserHnswIndexService.ts +758 -758
- package/src/vector/HnswWasmService.ts +731 -679
- package/src/vector/IHnswService.ts +233 -224
- package/src/vector/NodeHnswService.ts +833 -735
- package/src/vector/VectorManager.ts +478 -478
- package/src/vector/createHnswService.ts +135 -135
- package/src/vector/index.ts +56 -56
- package/src/wallet/ContextWalletService.ts +656 -656
- package/src/wallet/MainWalletService.ts +317 -317
|
@@ -1,364 +1,364 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ConsentRequestRecord,
|
|
3
|
-
ConsentStatus,
|
|
4
|
-
} from '../core/types/wallet.js';
|
|
5
|
-
import { normalizeSuiAddress } from '@mysten/sui/utils';
|
|
6
|
-
|
|
7
|
-
export interface ConsentRepository {
|
|
8
|
-
save(request: ConsentRequestRecord): Promise<void>;
|
|
9
|
-
updateStatus(requestId: string, status: ConsentStatus, updatedAt: number): Promise<void>;
|
|
10
|
-
getById(requestId: string): Promise<ConsentRequestRecord | null>;
|
|
11
|
-
listByTarget(targetWallet: string, status?: ConsentStatus): Promise<ConsentRequestRecord[]>;
|
|
12
|
-
listByRequester(requesterWallet: string, status?: ConsentStatus): Promise<ConsentRequestRecord[]>;
|
|
13
|
-
delete(requestId: string): Promise<void>;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
interface StoredConsentRecord extends ConsentRequestRecord {}
|
|
17
|
-
|
|
18
|
-
function normalizeRecord(record: ConsentRequestRecord): StoredConsentRecord {
|
|
19
|
-
return {
|
|
20
|
-
...record,
|
|
21
|
-
requesterWallet: normalizeSuiAddress(record.requesterWallet),
|
|
22
|
-
targetWallet: normalizeSuiAddress(record.targetWallet),
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* FileSystemConsentRepository - Node.js only implementation
|
|
28
|
-
* Uses file system for persistence. Not available in browser.
|
|
29
|
-
*/
|
|
30
|
-
export class FileSystemConsentRepository implements ConsentRepository {
|
|
31
|
-
private filePath: string;
|
|
32
|
-
private initialized = false;
|
|
33
|
-
|
|
34
|
-
constructor(options?: { filePath?: string }) {
|
|
35
|
-
this.filePath = options?.filePath ?? '';
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
async save(request: ConsentRequestRecord): Promise<void> {
|
|
39
|
-
const records = await this.readAll();
|
|
40
|
-
const normalized = normalizeRecord(request);
|
|
41
|
-
const index = records.findIndex((item) => item.requestId === normalized.requestId);
|
|
42
|
-
if (index >= 0) {
|
|
43
|
-
records[index] = normalized;
|
|
44
|
-
} else {
|
|
45
|
-
records.push(normalized);
|
|
46
|
-
}
|
|
47
|
-
await this.writeAll(records);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
async updateStatus(requestId: string, status: ConsentStatus, updatedAt: number): Promise<void> {
|
|
51
|
-
const records = await this.readAll();
|
|
52
|
-
const index = records.findIndex((item) => item.requestId === requestId);
|
|
53
|
-
if (index === -1) {
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
records[index] = {
|
|
58
|
-
...records[index],
|
|
59
|
-
status,
|
|
60
|
-
updatedAt,
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
await this.writeAll(records);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
async getById(requestId: string): Promise<ConsentRequestRecord | null> {
|
|
67
|
-
const records = await this.readAll();
|
|
68
|
-
const record = records.find((item) => item.requestId === requestId);
|
|
69
|
-
return record ? { ...record } : null;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
async listByTarget(targetWallet: string, status?: ConsentStatus): Promise<ConsentRequestRecord[]> {
|
|
73
|
-
const normalizedTarget = normalizeSuiAddress(targetWallet);
|
|
74
|
-
const records = await this.readAll();
|
|
75
|
-
return records
|
|
76
|
-
.filter((record) => record.targetWallet === normalizedTarget)
|
|
77
|
-
.filter((record) => (status ? record.status === status : true))
|
|
78
|
-
.map((record) => ({ ...record }));
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
async listByRequester(requesterWallet: string, status?: ConsentStatus): Promise<ConsentRequestRecord[]> {
|
|
82
|
-
const normalizedRequester = normalizeSuiAddress(requesterWallet);
|
|
83
|
-
const records = await this.readAll();
|
|
84
|
-
return records
|
|
85
|
-
.filter((record) => record.requesterWallet === normalizedRequester)
|
|
86
|
-
.filter((record) => (status ? record.status === status : true))
|
|
87
|
-
.map((record) => ({ ...record }));
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
async delete(requestId: string): Promise<void> {
|
|
91
|
-
const records = await this.readAll();
|
|
92
|
-
const filtered = records.filter((record) => record.requestId !== requestId);
|
|
93
|
-
if (filtered.length === records.length) {
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
await this.writeAll(filtered);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
private async readAll(): Promise<StoredConsentRecord[]> {
|
|
100
|
-
await this.ensureInitialized();
|
|
101
|
-
const fs = await import('fs/promises');
|
|
102
|
-
try {
|
|
103
|
-
const buffer = await fs.readFile(this.filePath);
|
|
104
|
-
const parsed = JSON.parse(buffer.toString()) as StoredConsentRecord[];
|
|
105
|
-
if (!Array.isArray(parsed)) {
|
|
106
|
-
return [];
|
|
107
|
-
}
|
|
108
|
-
return parsed.map((record) => normalizeRecord(record));
|
|
109
|
-
} catch (error: any) {
|
|
110
|
-
if (error?.code === 'ENOENT') {
|
|
111
|
-
return [];
|
|
112
|
-
}
|
|
113
|
-
throw error;
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
private async writeAll(records: StoredConsentRecord[]): Promise<void> {
|
|
118
|
-
await this.ensureInitialized();
|
|
119
|
-
const fs = await import('fs/promises');
|
|
120
|
-
const serialized = JSON.stringify(records, null, 2);
|
|
121
|
-
await fs.writeFile(this.filePath, serialized, { encoding: 'utf-8' });
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
private async ensureInitialized(): Promise<void> {
|
|
125
|
-
if (this.initialized) {
|
|
126
|
-
return;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
const fs = await import('fs/promises');
|
|
130
|
-
const path = await import('path');
|
|
131
|
-
|
|
132
|
-
if (!this.filePath) {
|
|
133
|
-
this.filePath = path.resolve(process.cwd(), 'storage/consents/requests.json');
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
const dir = path.dirname(this.filePath);
|
|
137
|
-
await fs.mkdir(dir, { recursive: true });
|
|
138
|
-
this.initialized = true;
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
export class InMemoryConsentRepository implements ConsentRepository {
|
|
143
|
-
private store = new Map<string, StoredConsentRecord>();
|
|
144
|
-
|
|
145
|
-
async save(request: ConsentRequestRecord): Promise<void> {
|
|
146
|
-
const normalized = normalizeRecord(request);
|
|
147
|
-
this.store.set(normalized.requestId, normalized);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
async updateStatus(requestId: string, status: ConsentStatus, updatedAt: number): Promise<void> {
|
|
151
|
-
const record = this.store.get(requestId);
|
|
152
|
-
if (!record) {
|
|
153
|
-
return;
|
|
154
|
-
}
|
|
155
|
-
this.store.set(requestId, {
|
|
156
|
-
...record,
|
|
157
|
-
status,
|
|
158
|
-
updatedAt,
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
async getById(requestId: string): Promise<ConsentRequestRecord | null> {
|
|
163
|
-
const record = this.store.get(requestId);
|
|
164
|
-
return record ? { ...record } : null;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
async listByTarget(targetWallet: string, status?: ConsentStatus): Promise<ConsentRequestRecord[]> {
|
|
168
|
-
const normalizedTarget = normalizeSuiAddress(targetWallet);
|
|
169
|
-
return Array.from(this.store.values())
|
|
170
|
-
.filter((record) => record.targetWallet === normalizedTarget)
|
|
171
|
-
.filter((record) => (status ? record.status === status : true))
|
|
172
|
-
.map((record) => ({ ...record }));
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
async listByRequester(requesterWallet: string, status?: ConsentStatus): Promise<ConsentRequestRecord[]> {
|
|
176
|
-
const normalizedRequester = normalizeSuiAddress(requesterWallet);
|
|
177
|
-
return Array.from(this.store.values())
|
|
178
|
-
.filter((record) => record.requesterWallet === normalizedRequester)
|
|
179
|
-
.filter((record) => (status ? record.status === status : true))
|
|
180
|
-
.map((record) => ({ ...record }));
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
async delete(requestId: string): Promise<void> {
|
|
184
|
-
this.store.delete(requestId);
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
* IndexedDBConsentRepository - Browser-compatible implementation
|
|
190
|
-
* Uses IndexedDB for persistent storage in browser environments.
|
|
191
|
-
*/
|
|
192
|
-
export class IndexedDBConsentRepository implements ConsentRepository {
|
|
193
|
-
private dbName = 'pdw-consent-store';
|
|
194
|
-
private storeName = 'consent-requests';
|
|
195
|
-
private dbVersion = 1;
|
|
196
|
-
private db: IDBDatabase | null = null;
|
|
197
|
-
|
|
198
|
-
constructor(options?: { dbName?: string }) {
|
|
199
|
-
if (options?.dbName) {
|
|
200
|
-
this.dbName = options.dbName;
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
private async getDB(): Promise<IDBDatabase> {
|
|
205
|
-
if (this.db) {
|
|
206
|
-
return this.db;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
return new Promise((resolve, reject) => {
|
|
210
|
-
const request = indexedDB.open(this.dbName, this.dbVersion);
|
|
211
|
-
|
|
212
|
-
request.onerror = () => reject(request.error);
|
|
213
|
-
request.onsuccess = () => {
|
|
214
|
-
this.db = request.result;
|
|
215
|
-
resolve(request.result);
|
|
216
|
-
};
|
|
217
|
-
|
|
218
|
-
request.onupgradeneeded = (event) => {
|
|
219
|
-
const db = (event.target as IDBOpenDBRequest).result;
|
|
220
|
-
if (!db.objectStoreNames.contains(this.storeName)) {
|
|
221
|
-
const store = db.createObjectStore(this.storeName, { keyPath: 'requestId' });
|
|
222
|
-
store.createIndex('targetWallet', 'targetWallet', { unique: false });
|
|
223
|
-
store.createIndex('requesterWallet', 'requesterWallet', { unique: false });
|
|
224
|
-
store.createIndex('status', 'status', { unique: false });
|
|
225
|
-
}
|
|
226
|
-
};
|
|
227
|
-
});
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
async save(request: ConsentRequestRecord): Promise<void> {
|
|
231
|
-
const db = await this.getDB();
|
|
232
|
-
const normalized = normalizeRecord(request);
|
|
233
|
-
|
|
234
|
-
return new Promise((resolve, reject) => {
|
|
235
|
-
const tx = db.transaction(this.storeName, 'readwrite');
|
|
236
|
-
const store = tx.objectStore(this.storeName);
|
|
237
|
-
const req = store.put(normalized);
|
|
238
|
-
|
|
239
|
-
req.onerror = () => reject(req.error);
|
|
240
|
-
req.onsuccess = () => resolve();
|
|
241
|
-
});
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
async updateStatus(requestId: string, status: ConsentStatus, updatedAt: number): Promise<void> {
|
|
245
|
-
const record = await this.getById(requestId);
|
|
246
|
-
if (!record) {
|
|
247
|
-
return;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
await this.save({
|
|
251
|
-
...record,
|
|
252
|
-
status,
|
|
253
|
-
updatedAt,
|
|
254
|
-
});
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
async getById(requestId: string): Promise<ConsentRequestRecord | null> {
|
|
258
|
-
const db = await this.getDB();
|
|
259
|
-
|
|
260
|
-
return new Promise((resolve, reject) => {
|
|
261
|
-
const tx = db.transaction(this.storeName, 'readonly');
|
|
262
|
-
const store = tx.objectStore(this.storeName);
|
|
263
|
-
const req = store.get(requestId);
|
|
264
|
-
|
|
265
|
-
req.onerror = () => reject(req.error);
|
|
266
|
-
req.onsuccess = () => {
|
|
267
|
-
const record = req.result as StoredConsentRecord | undefined;
|
|
268
|
-
resolve(record ? { ...record } : null);
|
|
269
|
-
};
|
|
270
|
-
});
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
async listByTarget(targetWallet: string, status?: ConsentStatus): Promise<ConsentRequestRecord[]> {
|
|
274
|
-
const normalizedTarget = normalizeSuiAddress(targetWallet);
|
|
275
|
-
const db = await this.getDB();
|
|
276
|
-
|
|
277
|
-
return new Promise((resolve, reject) => {
|
|
278
|
-
const tx = db.transaction(this.storeName, 'readonly');
|
|
279
|
-
const store = tx.objectStore(this.storeName);
|
|
280
|
-
const index = store.index('targetWallet');
|
|
281
|
-
const req = index.getAll(normalizedTarget);
|
|
282
|
-
|
|
283
|
-
req.onerror = () => reject(req.error);
|
|
284
|
-
req.onsuccess = () => {
|
|
285
|
-
let records = req.result as StoredConsentRecord[];
|
|
286
|
-
if (status) {
|
|
287
|
-
records = records.filter((r) => r.status === status);
|
|
288
|
-
}
|
|
289
|
-
resolve(records.map((r) => ({ ...r })));
|
|
290
|
-
};
|
|
291
|
-
});
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
async listByRequester(requesterWallet: string, status?: ConsentStatus): Promise<ConsentRequestRecord[]> {
|
|
295
|
-
const normalizedRequester = normalizeSuiAddress(requesterWallet);
|
|
296
|
-
const db = await this.getDB();
|
|
297
|
-
|
|
298
|
-
return new Promise((resolve, reject) => {
|
|
299
|
-
const tx = db.transaction(this.storeName, 'readonly');
|
|
300
|
-
const store = tx.objectStore(this.storeName);
|
|
301
|
-
const index = store.index('requesterWallet');
|
|
302
|
-
const req = index.getAll(normalizedRequester);
|
|
303
|
-
|
|
304
|
-
req.onerror = () => reject(req.error);
|
|
305
|
-
req.onsuccess = () => {
|
|
306
|
-
let records = req.result as StoredConsentRecord[];
|
|
307
|
-
if (status) {
|
|
308
|
-
records = records.filter((r) => r.status === status);
|
|
309
|
-
}
|
|
310
|
-
resolve(records.map((r) => ({ ...r })));
|
|
311
|
-
};
|
|
312
|
-
});
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
async delete(requestId: string): Promise<void> {
|
|
316
|
-
const db = await this.getDB();
|
|
317
|
-
|
|
318
|
-
return new Promise((resolve, reject) => {
|
|
319
|
-
const tx = db.transaction(this.storeName, 'readwrite');
|
|
320
|
-
const store = tx.objectStore(this.storeName);
|
|
321
|
-
const req = store.delete(requestId);
|
|
322
|
-
|
|
323
|
-
req.onerror = () => reject(req.error);
|
|
324
|
-
req.onsuccess = () => resolve();
|
|
325
|
-
});
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
/**
|
|
329
|
-
* Close the database connection
|
|
330
|
-
*/
|
|
331
|
-
close(): void {
|
|
332
|
-
if (this.db) {
|
|
333
|
-
this.db.close();
|
|
334
|
-
this.db = null;
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
/**
|
|
340
|
-
* Factory function to create the appropriate ConsentRepository based on environment
|
|
341
|
-
*/
|
|
342
|
-
export function createConsentRepository(options?: {
|
|
343
|
-
filePath?: string;
|
|
344
|
-
dbName?: string;
|
|
345
|
-
forceInMemory?: boolean;
|
|
346
|
-
}): ConsentRepository {
|
|
347
|
-
// Force in-memory for testing
|
|
348
|
-
if (options?.forceInMemory) {
|
|
349
|
-
return new InMemoryConsentRepository();
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
// Browser environment - use IndexedDB
|
|
353
|
-
if (typeof window !== 'undefined' && typeof indexedDB !== 'undefined') {
|
|
354
|
-
return new IndexedDBConsentRepository({ dbName: options?.dbName });
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
// Node.js environment - use FileSystem (will lazy-load fs/path via import())
|
|
358
|
-
if (typeof window === 'undefined') {
|
|
359
|
-
return new FileSystemConsentRepository({ filePath: options?.filePath });
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
// Fallback to in-memory
|
|
363
|
-
return new InMemoryConsentRepository();
|
|
364
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
ConsentRequestRecord,
|
|
3
|
+
ConsentStatus,
|
|
4
|
+
} from '../core/types/wallet.js';
|
|
5
|
+
import { normalizeSuiAddress } from '@mysten/sui/utils';
|
|
6
|
+
|
|
7
|
+
export interface ConsentRepository {
|
|
8
|
+
save(request: ConsentRequestRecord): Promise<void>;
|
|
9
|
+
updateStatus(requestId: string, status: ConsentStatus, updatedAt: number): Promise<void>;
|
|
10
|
+
getById(requestId: string): Promise<ConsentRequestRecord | null>;
|
|
11
|
+
listByTarget(targetWallet: string, status?: ConsentStatus): Promise<ConsentRequestRecord[]>;
|
|
12
|
+
listByRequester(requesterWallet: string, status?: ConsentStatus): Promise<ConsentRequestRecord[]>;
|
|
13
|
+
delete(requestId: string): Promise<void>;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
interface StoredConsentRecord extends ConsentRequestRecord {}
|
|
17
|
+
|
|
18
|
+
function normalizeRecord(record: ConsentRequestRecord): StoredConsentRecord {
|
|
19
|
+
return {
|
|
20
|
+
...record,
|
|
21
|
+
requesterWallet: normalizeSuiAddress(record.requesterWallet),
|
|
22
|
+
targetWallet: normalizeSuiAddress(record.targetWallet),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* FileSystemConsentRepository - Node.js only implementation
|
|
28
|
+
* Uses file system for persistence. Not available in browser.
|
|
29
|
+
*/
|
|
30
|
+
export class FileSystemConsentRepository implements ConsentRepository {
|
|
31
|
+
private filePath: string;
|
|
32
|
+
private initialized = false;
|
|
33
|
+
|
|
34
|
+
constructor(options?: { filePath?: string }) {
|
|
35
|
+
this.filePath = options?.filePath ?? '';
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async save(request: ConsentRequestRecord): Promise<void> {
|
|
39
|
+
const records = await this.readAll();
|
|
40
|
+
const normalized = normalizeRecord(request);
|
|
41
|
+
const index = records.findIndex((item) => item.requestId === normalized.requestId);
|
|
42
|
+
if (index >= 0) {
|
|
43
|
+
records[index] = normalized;
|
|
44
|
+
} else {
|
|
45
|
+
records.push(normalized);
|
|
46
|
+
}
|
|
47
|
+
await this.writeAll(records);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async updateStatus(requestId: string, status: ConsentStatus, updatedAt: number): Promise<void> {
|
|
51
|
+
const records = await this.readAll();
|
|
52
|
+
const index = records.findIndex((item) => item.requestId === requestId);
|
|
53
|
+
if (index === -1) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
records[index] = {
|
|
58
|
+
...records[index],
|
|
59
|
+
status,
|
|
60
|
+
updatedAt,
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
await this.writeAll(records);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async getById(requestId: string): Promise<ConsentRequestRecord | null> {
|
|
67
|
+
const records = await this.readAll();
|
|
68
|
+
const record = records.find((item) => item.requestId === requestId);
|
|
69
|
+
return record ? { ...record } : null;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async listByTarget(targetWallet: string, status?: ConsentStatus): Promise<ConsentRequestRecord[]> {
|
|
73
|
+
const normalizedTarget = normalizeSuiAddress(targetWallet);
|
|
74
|
+
const records = await this.readAll();
|
|
75
|
+
return records
|
|
76
|
+
.filter((record) => record.targetWallet === normalizedTarget)
|
|
77
|
+
.filter((record) => (status ? record.status === status : true))
|
|
78
|
+
.map((record) => ({ ...record }));
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
async listByRequester(requesterWallet: string, status?: ConsentStatus): Promise<ConsentRequestRecord[]> {
|
|
82
|
+
const normalizedRequester = normalizeSuiAddress(requesterWallet);
|
|
83
|
+
const records = await this.readAll();
|
|
84
|
+
return records
|
|
85
|
+
.filter((record) => record.requesterWallet === normalizedRequester)
|
|
86
|
+
.filter((record) => (status ? record.status === status : true))
|
|
87
|
+
.map((record) => ({ ...record }));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
async delete(requestId: string): Promise<void> {
|
|
91
|
+
const records = await this.readAll();
|
|
92
|
+
const filtered = records.filter((record) => record.requestId !== requestId);
|
|
93
|
+
if (filtered.length === records.length) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
await this.writeAll(filtered);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
private async readAll(): Promise<StoredConsentRecord[]> {
|
|
100
|
+
await this.ensureInitialized();
|
|
101
|
+
const fs = await import('fs/promises');
|
|
102
|
+
try {
|
|
103
|
+
const buffer = await fs.readFile(this.filePath);
|
|
104
|
+
const parsed = JSON.parse(buffer.toString()) as StoredConsentRecord[];
|
|
105
|
+
if (!Array.isArray(parsed)) {
|
|
106
|
+
return [];
|
|
107
|
+
}
|
|
108
|
+
return parsed.map((record) => normalizeRecord(record));
|
|
109
|
+
} catch (error: any) {
|
|
110
|
+
if (error?.code === 'ENOENT') {
|
|
111
|
+
return [];
|
|
112
|
+
}
|
|
113
|
+
throw error;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
private async writeAll(records: StoredConsentRecord[]): Promise<void> {
|
|
118
|
+
await this.ensureInitialized();
|
|
119
|
+
const fs = await import('fs/promises');
|
|
120
|
+
const serialized = JSON.stringify(records, null, 2);
|
|
121
|
+
await fs.writeFile(this.filePath, serialized, { encoding: 'utf-8' });
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
private async ensureInitialized(): Promise<void> {
|
|
125
|
+
if (this.initialized) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const fs = await import('fs/promises');
|
|
130
|
+
const path = await import('path');
|
|
131
|
+
|
|
132
|
+
if (!this.filePath) {
|
|
133
|
+
this.filePath = path.resolve(process.cwd(), 'storage/consents/requests.json');
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const dir = path.dirname(this.filePath);
|
|
137
|
+
await fs.mkdir(dir, { recursive: true });
|
|
138
|
+
this.initialized = true;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export class InMemoryConsentRepository implements ConsentRepository {
|
|
143
|
+
private store = new Map<string, StoredConsentRecord>();
|
|
144
|
+
|
|
145
|
+
async save(request: ConsentRequestRecord): Promise<void> {
|
|
146
|
+
const normalized = normalizeRecord(request);
|
|
147
|
+
this.store.set(normalized.requestId, normalized);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
async updateStatus(requestId: string, status: ConsentStatus, updatedAt: number): Promise<void> {
|
|
151
|
+
const record = this.store.get(requestId);
|
|
152
|
+
if (!record) {
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
this.store.set(requestId, {
|
|
156
|
+
...record,
|
|
157
|
+
status,
|
|
158
|
+
updatedAt,
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
async getById(requestId: string): Promise<ConsentRequestRecord | null> {
|
|
163
|
+
const record = this.store.get(requestId);
|
|
164
|
+
return record ? { ...record } : null;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
async listByTarget(targetWallet: string, status?: ConsentStatus): Promise<ConsentRequestRecord[]> {
|
|
168
|
+
const normalizedTarget = normalizeSuiAddress(targetWallet);
|
|
169
|
+
return Array.from(this.store.values())
|
|
170
|
+
.filter((record) => record.targetWallet === normalizedTarget)
|
|
171
|
+
.filter((record) => (status ? record.status === status : true))
|
|
172
|
+
.map((record) => ({ ...record }));
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
async listByRequester(requesterWallet: string, status?: ConsentStatus): Promise<ConsentRequestRecord[]> {
|
|
176
|
+
const normalizedRequester = normalizeSuiAddress(requesterWallet);
|
|
177
|
+
return Array.from(this.store.values())
|
|
178
|
+
.filter((record) => record.requesterWallet === normalizedRequester)
|
|
179
|
+
.filter((record) => (status ? record.status === status : true))
|
|
180
|
+
.map((record) => ({ ...record }));
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
async delete(requestId: string): Promise<void> {
|
|
184
|
+
this.store.delete(requestId);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* IndexedDBConsentRepository - Browser-compatible implementation
|
|
190
|
+
* Uses IndexedDB for persistent storage in browser environments.
|
|
191
|
+
*/
|
|
192
|
+
export class IndexedDBConsentRepository implements ConsentRepository {
|
|
193
|
+
private dbName = 'pdw-consent-store';
|
|
194
|
+
private storeName = 'consent-requests';
|
|
195
|
+
private dbVersion = 1;
|
|
196
|
+
private db: IDBDatabase | null = null;
|
|
197
|
+
|
|
198
|
+
constructor(options?: { dbName?: string }) {
|
|
199
|
+
if (options?.dbName) {
|
|
200
|
+
this.dbName = options.dbName;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
private async getDB(): Promise<IDBDatabase> {
|
|
205
|
+
if (this.db) {
|
|
206
|
+
return this.db;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
return new Promise((resolve, reject) => {
|
|
210
|
+
const request = indexedDB.open(this.dbName, this.dbVersion);
|
|
211
|
+
|
|
212
|
+
request.onerror = () => reject(request.error);
|
|
213
|
+
request.onsuccess = () => {
|
|
214
|
+
this.db = request.result;
|
|
215
|
+
resolve(request.result);
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
request.onupgradeneeded = (event) => {
|
|
219
|
+
const db = (event.target as IDBOpenDBRequest).result;
|
|
220
|
+
if (!db.objectStoreNames.contains(this.storeName)) {
|
|
221
|
+
const store = db.createObjectStore(this.storeName, { keyPath: 'requestId' });
|
|
222
|
+
store.createIndex('targetWallet', 'targetWallet', { unique: false });
|
|
223
|
+
store.createIndex('requesterWallet', 'requesterWallet', { unique: false });
|
|
224
|
+
store.createIndex('status', 'status', { unique: false });
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
async save(request: ConsentRequestRecord): Promise<void> {
|
|
231
|
+
const db = await this.getDB();
|
|
232
|
+
const normalized = normalizeRecord(request);
|
|
233
|
+
|
|
234
|
+
return new Promise((resolve, reject) => {
|
|
235
|
+
const tx = db.transaction(this.storeName, 'readwrite');
|
|
236
|
+
const store = tx.objectStore(this.storeName);
|
|
237
|
+
const req = store.put(normalized);
|
|
238
|
+
|
|
239
|
+
req.onerror = () => reject(req.error);
|
|
240
|
+
req.onsuccess = () => resolve();
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
async updateStatus(requestId: string, status: ConsentStatus, updatedAt: number): Promise<void> {
|
|
245
|
+
const record = await this.getById(requestId);
|
|
246
|
+
if (!record) {
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
await this.save({
|
|
251
|
+
...record,
|
|
252
|
+
status,
|
|
253
|
+
updatedAt,
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
async getById(requestId: string): Promise<ConsentRequestRecord | null> {
|
|
258
|
+
const db = await this.getDB();
|
|
259
|
+
|
|
260
|
+
return new Promise((resolve, reject) => {
|
|
261
|
+
const tx = db.transaction(this.storeName, 'readonly');
|
|
262
|
+
const store = tx.objectStore(this.storeName);
|
|
263
|
+
const req = store.get(requestId);
|
|
264
|
+
|
|
265
|
+
req.onerror = () => reject(req.error);
|
|
266
|
+
req.onsuccess = () => {
|
|
267
|
+
const record = req.result as StoredConsentRecord | undefined;
|
|
268
|
+
resolve(record ? { ...record } : null);
|
|
269
|
+
};
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
async listByTarget(targetWallet: string, status?: ConsentStatus): Promise<ConsentRequestRecord[]> {
|
|
274
|
+
const normalizedTarget = normalizeSuiAddress(targetWallet);
|
|
275
|
+
const db = await this.getDB();
|
|
276
|
+
|
|
277
|
+
return new Promise((resolve, reject) => {
|
|
278
|
+
const tx = db.transaction(this.storeName, 'readonly');
|
|
279
|
+
const store = tx.objectStore(this.storeName);
|
|
280
|
+
const index = store.index('targetWallet');
|
|
281
|
+
const req = index.getAll(normalizedTarget);
|
|
282
|
+
|
|
283
|
+
req.onerror = () => reject(req.error);
|
|
284
|
+
req.onsuccess = () => {
|
|
285
|
+
let records = req.result as StoredConsentRecord[];
|
|
286
|
+
if (status) {
|
|
287
|
+
records = records.filter((r) => r.status === status);
|
|
288
|
+
}
|
|
289
|
+
resolve(records.map((r) => ({ ...r })));
|
|
290
|
+
};
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
async listByRequester(requesterWallet: string, status?: ConsentStatus): Promise<ConsentRequestRecord[]> {
|
|
295
|
+
const normalizedRequester = normalizeSuiAddress(requesterWallet);
|
|
296
|
+
const db = await this.getDB();
|
|
297
|
+
|
|
298
|
+
return new Promise((resolve, reject) => {
|
|
299
|
+
const tx = db.transaction(this.storeName, 'readonly');
|
|
300
|
+
const store = tx.objectStore(this.storeName);
|
|
301
|
+
const index = store.index('requesterWallet');
|
|
302
|
+
const req = index.getAll(normalizedRequester);
|
|
303
|
+
|
|
304
|
+
req.onerror = () => reject(req.error);
|
|
305
|
+
req.onsuccess = () => {
|
|
306
|
+
let records = req.result as StoredConsentRecord[];
|
|
307
|
+
if (status) {
|
|
308
|
+
records = records.filter((r) => r.status === status);
|
|
309
|
+
}
|
|
310
|
+
resolve(records.map((r) => ({ ...r })));
|
|
311
|
+
};
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
async delete(requestId: string): Promise<void> {
|
|
316
|
+
const db = await this.getDB();
|
|
317
|
+
|
|
318
|
+
return new Promise((resolve, reject) => {
|
|
319
|
+
const tx = db.transaction(this.storeName, 'readwrite');
|
|
320
|
+
const store = tx.objectStore(this.storeName);
|
|
321
|
+
const req = store.delete(requestId);
|
|
322
|
+
|
|
323
|
+
req.onerror = () => reject(req.error);
|
|
324
|
+
req.onsuccess = () => resolve();
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Close the database connection
|
|
330
|
+
*/
|
|
331
|
+
close(): void {
|
|
332
|
+
if (this.db) {
|
|
333
|
+
this.db.close();
|
|
334
|
+
this.db = null;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Factory function to create the appropriate ConsentRepository based on environment
|
|
341
|
+
*/
|
|
342
|
+
export function createConsentRepository(options?: {
|
|
343
|
+
filePath?: string;
|
|
344
|
+
dbName?: string;
|
|
345
|
+
forceInMemory?: boolean;
|
|
346
|
+
}): ConsentRepository {
|
|
347
|
+
// Force in-memory for testing
|
|
348
|
+
if (options?.forceInMemory) {
|
|
349
|
+
return new InMemoryConsentRepository();
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// Browser environment - use IndexedDB
|
|
353
|
+
if (typeof window !== 'undefined' && typeof indexedDB !== 'undefined') {
|
|
354
|
+
return new IndexedDBConsentRepository({ dbName: options?.dbName });
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// Node.js environment - use FileSystem (will lazy-load fs/path via import())
|
|
358
|
+
if (typeof window === 'undefined') {
|
|
359
|
+
return new FileSystemConsentRepository({ filePath: options?.filePath });
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// Fallback to in-memory
|
|
363
|
+
return new InMemoryConsentRepository();
|
|
364
|
+
}
|