@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,287 +1,287 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* WalrusStorageManager - Core Walrus Storage Operations
|
|
3
|
-
*
|
|
4
|
-
* Handles blob upload/download using the Walrus distributed storage network.
|
|
5
|
-
* Extracted from StorageService for better separation of concerns.
|
|
6
|
-
*
|
|
7
|
-
* Features:
|
|
8
|
-
* - writeBlobFlow() for single blob uploads
|
|
9
|
-
* - Upload relay support (preferred on testnet)
|
|
10
|
-
* - Content integrity via blob_id
|
|
11
|
-
* - Direct blob retrieval from Walrus
|
|
12
|
-
*
|
|
13
|
-
* Performance: ~10-13 seconds per upload on testnet
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
import { SuiClient, getFullnodeUrl } from '@mysten/sui/client';
|
|
17
|
-
import { WalrusClient } from '@mysten/walrus';
|
|
18
|
-
import type { ClientWithExtensions } from '@mysten/sui/experimental';
|
|
19
|
-
import type { UnifiedSigner } from '../../client/signers/UnifiedSigner';
|
|
20
|
-
|
|
21
|
-
export interface WalrusStorageConfig {
|
|
22
|
-
suiClient?: SuiClient;
|
|
23
|
-
network?: 'testnet' | 'mainnet';
|
|
24
|
-
maxFileSize?: number;
|
|
25
|
-
timeout?: number;
|
|
26
|
-
useUploadRelay?: boolean;
|
|
27
|
-
epochs?: number;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export interface BlobUploadOptions {
|
|
31
|
-
signer: UnifiedSigner;
|
|
32
|
-
epochs?: number;
|
|
33
|
-
deletable?: boolean;
|
|
34
|
-
useUploadRelay?: boolean;
|
|
35
|
-
encrypt?: boolean;
|
|
36
|
-
metadata?: Record<string, string>;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export interface WalrusUploadResult {
|
|
40
|
-
blobId: string;
|
|
41
|
-
blobObjectId?: string;
|
|
42
|
-
isEncrypted: boolean;
|
|
43
|
-
storageEpochs: number;
|
|
44
|
-
uploadTimeMs: number;
|
|
45
|
-
contentSize: number;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export interface WalrusRetrievalResult {
|
|
49
|
-
content: Uint8Array;
|
|
50
|
-
source: 'walrus';
|
|
51
|
-
retrievalTime: number;
|
|
52
|
-
blobSize: number;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* WalrusStorageManager - Manages core Walrus storage operations
|
|
57
|
-
*
|
|
58
|
-
* Handles all low-level Walrus interactions including:
|
|
59
|
-
* - Client creation and configuration
|
|
60
|
-
* - Blob upload via writeBlobFlow
|
|
61
|
-
* - Blob retrieval from distributed storage
|
|
62
|
-
*/
|
|
63
|
-
export class WalrusStorageManager {
|
|
64
|
-
private suiClient: ClientWithExtensions<{ jsonRpc: SuiClient; walrus: WalrusClient }>;
|
|
65
|
-
private walrusWithRelay: WalrusClient;
|
|
66
|
-
private walrusWithoutRelay: WalrusClient;
|
|
67
|
-
private config: WalrusStorageConfig;
|
|
68
|
-
|
|
69
|
-
constructor(config: WalrusStorageConfig) {
|
|
70
|
-
this.config = config;
|
|
71
|
-
|
|
72
|
-
// Setup clients synchronously
|
|
73
|
-
const clients = this.createClients();
|
|
74
|
-
this.suiClient = clients.suiClient;
|
|
75
|
-
this.walrusWithRelay = clients.walrusWithRelay;
|
|
76
|
-
this.walrusWithoutRelay = clients.walrusWithoutRelay;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Create Walrus clients with upload relay support
|
|
81
|
-
*/
|
|
82
|
-
private createClients() {
|
|
83
|
-
const network = this.config.network || 'testnet';
|
|
84
|
-
const baseClient = this.config.suiClient || new SuiClient({
|
|
85
|
-
url: getFullnodeUrl(network),
|
|
86
|
-
network: network,
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
const uploadRelayHost = network === 'mainnet'
|
|
90
|
-
? 'https://upload-relay.mainnet.walrus.space'
|
|
91
|
-
: 'https://upload-relay.testnet.walrus.space';
|
|
92
|
-
|
|
93
|
-
// Client with upload relay (preferred)
|
|
94
|
-
const clientWithRelay = baseClient.$extend(
|
|
95
|
-
WalrusClient.experimental_asClientExtension({
|
|
96
|
-
network: network,
|
|
97
|
-
uploadRelay: {
|
|
98
|
-
host: uploadRelayHost,
|
|
99
|
-
sendTip: { max: 1_000 },
|
|
100
|
-
timeout: 60_000,
|
|
101
|
-
},
|
|
102
|
-
storageNodeClientOptions: {
|
|
103
|
-
timeout: 60_000,
|
|
104
|
-
},
|
|
105
|
-
})
|
|
106
|
-
);
|
|
107
|
-
|
|
108
|
-
// Client without upload relay (fallback)
|
|
109
|
-
const clientWithoutRelay = baseClient.$extend(
|
|
110
|
-
WalrusClient.experimental_asClientExtension({
|
|
111
|
-
network: network,
|
|
112
|
-
storageNodeClientOptions: {
|
|
113
|
-
timeout: 60_000,
|
|
114
|
-
},
|
|
115
|
-
})
|
|
116
|
-
);
|
|
117
|
-
|
|
118
|
-
return {
|
|
119
|
-
suiClient: clientWithRelay,
|
|
120
|
-
walrusWithRelay: clientWithRelay.walrus,
|
|
121
|
-
walrusWithoutRelay: clientWithoutRelay.walrus,
|
|
122
|
-
};
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Upload blob using writeBlobFlow pattern
|
|
127
|
-
*
|
|
128
|
-
* This is the core upload method for single blobs.
|
|
129
|
-
* Uses the official Walrus writeBlobFlow: encode → register → upload → certify
|
|
130
|
-
*
|
|
131
|
-
* @param data - Blob data as Uint8Array
|
|
132
|
-
* @param options - Upload options including signer and metadata
|
|
133
|
-
* @returns Upload result with blob ID and timing
|
|
134
|
-
*/
|
|
135
|
-
async uploadBlob(
|
|
136
|
-
data: Uint8Array,
|
|
137
|
-
options: BlobUploadOptions
|
|
138
|
-
): Promise<WalrusUploadResult> {
|
|
139
|
-
const startTime = performance.now();
|
|
140
|
-
|
|
141
|
-
try {
|
|
142
|
-
// Select client based on upload relay preference
|
|
143
|
-
const walrusClient = (options.useUploadRelay ?? this.config.useUploadRelay ?? true)
|
|
144
|
-
? this.walrusWithRelay
|
|
145
|
-
: this.walrusWithoutRelay;
|
|
146
|
-
|
|
147
|
-
// Detect SEAL encryption from metadata
|
|
148
|
-
const isSealEncrypted = !!(
|
|
149
|
-
options.metadata?.['encryption-type']?.includes('seal') &&
|
|
150
|
-
options.metadata?.['encrypted'] === 'true'
|
|
151
|
-
);
|
|
152
|
-
|
|
153
|
-
if (isSealEncrypted) {
|
|
154
|
-
console.log(`🔐 Uploading SEAL encrypted binary data (${data.length} bytes)`);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
// Create writeBlobFlow
|
|
158
|
-
const flow = walrusClient.writeBlobFlow({ blob: data });
|
|
159
|
-
|
|
160
|
-
// Step 1: Encode blob
|
|
161
|
-
await flow.encode();
|
|
162
|
-
|
|
163
|
-
// Get signer address
|
|
164
|
-
const signerAddress = options.signer.getAddress();
|
|
165
|
-
|
|
166
|
-
// Step 2: Register blob on-chain
|
|
167
|
-
const registerTx = flow.register({
|
|
168
|
-
epochs: options.epochs || this.config.epochs || 3,
|
|
169
|
-
deletable: options.deletable ?? true,
|
|
170
|
-
owner: signerAddress,
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
registerTx.setSender(signerAddress);
|
|
174
|
-
const { digest: registerDigest } = await options.signer.signAndExecuteTransaction(registerTx);
|
|
175
|
-
|
|
176
|
-
// Step 3: Upload to storage
|
|
177
|
-
await flow.upload({ digest: registerDigest });
|
|
178
|
-
|
|
179
|
-
// Step 4: Certify blob on-chain
|
|
180
|
-
const certifyTx = flow.certify();
|
|
181
|
-
certifyTx.setSender(signerAddress);
|
|
182
|
-
await options.signer.signAndExecuteTransaction(certifyTx);
|
|
183
|
-
|
|
184
|
-
// Get blob info
|
|
185
|
-
const blob = await flow.getBlob();
|
|
186
|
-
const uploadTimeMs = performance.now() - startTime;
|
|
187
|
-
|
|
188
|
-
console.log(`✅ Blob uploaded successfully`);
|
|
189
|
-
console.log(` Blob ID: ${blob.blobId}`);
|
|
190
|
-
console.log(` Size: ${data.length} bytes`);
|
|
191
|
-
console.log(` Upload time: ${uploadTimeMs.toFixed(1)}ms`);
|
|
192
|
-
|
|
193
|
-
return {
|
|
194
|
-
blobId: blob.blobId,
|
|
195
|
-
blobObjectId: blob.blobObject?.id?.id,
|
|
196
|
-
isEncrypted: isSealEncrypted,
|
|
197
|
-
storageEpochs: options.epochs || this.config.epochs || 3,
|
|
198
|
-
uploadTimeMs,
|
|
199
|
-
contentSize: data.length,
|
|
200
|
-
};
|
|
201
|
-
|
|
202
|
-
} catch (error) {
|
|
203
|
-
throw new Error(`Blob upload failed: ${error}`);
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
/**
|
|
208
|
-
* Retrieve blob by ID from Walrus
|
|
209
|
-
*
|
|
210
|
-
* @param blobId - The Walrus blob ID
|
|
211
|
-
* @returns Blob content as Uint8Array
|
|
212
|
-
*/
|
|
213
|
-
async getBlob(blobId: string): Promise<Uint8Array> {
|
|
214
|
-
try {
|
|
215
|
-
console.log(`📥 Retrieving blob ${blobId} from Walrus...`);
|
|
216
|
-
const content = await this.suiClient.walrus.readBlob({ blobId });
|
|
217
|
-
console.log(`✅ Retrieved ${content.length} bytes from Walrus`);
|
|
218
|
-
return content;
|
|
219
|
-
} catch (error) {
|
|
220
|
-
console.error(`❌ Failed to retrieve blob ${blobId}:`, error);
|
|
221
|
-
throw new Error(`Failed to retrieve blob ${blobId}: ${error}`);
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
/**
|
|
226
|
-
* Retrieve blob with detailed timing and metadata
|
|
227
|
-
*
|
|
228
|
-
* @param blobId - The Walrus blob ID
|
|
229
|
-
* @returns Retrieval result with timing information
|
|
230
|
-
*/
|
|
231
|
-
async retrieveBlob(blobId: string): Promise<WalrusRetrievalResult> {
|
|
232
|
-
const startTime = Date.now();
|
|
233
|
-
|
|
234
|
-
try {
|
|
235
|
-
console.log(`🔄 WALRUS RETRIEVAL: ${blobId}`);
|
|
236
|
-
|
|
237
|
-
const content = await this.suiClient.walrus.readBlob({ blobId });
|
|
238
|
-
const retrievalTime = Date.now() - startTime;
|
|
239
|
-
|
|
240
|
-
console.log(`✅ WALRUS RETRIEVAL SUCCESS:`);
|
|
241
|
-
console.log(` Blob ID: ${blobId}`);
|
|
242
|
-
console.log(` Content size: ${content.length} bytes`);
|
|
243
|
-
console.log(` Retrieval time: ${retrievalTime}ms`);
|
|
244
|
-
|
|
245
|
-
return {
|
|
246
|
-
content,
|
|
247
|
-
source: 'walrus' as const,
|
|
248
|
-
retrievalTime,
|
|
249
|
-
blobSize: content.length
|
|
250
|
-
};
|
|
251
|
-
|
|
252
|
-
} catch (error) {
|
|
253
|
-
const retrievalTime = Date.now() - startTime;
|
|
254
|
-
console.error(`❌ WALRUS RETRIEVAL FAILED:`);
|
|
255
|
-
console.error(` Blob ID: ${blobId}`);
|
|
256
|
-
console.error(` Time elapsed: ${retrievalTime}ms`);
|
|
257
|
-
|
|
258
|
-
throw new Error(`Walrus retrieval failed for ${blobId}: ${error}`);
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
/**
|
|
263
|
-
* Get Walrus client (with or without relay)
|
|
264
|
-
*/
|
|
265
|
-
getWalrusClient(useRelay: boolean = true): WalrusClient {
|
|
266
|
-
return useRelay ? this.walrusWithRelay : this.walrusWithoutRelay;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
/**
|
|
270
|
-
* Get Sui client with Walrus extension
|
|
271
|
-
*/
|
|
272
|
-
getSuiClient(): ClientWithExtensions<{ jsonRpc: SuiClient; walrus: WalrusClient }> {
|
|
273
|
-
return this.suiClient;
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
/**
|
|
277
|
-
* Get storage statistics
|
|
278
|
-
*/
|
|
279
|
-
getStats() {
|
|
280
|
-
return {
|
|
281
|
-
network: this.config.network || 'testnet',
|
|
282
|
-
useUploadRelay: this.config.useUploadRelay ?? true,
|
|
283
|
-
epochs: this.config.epochs || 3,
|
|
284
|
-
maxFileSize: this.config.maxFileSize || Number.MAX_SAFE_INTEGER,
|
|
285
|
-
};
|
|
286
|
-
}
|
|
287
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* WalrusStorageManager - Core Walrus Storage Operations
|
|
3
|
+
*
|
|
4
|
+
* Handles blob upload/download using the Walrus distributed storage network.
|
|
5
|
+
* Extracted from StorageService for better separation of concerns.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - writeBlobFlow() for single blob uploads
|
|
9
|
+
* - Upload relay support (preferred on testnet)
|
|
10
|
+
* - Content integrity via blob_id
|
|
11
|
+
* - Direct blob retrieval from Walrus
|
|
12
|
+
*
|
|
13
|
+
* Performance: ~10-13 seconds per upload on testnet
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { SuiClient, getFullnodeUrl } from '@mysten/sui/client';
|
|
17
|
+
import { WalrusClient } from '@mysten/walrus';
|
|
18
|
+
import type { ClientWithExtensions } from '@mysten/sui/experimental';
|
|
19
|
+
import type { UnifiedSigner } from '../../client/signers/UnifiedSigner';
|
|
20
|
+
|
|
21
|
+
export interface WalrusStorageConfig {
|
|
22
|
+
suiClient?: SuiClient;
|
|
23
|
+
network?: 'testnet' | 'mainnet';
|
|
24
|
+
maxFileSize?: number;
|
|
25
|
+
timeout?: number;
|
|
26
|
+
useUploadRelay?: boolean;
|
|
27
|
+
epochs?: number;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface BlobUploadOptions {
|
|
31
|
+
signer: UnifiedSigner;
|
|
32
|
+
epochs?: number;
|
|
33
|
+
deletable?: boolean;
|
|
34
|
+
useUploadRelay?: boolean;
|
|
35
|
+
encrypt?: boolean;
|
|
36
|
+
metadata?: Record<string, string>;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface WalrusUploadResult {
|
|
40
|
+
blobId: string;
|
|
41
|
+
blobObjectId?: string;
|
|
42
|
+
isEncrypted: boolean;
|
|
43
|
+
storageEpochs: number;
|
|
44
|
+
uploadTimeMs: number;
|
|
45
|
+
contentSize: number;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface WalrusRetrievalResult {
|
|
49
|
+
content: Uint8Array;
|
|
50
|
+
source: 'walrus';
|
|
51
|
+
retrievalTime: number;
|
|
52
|
+
blobSize: number;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* WalrusStorageManager - Manages core Walrus storage operations
|
|
57
|
+
*
|
|
58
|
+
* Handles all low-level Walrus interactions including:
|
|
59
|
+
* - Client creation and configuration
|
|
60
|
+
* - Blob upload via writeBlobFlow
|
|
61
|
+
* - Blob retrieval from distributed storage
|
|
62
|
+
*/
|
|
63
|
+
export class WalrusStorageManager {
|
|
64
|
+
private suiClient: ClientWithExtensions<{ jsonRpc: SuiClient; walrus: WalrusClient }>;
|
|
65
|
+
private walrusWithRelay: WalrusClient;
|
|
66
|
+
private walrusWithoutRelay: WalrusClient;
|
|
67
|
+
private config: WalrusStorageConfig;
|
|
68
|
+
|
|
69
|
+
constructor(config: WalrusStorageConfig) {
|
|
70
|
+
this.config = config;
|
|
71
|
+
|
|
72
|
+
// Setup clients synchronously
|
|
73
|
+
const clients = this.createClients();
|
|
74
|
+
this.suiClient = clients.suiClient;
|
|
75
|
+
this.walrusWithRelay = clients.walrusWithRelay;
|
|
76
|
+
this.walrusWithoutRelay = clients.walrusWithoutRelay;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Create Walrus clients with upload relay support
|
|
81
|
+
*/
|
|
82
|
+
private createClients() {
|
|
83
|
+
const network = this.config.network || 'testnet';
|
|
84
|
+
const baseClient = this.config.suiClient || new SuiClient({
|
|
85
|
+
url: getFullnodeUrl(network),
|
|
86
|
+
network: network,
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
const uploadRelayHost = network === 'mainnet'
|
|
90
|
+
? 'https://upload-relay.mainnet.walrus.space'
|
|
91
|
+
: 'https://upload-relay.testnet.walrus.space';
|
|
92
|
+
|
|
93
|
+
// Client with upload relay (preferred)
|
|
94
|
+
const clientWithRelay = baseClient.$extend(
|
|
95
|
+
WalrusClient.experimental_asClientExtension({
|
|
96
|
+
network: network,
|
|
97
|
+
uploadRelay: {
|
|
98
|
+
host: uploadRelayHost,
|
|
99
|
+
sendTip: { max: 1_000 },
|
|
100
|
+
timeout: 60_000,
|
|
101
|
+
},
|
|
102
|
+
storageNodeClientOptions: {
|
|
103
|
+
timeout: 60_000,
|
|
104
|
+
},
|
|
105
|
+
})
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
// Client without upload relay (fallback)
|
|
109
|
+
const clientWithoutRelay = baseClient.$extend(
|
|
110
|
+
WalrusClient.experimental_asClientExtension({
|
|
111
|
+
network: network,
|
|
112
|
+
storageNodeClientOptions: {
|
|
113
|
+
timeout: 60_000,
|
|
114
|
+
},
|
|
115
|
+
})
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
return {
|
|
119
|
+
suiClient: clientWithRelay,
|
|
120
|
+
walrusWithRelay: clientWithRelay.walrus,
|
|
121
|
+
walrusWithoutRelay: clientWithoutRelay.walrus,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Upload blob using writeBlobFlow pattern
|
|
127
|
+
*
|
|
128
|
+
* This is the core upload method for single blobs.
|
|
129
|
+
* Uses the official Walrus writeBlobFlow: encode → register → upload → certify
|
|
130
|
+
*
|
|
131
|
+
* @param data - Blob data as Uint8Array
|
|
132
|
+
* @param options - Upload options including signer and metadata
|
|
133
|
+
* @returns Upload result with blob ID and timing
|
|
134
|
+
*/
|
|
135
|
+
async uploadBlob(
|
|
136
|
+
data: Uint8Array,
|
|
137
|
+
options: BlobUploadOptions
|
|
138
|
+
): Promise<WalrusUploadResult> {
|
|
139
|
+
const startTime = performance.now();
|
|
140
|
+
|
|
141
|
+
try {
|
|
142
|
+
// Select client based on upload relay preference
|
|
143
|
+
const walrusClient = (options.useUploadRelay ?? this.config.useUploadRelay ?? true)
|
|
144
|
+
? this.walrusWithRelay
|
|
145
|
+
: this.walrusWithoutRelay;
|
|
146
|
+
|
|
147
|
+
// Detect SEAL encryption from metadata
|
|
148
|
+
const isSealEncrypted = !!(
|
|
149
|
+
options.metadata?.['encryption-type']?.includes('seal') &&
|
|
150
|
+
options.metadata?.['encrypted'] === 'true'
|
|
151
|
+
);
|
|
152
|
+
|
|
153
|
+
if (isSealEncrypted) {
|
|
154
|
+
console.log(`🔐 Uploading SEAL encrypted binary data (${data.length} bytes)`);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Create writeBlobFlow
|
|
158
|
+
const flow = walrusClient.writeBlobFlow({ blob: data });
|
|
159
|
+
|
|
160
|
+
// Step 1: Encode blob
|
|
161
|
+
await flow.encode();
|
|
162
|
+
|
|
163
|
+
// Get signer address
|
|
164
|
+
const signerAddress = options.signer.getAddress();
|
|
165
|
+
|
|
166
|
+
// Step 2: Register blob on-chain
|
|
167
|
+
const registerTx = flow.register({
|
|
168
|
+
epochs: options.epochs || this.config.epochs || 3,
|
|
169
|
+
deletable: options.deletable ?? true,
|
|
170
|
+
owner: signerAddress,
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
registerTx.setSender(signerAddress);
|
|
174
|
+
const { digest: registerDigest } = await options.signer.signAndExecuteTransaction(registerTx);
|
|
175
|
+
|
|
176
|
+
// Step 3: Upload to storage
|
|
177
|
+
await flow.upload({ digest: registerDigest });
|
|
178
|
+
|
|
179
|
+
// Step 4: Certify blob on-chain
|
|
180
|
+
const certifyTx = flow.certify();
|
|
181
|
+
certifyTx.setSender(signerAddress);
|
|
182
|
+
await options.signer.signAndExecuteTransaction(certifyTx);
|
|
183
|
+
|
|
184
|
+
// Get blob info
|
|
185
|
+
const blob = await flow.getBlob();
|
|
186
|
+
const uploadTimeMs = performance.now() - startTime;
|
|
187
|
+
|
|
188
|
+
console.log(`✅ Blob uploaded successfully`);
|
|
189
|
+
console.log(` Blob ID: ${blob.blobId}`);
|
|
190
|
+
console.log(` Size: ${data.length} bytes`);
|
|
191
|
+
console.log(` Upload time: ${uploadTimeMs.toFixed(1)}ms`);
|
|
192
|
+
|
|
193
|
+
return {
|
|
194
|
+
blobId: blob.blobId,
|
|
195
|
+
blobObjectId: blob.blobObject?.id?.id,
|
|
196
|
+
isEncrypted: isSealEncrypted,
|
|
197
|
+
storageEpochs: options.epochs || this.config.epochs || 3,
|
|
198
|
+
uploadTimeMs,
|
|
199
|
+
contentSize: data.length,
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
} catch (error) {
|
|
203
|
+
throw new Error(`Blob upload failed: ${error}`);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Retrieve blob by ID from Walrus
|
|
209
|
+
*
|
|
210
|
+
* @param blobId - The Walrus blob ID
|
|
211
|
+
* @returns Blob content as Uint8Array
|
|
212
|
+
*/
|
|
213
|
+
async getBlob(blobId: string): Promise<Uint8Array> {
|
|
214
|
+
try {
|
|
215
|
+
console.log(`📥 Retrieving blob ${blobId} from Walrus...`);
|
|
216
|
+
const content = await this.suiClient.walrus.readBlob({ blobId });
|
|
217
|
+
console.log(`✅ Retrieved ${content.length} bytes from Walrus`);
|
|
218
|
+
return content;
|
|
219
|
+
} catch (error) {
|
|
220
|
+
console.error(`❌ Failed to retrieve blob ${blobId}:`, error);
|
|
221
|
+
throw new Error(`Failed to retrieve blob ${blobId}: ${error}`);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Retrieve blob with detailed timing and metadata
|
|
227
|
+
*
|
|
228
|
+
* @param blobId - The Walrus blob ID
|
|
229
|
+
* @returns Retrieval result with timing information
|
|
230
|
+
*/
|
|
231
|
+
async retrieveBlob(blobId: string): Promise<WalrusRetrievalResult> {
|
|
232
|
+
const startTime = Date.now();
|
|
233
|
+
|
|
234
|
+
try {
|
|
235
|
+
console.log(`🔄 WALRUS RETRIEVAL: ${blobId}`);
|
|
236
|
+
|
|
237
|
+
const content = await this.suiClient.walrus.readBlob({ blobId });
|
|
238
|
+
const retrievalTime = Date.now() - startTime;
|
|
239
|
+
|
|
240
|
+
console.log(`✅ WALRUS RETRIEVAL SUCCESS:`);
|
|
241
|
+
console.log(` Blob ID: ${blobId}`);
|
|
242
|
+
console.log(` Content size: ${content.length} bytes`);
|
|
243
|
+
console.log(` Retrieval time: ${retrievalTime}ms`);
|
|
244
|
+
|
|
245
|
+
return {
|
|
246
|
+
content,
|
|
247
|
+
source: 'walrus' as const,
|
|
248
|
+
retrievalTime,
|
|
249
|
+
blobSize: content.length
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
} catch (error) {
|
|
253
|
+
const retrievalTime = Date.now() - startTime;
|
|
254
|
+
console.error(`❌ WALRUS RETRIEVAL FAILED:`);
|
|
255
|
+
console.error(` Blob ID: ${blobId}`);
|
|
256
|
+
console.error(` Time elapsed: ${retrievalTime}ms`);
|
|
257
|
+
|
|
258
|
+
throw new Error(`Walrus retrieval failed for ${blobId}: ${error}`);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Get Walrus client (with or without relay)
|
|
264
|
+
*/
|
|
265
|
+
getWalrusClient(useRelay: boolean = true): WalrusClient {
|
|
266
|
+
return useRelay ? this.walrusWithRelay : this.walrusWithoutRelay;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Get Sui client with Walrus extension
|
|
271
|
+
*/
|
|
272
|
+
getSuiClient(): ClientWithExtensions<{ jsonRpc: SuiClient; walrus: WalrusClient }> {
|
|
273
|
+
return this.suiClient;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Get storage statistics
|
|
278
|
+
*/
|
|
279
|
+
getStats() {
|
|
280
|
+
return {
|
|
281
|
+
network: this.config.network || 'testnet',
|
|
282
|
+
useUploadRelay: this.config.useUploadRelay ?? true,
|
|
283
|
+
epochs: this.config.epochs || 3,
|
|
284
|
+
maxFileSize: this.config.maxFileSize || Number.MAX_SAFE_INTEGER,
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
}
|