holosphere 2.0.0-alpha1 ā 2.0.0-alpha4
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/dist/2019-D2OG2idw.js +6680 -0
- package/dist/2019-D2OG2idw.js.map +1 -0
- package/dist/2019-EION3wKo.cjs +8 -0
- package/dist/2019-EION3wKo.cjs.map +1 -0
- package/dist/_commonjsHelpers-C37NGDzP.cjs +2 -0
- package/dist/_commonjsHelpers-C37NGDzP.cjs.map +1 -0
- package/dist/_commonjsHelpers-CUmg6egw.js +7 -0
- package/dist/_commonjsHelpers-CUmg6egw.js.map +1 -0
- package/dist/browser-BSniCNqO.js +3058 -0
- package/dist/browser-BSniCNqO.js.map +1 -0
- package/dist/browser-Cq59Ij19.cjs +2 -0
- package/dist/browser-Cq59Ij19.cjs.map +1 -0
- package/dist/cjs/holosphere.cjs +2 -0
- package/dist/cjs/holosphere.cjs.map +1 -0
- package/dist/esm/holosphere.js +53 -0
- package/dist/esm/holosphere.js.map +1 -0
- package/dist/index-BB_vVJgv.cjs +5 -0
- package/dist/index-BB_vVJgv.cjs.map +1 -0
- package/dist/index-CBitK71M.cjs +12 -0
- package/dist/index-CBitK71M.cjs.map +1 -0
- package/dist/index-CV0eOogK.js +37423 -0
- package/dist/index-CV0eOogK.js.map +1 -0
- package/dist/index-Cz-PLCUR.js +15104 -0
- package/dist/index-Cz-PLCUR.js.map +1 -0
- package/dist/indexeddb-storage-CRsZyB2f.cjs +2 -0
- package/dist/indexeddb-storage-CRsZyB2f.cjs.map +1 -0
- package/dist/indexeddb-storage-DZaGlY_a.js +132 -0
- package/dist/indexeddb-storage-DZaGlY_a.js.map +1 -0
- package/dist/memory-storage-BkUi6sZG.js +51 -0
- package/dist/memory-storage-BkUi6sZG.js.map +1 -0
- package/dist/memory-storage-C0DuUsdY.cjs +2 -0
- package/dist/memory-storage-C0DuUsdY.cjs.map +1 -0
- package/dist/secp256k1-0kPdAVkK.cjs +12 -0
- package/dist/secp256k1-0kPdAVkK.cjs.map +1 -0
- package/dist/secp256k1-DN4FVXcv.js +1890 -0
- package/dist/secp256k1-DN4FVXcv.js.map +1 -0
- package/docs/CONTRACTS.md +797 -0
- package/docs/FOSDEM_PROPOSAL.md +388 -0
- package/docs/LOCALFIRST.md +266 -0
- package/docs/contracts/api-interface.md +793 -0
- package/docs/data-model.md +476 -0
- package/docs/gun-async-usage.md +338 -0
- package/docs/plan.md +349 -0
- package/docs/quickstart.md +674 -0
- package/docs/research.md +362 -0
- package/docs/spec.md +244 -0
- package/docs/storage-backends.md +326 -0
- package/docs/tasks.md +947 -0
- package/examples/demo.html +47 -0
- package/package.json +10 -5
- package/src/contracts/abis/Appreciative.json +1280 -0
- package/src/contracts/abis/AppreciativeFactory.json +101 -0
- package/src/contracts/abis/Bundle.json +1435 -0
- package/src/contracts/abis/BundleFactory.json +106 -0
- package/src/contracts/abis/Holon.json +881 -0
- package/src/contracts/abis/Holons.json +330 -0
- package/src/contracts/abis/Managed.json +1262 -0
- package/src/contracts/abis/ManagedFactory.json +149 -0
- package/src/contracts/abis/Membrane.json +261 -0
- package/src/contracts/abis/Splitter.json +1624 -0
- package/src/contracts/abis/SplitterFactory.json +220 -0
- package/src/contracts/abis/TestToken.json +321 -0
- package/src/contracts/abis/Zoned.json +1461 -0
- package/src/contracts/abis/ZonedFactory.json +154 -0
- package/src/contracts/chain-manager.js +375 -0
- package/src/contracts/deployer.js +443 -0
- package/src/contracts/event-listener.js +507 -0
- package/src/contracts/holon-contracts.js +344 -0
- package/src/contracts/index.js +83 -0
- package/src/contracts/networks.js +224 -0
- package/src/contracts/operations.js +670 -0
- package/src/contracts/queries.js +589 -0
- package/src/core/holosphere.js +453 -1
- package/src/crypto/nostr-utils.js +263 -0
- package/src/federation/handshake.js +455 -0
- package/src/federation/hologram.js +1 -1
- package/src/hierarchical/upcast.js +6 -5
- package/src/index.js +463 -1939
- package/src/lib/ai-methods.js +308 -0
- package/src/lib/contract-methods.js +293 -0
- package/src/lib/errors.js +23 -0
- package/src/lib/federation-methods.js +238 -0
- package/src/lib/index.js +26 -0
- package/src/spatial/h3-operations.js +2 -2
- package/src/storage/backends/gundb-backend.js +377 -46
- package/src/storage/global-tables.js +28 -1
- package/src/storage/gun-auth.js +303 -0
- package/src/storage/gun-federation.js +776 -0
- package/src/storage/gun-references.js +198 -0
- package/src/storage/gun-schema.js +291 -0
- package/src/storage/gun-wrapper.js +347 -31
- package/src/storage/indexeddb-storage.js +49 -11
- package/src/storage/memory-storage.js +5 -0
- package/src/storage/nostr-async.js +45 -23
- package/src/storage/nostr-client.js +11 -5
- package/src/storage/persistent-storage.js +6 -1
- package/src/storage/unified-storage.js +119 -0
- package/src/subscriptions/manager.js +1 -1
- package/types/index.d.ts +133 -0
- package/tests/unit/ai/aggregation.test.js +0 -295
- package/tests/unit/ai/breakdown.test.js +0 -446
- package/tests/unit/ai/classifier.test.js +0 -294
- package/tests/unit/ai/council.test.js +0 -262
- package/tests/unit/ai/embeddings.test.js +0 -384
- package/tests/unit/ai/federation-ai.test.js +0 -344
- package/tests/unit/ai/h3-ai.test.js +0 -458
- package/tests/unit/ai/index.test.js +0 -304
- package/tests/unit/ai/json-ops.test.js +0 -307
- package/tests/unit/ai/llm-service.test.js +0 -390
- package/tests/unit/ai/nl-query.test.js +0 -383
- package/tests/unit/ai/relationships.test.js +0 -311
- package/tests/unit/ai/schema-extractor.test.js +0 -384
- package/tests/unit/ai/spatial.test.js +0 -279
- package/tests/unit/ai/tts.test.js +0 -279
- package/tests/unit/content.test.js +0 -332
- package/tests/unit/contract/core.test.js +0 -88
- package/tests/unit/contract/crypto.test.js +0 -198
- package/tests/unit/contract/data.test.js +0 -223
- package/tests/unit/contract/federation.test.js +0 -181
- package/tests/unit/contract/hierarchical.test.js +0 -113
- package/tests/unit/contract/schema.test.js +0 -114
- package/tests/unit/contract/social.test.js +0 -217
- package/tests/unit/contract/spatial.test.js +0 -110
- package/tests/unit/contract/subscriptions.test.js +0 -128
- package/tests/unit/contract/utils.test.js +0 -159
- package/tests/unit/core.test.js +0 -152
- package/tests/unit/crypto.test.js +0 -328
- package/tests/unit/federation.test.js +0 -234
- package/tests/unit/gun-async.test.js +0 -252
- package/tests/unit/hierarchical.test.js +0 -399
- package/tests/unit/integration/scenario-01-geographic-storage.test.js +0 -74
- package/tests/unit/integration/scenario-02-federation.test.js +0 -76
- package/tests/unit/integration/scenario-03-subscriptions.test.js +0 -102
- package/tests/unit/integration/scenario-04-validation.test.js +0 -129
- package/tests/unit/integration/scenario-05-hierarchy.test.js +0 -125
- package/tests/unit/integration/scenario-06-social.test.js +0 -135
- package/tests/unit/integration/scenario-07-persistence.test.js +0 -130
- package/tests/unit/integration/scenario-08-authorization.test.js +0 -161
- package/tests/unit/integration/scenario-09-cross-dimensional.test.js +0 -139
- package/tests/unit/integration/scenario-10-cross-holosphere-capabilities.test.js +0 -357
- package/tests/unit/integration/scenario-11-cross-holosphere-federation.test.js +0 -410
- package/tests/unit/integration/scenario-12-capability-federated-read.test.js +0 -719
- package/tests/unit/performance/benchmark.test.js +0 -85
- package/tests/unit/schema.test.js +0 -213
- package/tests/unit/spatial.test.js +0 -158
- package/tests/unit/storage.test.js +0 -195
- package/tests/unit/subscriptions.test.js +0 -328
- package/tests/unit/test-data-permanence-debug.js +0 -197
- package/tests/unit/test-data-permanence.js +0 -340
- package/tests/unit/test-key-persistence-fixed.js +0 -148
- package/tests/unit/test-key-persistence.js +0 -172
- package/tests/unit/test-relay-permanence.js +0 -376
- package/tests/unit/test-second-node.js +0 -95
- package/tests/unit/test-simple-write.js +0 -89
|
@@ -1,376 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Comprehensive Data Permanence Test Through Relays
|
|
3
|
-
*
|
|
4
|
-
* This test validates complete data persistence through the Nostr relay network:
|
|
5
|
-
* 1. Write data from Node 1
|
|
6
|
-
* 2. Verify immediate readback on Node 1
|
|
7
|
-
* 3. Wait for relay propagation
|
|
8
|
-
* 4. Create Node 2 and verify it can read Node 1's data
|
|
9
|
-
* 5. Restart Node 1 (new instance) and verify data recovery
|
|
10
|
-
* 6. Update data and verify updates propagate
|
|
11
|
-
* 7. Verify batch writes persist
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
import { HoloSphere } from './dist/esm/holosphere.js';
|
|
15
|
-
|
|
16
|
-
// Relay configuration - use env vars or these defaults
|
|
17
|
-
const RELAYS = process.env.HOLOSPHERE_RELAYS?.split(',') || [
|
|
18
|
-
'wss://relay.holons.io',
|
|
19
|
-
'wss://relay.nostr.band',
|
|
20
|
-
];
|
|
21
|
-
|
|
22
|
-
// Test configuration
|
|
23
|
-
const TEST_CONFIG = {
|
|
24
|
-
appName: 'relay-permanence-test',
|
|
25
|
-
relays: RELAYS,
|
|
26
|
-
logLevel: 'INFO'
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
const TEST_HOLON = 'global://permanence';
|
|
30
|
-
const WAIT_FOR_SYNC = 4000; // 4 seconds for relay sync
|
|
31
|
-
|
|
32
|
-
// Colors for console
|
|
33
|
-
const c = {
|
|
34
|
-
reset: '\x1b[0m',
|
|
35
|
-
green: '\x1b[32m',
|
|
36
|
-
red: '\x1b[31m',
|
|
37
|
-
yellow: '\x1b[33m',
|
|
38
|
-
blue: '\x1b[34m',
|
|
39
|
-
cyan: '\x1b[36m',
|
|
40
|
-
bold: '\x1b[1m'
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
function log(msg, color = 'reset') {
|
|
44
|
-
console.log(`${c[color]}${msg}${c.reset}`);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
function section(title) {
|
|
48
|
-
console.log('\n' + 'ā'.repeat(70));
|
|
49
|
-
log(` ${title}`, 'cyan');
|
|
50
|
-
console.log('ā'.repeat(70) + '\n');
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
function test(name, passed, details = '') {
|
|
54
|
-
const icon = passed ? 'ā
' : 'ā';
|
|
55
|
-
const color = passed ? 'green' : 'red';
|
|
56
|
-
log(`${icon} ${name}`, color);
|
|
57
|
-
if (details) console.log(` ${details}`);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
async function wait(ms, message) {
|
|
61
|
-
if (message) log(`ā³ ${message}`, 'yellow');
|
|
62
|
-
await new Promise(resolve => setTimeout(resolve, ms));
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// Track test results
|
|
66
|
-
const results = {
|
|
67
|
-
passed: 0,
|
|
68
|
-
failed: 0,
|
|
69
|
-
tests: []
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
function addResult(name, passed, details = '') {
|
|
73
|
-
test(name, passed, details);
|
|
74
|
-
results.tests.push({ name, passed, details });
|
|
75
|
-
if (passed) results.passed++;
|
|
76
|
-
else results.failed++;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Test 1: Write data from Node 1 and verify immediate readback
|
|
81
|
-
*/
|
|
82
|
-
async function test1_WriteAndRead(hs) {
|
|
83
|
-
section('TEST 1: Write Data and Immediate Readback');
|
|
84
|
-
|
|
85
|
-
const testData = {
|
|
86
|
-
id: `perm-test-${Date.now()}`,
|
|
87
|
-
message: 'Data permanence test',
|
|
88
|
-
timestamp: Date.now(),
|
|
89
|
-
metadata: {
|
|
90
|
-
test: 'write-read',
|
|
91
|
-
node: 1
|
|
92
|
-
}
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
log('Writing test data from Node 1...', 'yellow');
|
|
96
|
-
const writeResult = await hs.write(TEST_HOLON, 'data', testData);
|
|
97
|
-
addResult('Write operation successful', writeResult, `ID: ${testData.id}`);
|
|
98
|
-
|
|
99
|
-
if (!writeResult) {
|
|
100
|
-
log('ā ļø Write failed - skipping read test', 'red');
|
|
101
|
-
return { success: false, testData };
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
await wait(500, 'Waiting for local cache...');
|
|
105
|
-
|
|
106
|
-
log('Reading data back on Node 1...', 'yellow');
|
|
107
|
-
const readData = await hs.read(TEST_HOLON, 'data');
|
|
108
|
-
|
|
109
|
-
const found = readData && readData.some(d => d.id === testData.id);
|
|
110
|
-
addResult('Data readable immediately after write', found,
|
|
111
|
-
found ? `Found ${readData.length} record(s)` : 'Data not found');
|
|
112
|
-
|
|
113
|
-
if (found) {
|
|
114
|
-
const record = readData.find(d => d.id === testData.id);
|
|
115
|
-
const matches = record.message === testData.message;
|
|
116
|
-
addResult('Data content matches original', matches);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
return { success: writeResult && found, testData };
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* Test 2: Verify data persists after relay sync period
|
|
124
|
-
*/
|
|
125
|
-
async function test2_RelayPersistence(hs, testData) {
|
|
126
|
-
section('TEST 2: Data Persistence After Relay Sync');
|
|
127
|
-
|
|
128
|
-
await wait(WAIT_FOR_SYNC, `Waiting ${WAIT_FOR_SYNC/1000}s for relay synchronization...`);
|
|
129
|
-
|
|
130
|
-
log('Re-reading data after sync period...', 'yellow');
|
|
131
|
-
const readData = await hs.read(TEST_HOLON, 'data');
|
|
132
|
-
|
|
133
|
-
const found = readData && readData.some(d => d.id === testData.id);
|
|
134
|
-
addResult('Data persists after relay sync', found,
|
|
135
|
-
found ? `Found ${readData.length} record(s)` : 'Data disappeared');
|
|
136
|
-
|
|
137
|
-
return { success: found };
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* Test 3: Create second node and verify cross-node data visibility
|
|
142
|
-
*/
|
|
143
|
-
async function test3_CrossNodeSync(testData, privateKey) {
|
|
144
|
-
section('TEST 3: Cross-Node Data Synchronization');
|
|
145
|
-
|
|
146
|
-
log('Creating Node 2 with same private key...', 'yellow');
|
|
147
|
-
const hs2 = new HoloSphere({
|
|
148
|
-
...TEST_CONFIG,
|
|
149
|
-
privateKey // Same key to see same events
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
log(`Node 2 Public Key: ${hs2.client.publicKey}`, 'blue');
|
|
153
|
-
|
|
154
|
-
await wait(WAIT_FOR_SYNC, `Waiting ${WAIT_FOR_SYNC/1000}s for Node 2 relay connection...`);
|
|
155
|
-
|
|
156
|
-
log('Node 2 reading data from relays...', 'yellow');
|
|
157
|
-
const readData = await hs2.read(TEST_HOLON, 'data');
|
|
158
|
-
|
|
159
|
-
const found = readData && readData.some(d => d.id === testData.id);
|
|
160
|
-
addResult('Node 2 can read Node 1 data', found,
|
|
161
|
-
found ? `Found ${readData.length} record(s)` : 'Data not visible on Node 2');
|
|
162
|
-
|
|
163
|
-
if (found) {
|
|
164
|
-
const record = readData.find(d => d.id === testData.id);
|
|
165
|
-
const matches = record.message === testData.message;
|
|
166
|
-
addResult('Data content matches on Node 2', matches);
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
return { success: found, hs2 };
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
/**
|
|
173
|
-
* Test 4: Restart Node 1 and verify data recovery from relays
|
|
174
|
-
*/
|
|
175
|
-
async function test4_NodeRestart(testData, privateKey) {
|
|
176
|
-
section('TEST 4: Data Recovery After Node Restart');
|
|
177
|
-
|
|
178
|
-
log('Simulating Node 1 restart (new instance with same key)...', 'yellow');
|
|
179
|
-
const hsRestart = new HoloSphere({
|
|
180
|
-
...TEST_CONFIG,
|
|
181
|
-
privateKey // Same key
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
log(`Restarted Node Public Key: ${hsRestart.client.publicKey}`, 'blue');
|
|
185
|
-
|
|
186
|
-
await wait(WAIT_FOR_SYNC, `Waiting ${WAIT_FOR_SYNC/1000}s for relay connection...`);
|
|
187
|
-
|
|
188
|
-
log('Restarted node reading from relays...', 'yellow');
|
|
189
|
-
const readData = await hsRestart.read(TEST_HOLON, 'data');
|
|
190
|
-
|
|
191
|
-
const found = readData && readData.some(d => d.id === testData.id);
|
|
192
|
-
addResult('Data recovered after restart', found,
|
|
193
|
-
found ? `Found ${readData.length} record(s)` : 'Data not recovered');
|
|
194
|
-
|
|
195
|
-
return { success: found, hsRestart };
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
/**
|
|
199
|
-
* Test 5: Update data and verify update persistence
|
|
200
|
-
*/
|
|
201
|
-
async function test5_UpdatePersistence(hs, testData) {
|
|
202
|
-
section('TEST 5: Data Update and Update Persistence');
|
|
203
|
-
|
|
204
|
-
const updatedData = {
|
|
205
|
-
...testData,
|
|
206
|
-
message: 'Updated message - testing permanence',
|
|
207
|
-
metadata: {
|
|
208
|
-
...testData.metadata,
|
|
209
|
-
updated: true,
|
|
210
|
-
updateTimestamp: Date.now()
|
|
211
|
-
}
|
|
212
|
-
};
|
|
213
|
-
|
|
214
|
-
log('Updating data...', 'yellow');
|
|
215
|
-
const writeResult = await hs.write(TEST_HOLON, 'data', updatedData);
|
|
216
|
-
addResult('Update write successful', writeResult);
|
|
217
|
-
|
|
218
|
-
await wait(WAIT_FOR_SYNC, `Waiting ${WAIT_FOR_SYNC/1000}s for update propagation...`);
|
|
219
|
-
|
|
220
|
-
log('Reading updated data...', 'yellow');
|
|
221
|
-
const readData = await hs.read(TEST_HOLON, 'data');
|
|
222
|
-
|
|
223
|
-
const found = readData && readData.find(d => d.id === testData.id);
|
|
224
|
-
const updatePersisted = found && found.metadata && found.metadata.updated === true;
|
|
225
|
-
|
|
226
|
-
addResult('Update persisted correctly', updatePersisted,
|
|
227
|
-
updatePersisted ? `Message: "${found.message}"` : 'Update not found');
|
|
228
|
-
|
|
229
|
-
return { success: writeResult && updatePersisted };
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
/**
|
|
233
|
-
* Test 6: Verify update visible on second node
|
|
234
|
-
*/
|
|
235
|
-
async function test6_UpdateCrossNode(hs2, testData) {
|
|
236
|
-
section('TEST 6: Update Visibility Across Nodes');
|
|
237
|
-
|
|
238
|
-
await wait(WAIT_FOR_SYNC, `Waiting ${WAIT_FOR_SYNC/1000}s for update to sync to Node 2...`);
|
|
239
|
-
|
|
240
|
-
log('Node 2 reading updated data...', 'yellow');
|
|
241
|
-
const readData = await hs2.read(TEST_HOLON, 'data');
|
|
242
|
-
|
|
243
|
-
const found = readData && readData.find(d => d.id === testData.id);
|
|
244
|
-
const updateVisible = found && found.metadata && found.metadata.updated === true;
|
|
245
|
-
|
|
246
|
-
addResult('Update visible on Node 2', updateVisible,
|
|
247
|
-
updateVisible ? `Message: "${found.message}"` : 'Update not visible');
|
|
248
|
-
|
|
249
|
-
return { success: updateVisible };
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
/**
|
|
253
|
-
* Test 7: Multiple writes and verify all persist
|
|
254
|
-
*/
|
|
255
|
-
async function test7_BatchPersistence(hs) {
|
|
256
|
-
section('TEST 7: Batch Write Persistence');
|
|
257
|
-
|
|
258
|
-
const count = 5;
|
|
259
|
-
const records = [];
|
|
260
|
-
|
|
261
|
-
log(`Writing ${count} records...`, 'yellow');
|
|
262
|
-
for (let i = 0; i < count; i++) {
|
|
263
|
-
const record = {
|
|
264
|
-
id: `batch-${Date.now()}-${i}`,
|
|
265
|
-
index: i,
|
|
266
|
-
timestamp: Date.now(),
|
|
267
|
-
message: `Batch record ${i + 1}/${count}`
|
|
268
|
-
};
|
|
269
|
-
records.push(record);
|
|
270
|
-
const result = await hs.write(TEST_HOLON, 'data', record);
|
|
271
|
-
if (result) {
|
|
272
|
-
log(` ā Written: ${record.id}`, 'blue');
|
|
273
|
-
} else {
|
|
274
|
-
log(` ā Failed: ${record.id}`, 'red');
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
await wait(WAIT_FOR_SYNC, `Waiting ${WAIT_FOR_SYNC/1000}s for batch sync...`);
|
|
279
|
-
|
|
280
|
-
log('Reading all records...', 'yellow');
|
|
281
|
-
const readData = await hs.read(TEST_HOLON, 'data');
|
|
282
|
-
|
|
283
|
-
const foundCount = records.filter(r =>
|
|
284
|
-
readData && readData.some(d => d.id === r.id)
|
|
285
|
-
).length;
|
|
286
|
-
|
|
287
|
-
const allFound = foundCount === count;
|
|
288
|
-
addResult('All batch records persisted', allFound,
|
|
289
|
-
`Found ${foundCount}/${count} records`);
|
|
290
|
-
|
|
291
|
-
return { success: allFound, records };
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
/**
|
|
295
|
-
* Main test runner
|
|
296
|
-
*/
|
|
297
|
-
async function runTests() {
|
|
298
|
-
log('\nāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā', 'cyan');
|
|
299
|
-
log('ā HOLOSPHERE DATA PERMANENCE TEST - NOSTR RELAY NETWORK ā', 'cyan');
|
|
300
|
-
log('āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā', 'cyan');
|
|
301
|
-
|
|
302
|
-
log(`\nTest Configuration:`, 'yellow');
|
|
303
|
-
log(` App Name: ${TEST_CONFIG.appName}`, 'blue');
|
|
304
|
-
log(` Test Holon: ${TEST_HOLON}`, 'blue');
|
|
305
|
-
log(` Relays:`, 'blue');
|
|
306
|
-
TEST_CONFIG.relays.forEach(relay => log(` ⢠${relay}`, 'blue'));
|
|
307
|
-
log(` Sync Wait Time: ${WAIT_FOR_SYNC / 1000}s`, 'blue');
|
|
308
|
-
|
|
309
|
-
try {
|
|
310
|
-
// Initialize Node 1
|
|
311
|
-
log('\nš” Initializing Node 1...', 'yellow');
|
|
312
|
-
const hs1 = new HoloSphere(TEST_CONFIG);
|
|
313
|
-
const privateKey = hs1.client.privateKey;
|
|
314
|
-
log(`Node 1 Public Key: ${hs1.client.publicKey}`, 'blue');
|
|
315
|
-
|
|
316
|
-
await wait(2000, 'Waiting for initial relay connections...');
|
|
317
|
-
|
|
318
|
-
// Run all tests
|
|
319
|
-
const { success: t1, testData } = await test1_WriteAndRead(hs1);
|
|
320
|
-
if (!t1) {
|
|
321
|
-
log('\nā ļø Initial write failed - cannot continue tests', 'red');
|
|
322
|
-
throw new Error('Initial write failed');
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
const { success: t2 } = await test2_RelayPersistence(hs1, testData);
|
|
326
|
-
const { success: t3, hs2 } = await test3_CrossNodeSync(testData, privateKey);
|
|
327
|
-
const { success: t4 } = await test4_NodeRestart(testData, privateKey);
|
|
328
|
-
const { success: t5 } = await test5_UpdatePersistence(hs1, testData);
|
|
329
|
-
const { success: t6 } = await test6_UpdateCrossNode(hs2, testData);
|
|
330
|
-
const { success: t7 } = await test7_BatchPersistence(hs1);
|
|
331
|
-
|
|
332
|
-
} catch (error) {
|
|
333
|
-
log('\nā TEST SUITE FAILED WITH ERROR:', 'red');
|
|
334
|
-
console.error(error);
|
|
335
|
-
results.failed++;
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
// Print summary
|
|
339
|
-
section('TEST SUMMARY');
|
|
340
|
-
|
|
341
|
-
results.tests.forEach(t => {
|
|
342
|
-
test(t.name, t.passed, t.details);
|
|
343
|
-
});
|
|
344
|
-
|
|
345
|
-
console.log('\n' + 'ā'.repeat(70));
|
|
346
|
-
log(`Total Tests: ${results.tests.length}`, 'blue');
|
|
347
|
-
log(`Passed: ${results.passed}`, 'green');
|
|
348
|
-
log(`Failed: ${results.failed}`, 'red');
|
|
349
|
-
const successRate = ((results.passed / results.tests.length) * 100).toFixed(1);
|
|
350
|
-
log(`Success Rate: ${successRate}%`, results.failed === 0 ? 'green' : 'yellow');
|
|
351
|
-
console.log('ā'.repeat(70) + '\n');
|
|
352
|
-
|
|
353
|
-
if (results.failed === 0) {
|
|
354
|
-
log('š ALL TESTS PASSED!', 'green');
|
|
355
|
-
log('ā Data writes to relays successfully', 'green');
|
|
356
|
-
log('ā Data persists across time', 'green');
|
|
357
|
-
log('ā Data syncs across multiple nodes', 'green');
|
|
358
|
-
log('ā Data survives node restarts', 'green');
|
|
359
|
-
log('ā Updates propagate correctly', 'green');
|
|
360
|
-
log('ā Batch operations work reliably', 'green');
|
|
361
|
-
log('\nš Your data is PERMANENT on the Nostr relay network!', 'bold');
|
|
362
|
-
} else {
|
|
363
|
-
log('ā ļø SOME TESTS FAILED', 'yellow');
|
|
364
|
-
log('Please review the results above.', 'yellow');
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
log('\nTest complete.\n');
|
|
368
|
-
|
|
369
|
-
setTimeout(() => process.exit(results.failed === 0 ? 0 : 1), 1000);
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
// Run the test suite
|
|
373
|
-
runTests().catch(error => {
|
|
374
|
-
console.error('ā Fatal error:', error);
|
|
375
|
-
process.exit(1);
|
|
376
|
-
});
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Test Second Node - Verify quest synchronization
|
|
3
|
-
*
|
|
4
|
-
* This script simulates a second node connecting to the same relays
|
|
5
|
-
* and verifying it can see quests created by the first node.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { HoloSphere } from './dist/esm/holosphere.js';
|
|
9
|
-
|
|
10
|
-
// Relay configuration - use env vars or these defaults
|
|
11
|
-
const RELAYS = process.env.HOLOSPHERE_RELAYS?.split(',') || [
|
|
12
|
-
'wss://relay.holons.io',
|
|
13
|
-
'wss://relay.nostr.band',
|
|
14
|
-
];
|
|
15
|
-
|
|
16
|
-
console.log('\n=== Second Node Test ===\n');
|
|
17
|
-
console.log('This node will connect to the same relays and fetch quests...\n');
|
|
18
|
-
|
|
19
|
-
// Initialize with the SAME configuration as the first node
|
|
20
|
-
const hs = new HoloSphere({
|
|
21
|
-
appName: 'quest-game', // MUST match the first node's appName
|
|
22
|
-
relays: RELAYS,
|
|
23
|
-
logLevel: 'INFO'
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
console.log('Second Node initialized with relays:', hs.config.relays);
|
|
27
|
-
console.log('Second Node Public Key:', hs.client.publicKey);
|
|
28
|
-
console.log('(Note: Different public key is OK - we can still read public quests)\n');
|
|
29
|
-
|
|
30
|
-
// Use the same holon ID as the first node
|
|
31
|
-
const QUEST_HOLON = 'global://quests';
|
|
32
|
-
|
|
33
|
-
async function testSync() {
|
|
34
|
-
// Wait for relay connections to establish
|
|
35
|
-
console.log('ā³ Waiting 3 seconds for relay connections...');
|
|
36
|
-
await new Promise(resolve => setTimeout(resolve, 3000));
|
|
37
|
-
|
|
38
|
-
console.log('\nš Fetching quests from relays...');
|
|
39
|
-
|
|
40
|
-
const quests = await hs.read(QUEST_HOLON, 'quests');
|
|
41
|
-
|
|
42
|
-
if (quests && quests.length > 0) {
|
|
43
|
-
console.log(`\nā
SUCCESS! Found ${quests.length} quest(s) from the first node:\n`);
|
|
44
|
-
quests.forEach((quest, index) => {
|
|
45
|
-
console.log(`${index + 1}. ${quest.title}`);
|
|
46
|
-
console.log(` ID: ${quest.id}`);
|
|
47
|
-
console.log(` Status: ${quest.status || 'active'}`);
|
|
48
|
-
console.log(` Description: ${quest.description || 'No description'}`);
|
|
49
|
-
console.log(` Reward: ${quest.reward || 0} gold`);
|
|
50
|
-
console.log('');
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
console.log('ā
QUEST SYNCHRONIZATION IS WORKING!');
|
|
54
|
-
console.log(' Quests created on Node 1 are visible on Node 2.\n');
|
|
55
|
-
} else {
|
|
56
|
-
console.log('\nā No quests found.');
|
|
57
|
-
console.log(' Possible reasons:');
|
|
58
|
-
console.log(' 1. First node hasn\'t created quests yet');
|
|
59
|
-
console.log(' 2. Quests haven\'t synced to relays yet (try again in a few seconds)');
|
|
60
|
-
console.log(' 3. Different appName between nodes');
|
|
61
|
-
console.log(' 4. Relay connectivity issues\n');
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// Test creating a quest from this node
|
|
65
|
-
console.log('š Creating a quest from the second node...\n');
|
|
66
|
-
|
|
67
|
-
const newQuest = {
|
|
68
|
-
id: `quest-${Date.now()}-from-node2`,
|
|
69
|
-
title: 'Explore the Mysterious Cave',
|
|
70
|
-
description: 'Discover what lies deep within the cave',
|
|
71
|
-
reward: 750,
|
|
72
|
-
difficulty: 'medium'
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
const result = await hs.write(QUEST_HOLON, 'quests', newQuest);
|
|
76
|
-
|
|
77
|
-
if (result) {
|
|
78
|
-
console.log('ā
Quest created from Node 2!');
|
|
79
|
-
console.log(' The first node should now see 3 quests total.\n');
|
|
80
|
-
} else {
|
|
81
|
-
console.log('ā Failed to create quest from Node 2\n');
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// Fetch again to see all quests
|
|
85
|
-
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
86
|
-
const allQuests = await hs.read(QUEST_HOLON, 'quests');
|
|
87
|
-
console.log(`š Total quests after Node 2 creation: ${allQuests ? allQuests.length : 0}\n`);
|
|
88
|
-
|
|
89
|
-
console.log('Test complete! Press Ctrl+C to exit.');
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
testSync().catch(error => {
|
|
93
|
-
console.error('ā Test failed:', error);
|
|
94
|
-
process.exit(1);
|
|
95
|
-
});
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Simple write test to debug relay issues
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { HoloSphere } from './dist/esm/holosphere.js';
|
|
6
|
-
|
|
7
|
-
// Relay configuration - use env vars or these defaults
|
|
8
|
-
const RELAYS = process.env.HOLOSPHERE_RELAYS?.split(',') || [
|
|
9
|
-
'wss://relay.holons.io',
|
|
10
|
-
'wss://relay.nostr.band',
|
|
11
|
-
];
|
|
12
|
-
|
|
13
|
-
console.log('\n=== SIMPLE WRITE TEST ===\n');
|
|
14
|
-
|
|
15
|
-
const hs = new HoloSphere({
|
|
16
|
-
appName: 'simple-test',
|
|
17
|
-
relays: RELAYS,
|
|
18
|
-
logLevel: 'DEBUG'
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
console.log(`Public Key: ${hs.client.publicKey}`);
|
|
22
|
-
console.log(`Relays:`, hs.config.relays);
|
|
23
|
-
|
|
24
|
-
// Wait for connections
|
|
25
|
-
await new Promise(resolve => setTimeout(resolve, 3000));
|
|
26
|
-
|
|
27
|
-
console.log('\n--- Writing data ---\n');
|
|
28
|
-
|
|
29
|
-
const testData = {
|
|
30
|
-
id: 'test-123',
|
|
31
|
-
message: 'Hello, relay!',
|
|
32
|
-
timestamp: Date.now()
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
try {
|
|
36
|
-
// Get more details from the write
|
|
37
|
-
const storage = await import('./src/storage/nostr-wrapper.js');
|
|
38
|
-
const nostrAsync = await import('./src/storage/nostr-async.js');
|
|
39
|
-
|
|
40
|
-
const path = storage.buildPath('simple-test', 'global://test', 'data', testData.id);
|
|
41
|
-
console.log(`Path: ${path}`);
|
|
42
|
-
|
|
43
|
-
// Call nostrPut directly to see the result
|
|
44
|
-
const result = await nostrAsync.nostrPut(hs.client, path, testData);
|
|
45
|
-
|
|
46
|
-
console.log('\n--- Publish Result ---');
|
|
47
|
-
console.log(`Event ID: ${result.event.id}`);
|
|
48
|
-
console.log(`Event created_at: ${result.event.created_at}`);
|
|
49
|
-
console.log(`Event pubkey: ${result.event.pubkey}`);
|
|
50
|
-
console.log(`Event tags:`, JSON.stringify(result.event.tags, null, 2));
|
|
51
|
-
console.log(`\nRelay Results:`);
|
|
52
|
-
|
|
53
|
-
result.results.forEach((r, i) => {
|
|
54
|
-
console.log(`\n Relay ${i + 1}: ${hs.config.relays[i]}`);
|
|
55
|
-
console.log(` Status: ${r.status}`);
|
|
56
|
-
if (r.status === 'fulfilled') {
|
|
57
|
-
console.log(` Value: ${r.value}`);
|
|
58
|
-
} else if (r.status === 'rejected') {
|
|
59
|
-
console.log(` Reason: ${r.reason}`);
|
|
60
|
-
}
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
const success = result.results.some(r => r.status === 'fulfilled');
|
|
64
|
-
console.log(`\n--- Summary ---`);
|
|
65
|
-
console.log(`Success: ${success}`);
|
|
66
|
-
console.log(`Fulfilled: ${result.results.filter(r => r.status === 'fulfilled').length}/${result.results.length}`);
|
|
67
|
-
|
|
68
|
-
// Now try reading it back
|
|
69
|
-
console.log('\n--- Reading data back ---\n');
|
|
70
|
-
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
71
|
-
|
|
72
|
-
const readData = await hs.read('global://test', 'data');
|
|
73
|
-
console.log(`Found ${readData ? readData.length : 0} records`);
|
|
74
|
-
|
|
75
|
-
if (readData && readData.length > 0) {
|
|
76
|
-
readData.forEach((d, i) => {
|
|
77
|
-
console.log(`\nRecord ${i + 1}:`);
|
|
78
|
-
console.log(JSON.stringify(d, null, 2));
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
} catch (error) {
|
|
83
|
-
console.error('\nā Error:', error);
|
|
84
|
-
console.error(error.stack);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
console.log('\n=== TEST COMPLETE ===\n');
|
|
88
|
-
|
|
89
|
-
setTimeout(() => process.exit(0), 1000);
|