@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,616 +1,614 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SEAL Service Integration
|
|
3
|
-
*
|
|
4
|
-
* Production-ready SEAL service wrapper with comprehensive error handling,
|
|
5
|
-
* session management, and performance analytics integration.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { SuiClient } from '@mysten/sui/client';
|
|
9
|
-
import { Transaction } from '@mysten/sui/transactions';
|
|
10
|
-
import { fromHex, toHex, normalizeSuiAddress } from '@mysten/sui/utils';
|
|
11
|
-
import { SealClient, SessionKey, EncryptedObject } from '@mysten/seal';
|
|
12
|
-
import type {
|
|
13
|
-
SealClientOptions,
|
|
14
|
-
EncryptOptions,
|
|
15
|
-
DecryptOptions,
|
|
16
|
-
KeyServerConfig
|
|
17
|
-
} from '@mysten/seal';
|
|
18
|
-
|
|
19
|
-
// SEAL SDK types and interfaces
|
|
20
|
-
interface SealConfig {
|
|
21
|
-
suiClient: SuiClient;
|
|
22
|
-
packageId: string;
|
|
23
|
-
keyServerUrls: string[];
|
|
24
|
-
keyServerObjectIds: string[];
|
|
25
|
-
threshold: number;
|
|
26
|
-
network: 'testnet' | 'mainnet';
|
|
27
|
-
enableMetrics: boolean;
|
|
28
|
-
retryAttempts: number;
|
|
29
|
-
timeoutMs: number;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
interface EncryptionOptions {
|
|
33
|
-
data: Uint8Array;
|
|
34
|
-
id: string;
|
|
35
|
-
threshold?: number;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
interface DecryptionOptions {
|
|
39
|
-
encryptedObject: Uint8Array;
|
|
40
|
-
sessionKey: any;
|
|
41
|
-
txBytes: Uint8Array;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
interface SessionConfig {
|
|
45
|
-
address: string;
|
|
46
|
-
packageId: string;
|
|
47
|
-
ttlMin: number;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
interface PerformanceMetric {
|
|
51
|
-
operation: string;
|
|
52
|
-
startTime: number;
|
|
53
|
-
endTime: number;
|
|
54
|
-
duration: number;
|
|
55
|
-
success: boolean;
|
|
56
|
-
errorType?: string;
|
|
57
|
-
metadata?: any;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* SEAL Service - Production Implementation
|
|
62
|
-
*/
|
|
63
|
-
export class SealService {
|
|
64
|
-
private sealClient: SealClient | null = null;
|
|
65
|
-
private sessionKey: SessionKey | null = null;
|
|
66
|
-
private config: SealConfig;
|
|
67
|
-
private performanceMetrics: PerformanceMetric[] = [];
|
|
68
|
-
private activeSessions: Map<string, any> = new Map();
|
|
69
|
-
|
|
70
|
-
constructor(config: SealConfig) {
|
|
71
|
-
this.config = config;
|
|
72
|
-
console.log('✅ SEAL SDK components loaded successfully');
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Initialize SEAL client with retry logic
|
|
77
|
-
*/
|
|
78
|
-
async initializeClient(): Promise<void> {
|
|
79
|
-
const metric = this.startMetric('seal_client_init');
|
|
80
|
-
|
|
81
|
-
try {
|
|
82
|
-
// Configure server configs from testnet servers
|
|
83
|
-
const serverConfigs: KeyServerConfig[] = this.config.keyServerObjectIds.map((objectId, index) => ({
|
|
84
|
-
objectId,
|
|
85
|
-
weight: 1
|
|
86
|
-
}));
|
|
87
|
-
|
|
88
|
-
const sealClientOptions: SealClientOptions = {
|
|
89
|
-
suiClient: this.config.suiClient,
|
|
90
|
-
serverConfigs,
|
|
91
|
-
verifyKeyServers: this.config.network === 'mainnet' // Only verify on mainnet
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
this.sealClient = new SealClient(sealClientOptions);
|
|
95
|
-
|
|
96
|
-
this.completeMetric(metric, true, { serverCount: serverConfigs.length });
|
|
97
|
-
console.log('✅ SEAL client initialized with', serverConfigs.length, 'servers');
|
|
98
|
-
|
|
99
|
-
} catch (error) {
|
|
100
|
-
this.completeMetric(metric, false, undefined, error);
|
|
101
|
-
throw new Error(`Failed to initialize SEAL client: ${error}`);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Create and manage session key
|
|
107
|
-
*/
|
|
108
|
-
async createSession(config: SessionConfig, signature?: Uint8Array | string): Promise<any> {
|
|
109
|
-
const metric = this.startMetric('session_creation');
|
|
110
|
-
|
|
111
|
-
try {
|
|
112
|
-
const sessionKey = await SessionKey.create({
|
|
113
|
-
address: config.address,
|
|
114
|
-
packageId: config.packageId,
|
|
115
|
-
ttlMin: config.ttlMin,
|
|
116
|
-
suiClient: this.config.suiClient
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
const message = sessionKey.getPersonalMessage();
|
|
120
|
-
|
|
121
|
-
// In production, signature would come from wallet
|
|
122
|
-
if (signature) {
|
|
123
|
-
// Convert Uint8Array to hex string if needed
|
|
124
|
-
const signatureString = typeof signature === 'string' ? signature : toHex(signature);
|
|
125
|
-
await sessionKey.setPersonalMessageSignature(signatureString);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// Store session for management
|
|
129
|
-
this.activeSessions.set(config.address, {
|
|
130
|
-
sessionKey,
|
|
131
|
-
createdAt: Date.now(),
|
|
132
|
-
ttl: config.ttlMin * 60 * 1000,
|
|
133
|
-
address: config.address
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
this.completeMetric(metric, true, {
|
|
137
|
-
address: config.address,
|
|
138
|
-
ttlMin: config.ttlMin,
|
|
139
|
-
messageLength: message.length
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
return { sessionKey, personalMessage: message };
|
|
143
|
-
|
|
144
|
-
} catch (error) {
|
|
145
|
-
this.completeMetric(metric, false, undefined, error);
|
|
146
|
-
throw new Error(`Failed to create session: ${error}`);
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* Encrypt data with comprehensive error handling
|
|
152
|
-
*/
|
|
153
|
-
async encryptData(options: EncryptionOptions): Promise<{ encryptedObject: Uint8Array; key: Uint8Array }> {
|
|
154
|
-
const metric = this.startMetric('encryption');
|
|
155
|
-
|
|
156
|
-
try {
|
|
157
|
-
if (!this.sealClient) {
|
|
158
|
-
await this.initializeClient();
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
if (!this.sealClient) {
|
|
162
|
-
throw new Error('Failed to initialize SEAL client');
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
const threshold = options.threshold || this.config.threshold;
|
|
166
|
-
|
|
167
|
-
// Validate threshold against available servers
|
|
168
|
-
if (threshold > this.config.keyServerObjectIds.length) {
|
|
169
|
-
throw new Error(`Threshold ${threshold} exceeds available servers ${this.config.keyServerObjectIds.length}`);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
const result = await this.sealClient.encrypt({
|
|
173
|
-
threshold,
|
|
174
|
-
packageId: this.config.packageId,
|
|
175
|
-
id: options.id,
|
|
176
|
-
data: options.data
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
this.completeMetric(metric, true, {
|
|
180
|
-
dataSize: options.data.length,
|
|
181
|
-
threshold,
|
|
182
|
-
encryptedSize: result.encryptedObject.length,
|
|
183
|
-
keySize: result.key.length
|
|
184
|
-
});
|
|
185
|
-
|
|
186
|
-
return result;
|
|
187
|
-
|
|
188
|
-
} catch (error) {
|
|
189
|
-
this.completeMetric(metric, false, undefined, error);
|
|
190
|
-
|
|
191
|
-
// Enhanced error handling
|
|
192
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
193
|
-
if (errorMessage.includes('threshold')) {
|
|
194
|
-
throw new Error(`Encryption threshold error: ${errorMessage}`);
|
|
195
|
-
}
|
|
196
|
-
if (errorMessage.includes('network')) {
|
|
197
|
-
throw new Error(`Network error during encryption: ${errorMessage}`);
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
throw new Error(`Encryption failed: ${errorMessage}`);
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
/**
|
|
205
|
-
* Decrypt data with session management
|
|
206
|
-
*/
|
|
207
|
-
async decryptData(options: DecryptionOptions): Promise<Uint8Array> {
|
|
208
|
-
const metric = this.startMetric('decryption');
|
|
209
|
-
|
|
210
|
-
try {
|
|
211
|
-
if (!this.sealClient) {
|
|
212
|
-
await this.initializeClient();
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
if (!this.sealClient) {
|
|
216
|
-
throw new Error('Failed to initialize SEAL client');
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
// Add detailed debugging for SEAL decryption
|
|
220
|
-
console.log('🔍 SEAL decrypt parameters:');
|
|
221
|
-
console.log(` - Encrypted data type: ${typeof options.encryptedObject}`);
|
|
222
|
-
console.log(` - Encrypted data length: ${options.encryptedObject.length}`);
|
|
223
|
-
console.log(` - Session key type: ${typeof options.sessionKey}`);
|
|
224
|
-
console.log(` - Session key constructor: ${options.sessionKey?.constructor?.name}`);
|
|
225
|
-
console.log(` - Transaction bytes type: ${typeof options.txBytes}`);
|
|
226
|
-
console.log(` - Transaction bytes length: ${options.txBytes.length}`);
|
|
227
|
-
|
|
228
|
-
// Check if session key has expected methods
|
|
229
|
-
if (options.sessionKey) {
|
|
230
|
-
console.log(` - Session key methods: ${Object.getOwnPropertyNames(Object.getPrototypeOf(options.sessionKey)).join(', ')}`);
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
// Try SEAL decryption with error boundary
|
|
234
|
-
let result;
|
|
235
|
-
try {
|
|
236
|
-
console.log('🔍 Attempting SEAL client decrypt...');
|
|
237
|
-
result = await this.sealClient.decrypt({
|
|
238
|
-
data: options.encryptedObject,
|
|
239
|
-
sessionKey: options.sessionKey,
|
|
240
|
-
txBytes: options.txBytes
|
|
241
|
-
});
|
|
242
|
-
console.log('🔍 SEAL decrypt completed without throwing');
|
|
243
|
-
} catch (innerError) {
|
|
244
|
-
console.log('🔍 SEAL decrypt threw an error:', innerError);
|
|
245
|
-
throw innerError;
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
console.log(`🔍 SEAL decrypt result:`, {
|
|
249
|
-
result,
|
|
250
|
-
resultType: typeof result,
|
|
251
|
-
resultLength: result ? result.length : 'undefined',
|
|
252
|
-
hasResult: !!result,
|
|
253
|
-
isUint8Array: result instanceof Uint8Array
|
|
254
|
-
});
|
|
255
|
-
|
|
256
|
-
if (!result) {
|
|
257
|
-
throw new Error('SEAL decrypt returned undefined/null result');
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
this.completeMetric(metric, true, {
|
|
261
|
-
encryptedSize: options.encryptedObject.length,
|
|
262
|
-
decryptedSize: result ? result.length : 0
|
|
263
|
-
});
|
|
264
|
-
|
|
265
|
-
return result;
|
|
266
|
-
|
|
267
|
-
} catch (error) {
|
|
268
|
-
this.completeMetric(metric, false, undefined, error);
|
|
269
|
-
|
|
270
|
-
// Enhanced error handling for decryption with detailed logging
|
|
271
|
-
console.log('🚨 SEAL decrypt error details:', {
|
|
272
|
-
error,
|
|
273
|
-
errorType: typeof error,
|
|
274
|
-
errorConstructor: error?.constructor?.name,
|
|
275
|
-
errorMessage: error instanceof Error ? error.message : String(error),
|
|
276
|
-
errorStack: error instanceof Error ? error.stack : 'No stack trace'
|
|
277
|
-
});
|
|
278
|
-
|
|
279
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
280
|
-
if (errorMessage.includes('access')) {
|
|
281
|
-
throw new Error(`Access denied for decryption: ${errorMessage}`);
|
|
282
|
-
}
|
|
283
|
-
if (errorMessage.includes('session')) {
|
|
284
|
-
throw new Error(`Session error during decryption: ${errorMessage}`);
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
throw new Error(`Decryption failed: ${errorMessage}`);
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
/**
|
|
292
|
-
* Create transaction for seal_approve using
|
|
293
|
-
* Matches Move signature: seal_approve(
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
const
|
|
309
|
-
|
|
310
|
-
//
|
|
311
|
-
//
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
tx.pure.
|
|
317
|
-
tx.object(
|
|
318
|
-
|
|
319
|
-
]
|
|
320
|
-
});
|
|
321
|
-
|
|
322
|
-
// Set the sender for the transaction
|
|
323
|
-
tx.setSender(userAddress);
|
|
324
|
-
|
|
325
|
-
const txBytes = await tx.build({
|
|
326
|
-
client: this.config.suiClient,
|
|
327
|
-
onlyTransactionKind: true
|
|
328
|
-
});
|
|
329
|
-
|
|
330
|
-
this.completeMetric(metric, true, {
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
*
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
const
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
//
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
tx.pure.
|
|
370
|
-
tx.object(
|
|
371
|
-
|
|
372
|
-
]
|
|
373
|
-
});
|
|
374
|
-
|
|
375
|
-
this.completeMetric(metric, true, {
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
if
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
metric.
|
|
480
|
-
metric.
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
const
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
op.
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
if (healthyServers
|
|
573
|
-
status = '
|
|
574
|
-
} else
|
|
575
|
-
status = '
|
|
576
|
-
}
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
}
|
|
615
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* SEAL Service Integration
|
|
3
|
+
*
|
|
4
|
+
* Production-ready SEAL service wrapper with comprehensive error handling,
|
|
5
|
+
* session management, and performance analytics integration.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { SuiClient } from '@mysten/sui/client';
|
|
9
|
+
import { Transaction } from '@mysten/sui/transactions';
|
|
10
|
+
import { fromHex, toHex, normalizeSuiAddress } from '@mysten/sui/utils';
|
|
11
|
+
import { SealClient, SessionKey, EncryptedObject } from '@mysten/seal';
|
|
12
|
+
import type {
|
|
13
|
+
SealClientOptions,
|
|
14
|
+
EncryptOptions,
|
|
15
|
+
DecryptOptions,
|
|
16
|
+
KeyServerConfig
|
|
17
|
+
} from '@mysten/seal';
|
|
18
|
+
|
|
19
|
+
// SEAL SDK types and interfaces
|
|
20
|
+
interface SealConfig {
|
|
21
|
+
suiClient: SuiClient;
|
|
22
|
+
packageId: string;
|
|
23
|
+
keyServerUrls: string[];
|
|
24
|
+
keyServerObjectIds: string[];
|
|
25
|
+
threshold: number;
|
|
26
|
+
network: 'testnet' | 'mainnet';
|
|
27
|
+
enableMetrics: boolean;
|
|
28
|
+
retryAttempts: number;
|
|
29
|
+
timeoutMs: number;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
interface EncryptionOptions {
|
|
33
|
+
data: Uint8Array;
|
|
34
|
+
id: string;
|
|
35
|
+
threshold?: number;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
interface DecryptionOptions {
|
|
39
|
+
encryptedObject: Uint8Array;
|
|
40
|
+
sessionKey: any;
|
|
41
|
+
txBytes: Uint8Array;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
interface SessionConfig {
|
|
45
|
+
address: string;
|
|
46
|
+
packageId: string;
|
|
47
|
+
ttlMin: number;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
interface PerformanceMetric {
|
|
51
|
+
operation: string;
|
|
52
|
+
startTime: number;
|
|
53
|
+
endTime: number;
|
|
54
|
+
duration: number;
|
|
55
|
+
success: boolean;
|
|
56
|
+
errorType?: string;
|
|
57
|
+
metadata?: any;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* SEAL Service - Production Implementation
|
|
62
|
+
*/
|
|
63
|
+
export class SealService {
|
|
64
|
+
private sealClient: SealClient | null = null;
|
|
65
|
+
private sessionKey: SessionKey | null = null;
|
|
66
|
+
private config: SealConfig;
|
|
67
|
+
private performanceMetrics: PerformanceMetric[] = [];
|
|
68
|
+
private activeSessions: Map<string, any> = new Map();
|
|
69
|
+
|
|
70
|
+
constructor(config: SealConfig) {
|
|
71
|
+
this.config = config;
|
|
72
|
+
console.log('✅ SEAL SDK components loaded successfully');
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Initialize SEAL client with retry logic
|
|
77
|
+
*/
|
|
78
|
+
async initializeClient(): Promise<void> {
|
|
79
|
+
const metric = this.startMetric('seal_client_init');
|
|
80
|
+
|
|
81
|
+
try {
|
|
82
|
+
// Configure server configs from testnet servers
|
|
83
|
+
const serverConfigs: KeyServerConfig[] = this.config.keyServerObjectIds.map((objectId, index) => ({
|
|
84
|
+
objectId,
|
|
85
|
+
weight: 1
|
|
86
|
+
}));
|
|
87
|
+
|
|
88
|
+
const sealClientOptions: SealClientOptions = {
|
|
89
|
+
suiClient: this.config.suiClient,
|
|
90
|
+
serverConfigs,
|
|
91
|
+
verifyKeyServers: this.config.network === 'mainnet' // Only verify on mainnet
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
this.sealClient = new SealClient(sealClientOptions);
|
|
95
|
+
|
|
96
|
+
this.completeMetric(metric, true, { serverCount: serverConfigs.length });
|
|
97
|
+
console.log('✅ SEAL client initialized with', serverConfigs.length, 'servers');
|
|
98
|
+
|
|
99
|
+
} catch (error) {
|
|
100
|
+
this.completeMetric(metric, false, undefined, error);
|
|
101
|
+
throw new Error(`Failed to initialize SEAL client: ${error}`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Create and manage session key
|
|
107
|
+
*/
|
|
108
|
+
async createSession(config: SessionConfig, signature?: Uint8Array | string): Promise<any> {
|
|
109
|
+
const metric = this.startMetric('session_creation');
|
|
110
|
+
|
|
111
|
+
try {
|
|
112
|
+
const sessionKey = await SessionKey.create({
|
|
113
|
+
address: config.address,
|
|
114
|
+
packageId: config.packageId,
|
|
115
|
+
ttlMin: config.ttlMin,
|
|
116
|
+
suiClient: this.config.suiClient
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
const message = sessionKey.getPersonalMessage();
|
|
120
|
+
|
|
121
|
+
// In production, signature would come from wallet
|
|
122
|
+
if (signature) {
|
|
123
|
+
// Convert Uint8Array to hex string if needed
|
|
124
|
+
const signatureString = typeof signature === 'string' ? signature : toHex(signature);
|
|
125
|
+
await sessionKey.setPersonalMessageSignature(signatureString);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Store session for management
|
|
129
|
+
this.activeSessions.set(config.address, {
|
|
130
|
+
sessionKey,
|
|
131
|
+
createdAt: Date.now(),
|
|
132
|
+
ttl: config.ttlMin * 60 * 1000,
|
|
133
|
+
address: config.address
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
this.completeMetric(metric, true, {
|
|
137
|
+
address: config.address,
|
|
138
|
+
ttlMin: config.ttlMin,
|
|
139
|
+
messageLength: message.length
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
return { sessionKey, personalMessage: message };
|
|
143
|
+
|
|
144
|
+
} catch (error) {
|
|
145
|
+
this.completeMetric(metric, false, undefined, error);
|
|
146
|
+
throw new Error(`Failed to create session: ${error}`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Encrypt data with comprehensive error handling
|
|
152
|
+
*/
|
|
153
|
+
async encryptData(options: EncryptionOptions): Promise<{ encryptedObject: Uint8Array; key: Uint8Array }> {
|
|
154
|
+
const metric = this.startMetric('encryption');
|
|
155
|
+
|
|
156
|
+
try {
|
|
157
|
+
if (!this.sealClient) {
|
|
158
|
+
await this.initializeClient();
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (!this.sealClient) {
|
|
162
|
+
throw new Error('Failed to initialize SEAL client');
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const threshold = options.threshold || this.config.threshold;
|
|
166
|
+
|
|
167
|
+
// Validate threshold against available servers
|
|
168
|
+
if (threshold > this.config.keyServerObjectIds.length) {
|
|
169
|
+
throw new Error(`Threshold ${threshold} exceeds available servers ${this.config.keyServerObjectIds.length}`);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const result = await this.sealClient.encrypt({
|
|
173
|
+
threshold,
|
|
174
|
+
packageId: this.config.packageId,
|
|
175
|
+
id: options.id,
|
|
176
|
+
data: options.data
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
this.completeMetric(metric, true, {
|
|
180
|
+
dataSize: options.data.length,
|
|
181
|
+
threshold,
|
|
182
|
+
encryptedSize: result.encryptedObject.length,
|
|
183
|
+
keySize: result.key.length
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
return result;
|
|
187
|
+
|
|
188
|
+
} catch (error) {
|
|
189
|
+
this.completeMetric(metric, false, undefined, error);
|
|
190
|
+
|
|
191
|
+
// Enhanced error handling
|
|
192
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
193
|
+
if (errorMessage.includes('threshold')) {
|
|
194
|
+
throw new Error(`Encryption threshold error: ${errorMessage}`);
|
|
195
|
+
}
|
|
196
|
+
if (errorMessage.includes('network')) {
|
|
197
|
+
throw new Error(`Network error during encryption: ${errorMessage}`);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
throw new Error(`Encryption failed: ${errorMessage}`);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Decrypt data with session management
|
|
206
|
+
*/
|
|
207
|
+
async decryptData(options: DecryptionOptions): Promise<Uint8Array> {
|
|
208
|
+
const metric = this.startMetric('decryption');
|
|
209
|
+
|
|
210
|
+
try {
|
|
211
|
+
if (!this.sealClient) {
|
|
212
|
+
await this.initializeClient();
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
if (!this.sealClient) {
|
|
216
|
+
throw new Error('Failed to initialize SEAL client');
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// Add detailed debugging for SEAL decryption
|
|
220
|
+
console.log('🔍 SEAL decrypt parameters:');
|
|
221
|
+
console.log(` - Encrypted data type: ${typeof options.encryptedObject}`);
|
|
222
|
+
console.log(` - Encrypted data length: ${options.encryptedObject.length}`);
|
|
223
|
+
console.log(` - Session key type: ${typeof options.sessionKey}`);
|
|
224
|
+
console.log(` - Session key constructor: ${options.sessionKey?.constructor?.name}`);
|
|
225
|
+
console.log(` - Transaction bytes type: ${typeof options.txBytes}`);
|
|
226
|
+
console.log(` - Transaction bytes length: ${options.txBytes.length}`);
|
|
227
|
+
|
|
228
|
+
// Check if session key has expected methods
|
|
229
|
+
if (options.sessionKey) {
|
|
230
|
+
console.log(` - Session key methods: ${Object.getOwnPropertyNames(Object.getPrototypeOf(options.sessionKey)).join(', ')}`);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// Try SEAL decryption with error boundary
|
|
234
|
+
let result;
|
|
235
|
+
try {
|
|
236
|
+
console.log('🔍 Attempting SEAL client decrypt...');
|
|
237
|
+
result = await this.sealClient.decrypt({
|
|
238
|
+
data: options.encryptedObject,
|
|
239
|
+
sessionKey: options.sessionKey,
|
|
240
|
+
txBytes: options.txBytes
|
|
241
|
+
});
|
|
242
|
+
console.log('🔍 SEAL decrypt completed without throwing');
|
|
243
|
+
} catch (innerError) {
|
|
244
|
+
console.log('🔍 SEAL decrypt threw an error:', innerError);
|
|
245
|
+
throw innerError;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
console.log(`🔍 SEAL decrypt result:`, {
|
|
249
|
+
result,
|
|
250
|
+
resultType: typeof result,
|
|
251
|
+
resultLength: result ? result.length : 'undefined',
|
|
252
|
+
hasResult: !!result,
|
|
253
|
+
isUint8Array: result instanceof Uint8Array
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
if (!result) {
|
|
257
|
+
throw new Error('SEAL decrypt returned undefined/null result');
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
this.completeMetric(metric, true, {
|
|
261
|
+
encryptedSize: options.encryptedObject.length,
|
|
262
|
+
decryptedSize: result ? result.length : 0
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
return result;
|
|
266
|
+
|
|
267
|
+
} catch (error) {
|
|
268
|
+
this.completeMetric(metric, false, undefined, error);
|
|
269
|
+
|
|
270
|
+
// Enhanced error handling for decryption with detailed logging
|
|
271
|
+
console.log('🚨 SEAL decrypt error details:', {
|
|
272
|
+
error,
|
|
273
|
+
errorType: typeof error,
|
|
274
|
+
errorConstructor: error?.constructor?.name,
|
|
275
|
+
errorMessage: error instanceof Error ? error.message : String(error),
|
|
276
|
+
errorStack: error instanceof Error ? error.stack : 'No stack trace'
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
280
|
+
if (errorMessage.includes('access')) {
|
|
281
|
+
throw new Error(`Access denied for decryption: ${errorMessage}`);
|
|
282
|
+
}
|
|
283
|
+
if (errorMessage.includes('session')) {
|
|
284
|
+
throw new Error(`Session error during decryption: ${errorMessage}`);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
throw new Error(`Decryption failed: ${errorMessage}`);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Create transaction for seal_approve using capability pattern
|
|
293
|
+
* Matches Move signature: seal_approve(cap: &MemoryCap, key_id: vector<u8>, ctx: &TxContext)
|
|
294
|
+
*
|
|
295
|
+
* @param keyId - SEAL key ID (hex string or bytes)
|
|
296
|
+
* @param userAddress - User's wallet address (sender)
|
|
297
|
+
* @param memoryCapId - Object ID of the MemoryCap
|
|
298
|
+
*/
|
|
299
|
+
async createSealApproveTransaction(
|
|
300
|
+
keyId: string,
|
|
301
|
+
userAddress: string,
|
|
302
|
+
memoryCapId: string,
|
|
303
|
+
_accessRegistry?: string // Deprecated, kept for backward compatibility
|
|
304
|
+
): Promise<Uint8Array> {
|
|
305
|
+
const metric = this.startMetric('transaction_creation');
|
|
306
|
+
|
|
307
|
+
try {
|
|
308
|
+
const tx = new Transaction();
|
|
309
|
+
|
|
310
|
+
// Capability-based seal_approve call
|
|
311
|
+
// CRITICAL: key_id MUST be first argument for SEAL key server!
|
|
312
|
+
// entry fun seal_approve(key_id: vector<u8>, cap: &MemoryCap, ctx: &TxContext)
|
|
313
|
+
tx.moveCall({
|
|
314
|
+
target: `${this.config.packageId}::capability::seal_approve`,
|
|
315
|
+
arguments: [
|
|
316
|
+
tx.pure.vector("u8", fromHex(keyId)), // Arg 1: SEAL key ID (MUST BE FIRST!)
|
|
317
|
+
tx.object(memoryCapId), // Arg 2: MemoryCap object reference
|
|
318
|
+
// ctx: &TxContext is auto-provided by Sui
|
|
319
|
+
]
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
// Set the sender for the transaction
|
|
323
|
+
tx.setSender(userAddress);
|
|
324
|
+
|
|
325
|
+
const txBytes = await tx.build({
|
|
326
|
+
client: this.config.suiClient,
|
|
327
|
+
onlyTransactionKind: true
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
this.completeMetric(metric, true, {
|
|
331
|
+
keyId,
|
|
332
|
+
memoryCapId,
|
|
333
|
+
txSize: txBytes.length,
|
|
334
|
+
userAddress
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
return txBytes;
|
|
338
|
+
|
|
339
|
+
} catch (error) {
|
|
340
|
+
this.completeMetric(metric, false, undefined, error);
|
|
341
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
342
|
+
throw new Error(`Failed to create transaction: ${errorMessage}`);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* Build a seal_approve transaction using capability pattern
|
|
348
|
+
* Matches Move signature: seal_approve(cap: &MemoryCap, key_id: vector<u8>, ctx: &TxContext)
|
|
349
|
+
*
|
|
350
|
+
* @param keyId - SEAL key ID (bytes)
|
|
351
|
+
* @param memoryCapId - Object ID of the MemoryCap
|
|
352
|
+
*/
|
|
353
|
+
buildSealApproveTransaction(
|
|
354
|
+
keyId: Uint8Array,
|
|
355
|
+
memoryCapId: string,
|
|
356
|
+
_accessRegistry?: string // Deprecated, kept for backward compatibility
|
|
357
|
+
): Transaction {
|
|
358
|
+
const metric = this.startMetric('transaction_creation_wallet');
|
|
359
|
+
|
|
360
|
+
try {
|
|
361
|
+
const tx = new Transaction();
|
|
362
|
+
|
|
363
|
+
// Capability-based seal_approve call
|
|
364
|
+
// CRITICAL: key_id MUST be first argument for SEAL key server!
|
|
365
|
+
// entry fun seal_approve(key_id: vector<u8>, cap: &MemoryCap, ctx: &TxContext)
|
|
366
|
+
tx.moveCall({
|
|
367
|
+
target: `${this.config.packageId}::capability::seal_approve`,
|
|
368
|
+
arguments: [
|
|
369
|
+
tx.pure.vector('u8', Array.from(keyId)), // Arg 1: SEAL key ID (MUST BE FIRST!)
|
|
370
|
+
tx.object(memoryCapId), // Arg 2: MemoryCap object reference
|
|
371
|
+
// ctx: &TxContext is auto-provided by Sui
|
|
372
|
+
]
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
this.completeMetric(metric, true, {
|
|
376
|
+
keyIdLength: keyId.length,
|
|
377
|
+
memoryCapId
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
return tx;
|
|
381
|
+
|
|
382
|
+
} catch (error) {
|
|
383
|
+
this.completeMetric(metric, false, undefined, error);
|
|
384
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
385
|
+
throw new Error(`Failed to create transaction for capability: ${errorMessage}`);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* Parse encrypted object structure
|
|
391
|
+
*/
|
|
392
|
+
parseEncryptedObject(encryptedBytes: Uint8Array): any {
|
|
393
|
+
const metric = this.startMetric('object_parsing');
|
|
394
|
+
|
|
395
|
+
try {
|
|
396
|
+
const parsed = EncryptedObject.parse(encryptedBytes);
|
|
397
|
+
|
|
398
|
+
this.completeMetric(metric, true, {
|
|
399
|
+
version: parsed.version,
|
|
400
|
+
packageId: parsed.packageId,
|
|
401
|
+
threshold: parsed.threshold,
|
|
402
|
+
dataSize: encryptedBytes.length
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
return parsed;
|
|
406
|
+
|
|
407
|
+
} catch (error) {
|
|
408
|
+
this.completeMetric(metric, false, undefined, error);
|
|
409
|
+
throw new Error(`Failed to parse encrypted object: ${error}`);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
/**
|
|
414
|
+
* Session management utilities
|
|
415
|
+
*/
|
|
416
|
+
getActiveSession(address: string): any | null {
|
|
417
|
+
const session = this.activeSessions.get(address);
|
|
418
|
+
if (!session) return null;
|
|
419
|
+
|
|
420
|
+
// Check if session is expired
|
|
421
|
+
const now = Date.now();
|
|
422
|
+
if (now > session.createdAt + session.ttl) {
|
|
423
|
+
this.activeSessions.delete(address);
|
|
424
|
+
return null;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
return session.sessionKey;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
cleanupExpiredSessions(): number {
|
|
431
|
+
const now = Date.now();
|
|
432
|
+
let cleanedCount = 0;
|
|
433
|
+
|
|
434
|
+
for (const [address, session] of this.activeSessions.entries()) {
|
|
435
|
+
if (now > session.createdAt + session.ttl) {
|
|
436
|
+
this.activeSessions.delete(address);
|
|
437
|
+
cleanedCount++;
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
console.log(`🧹 Cleaned up ${cleanedCount} expired sessions`);
|
|
442
|
+
return cleanedCount;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
getSessionStats(): { total: number; expired: number; active: number } {
|
|
446
|
+
const now = Date.now();
|
|
447
|
+
let active = 0;
|
|
448
|
+
let expired = 0;
|
|
449
|
+
|
|
450
|
+
for (const session of this.activeSessions.values()) {
|
|
451
|
+
if (now > session.createdAt + session.ttl) {
|
|
452
|
+
expired++;
|
|
453
|
+
} else {
|
|
454
|
+
active++;
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
return { total: this.activeSessions.size, active, expired };
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* Performance metrics and analytics
|
|
463
|
+
*/
|
|
464
|
+
private startMetric(operation: string): PerformanceMetric {
|
|
465
|
+
const metric: PerformanceMetric = {
|
|
466
|
+
operation,
|
|
467
|
+
startTime: Date.now(),
|
|
468
|
+
endTime: 0,
|
|
469
|
+
duration: 0,
|
|
470
|
+
success: false
|
|
471
|
+
};
|
|
472
|
+
|
|
473
|
+
return metric;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
private completeMetric(metric: PerformanceMetric, success: boolean, metadata?: any, error?: any): void {
|
|
477
|
+
metric.endTime = Date.now();
|
|
478
|
+
metric.duration = metric.endTime - metric.startTime;
|
|
479
|
+
metric.success = success;
|
|
480
|
+
metric.metadata = metadata;
|
|
481
|
+
|
|
482
|
+
if (error) {
|
|
483
|
+
metric.errorType = error.constructor.name;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
this.performanceMetrics.push(metric);
|
|
487
|
+
|
|
488
|
+
// Limit metrics storage to prevent memory leaks
|
|
489
|
+
if (this.performanceMetrics.length > 1000) {
|
|
490
|
+
this.performanceMetrics.splice(0, 500); // Keep last 500 metrics
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
getPerformanceMetrics(): PerformanceMetric[] {
|
|
495
|
+
return [...this.performanceMetrics];
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
getPerformanceStats() {
|
|
499
|
+
if (this.performanceMetrics.length === 0) {
|
|
500
|
+
return { totalOperations: 0, averageTime: 0, successRate: 0 };
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
const successful = this.performanceMetrics.filter(m => m.success);
|
|
504
|
+
const totalTime = this.performanceMetrics.reduce((sum, m) => sum + m.duration, 0);
|
|
505
|
+
|
|
506
|
+
return {
|
|
507
|
+
totalOperations: this.performanceMetrics.length,
|
|
508
|
+
successfulOperations: successful.length,
|
|
509
|
+
successRate: (successful.length / this.performanceMetrics.length) * 100,
|
|
510
|
+
averageTime: totalTime / this.performanceMetrics.length,
|
|
511
|
+
averageSuccessTime: successful.length > 0 ?
|
|
512
|
+
successful.reduce((sum, m) => sum + m.duration, 0) / successful.length : 0,
|
|
513
|
+
operationBreakdown: this.getOperationBreakdown()
|
|
514
|
+
};
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
private getOperationBreakdown(): Record<string, any> {
|
|
518
|
+
const breakdown: Record<string, any> = {};
|
|
519
|
+
|
|
520
|
+
for (const metric of this.performanceMetrics) {
|
|
521
|
+
if (!breakdown[metric.operation]) {
|
|
522
|
+
breakdown[metric.operation] = {
|
|
523
|
+
count: 0,
|
|
524
|
+
totalTime: 0,
|
|
525
|
+
successCount: 0,
|
|
526
|
+
avgTime: 0,
|
|
527
|
+
successRate: 0
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
const op = breakdown[metric.operation];
|
|
532
|
+
op.count++;
|
|
533
|
+
op.totalTime += metric.duration;
|
|
534
|
+
if (metric.success) op.successCount++;
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
// Calculate averages and rates
|
|
538
|
+
for (const op of Object.values(breakdown) as any[]) {
|
|
539
|
+
op.avgTime = op.totalTime / op.count;
|
|
540
|
+
op.successRate = (op.successCount / op.count) * 100;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
return breakdown;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
/**
|
|
547
|
+
* Health checks and diagnostics
|
|
548
|
+
*/
|
|
549
|
+
async healthCheck(): Promise<{ status: 'healthy' | 'degraded' | 'unhealthy'; details: any }> {
|
|
550
|
+
const checks = {
|
|
551
|
+
sealClientInitialized: !!this.sealClient,
|
|
552
|
+
activeSessions: this.activeSessions.size,
|
|
553
|
+
performanceMetrics: this.performanceMetrics.length,
|
|
554
|
+
keyServers: this.config.keyServerObjectIds.length
|
|
555
|
+
};
|
|
556
|
+
|
|
557
|
+
// Test key server connectivity
|
|
558
|
+
const serverHealth = await Promise.allSettled(
|
|
559
|
+
this.config.keyServerUrls.map(async (url) => {
|
|
560
|
+
const response = await fetch(url, { signal: AbortSignal.timeout(5000) });
|
|
561
|
+
return { url, status: response.status, ok: response.ok };
|
|
562
|
+
})
|
|
563
|
+
);
|
|
564
|
+
|
|
565
|
+
const healthyServers = serverHealth.filter(result =>
|
|
566
|
+
result.status === 'fulfilled' && result.value.ok
|
|
567
|
+
).length;
|
|
568
|
+
|
|
569
|
+
let status: 'healthy' | 'degraded' | 'unhealthy';
|
|
570
|
+
if (healthyServers === this.config.keyServerUrls.length) {
|
|
571
|
+
status = 'healthy';
|
|
572
|
+
} else if (healthyServers >= this.config.threshold) {
|
|
573
|
+
status = 'degraded';
|
|
574
|
+
} else {
|
|
575
|
+
status = 'unhealthy';
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
return {
|
|
579
|
+
status,
|
|
580
|
+
details: {
|
|
581
|
+
...checks,
|
|
582
|
+
serverHealth: {
|
|
583
|
+
total: this.config.keyServerUrls.length,
|
|
584
|
+
healthy: healthyServers,
|
|
585
|
+
threshold: this.config.threshold
|
|
586
|
+
},
|
|
587
|
+
performanceStats: this.getPerformanceStats()
|
|
588
|
+
}
|
|
589
|
+
};
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
/**
|
|
593
|
+
* Configuration and utilities
|
|
594
|
+
*/
|
|
595
|
+
getConfiguration(): Partial<SealConfig> {
|
|
596
|
+
return {
|
|
597
|
+
packageId: this.config.packageId,
|
|
598
|
+
network: this.config.network,
|
|
599
|
+
threshold: this.config.threshold,
|
|
600
|
+
enableMetrics: this.config.enableMetrics,
|
|
601
|
+
retryAttempts: this.config.retryAttempts,
|
|
602
|
+
timeoutMs: this.config.timeoutMs
|
|
603
|
+
};
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
updateConfiguration(updates: Partial<SealConfig>): void {
|
|
607
|
+
this.config = { ...this.config, ...updates };
|
|
608
|
+
|
|
609
|
+
// Reinitialize client if critical settings changed
|
|
610
|
+
if (updates.keyServerObjectIds || updates.suiClient) {
|
|
611
|
+
this.sealClient = null;
|
|
612
|
+
}
|
|
613
|
+
}
|
|
616
614
|
}
|