chunktech 0.2.0 → 0.3.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 +280 -160
- package/dist/crosschain.d.ts.map +1 -1
- package/dist/crosschain.js +28 -5
- package/dist/crosschain.js.map +1 -1
- package/dist/extension-loader.d.ts +33 -0
- package/dist/extension-loader.d.ts.map +1 -0
- package/dist/extension-loader.js +299 -0
- package/dist/extension-loader.js.map +1 -0
- package/dist/extension-uploader.d.ts +69 -0
- package/dist/extension-uploader.d.ts.map +1 -0
- package/dist/extension-uploader.js +153 -0
- package/dist/extension-uploader.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -2,15 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
On-chain file storage via chunked transactions for EVM chains.
|
|
4
4
|
|
|
5
|
-
Store and retrieve files on Ethereum, Base, and Arbitrum using transaction calldata.
|
|
5
|
+
Store and retrieve files on Ethereum, Base, and Arbitrum using transaction calldata. Includes specialized support for censorship-resistant browser extension distribution.
|
|
6
6
|
|
|
7
7
|
## Features
|
|
8
8
|
|
|
9
9
|
- **Chunk** - Split files into 33.3KB pieces for on-chain storage
|
|
10
|
-
- **Send** - Broadcast chunks as transactions
|
|
10
|
+
- **Send** - Broadcast chunks as self-transfer transactions
|
|
11
11
|
- **Track** - Monitor transaction confirmations
|
|
12
12
|
- **Reassemble** - Reconstruct files from on-chain data
|
|
13
13
|
- **Encrypt** - Optional X3DH encryption for private data
|
|
14
|
+
- **Cross-Chain** - Store data on L2, pointer on mainnet
|
|
15
|
+
- **Extensions** - Distribute Chrome/Firefox extensions via inscriptions
|
|
14
16
|
|
|
15
17
|
## Installation
|
|
16
18
|
|
|
@@ -23,27 +25,6 @@ For encryption support:
|
|
|
23
25
|
npm install @noble/curves @noble/hashes
|
|
24
26
|
```
|
|
25
27
|
|
|
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
28
|
## Quick Start
|
|
48
29
|
|
|
49
30
|
```typescript
|
|
@@ -52,157 +33,220 @@ import { createWalletClient, http } from 'viem';
|
|
|
52
33
|
import { base } from 'viem/chains';
|
|
53
34
|
import { privateKeyToAccount } from 'viem/accounts';
|
|
54
35
|
|
|
55
|
-
// Load from environment
|
|
56
36
|
const account = privateKeyToAccount(`0x${process.env.PRIVATE_KEY}`);
|
|
57
37
|
const walletClient = createWalletClient({
|
|
58
38
|
account,
|
|
59
39
|
chain: base,
|
|
60
|
-
transport: http(
|
|
40
|
+
transport: http(),
|
|
61
41
|
});
|
|
62
42
|
|
|
63
|
-
// Initialize ChunkTech
|
|
64
43
|
const ct = new ChunkTech({ walletClient });
|
|
65
44
|
|
|
66
|
-
// Upload
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
onProgress: (sent, total) => console.log(`${sent}/${total} chunks sent`),
|
|
45
|
+
// Upload
|
|
46
|
+
const result = await ct.upload(fileData, {
|
|
47
|
+
onProgress: (sent, total) => console.log(`${sent}/${total}`),
|
|
70
48
|
});
|
|
71
49
|
|
|
72
|
-
|
|
73
|
-
console.log('TX Hashes:', result.txHashes);
|
|
74
|
-
|
|
75
|
-
// Download the file
|
|
50
|
+
// Download
|
|
76
51
|
const downloaded = await ct.download(result.txHashes);
|
|
77
|
-
console.log('Retrieved:', downloaded.data);
|
|
78
52
|
```
|
|
79
53
|
|
|
80
|
-
##
|
|
54
|
+
## Browser Extension Distribution
|
|
81
55
|
|
|
82
|
-
|
|
56
|
+
Distribute Chrome and Firefox extensions as on-chain inscriptions. The inscription itself is the installer - a self-contained HTML page that fetches extension data from L2 and offers downloads.
|
|
83
57
|
|
|
84
|
-
|
|
58
|
+
```
|
|
59
|
+
┌─────────────────────────────────────────────────────────┐
|
|
60
|
+
│ Inscription (Ethereum) │
|
|
61
|
+
│ │
|
|
62
|
+
│ Self-contained HTML that: │
|
|
63
|
+
│ ├── Shows extension info + download buttons │
|
|
64
|
+
│ ├── Fetches chunks from Base via RPC │
|
|
65
|
+
│ ├── Reassembles + verifies SHA256 │
|
|
66
|
+
│ └── Downloads as .zip (Chrome) or .xpi (Firefox) │
|
|
67
|
+
│ │
|
|
68
|
+
└─────────────────────────────────────────────────────────┘
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Upload Extension
|
|
85
72
|
|
|
86
73
|
```typescript
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
}
|
|
93
|
-
```
|
|
74
|
+
import { ExtensionUploader } from 'chunktech';
|
|
75
|
+
import { createWalletClient, http } from 'viem';
|
|
76
|
+
import { base, mainnet } from 'viem/chains';
|
|
77
|
+
import { privateKeyToAccount } from 'viem/accounts';
|
|
78
|
+
import { readFileSync } from 'fs';
|
|
94
79
|
|
|
95
|
-
|
|
80
|
+
const account = privateKeyToAccount(`0x${process.env.PRIVATE_KEY}`);
|
|
96
81
|
|
|
97
|
-
|
|
82
|
+
const uploader = new ExtensionUploader({
|
|
83
|
+
keyChain: 'ethereum', // Inscription lives here (1 tx)
|
|
84
|
+
dataChain: 'base', // Extension data lives here (cheap)
|
|
85
|
+
keyWalletClient: createWalletClient({
|
|
86
|
+
account,
|
|
87
|
+
chain: mainnet,
|
|
88
|
+
transport: http(),
|
|
89
|
+
}),
|
|
90
|
+
dataWalletClient: createWalletClient({
|
|
91
|
+
account,
|
|
92
|
+
chain: base,
|
|
93
|
+
transport: http(),
|
|
94
|
+
}),
|
|
95
|
+
});
|
|
98
96
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
97
|
+
const result = await uploader.upload({
|
|
98
|
+
name: 'My Extension',
|
|
99
|
+
version: '1.0.0',
|
|
100
|
+
developer: 'vitalik.eth',
|
|
101
|
+
description: 'A censorship-resistant browser extension',
|
|
102
|
+
homepage: 'https://myextension.xyz',
|
|
103
|
+
chrome: readFileSync('dist/chrome.zip'),
|
|
104
|
+
firefox: readFileSync('dist/firefox.xpi'),
|
|
105
|
+
}, {
|
|
106
|
+
onProgress: (phase, sent, total) => {
|
|
107
|
+
console.log(`${phase}: ${sent}/${total}`);
|
|
108
|
+
},
|
|
106
109
|
});
|
|
107
110
|
|
|
108
|
-
|
|
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
|
-
}
|
|
111
|
+
console.log('Inscription TX:', result.inscriptionTxHash);
|
|
112
|
+
// View at: https://ethscriptions.com/ethscriptions/0x...
|
|
115
113
|
```
|
|
116
114
|
|
|
117
|
-
###
|
|
115
|
+
### What Users See
|
|
116
|
+
|
|
117
|
+
The inscription renders as a download page:
|
|
118
|
+
|
|
119
|
+
```
|
|
120
|
+
╔═══════════════════════════════════════════════════╗
|
|
121
|
+
║ My Extension v1.0.0 ║
|
|
122
|
+
║ vitalik.eth ║
|
|
123
|
+
╚═══════════════════════════════════════════════════╝
|
|
124
|
+
|
|
125
|
+
A censorship-resistant browser extension
|
|
126
|
+
|
|
127
|
+
┌─────────────────┐ ┌─────────────────┐
|
|
128
|
+
│ Chrome/Brave │ │ Firefox │
|
|
129
|
+
│ [Detected] │ │ │
|
|
130
|
+
│ [Download] │ │ [Download] │
|
|
131
|
+
│ 142 KB │ │ 138 KB │
|
|
132
|
+
└─────────────────┘ └─────────────────┘
|
|
133
|
+
|
|
134
|
+
Installation Instructions:
|
|
135
|
+
1. Download the extension
|
|
136
|
+
2. Unzip (Chrome) or keep as .xpi (Firefox)
|
|
137
|
+
3. Load in developer mode / Install from file
|
|
138
|
+
```
|
|
118
139
|
|
|
119
|
-
|
|
140
|
+
### Why This Matters
|
|
141
|
+
|
|
142
|
+
- **Censorship-resistant** - No app store can remove it
|
|
143
|
+
- **Immutable** - Code is permanently on-chain
|
|
144
|
+
- **Verifiable** - SHA256 verified on download
|
|
145
|
+
- **Self-contained** - The inscription IS the installer
|
|
146
|
+
- **Multi-browser** - Chrome, Brave, Edge, Firefox from one inscription
|
|
147
|
+
|
|
148
|
+
## Cross-Chain Upload
|
|
149
|
+
|
|
150
|
+
Store bulk data on L2 (cheap), pointer on mainnet (durable):
|
|
120
151
|
|
|
121
152
|
```typescript
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
153
|
+
import { CrossChainUploader } from 'chunktech';
|
|
154
|
+
|
|
155
|
+
const uploader = new CrossChainUploader({
|
|
156
|
+
keyChain: 'ethereum',
|
|
157
|
+
dataChain: 'base',
|
|
158
|
+
keyWalletClient,
|
|
159
|
+
dataWalletClient,
|
|
125
160
|
});
|
|
126
161
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
totalChunks: number; // Number of chunks retrieved
|
|
132
|
-
}
|
|
133
|
-
```
|
|
162
|
+
const result = await uploader.upload(fileData, {
|
|
163
|
+
format: 'html',
|
|
164
|
+
title: 'My File',
|
|
165
|
+
});
|
|
134
166
|
|
|
135
|
-
|
|
167
|
+
// result.keyTxHash = mainnet inscription (self-loading HTML)
|
|
168
|
+
// result.dataTxHashes = Base data chunks
|
|
169
|
+
```
|
|
136
170
|
|
|
137
|
-
|
|
171
|
+
## API Reference
|
|
138
172
|
|
|
139
|
-
|
|
140
|
-
import { generateEncryptionKeys, deriveKeysFromSignature } from 'chunktech';
|
|
173
|
+
### ChunkTech
|
|
141
174
|
|
|
142
|
-
|
|
143
|
-
const myKeys = await generateEncryptionKeys();
|
|
175
|
+
Main class for single-chain uploads.
|
|
144
176
|
|
|
145
|
-
|
|
146
|
-
const
|
|
147
|
-
|
|
177
|
+
```typescript
|
|
178
|
+
const ct = new ChunkTech({
|
|
179
|
+
walletClient: WalletClient, // viem wallet
|
|
180
|
+
publicClient?: PublicClient, // Optional
|
|
181
|
+
chain?: Chain, // Auto-detected
|
|
182
|
+
rpcUrl?: string, // Custom RPC
|
|
183
|
+
});
|
|
148
184
|
|
|
149
|
-
// Upload
|
|
150
|
-
await ct.upload(data, {
|
|
151
|
-
encrypt
|
|
152
|
-
keys
|
|
153
|
-
recipients
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
],
|
|
185
|
+
// Upload
|
|
186
|
+
const result = await ct.upload(data, {
|
|
187
|
+
encrypt?: boolean,
|
|
188
|
+
keys?: EncryptionKeys,
|
|
189
|
+
recipients?: Recipient[],
|
|
190
|
+
onProgress?: (sent, total) => void,
|
|
191
|
+
confirmations?: number,
|
|
157
192
|
});
|
|
158
193
|
|
|
159
|
-
// Download
|
|
194
|
+
// Download
|
|
160
195
|
const result = await ct.download(txHashes, {
|
|
161
|
-
keys
|
|
162
|
-
recipientId
|
|
196
|
+
keys?: EncryptionKeys,
|
|
197
|
+
recipientId?: string,
|
|
163
198
|
});
|
|
164
199
|
```
|
|
165
200
|
|
|
166
|
-
|
|
201
|
+
### ExtensionUploader
|
|
167
202
|
|
|
168
|
-
|
|
203
|
+
Specialized uploader for browser extensions.
|
|
169
204
|
|
|
170
205
|
```typescript
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
206
|
+
const uploader = new ExtensionUploader({
|
|
207
|
+
keyChain: 'ethereum' | 'sepolia',
|
|
208
|
+
dataChain: 'base' | 'baseSepolia',
|
|
209
|
+
keyWalletClient: WalletClient,
|
|
210
|
+
dataWalletClient: WalletClient,
|
|
211
|
+
keyRpcUrl?: string,
|
|
212
|
+
dataRpcUrl?: string,
|
|
178
213
|
});
|
|
179
214
|
|
|
180
|
-
const result = await uploader.upload(
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
215
|
+
const result = await uploader.upload({
|
|
216
|
+
name: string,
|
|
217
|
+
version: string,
|
|
218
|
+
developer: string,
|
|
219
|
+
description?: string,
|
|
220
|
+
homepage?: string,
|
|
221
|
+
chrome?: Uint8Array,
|
|
222
|
+
firefox?: Uint8Array,
|
|
223
|
+
}, {
|
|
224
|
+
onProgress?: (phase, sent, total) => void,
|
|
225
|
+
confirmations?: number,
|
|
186
226
|
});
|
|
187
|
-
|
|
188
|
-
console.log('Mainnet TX:', result.keyTxHash);
|
|
189
|
-
console.log('Base TXs:', result.dataTxHashes);
|
|
190
227
|
```
|
|
191
228
|
|
|
192
|
-
|
|
193
|
-
- **Mainnet TX** = The "unchunker" (HTML loader with manifest)
|
|
194
|
-
- **Base TXs** = ALL data chunks (100% of file data on L2)
|
|
229
|
+
### CrossChainUploader
|
|
195
230
|
|
|
196
|
-
|
|
197
|
-
- Fetches ALL chunks from Base L2 via RPC
|
|
198
|
-
- Reassembles and verifies SHA256
|
|
199
|
-
- Provides download button
|
|
231
|
+
General-purpose cross-chain uploader with HTML loader.
|
|
200
232
|
|
|
201
|
-
|
|
233
|
+
```typescript
|
|
234
|
+
const uploader = new CrossChainUploader({
|
|
235
|
+
keyChain: ChainName,
|
|
236
|
+
dataChain: ChainName,
|
|
237
|
+
keyWalletClient: WalletClient,
|
|
238
|
+
dataWalletClient: WalletClient,
|
|
239
|
+
});
|
|
202
240
|
|
|
203
|
-
|
|
241
|
+
const result = await uploader.upload(data, {
|
|
242
|
+
format?: 'html' | 'json',
|
|
243
|
+
title?: string,
|
|
244
|
+
description?: string,
|
|
245
|
+
mimeType?: string,
|
|
246
|
+
});
|
|
247
|
+
```
|
|
204
248
|
|
|
205
|
-
|
|
249
|
+
### Low-Level Utilities
|
|
206
250
|
|
|
207
251
|
```typescript
|
|
208
252
|
import {
|
|
@@ -212,76 +256,152 @@ import {
|
|
|
212
256
|
decodeChunk,
|
|
213
257
|
reassembleChunks,
|
|
214
258
|
ChunkTracker,
|
|
259
|
+
estimateChunks,
|
|
215
260
|
|
|
216
261
|
// Sending
|
|
217
262
|
sendChunk,
|
|
218
263
|
sendChunks,
|
|
264
|
+
sendChunksParallel,
|
|
219
265
|
|
|
220
266
|
// Tracking
|
|
267
|
+
waitForTransaction,
|
|
221
268
|
waitForTransactions,
|
|
222
269
|
TransactionMonitor,
|
|
223
270
|
|
|
224
271
|
// Fetching
|
|
225
272
|
fetchChunk,
|
|
273
|
+
fetchChunks,
|
|
226
274
|
assembleFromHashes,
|
|
227
275
|
StreamingAssembler,
|
|
276
|
+
|
|
277
|
+
// Encryption
|
|
278
|
+
generateEncryptionKeys,
|
|
279
|
+
deriveKeysFromSignature,
|
|
280
|
+
encryptForRecipients,
|
|
281
|
+
decryptForRecipient,
|
|
228
282
|
} from 'chunktech';
|
|
229
283
|
```
|
|
230
284
|
|
|
231
|
-
|
|
285
|
+
## Encryption
|
|
286
|
+
|
|
287
|
+
Optional X3DH + AES-256-GCM encryption for private data.
|
|
232
288
|
|
|
233
289
|
```typescript
|
|
234
|
-
|
|
235
|
-
const chunked = chunkData(myData);
|
|
236
|
-
console.log(`${chunked.total} chunks, ID: ${chunked.id}`);
|
|
290
|
+
import { generateEncryptionKeys } from 'chunktech';
|
|
237
291
|
|
|
238
|
-
|
|
239
|
-
const calldata = encodeChunk(chunked.chunks[0]);
|
|
292
|
+
const myKeys = await generateEncryptionKeys();
|
|
240
293
|
|
|
241
|
-
//
|
|
242
|
-
|
|
294
|
+
// Upload encrypted
|
|
295
|
+
await ct.upload(data, {
|
|
296
|
+
encrypt: true,
|
|
297
|
+
keys: myKeys,
|
|
298
|
+
recipients: [
|
|
299
|
+
{ id: 'alice', bundle: aliceKeys.bundle },
|
|
300
|
+
],
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
// Download encrypted
|
|
304
|
+
const result = await ct.download(txHashes, {
|
|
305
|
+
keys: myKeys,
|
|
306
|
+
recipientId: 'sender',
|
|
307
|
+
});
|
|
243
308
|
```
|
|
244
309
|
|
|
245
|
-
|
|
310
|
+
## Supported Chains
|
|
311
|
+
|
|
312
|
+
| Chain | ID | Use Case |
|
|
313
|
+
|-------|-----|----------|
|
|
314
|
+
| Ethereum | 1 | Inscriptions, durability |
|
|
315
|
+
| Base | 8453 | Cheap data storage |
|
|
316
|
+
| Arbitrum | 42161 | Cheap data storage |
|
|
317
|
+
| Sepolia | 11155111 | Testing |
|
|
318
|
+
| Base Sepolia | 84532 | Testing |
|
|
319
|
+
| Arbitrum Sepolia | 421614 | Testing |
|
|
320
|
+
|
|
321
|
+
## Cost Estimates
|
|
322
|
+
|
|
323
|
+
For a 500KB extension on Base:
|
|
246
324
|
|
|
247
|
-
```typescript
|
|
248
|
-
const tracker = new ChunkTracker();
|
|
249
|
-
|
|
250
|
-
for (const txHash of incomingHashes) {
|
|
251
|
-
const result = await fetchChunk(publicClient, txHash);
|
|
252
|
-
if (result.chunk) {
|
|
253
|
-
const assembled = tracker.add(result.chunk);
|
|
254
|
-
if (assembled) {
|
|
255
|
-
console.log('Complete!', assembled);
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
// Check progress
|
|
261
|
-
console.log(tracker.getIncomplete());
|
|
262
|
-
// [{ id: '...', have: 2, need: 5 }]
|
|
263
325
|
```
|
|
326
|
+
Chunks: ~15 (at 33KB each)
|
|
327
|
+
Cost per chunk: ~$0.002
|
|
328
|
+
Total: ~$0.03
|
|
264
329
|
|
|
265
|
-
|
|
330
|
+
+ 1 Ethereum inscription: ~$2-5 (varies with gas)
|
|
331
|
+
```
|
|
266
332
|
|
|
267
|
-
|
|
268
|
-
|-------|----------|
|
|
269
|
-
| Ethereum | 1 |
|
|
270
|
-
| Base | 8453 |
|
|
271
|
-
| Arbitrum | 42161 |
|
|
272
|
-
| Sepolia | 11155111 |
|
|
273
|
-
| Base Sepolia | 84532 |
|
|
274
|
-
| Arbitrum Sepolia | 421614 |
|
|
333
|
+
## How It Works
|
|
275
334
|
|
|
276
|
-
|
|
335
|
+
1. **Chunking** - Files split into 33.3KB pieces with metadata (ID, part, total)
|
|
336
|
+
2. **Encoding** - Each chunk → JSON → base64 → prefixed calldata
|
|
337
|
+
3. **Sending** - Self-transfer transactions (to == from, value = 0)
|
|
338
|
+
4. **Storage** - Calldata stored permanently in transaction history
|
|
339
|
+
5. **Retrieval** - Fetch via `eth_getTransactionByHash`, decode, reassemble
|
|
340
|
+
6. **Verification** - SHA256 hash checked after reassembly
|
|
277
341
|
|
|
278
|
-
|
|
279
|
-
|
|
342
|
+
## On-Chain Viewer Pages
|
|
343
|
+
|
|
344
|
+
Create standalone HTML pages that fetch, verify, and display on-chain content. Perfect for:
|
|
345
|
+
- NPM packages with auditable source
|
|
346
|
+
- Browser extensions with install instructions
|
|
347
|
+
- Any file needing public verification
|
|
348
|
+
|
|
349
|
+
### Quick Inscribe
|
|
350
|
+
|
|
351
|
+
```javascript
|
|
352
|
+
import { readFileSync } from 'fs';
|
|
353
|
+
import { createWalletClient, http, toHex } from 'viem';
|
|
354
|
+
import { base } from 'viem/chains';
|
|
355
|
+
import { createHash } from 'crypto';
|
|
280
356
|
|
|
281
|
-
|
|
282
|
-
|
|
357
|
+
const zipData = readFileSync('package.zip');
|
|
358
|
+
const base64 = zipData.toString('base64');
|
|
359
|
+
const sha256 = createHash('sha256').update(zipData).digest('hex');
|
|
360
|
+
|
|
361
|
+
const dataUri = `data:application/zip;base64,${base64}`;
|
|
362
|
+
const calldata = toHex(new TextEncoder().encode(dataUri));
|
|
363
|
+
|
|
364
|
+
const hash = await walletClient.sendTransaction({
|
|
365
|
+
to: account.address,
|
|
366
|
+
data: calldata,
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
console.log(`TX: ${hash}`);
|
|
370
|
+
console.log(`SHA256: ${sha256}`);
|
|
283
371
|
```
|
|
284
372
|
|
|
373
|
+
### Viewer HTML
|
|
374
|
+
|
|
375
|
+
The viewer fetches from any RPC, verifies SHA256, and displays source:
|
|
376
|
+
|
|
377
|
+
```
|
|
378
|
+
┌─────────────────────────────────────────┐
|
|
379
|
+
│ MyPackage v1.0.0 │
|
|
380
|
+
│ │
|
|
381
|
+
│ [Download] [Verify On-Chain] │
|
|
382
|
+
│ │
|
|
383
|
+
│ ┌─────────────────────────────────┐ │
|
|
384
|
+
│ │ README │ index.ts │ package.json│ │
|
|
385
|
+
│ ├─────────────────────────────────┤ │
|
|
386
|
+
│ │ │ │
|
|
387
|
+
│ │ // Source code displayed here │ │
|
|
388
|
+
│ │ │ │
|
|
389
|
+
│ └─────────────────────────────────┘ │
|
|
390
|
+
└─────────────────────────────────────────┘
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
Key features:
|
|
394
|
+
- Fetches tx via public RPC (no backend)
|
|
395
|
+
- SHA256 verification on download
|
|
396
|
+
- Source code tabs for auditing
|
|
397
|
+
- Works offline once loaded
|
|
398
|
+
|
|
399
|
+
See `skill.md` for full implementation details.
|
|
400
|
+
|
|
401
|
+
## Acknowledgments
|
|
402
|
+
|
|
403
|
+
- [calldata-rpc](https://github.com/chopperdaddy/calldata-rpc) by [@chopperdaddy](https://github.com/chopperdaddy) - Decentralized RPC endpoint discovery via IPFS and ENS, used in the HTML loaders for reliable chain access.
|
|
404
|
+
|
|
285
405
|
## License
|
|
286
406
|
|
|
287
407
|
MIT
|
package/dist/crosschain.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"crosschain.d.ts","sourceRoot":"","sources":["../src/crosschain.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,KAAK,EAEV,gBAAgB,EAChB,uBAAuB,EACvB,sBAAsB,EACtB,kBAAkB,EAEnB,MAAM,YAAY,CAAC;AAuBpB,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,eAAe,CAAe;IACtC,OAAO,CAAC,gBAAgB,CAAe;IAEvC,OAAO,CAAC,eAAe,CAAM;IAC7B,OAAO,CAAC,gBAAgB,CAAM;IAC9B,OAAO,CAAC,QAAQ,CAAY;IAC5B,OAAO,CAAC,SAAS,CAAY;gBAEjB,MAAM,EAAE,gBAAgB;IAiBpC;;OAEG;IACG,MAAM,CACV,IAAI,EAAE,UAAU,GAAG,WAAW,GAAG,MAAM,EACvC,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,sBAAsB,CAAC;CAwFnC;AAMD,iBAAS,kBAAkB,CACzB,QAAQ,EAAE,kBAAkB,EAC5B,OAAO,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAC9C,MAAM,
|
|
1
|
+
{"version":3,"file":"crosschain.d.ts","sourceRoot":"","sources":["../src/crosschain.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,KAAK,EAEV,gBAAgB,EAChB,uBAAuB,EACvB,sBAAsB,EACtB,kBAAkB,EAEnB,MAAM,YAAY,CAAC;AAuBpB,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,eAAe,CAAe;IACtC,OAAO,CAAC,gBAAgB,CAAe;IAEvC,OAAO,CAAC,eAAe,CAAM;IAC7B,OAAO,CAAC,gBAAgB,CAAM;IAC9B,OAAO,CAAC,QAAQ,CAAY;IAC5B,OAAO,CAAC,SAAS,CAAY;gBAEjB,MAAM,EAAE,gBAAgB;IAiBpC;;OAEG;IACG,MAAM,CACV,IAAI,EAAE,UAAU,GAAG,WAAW,GAAG,MAAM,EACvC,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,sBAAsB,CAAC;CAwFnC;AAMD,iBAAS,kBAAkB,CACzB,QAAQ,EAAE,kBAAkB,EAC5B,OAAO,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAC9C,MAAM,CA+IR;AA0ED,OAAO,EAAE,kBAAkB,EAAE,CAAC"}
|
package/dist/crosschain.js
CHANGED
|
@@ -172,9 +172,23 @@ h1{font-size:1.5rem;margin-bottom:8px;background:linear-gradient(135deg,#667eea,
|
|
|
172
172
|
</div>
|
|
173
173
|
<script>
|
|
174
174
|
const M=${JSON.stringify(manifest)};
|
|
175
|
-
|
|
175
|
+
// RPC discovery via calldata-rpc (https://github.com/chopperdaddy/calldata-rpc)
|
|
176
|
+
// Decentralized RPC endpoints hosted on IPFS via ENS
|
|
177
|
+
const TESTNET_RPC={84532:"https://sepolia.base.org",421614:"https://sepolia-rollup.arbitrum.io/rpc"};
|
|
176
178
|
|
|
177
|
-
async function
|
|
179
|
+
async function getRpcUrls(chainId){
|
|
180
|
+
if(TESTNET_RPC[chainId])return[TESTNET_RPC[chainId]];
|
|
181
|
+
const endpoints=["https://rpcs.calldata.eth.limo","https://rpcs.calldata.eth.link"];
|
|
182
|
+
for(const base of endpoints){
|
|
183
|
+
try{
|
|
184
|
+
const r=await fetch(base);
|
|
185
|
+
if(r.ok){const d=await r.json();if(d[chainId]&&Array.isArray(d[chainId]))return d[chainId];}
|
|
186
|
+
}catch(e){}
|
|
187
|
+
}
|
|
188
|
+
return[];
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
async function fetchChunkFromRpc(rpc,hash){
|
|
178
192
|
const r=await fetch(rpc,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({jsonrpc:"2.0",method:"eth_getTransactionByHash",params:[hash],id:1})});
|
|
179
193
|
const j=await r.json();
|
|
180
194
|
if(!j.result||!j.result.input)throw new Error("TX not found: "+hash);
|
|
@@ -191,19 +205,28 @@ async function fetchChunk(rpc,hash){
|
|
|
191
205
|
return{part:payload.part,data};
|
|
192
206
|
}
|
|
193
207
|
|
|
208
|
+
async function fetchChunk(rpcs,hash){
|
|
209
|
+
let lastErr;
|
|
210
|
+
for(const rpc of rpcs){
|
|
211
|
+
try{return await fetchChunkFromRpc(rpc,hash);}catch(e){lastErr=e;}
|
|
212
|
+
}
|
|
213
|
+
throw lastErr||new Error("No RPCs available");
|
|
214
|
+
}
|
|
215
|
+
|
|
194
216
|
async function load(){
|
|
195
217
|
const status=document.getElementById("status");
|
|
196
218
|
const progress=document.getElementById("progress");
|
|
197
219
|
const error=document.getElementById("error");
|
|
198
220
|
const download=document.getElementById("download");
|
|
199
|
-
|
|
200
|
-
|
|
221
|
+
status.textContent="Discovering RPC endpoints...";
|
|
222
|
+
const rpcs=await getRpcUrls(M.dataChainId);
|
|
223
|
+
if(!rpcs.length){error.textContent="No RPC endpoints for chain: "+M.dataChainId;error.style.display="block";return;}
|
|
201
224
|
const chunks=[];
|
|
202
225
|
try{
|
|
203
226
|
// Fetch ALL chunks from L2
|
|
204
227
|
for(let i=0;i<M.dataTxHashes.length;i++){
|
|
205
228
|
status.textContent="Loading chunk "+(i+1)+"/"+M.totalChunks+" from "+M.dataChain+"...";
|
|
206
|
-
const chunk=await fetchChunk(
|
|
229
|
+
const chunk=await fetchChunk(rpcs,M.dataTxHashes[i]);
|
|
207
230
|
chunks.push(chunk);
|
|
208
231
|
progress.style.width=((i+1)/M.totalChunks*100)+"%";
|
|
209
232
|
}
|
package/dist/crosschain.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"crosschain.js","sourceRoot":"","sources":["../src/crosschain.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"crosschain.js","sourceRoot":"","sources":["../src/crosschain.ts"],"names":[],"mappings":"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"}
|