chunktech 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +250 -0
- package/dist/assembler.d.ts +58 -0
- package/dist/assembler.d.ts.map +1 -0
- package/dist/assembler.js +158 -0
- package/dist/assembler.js.map +1 -0
- package/dist/chunker.d.ts +65 -0
- package/dist/chunker.d.ts.map +1 -0
- package/dist/chunker.js +220 -0
- package/dist/chunker.js.map +1 -0
- package/dist/crypto.d.ts +38 -0
- package/dist/crypto.d.ts.map +1 -0
- package/dist/crypto.js +242 -0
- package/dist/crypto.js.map +1 -0
- package/dist/index.d.ts +60 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +180 -0
- package/dist/index.js.map +1 -0
- package/dist/sender.d.ts +30 -0
- package/dist/sender.d.ts.map +1 -0
- package/dist/sender.js +79 -0
- package/dist/sender.js.map +1 -0
- package/dist/tracker.d.ts +63 -0
- package/dist/tracker.d.ts.map +1 -0
- package/dist/tracker.js +199 -0
- package/dist/tracker.js.map +1 -0
- package/dist/types.d.ts +138 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +21 -0
- package/dist/types.js.map +1 -0
- package/package.json +47 -0
package/README.md
ADDED
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
# ChunkTech
|
|
2
|
+
|
|
3
|
+
On-chain file storage via chunked transactions for EVM chains.
|
|
4
|
+
|
|
5
|
+
Store and retrieve files on Ethereum, Base, and Arbitrum using transaction calldata.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **Chunk** - Split files into 33.3KB pieces for on-chain storage
|
|
10
|
+
- **Send** - Broadcast chunks as transactions
|
|
11
|
+
- **Track** - Monitor transaction confirmations
|
|
12
|
+
- **Reassemble** - Reconstruct files from on-chain data
|
|
13
|
+
- **Encrypt** - Optional X3DH encryption for private data
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install chunktech viem
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
For encryption support:
|
|
22
|
+
```bash
|
|
23
|
+
npm install @noble/curves @noble/hashes
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Configuration
|
|
27
|
+
|
|
28
|
+
Copy `.env.example` to `.env` and configure:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
cp .env.example .env
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
```env
|
|
35
|
+
# Private key for signing transactions (without 0x prefix)
|
|
36
|
+
PRIVATE_KEY=your_private_key_here
|
|
37
|
+
|
|
38
|
+
# RPC URLs (optional - uses public RPCs if not set)
|
|
39
|
+
RPC_BASE=https://mainnet.base.org
|
|
40
|
+
RPC_ARBITRUM=https://arb1.arbitrum.io/rpc
|
|
41
|
+
RPC_ETHEREUM=https://eth.llamarpc.com
|
|
42
|
+
|
|
43
|
+
# Default chain
|
|
44
|
+
DEFAULT_CHAIN=base
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Quick Start
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
import { ChunkTech } from 'chunktech';
|
|
51
|
+
import { createWalletClient, http } from 'viem';
|
|
52
|
+
import { base } from 'viem/chains';
|
|
53
|
+
import { privateKeyToAccount } from 'viem/accounts';
|
|
54
|
+
|
|
55
|
+
// Load from environment
|
|
56
|
+
const account = privateKeyToAccount(`0x${process.env.PRIVATE_KEY}`);
|
|
57
|
+
const walletClient = createWalletClient({
|
|
58
|
+
account,
|
|
59
|
+
chain: base,
|
|
60
|
+
transport: http(process.env.RPC_BASE),
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
// Initialize ChunkTech
|
|
64
|
+
const ct = new ChunkTech({ walletClient });
|
|
65
|
+
|
|
66
|
+
// Upload a file
|
|
67
|
+
const file = new Uint8Array([...]); // Your file data
|
|
68
|
+
const result = await ct.upload(file, {
|
|
69
|
+
onProgress: (sent, total) => console.log(`${sent}/${total} chunks sent`),
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
console.log('Chunk ID:', result.chunkId);
|
|
73
|
+
console.log('TX Hashes:', result.txHashes);
|
|
74
|
+
|
|
75
|
+
// Download the file
|
|
76
|
+
const downloaded = await ct.download(result.txHashes);
|
|
77
|
+
console.log('Retrieved:', downloaded.data);
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## API
|
|
81
|
+
|
|
82
|
+
### `new ChunkTech(config)`
|
|
83
|
+
|
|
84
|
+
Create a new ChunkTech instance.
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
interface ChunkTechConfig {
|
|
88
|
+
walletClient: WalletClient; // viem WalletClient for signing
|
|
89
|
+
publicClient?: PublicClient; // Optional, created from walletClient if not provided
|
|
90
|
+
chain?: Chain; // Optional, detected from walletClient
|
|
91
|
+
rpcUrl?: string; // Optional custom RPC URL
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### `upload(data, options)`
|
|
96
|
+
|
|
97
|
+
Upload data to the blockchain.
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
const result = await ct.upload(data, {
|
|
101
|
+
encrypt: false, // Enable encryption
|
|
102
|
+
keys: encryptionKeys, // Required if encrypt: true
|
|
103
|
+
recipients: [...], // Recipients for encrypted data
|
|
104
|
+
onProgress: (sent, total) => {}, // Progress callback
|
|
105
|
+
confirmations: 1, // Wait for confirmations
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// Returns:
|
|
109
|
+
{
|
|
110
|
+
chunkId: string; // Unique ID for this upload
|
|
111
|
+
txHashes: Hash[]; // Transaction hashes
|
|
112
|
+
totalChunks: number; // Number of chunks sent
|
|
113
|
+
totalBytes: number; // Original data size
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### `download(txHashes, options)`
|
|
118
|
+
|
|
119
|
+
Download and reassemble data from the blockchain.
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
const result = await ct.download(txHashes, {
|
|
123
|
+
keys: encryptionKeys, // Required if data was encrypted
|
|
124
|
+
recipientId: 'myId', // Required if data was encrypted
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
// Returns:
|
|
128
|
+
{
|
|
129
|
+
data: Uint8Array; // The reassembled file
|
|
130
|
+
chunkId: string; // Chunk set ID
|
|
131
|
+
totalChunks: number; // Number of chunks retrieved
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Encryption
|
|
136
|
+
|
|
137
|
+
ChunkTech supports optional X3DH encryption for private data.
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
import { generateEncryptionKeys, deriveKeysFromSignature } from 'chunktech';
|
|
141
|
+
|
|
142
|
+
// Generate new keys
|
|
143
|
+
const myKeys = await generateEncryptionKeys();
|
|
144
|
+
|
|
145
|
+
// Or derive from wallet signature (deterministic)
|
|
146
|
+
const signature = await wallet.signMessage('chunktech-keys');
|
|
147
|
+
const myKeys = await deriveKeysFromSignature(signature);
|
|
148
|
+
|
|
149
|
+
// Upload encrypted data
|
|
150
|
+
await ct.upload(data, {
|
|
151
|
+
encrypt: true,
|
|
152
|
+
keys: myKeys,
|
|
153
|
+
recipients: [
|
|
154
|
+
{ id: 'alice', bundle: aliceBundle },
|
|
155
|
+
{ id: 'bob', bundle: bobBundle },
|
|
156
|
+
],
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
// Download encrypted data
|
|
160
|
+
const result = await ct.download(txHashes, {
|
|
161
|
+
keys: myKeys,
|
|
162
|
+
recipientId: 'sender', // Use 'sender' if you're the uploader
|
|
163
|
+
});
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Low-Level API
|
|
167
|
+
|
|
168
|
+
For more control, use the individual modules:
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
import {
|
|
172
|
+
// Chunking
|
|
173
|
+
chunkData,
|
|
174
|
+
encodeChunk,
|
|
175
|
+
decodeChunk,
|
|
176
|
+
reassembleChunks,
|
|
177
|
+
ChunkTracker,
|
|
178
|
+
|
|
179
|
+
// Sending
|
|
180
|
+
sendChunk,
|
|
181
|
+
sendChunks,
|
|
182
|
+
|
|
183
|
+
// Tracking
|
|
184
|
+
waitForTransactions,
|
|
185
|
+
TransactionMonitor,
|
|
186
|
+
|
|
187
|
+
// Fetching
|
|
188
|
+
fetchChunk,
|
|
189
|
+
assembleFromHashes,
|
|
190
|
+
StreamingAssembler,
|
|
191
|
+
} from 'chunktech';
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### Chunking
|
|
195
|
+
|
|
196
|
+
```typescript
|
|
197
|
+
// Split data into chunks
|
|
198
|
+
const chunked = chunkData(myData);
|
|
199
|
+
console.log(`${chunked.total} chunks, ID: ${chunked.id}`);
|
|
200
|
+
|
|
201
|
+
// Encode for on-chain storage
|
|
202
|
+
const calldata = encodeChunk(chunked.chunks[0]);
|
|
203
|
+
|
|
204
|
+
// Decode from calldata
|
|
205
|
+
const chunk = decodeChunk(calldata);
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Streaming Reassembly
|
|
209
|
+
|
|
210
|
+
```typescript
|
|
211
|
+
const tracker = new ChunkTracker();
|
|
212
|
+
|
|
213
|
+
for (const txHash of incomingHashes) {
|
|
214
|
+
const result = await fetchChunk(publicClient, txHash);
|
|
215
|
+
if (result.chunk) {
|
|
216
|
+
const assembled = tracker.add(result.chunk);
|
|
217
|
+
if (assembled) {
|
|
218
|
+
console.log('Complete!', assembled);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Check progress
|
|
224
|
+
console.log(tracker.getIncomplete());
|
|
225
|
+
// [{ id: '...', have: 2, need: 5 }]
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
## Supported Chains
|
|
229
|
+
|
|
230
|
+
| Chain | Chain ID |
|
|
231
|
+
|-------|----------|
|
|
232
|
+
| Ethereum | 1 |
|
|
233
|
+
| Base | 8453 |
|
|
234
|
+
| Arbitrum | 42161 |
|
|
235
|
+
| Sepolia | 11155111 |
|
|
236
|
+
| Base Sepolia | 84532 |
|
|
237
|
+
| Arbitrum Sepolia | 421614 |
|
|
238
|
+
|
|
239
|
+
## Constants
|
|
240
|
+
|
|
241
|
+
```typescript
|
|
242
|
+
import { MAX_CHUNK_SIZE } from 'chunktech';
|
|
243
|
+
|
|
244
|
+
// MAX_CHUNK_SIZE = 33333 (33.3KB)
|
|
245
|
+
// This ensures wrapped chunks stay under 128KB tx limit
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
## License
|
|
249
|
+
|
|
250
|
+
MIT
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ChunkTech - Assembler
|
|
3
|
+
* Fetch and reassemble chunks from on-chain transactions
|
|
4
|
+
*/
|
|
5
|
+
import type { PublicClient, Hash } from 'viem';
|
|
6
|
+
import type { Chunk, DownloadOptions } from './types.js';
|
|
7
|
+
export interface FetchResult {
|
|
8
|
+
chunk: Chunk | null;
|
|
9
|
+
hash: Hash;
|
|
10
|
+
encrypted: boolean;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Fetch calldata from a transaction
|
|
14
|
+
*/
|
|
15
|
+
export declare function fetchTransaction(publicClient: PublicClient, hash: Hash): Promise<string | null>;
|
|
16
|
+
/**
|
|
17
|
+
* Fetch and decode a chunk from a transaction
|
|
18
|
+
*/
|
|
19
|
+
export declare function fetchChunk(publicClient: PublicClient, hash: Hash): Promise<FetchResult>;
|
|
20
|
+
/**
|
|
21
|
+
* Fetch multiple chunks from transactions
|
|
22
|
+
*/
|
|
23
|
+
export declare function fetchChunks(publicClient: PublicClient, hashes: Hash[]): Promise<FetchResult[]>;
|
|
24
|
+
/**
|
|
25
|
+
* Fetch chunks in parallel
|
|
26
|
+
*/
|
|
27
|
+
export declare function fetchChunksParallel(publicClient: PublicClient, hashes: Hash[]): Promise<FetchResult[]>;
|
|
28
|
+
/**
|
|
29
|
+
* Fetch and reassemble data from transaction hashes
|
|
30
|
+
*/
|
|
31
|
+
export declare function assembleFromHashes(publicClient: PublicClient, hashes: Hash[], options?: DownloadOptions): Promise<Uint8Array | null>;
|
|
32
|
+
export declare class StreamingAssembler {
|
|
33
|
+
private publicClient;
|
|
34
|
+
private tracker;
|
|
35
|
+
private options;
|
|
36
|
+
constructor(publicClient: PublicClient, options?: DownloadOptions);
|
|
37
|
+
/**
|
|
38
|
+
* Add a transaction hash and check for completion
|
|
39
|
+
*/
|
|
40
|
+
addHash(hash: Hash): Promise<Uint8Array | null>;
|
|
41
|
+
/**
|
|
42
|
+
* Add multiple transaction hashes
|
|
43
|
+
*/
|
|
44
|
+
addHashes(hashes: Hash[]): Promise<Uint8Array | null>;
|
|
45
|
+
/**
|
|
46
|
+
* Get incomplete chunk sets
|
|
47
|
+
*/
|
|
48
|
+
getIncomplete(): Array<{
|
|
49
|
+
id: string;
|
|
50
|
+
have: number;
|
|
51
|
+
need: number;
|
|
52
|
+
}>;
|
|
53
|
+
/**
|
|
54
|
+
* Clear all tracked data
|
|
55
|
+
*/
|
|
56
|
+
clear(): void;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=assembler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assembler.d.ts","sourceRoot":"","sources":["../src/assembler.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC/C,OAAO,KAAK,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAQzD,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,IAAI,EAAE,IAAI,CAAC;IACX,SAAS,EAAE,OAAO,CAAC;CACpB;AAMD;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,YAAY,EAAE,YAAY,EAC1B,IAAI,EAAE,IAAI,GACT,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAaxB;AAED;;GAEG;AACH,wBAAsB,UAAU,CAC9B,YAAY,EAAE,YAAY,EAC1B,IAAI,EAAE,IAAI,GACT,OAAO,CAAC,WAAW,CAAC,CAWtB;AAED;;GAEG;AACH,wBAAsB,WAAW,CAC/B,YAAY,EAAE,YAAY,EAC1B,MAAM,EAAE,IAAI,EAAE,GACb,OAAO,CAAC,WAAW,EAAE,CAAC,CASxB;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,YAAY,EAAE,YAAY,EAC1B,MAAM,EAAE,IAAI,EAAE,GACb,OAAO,CAAC,WAAW,EAAE,CAAC,CAExB;AAMD;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,YAAY,EAAE,YAAY,EAC1B,MAAM,EAAE,IAAI,EAAE,EACd,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAkC5B;AAMD,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,OAAO,CAAsB;IACrC,OAAO,CAAC,OAAO,CAAkB;gBAErB,YAAY,EAAE,YAAY,EAAE,OAAO,GAAE,eAAoB;IAKrE;;OAEG;IACG,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAsBrD;;OAEG;IACG,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAU3D;;OAEG;IACH,aAAa,IAAI,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAIlE;;OAEG;IACH,KAAK,IAAI,IAAI;CAGd"}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ChunkTech - Assembler
|
|
3
|
+
* Fetch and reassemble chunks from on-chain transactions
|
|
4
|
+
*/
|
|
5
|
+
import { decodeChunk, reassembleChunks, isEncryptedChunk, ChunkTracker } from './chunker.js';
|
|
6
|
+
import { decryptForRecipient } from './crypto.js';
|
|
7
|
+
// ============================================================================
|
|
8
|
+
// Fetching
|
|
9
|
+
// ============================================================================
|
|
10
|
+
/**
|
|
11
|
+
* Fetch calldata from a transaction
|
|
12
|
+
*/
|
|
13
|
+
export async function fetchTransaction(publicClient, hash) {
|
|
14
|
+
try {
|
|
15
|
+
const tx = await publicClient.getTransaction({ hash });
|
|
16
|
+
if (!tx || !tx.input) {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
// Convert hex to string
|
|
20
|
+
return hexToString(tx.input);
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Fetch and decode a chunk from a transaction
|
|
28
|
+
*/
|
|
29
|
+
export async function fetchChunk(publicClient, hash) {
|
|
30
|
+
const calldata = await fetchTransaction(publicClient, hash);
|
|
31
|
+
if (!calldata) {
|
|
32
|
+
return { chunk: null, hash, encrypted: false };
|
|
33
|
+
}
|
|
34
|
+
const chunk = decodeChunk(calldata);
|
|
35
|
+
const encrypted = isEncryptedChunk(calldata);
|
|
36
|
+
return { chunk, hash, encrypted };
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Fetch multiple chunks from transactions
|
|
40
|
+
*/
|
|
41
|
+
export async function fetchChunks(publicClient, hashes) {
|
|
42
|
+
const results = [];
|
|
43
|
+
for (const hash of hashes) {
|
|
44
|
+
const result = await fetchChunk(publicClient, hash);
|
|
45
|
+
results.push(result);
|
|
46
|
+
}
|
|
47
|
+
return results;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Fetch chunks in parallel
|
|
51
|
+
*/
|
|
52
|
+
export async function fetchChunksParallel(publicClient, hashes) {
|
|
53
|
+
return Promise.all(hashes.map((hash) => fetchChunk(publicClient, hash)));
|
|
54
|
+
}
|
|
55
|
+
// ============================================================================
|
|
56
|
+
// Assembler
|
|
57
|
+
// ============================================================================
|
|
58
|
+
/**
|
|
59
|
+
* Fetch and reassemble data from transaction hashes
|
|
60
|
+
*/
|
|
61
|
+
export async function assembleFromHashes(publicClient, hashes, options = {}) {
|
|
62
|
+
const results = await fetchChunksParallel(publicClient, hashes);
|
|
63
|
+
// Extract valid chunks
|
|
64
|
+
const chunks = [];
|
|
65
|
+
let encrypted = false;
|
|
66
|
+
for (const result of results) {
|
|
67
|
+
if (result.chunk) {
|
|
68
|
+
chunks.push(result.chunk);
|
|
69
|
+
if (result.encrypted) {
|
|
70
|
+
encrypted = true;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
if (chunks.length === 0) {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
// Reassemble
|
|
78
|
+
const data = reassembleChunks(chunks);
|
|
79
|
+
if (!data) {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
// Decrypt if needed
|
|
83
|
+
if (encrypted && options.keys && options.recipientId) {
|
|
84
|
+
const payload = JSON.parse(new TextDecoder().decode(data));
|
|
85
|
+
return decryptForRecipient(options.recipientId, options.keys, payload);
|
|
86
|
+
}
|
|
87
|
+
return data;
|
|
88
|
+
}
|
|
89
|
+
// ============================================================================
|
|
90
|
+
// Streaming Assembler
|
|
91
|
+
// ============================================================================
|
|
92
|
+
export class StreamingAssembler {
|
|
93
|
+
publicClient;
|
|
94
|
+
tracker = new ChunkTracker();
|
|
95
|
+
options;
|
|
96
|
+
constructor(publicClient, options = {}) {
|
|
97
|
+
this.publicClient = publicClient;
|
|
98
|
+
this.options = options;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Add a transaction hash and check for completion
|
|
102
|
+
*/
|
|
103
|
+
async addHash(hash) {
|
|
104
|
+
const result = await fetchChunk(this.publicClient, hash);
|
|
105
|
+
if (!result.chunk) {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
const data = this.tracker.add(result.chunk);
|
|
109
|
+
if (!data) {
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
// Decrypt if needed
|
|
113
|
+
if (result.encrypted && this.options.keys && this.options.recipientId) {
|
|
114
|
+
const payload = JSON.parse(new TextDecoder().decode(data));
|
|
115
|
+
return decryptForRecipient(this.options.recipientId, this.options.keys, payload);
|
|
116
|
+
}
|
|
117
|
+
return data;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Add multiple transaction hashes
|
|
121
|
+
*/
|
|
122
|
+
async addHashes(hashes) {
|
|
123
|
+
for (const hash of hashes) {
|
|
124
|
+
const result = await this.addHash(hash);
|
|
125
|
+
if (result) {
|
|
126
|
+
return result;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Get incomplete chunk sets
|
|
133
|
+
*/
|
|
134
|
+
getIncomplete() {
|
|
135
|
+
return this.tracker.getIncomplete();
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Clear all tracked data
|
|
139
|
+
*/
|
|
140
|
+
clear() {
|
|
141
|
+
this.tracker.clear();
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
// ============================================================================
|
|
145
|
+
// Utilities
|
|
146
|
+
// ============================================================================
|
|
147
|
+
function hexToString(hex) {
|
|
148
|
+
// Remove 0x prefix if present
|
|
149
|
+
const cleanHex = hex.startsWith('0x') ? hex.slice(2) : hex;
|
|
150
|
+
// Convert hex to bytes
|
|
151
|
+
const bytes = new Uint8Array(cleanHex.length / 2);
|
|
152
|
+
for (let i = 0; i < cleanHex.length; i += 2) {
|
|
153
|
+
bytes[i / 2] = parseInt(cleanHex.substr(i, 2), 16);
|
|
154
|
+
}
|
|
155
|
+
// Decode as UTF-8
|
|
156
|
+
return new TextDecoder().decode(bytes);
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=assembler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assembler.js","sourceRoot":"","sources":["../src/assembler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ChunkTech - File Chunking
|
|
3
|
+
* Split files into chunks for on-chain storage
|
|
4
|
+
*/
|
|
5
|
+
import type { Chunk, ChunkedData } from './types.js';
|
|
6
|
+
/**
|
|
7
|
+
* Generate a random chunk set ID
|
|
8
|
+
*/
|
|
9
|
+
export declare function generateChunkId(): string;
|
|
10
|
+
/**
|
|
11
|
+
* Split data into chunks
|
|
12
|
+
*/
|
|
13
|
+
export declare function chunkData(data: Uint8Array, chunkId?: string): ChunkedData;
|
|
14
|
+
/**
|
|
15
|
+
* Encode chunk to calldata string
|
|
16
|
+
*/
|
|
17
|
+
export declare function encodeChunk(chunk: Chunk, encrypted?: boolean): string;
|
|
18
|
+
/**
|
|
19
|
+
* Decode calldata string to chunk
|
|
20
|
+
*/
|
|
21
|
+
export declare function decodeChunk(calldata: string): Chunk | null;
|
|
22
|
+
/**
|
|
23
|
+
* Check if calldata is a chunk
|
|
24
|
+
*/
|
|
25
|
+
export declare function isChunk(calldata: string): boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Check if calldata is an encrypted chunk
|
|
28
|
+
*/
|
|
29
|
+
export declare function isEncryptedChunk(calldata: string): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Reassemble chunks back into original data
|
|
32
|
+
*/
|
|
33
|
+
export declare function reassembleChunks(chunks: Chunk[]): Uint8Array | null;
|
|
34
|
+
export declare class ChunkTracker {
|
|
35
|
+
private chunks;
|
|
36
|
+
/**
|
|
37
|
+
* Add a chunk, returns assembled data if complete
|
|
38
|
+
*/
|
|
39
|
+
add(chunk: Chunk): Uint8Array | null;
|
|
40
|
+
/**
|
|
41
|
+
* Get incomplete chunk sets
|
|
42
|
+
*/
|
|
43
|
+
getIncomplete(): Array<{
|
|
44
|
+
id: string;
|
|
45
|
+
have: number;
|
|
46
|
+
need: number;
|
|
47
|
+
}>;
|
|
48
|
+
/**
|
|
49
|
+
* Get chunks for a specific ID
|
|
50
|
+
*/
|
|
51
|
+
getChunks(id: string): Chunk[];
|
|
52
|
+
/**
|
|
53
|
+
* Clear all tracked chunks
|
|
54
|
+
*/
|
|
55
|
+
clear(): void;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Estimate number of chunks needed for data
|
|
59
|
+
*/
|
|
60
|
+
export declare function estimateChunks(dataSize: number): number;
|
|
61
|
+
/**
|
|
62
|
+
* Estimate total calldata size (rough approximation)
|
|
63
|
+
*/
|
|
64
|
+
export declare function estimateCalldataSize(dataSize: number): number;
|
|
65
|
+
//# sourceMappingURL=chunker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunker.d.ts","sourceRoot":"","sources":["../src/chunker.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAiB,MAAM,YAAY,CAAC;AAOpE;;GAEG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAMxC;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,WAAW,CAmBzE;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,UAAQ,GAAG,MAAM,CAenE;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,KAAK,GAAG,IAAI,CAsB1D;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAKjD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAE1D;AAMD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,UAAU,GAAG,IAAI,CAqCnE;AAMD,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAA8B;IAE5C;;OAEG;IACH,GAAG,CAAC,KAAK,EAAE,KAAK,GAAG,UAAU,GAAG,IAAI;IAuBpC;;OAEG;IACH,aAAa,IAAI,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAYlE;;OAEG;IACH,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,KAAK,EAAE;IAI9B;;OAEG;IACH,KAAK,IAAI,IAAI;CAGd;AAMD;;GAEG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAK7D"}
|