holosphere 2.0.0-alpha2 → 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.
Files changed (98) hide show
  1. package/dist/2019-D2OG2idw.js +6680 -0
  2. package/dist/2019-D2OG2idw.js.map +1 -0
  3. package/dist/2019-EION3wKo.cjs +8 -0
  4. package/dist/2019-EION3wKo.cjs.map +1 -0
  5. package/dist/_commonjsHelpers-C37NGDzP.cjs +2 -0
  6. package/dist/_commonjsHelpers-C37NGDzP.cjs.map +1 -0
  7. package/dist/_commonjsHelpers-CUmg6egw.js +7 -0
  8. package/dist/_commonjsHelpers-CUmg6egw.js.map +1 -0
  9. package/dist/browser-BSniCNqO.js +3058 -0
  10. package/dist/browser-BSniCNqO.js.map +1 -0
  11. package/dist/browser-Cq59Ij19.cjs +2 -0
  12. package/dist/browser-Cq59Ij19.cjs.map +1 -0
  13. package/dist/cjs/holosphere.cjs +1 -1
  14. package/dist/esm/holosphere.js +50 -53
  15. package/dist/index-BB_vVJgv.cjs +5 -0
  16. package/dist/index-BB_vVJgv.cjs.map +1 -0
  17. package/dist/index-CBitK71M.cjs +12 -0
  18. package/dist/index-CBitK71M.cjs.map +1 -0
  19. package/dist/index-CV0eOogK.js +37423 -0
  20. package/dist/index-CV0eOogK.js.map +1 -0
  21. package/dist/index-Cz-PLCUR.js +15104 -0
  22. package/dist/index-Cz-PLCUR.js.map +1 -0
  23. package/dist/indexeddb-storage-CRsZyB2f.cjs +2 -0
  24. package/dist/indexeddb-storage-CRsZyB2f.cjs.map +1 -0
  25. package/dist/{indexeddb-storage-CMW4qRQS.js → indexeddb-storage-DZaGlY_a.js} +49 -13
  26. package/dist/indexeddb-storage-DZaGlY_a.js.map +1 -0
  27. package/dist/{memory-storage-DQzcAZlf.js → memory-storage-BkUi6sZG.js} +6 -2
  28. package/dist/memory-storage-BkUi6sZG.js.map +1 -0
  29. package/dist/{memory-storage-DmePEP2q.cjs → memory-storage-C0DuUsdY.cjs} +2 -2
  30. package/dist/memory-storage-C0DuUsdY.cjs.map +1 -0
  31. package/dist/secp256k1-0kPdAVkK.cjs +12 -0
  32. package/dist/secp256k1-0kPdAVkK.cjs.map +1 -0
  33. package/dist/{secp256k1-vOXp40Fx.js → secp256k1-DN4FVXcv.js} +2 -393
  34. package/dist/secp256k1-DN4FVXcv.js.map +1 -0
  35. package/docs/CONTRACTS.md +797 -0
  36. package/examples/demo.html +47 -0
  37. package/package.json +10 -5
  38. package/src/contracts/abis/Appreciative.json +1280 -0
  39. package/src/contracts/abis/AppreciativeFactory.json +101 -0
  40. package/src/contracts/abis/Bundle.json +1435 -0
  41. package/src/contracts/abis/BundleFactory.json +106 -0
  42. package/src/contracts/abis/Holon.json +881 -0
  43. package/src/contracts/abis/Holons.json +330 -0
  44. package/src/contracts/abis/Managed.json +1262 -0
  45. package/src/contracts/abis/ManagedFactory.json +149 -0
  46. package/src/contracts/abis/Membrane.json +261 -0
  47. package/src/contracts/abis/Splitter.json +1624 -0
  48. package/src/contracts/abis/SplitterFactory.json +220 -0
  49. package/src/contracts/abis/TestToken.json +321 -0
  50. package/src/contracts/abis/Zoned.json +1461 -0
  51. package/src/contracts/abis/ZonedFactory.json +154 -0
  52. package/src/contracts/chain-manager.js +375 -0
  53. package/src/contracts/deployer.js +443 -0
  54. package/src/contracts/event-listener.js +507 -0
  55. package/src/contracts/holon-contracts.js +344 -0
  56. package/src/contracts/index.js +83 -0
  57. package/src/contracts/networks.js +224 -0
  58. package/src/contracts/operations.js +670 -0
  59. package/src/contracts/queries.js +589 -0
  60. package/src/core/holosphere.js +453 -1
  61. package/src/crypto/nostr-utils.js +263 -0
  62. package/src/federation/handshake.js +455 -0
  63. package/src/federation/hologram.js +1 -1
  64. package/src/hierarchical/upcast.js +6 -5
  65. package/src/index.js +463 -1939
  66. package/src/lib/ai-methods.js +308 -0
  67. package/src/lib/contract-methods.js +293 -0
  68. package/src/lib/errors.js +23 -0
  69. package/src/lib/federation-methods.js +238 -0
  70. package/src/lib/index.js +26 -0
  71. package/src/spatial/h3-operations.js +2 -2
  72. package/src/storage/backends/gundb-backend.js +377 -46
  73. package/src/storage/global-tables.js +28 -1
  74. package/src/storage/gun-auth.js +303 -0
  75. package/src/storage/gun-federation.js +776 -0
  76. package/src/storage/gun-references.js +198 -0
  77. package/src/storage/gun-schema.js +291 -0
  78. package/src/storage/gun-wrapper.js +347 -31
  79. package/src/storage/indexeddb-storage.js +49 -11
  80. package/src/storage/memory-storage.js +5 -0
  81. package/src/storage/nostr-async.js +45 -23
  82. package/src/storage/nostr-client.js +11 -5
  83. package/src/storage/persistent-storage.js +6 -1
  84. package/src/storage/unified-storage.js +119 -0
  85. package/src/subscriptions/manager.js +1 -1
  86. package/types/index.d.ts +133 -0
  87. package/dist/index-CDfIuXew.js +0 -15974
  88. package/dist/index-CDfIuXew.js.map +0 -1
  89. package/dist/index-ifOgtDvd.cjs +0 -3
  90. package/dist/index-ifOgtDvd.cjs.map +0 -1
  91. package/dist/indexeddb-storage-CMW4qRQS.js.map +0 -1
  92. package/dist/indexeddb-storage-DLZOgetM.cjs +0 -2
  93. package/dist/indexeddb-storage-DLZOgetM.cjs.map +0 -1
  94. package/dist/memory-storage-DQzcAZlf.js.map +0 -1
  95. package/dist/memory-storage-DmePEP2q.cjs.map +0 -1
  96. package/dist/secp256k1-CP0ZkpAx.cjs +0 -13
  97. package/dist/secp256k1-CP0ZkpAx.cjs.map +0 -1
  98. package/dist/secp256k1-vOXp40Fx.js.map +0 -1
@@ -0,0 +1,507 @@
1
+ /**
2
+ * Event Listener for Sankey Flow Visualization
3
+ *
4
+ * Listens to contract events and transforms them into a format
5
+ * suitable for Sankey diagram visualization of fund flows.
6
+ */
7
+
8
+ /**
9
+ * Standard Sankey event types emitted by our contracts
10
+ */
11
+ export const SANKEY_EVENTS = {
12
+ // Fund flow events
13
+ FundsReceived: 'FundsReceived',
14
+ FundsCascaded: 'FundsCascaded',
15
+ FundsAllocated: 'FundsAllocated',
16
+ FundsClaimed: 'FundsClaimed',
17
+ FundsTransferred: 'FundsTransferred',
18
+
19
+ // Distribution summary
20
+ DistributionCompleted: 'DistributionCompleted',
21
+
22
+ // Structure events
23
+ ChildContractCreated: 'ChildContractCreated',
24
+ HolonCreated: 'HolonCreated',
25
+
26
+ // Membership events
27
+ MemberAdded: 'MemberAdded',
28
+ MemberRemoved: 'MemberRemoved',
29
+
30
+ // Weight/Zone events
31
+ WeightChanged: 'WeightChanged',
32
+ ZoneAssigned: 'ZoneAssigned',
33
+ AppreciationGiven: 'AppreciationGiven',
34
+
35
+ // Configuration events
36
+ SplitConfigured: 'SplitConfigured',
37
+ ContractSplitConfigured: 'ContractSplitConfigured'
38
+ };
39
+
40
+ /**
41
+ * EventListener class for tracking contract events
42
+ */
43
+ export class EventListener {
44
+ constructor(chainManager) {
45
+ this.chainManager = chainManager;
46
+ this.listeners = new Map();
47
+ this.eventHistory = [];
48
+ this.sankeyNodes = new Map(); // address/userId -> node data
49
+ this.sankeyLinks = []; // {source, target, value, ...}
50
+ }
51
+
52
+ /**
53
+ * Start listening to all Sankey-relevant events on a contract
54
+ * @param {string} contractAddress - The contract address
55
+ * @param {string} holonId - Human-readable holon identifier
56
+ * @param {Object} contract - ethers.js contract instance
57
+ */
58
+ async listenToContract(contractAddress, holonId, contract) {
59
+ const eventFilters = [
60
+ 'FundsReceived',
61
+ 'FundsCascaded',
62
+ 'FundsAllocated',
63
+ 'FundsClaimed',
64
+ 'FundsTransferred',
65
+ 'DistributionCompleted',
66
+ 'MemberAdded',
67
+ 'WeightChanged',
68
+ 'ZoneAssigned',
69
+ 'AppreciationGiven'
70
+ ];
71
+
72
+ for (const eventName of eventFilters) {
73
+ try {
74
+ const filter = contract.filters[eventName]?.();
75
+ if (filter) {
76
+ contract.on(eventName, (...args) => {
77
+ this._handleEvent(eventName, args, contractAddress, holonId);
78
+ });
79
+ }
80
+ } catch (e) {
81
+ // Event not found on this contract, skip
82
+ }
83
+ }
84
+
85
+ this.listeners.set(contractAddress, { contract, holonId });
86
+ }
87
+
88
+ /**
89
+ * Stop listening to a contract
90
+ */
91
+ stopListening(contractAddress) {
92
+ const listener = this.listeners.get(contractAddress);
93
+ if (listener) {
94
+ listener.contract.removeAllListeners();
95
+ this.listeners.delete(contractAddress);
96
+ }
97
+ }
98
+
99
+ /**
100
+ * Stop all listeners
101
+ */
102
+ stopAll() {
103
+ for (const [address, listener] of this.listeners) {
104
+ listener.contract.removeAllListeners();
105
+ }
106
+ this.listeners.clear();
107
+ }
108
+
109
+ /**
110
+ * Handle incoming event and transform to Sankey data
111
+ */
112
+ _handleEvent(eventName, args, contractAddress, holonId) {
113
+ const event = args[args.length - 1]; // Last arg is the event object
114
+ const timestamp = Date.now();
115
+
116
+ const parsed = {
117
+ type: eventName,
118
+ contractAddress,
119
+ holonId,
120
+ timestamp,
121
+ blockNumber: event?.blockNumber,
122
+ transactionHash: event?.transactionHash,
123
+ data: this._parseEventData(eventName, args)
124
+ };
125
+
126
+ this.eventHistory.push(parsed);
127
+ this._updateSankeyData(parsed);
128
+
129
+ // Emit custom event for real-time updates
130
+ if (typeof window !== 'undefined') {
131
+ window.dispatchEvent(new CustomEvent('sankey-event', { detail: parsed }));
132
+ }
133
+ }
134
+
135
+ /**
136
+ * Parse event data based on event type
137
+ */
138
+ _parseEventData(eventName, args) {
139
+ switch (eventName) {
140
+ case 'FundsReceived':
141
+ return {
142
+ contractAddress: args[0],
143
+ sender: args[1],
144
+ tokenAddress: args[2],
145
+ amount: args[3]?.toString()
146
+ };
147
+
148
+ case 'FundsCascaded':
149
+ return {
150
+ fromContract: args[0],
151
+ toContract: args[1],
152
+ fromHolonId: args[2],
153
+ toHolonId: args[3],
154
+ tokenAddress: args[4],
155
+ amount: args[5]?.toString(),
156
+ splitType: args[6]
157
+ };
158
+
159
+ case 'FundsAllocated':
160
+ return {
161
+ contractAddress: args[0],
162
+ holonId: args[1],
163
+ userId: args[2],
164
+ tokenAddress: args[3],
165
+ amount: args[4]?.toString(),
166
+ distributionType: args[5]
167
+ };
168
+
169
+ case 'FundsClaimed':
170
+ return {
171
+ contractAddress: args[0],
172
+ holonId: args[1],
173
+ userId: args[2],
174
+ beneficiary: args[3],
175
+ tokenAddress: args[4],
176
+ amount: args[5]?.toString()
177
+ };
178
+
179
+ case 'FundsTransferred':
180
+ return {
181
+ contractAddress: args[0],
182
+ holonId: args[1],
183
+ userId: args[2],
184
+ recipient: args[3],
185
+ tokenAddress: args[4],
186
+ amount: args[5]?.toString()
187
+ };
188
+
189
+ case 'DistributionCompleted':
190
+ return {
191
+ contractAddress: args[0],
192
+ holonId: args[1],
193
+ tokenAddress: args[2],
194
+ totalAmount: args[3]?.toString(),
195
+ recipientCount: Number(args[4]),
196
+ cascadeCount: Number(args[5])
197
+ };
198
+
199
+ case 'MemberAdded':
200
+ return {
201
+ contractAddress: args[0],
202
+ holonId: args[1],
203
+ userId: args[2],
204
+ addedBy: args[3]
205
+ };
206
+
207
+ case 'WeightChanged':
208
+ return {
209
+ contractAddress: args[0],
210
+ holonId: args[1],
211
+ userId: args[2],
212
+ oldWeight: args[3]?.toString(),
213
+ newWeight: args[4]?.toString()
214
+ };
215
+
216
+ case 'ZoneAssigned':
217
+ return {
218
+ contractAddress: args[0],
219
+ holonId: args[1],
220
+ userId: args[2],
221
+ oldZone: args[3]?.toString(),
222
+ newZone: args[4]?.toString()
223
+ };
224
+
225
+ case 'AppreciationGiven':
226
+ return {
227
+ contractAddress: args[0],
228
+ holonId: args[1],
229
+ fromUserId: args[2],
230
+ toUserId: args[3],
231
+ amount: args[4]?.toString()
232
+ };
233
+
234
+ default:
235
+ return { raw: args.slice(0, -1) };
236
+ }
237
+ }
238
+
239
+ /**
240
+ * Update Sankey nodes and links based on event
241
+ */
242
+ _updateSankeyData(event) {
243
+ const { type, data } = event;
244
+
245
+ switch (type) {
246
+ case 'FundsReceived':
247
+ // Add external source node
248
+ this._ensureNode(data.sender, 'external', 'External');
249
+ this._ensureNode(data.contractAddress, 'contract', event.holonId);
250
+ this.sankeyLinks.push({
251
+ source: data.sender,
252
+ target: data.contractAddress,
253
+ value: BigInt(data.amount),
254
+ token: data.tokenAddress,
255
+ type: 'external_inflow'
256
+ });
257
+ break;
258
+
259
+ case 'FundsCascaded':
260
+ this._ensureNode(data.fromContract, 'contract', data.fromHolonId);
261
+ this._ensureNode(data.toContract, 'contract', data.toHolonId);
262
+ this.sankeyLinks.push({
263
+ source: data.fromContract,
264
+ target: data.toContract,
265
+ value: BigInt(data.amount),
266
+ token: data.tokenAddress,
267
+ type: 'cascade',
268
+ splitType: data.splitType
269
+ });
270
+ break;
271
+
272
+ case 'FundsAllocated':
273
+ this._ensureNode(data.contractAddress, 'contract', data.holonId);
274
+ this._ensureNode(data.userId, 'user', data.userId);
275
+ this.sankeyLinks.push({
276
+ source: data.contractAddress,
277
+ target: data.userId,
278
+ value: BigInt(data.amount),
279
+ token: data.tokenAddress,
280
+ type: 'allocation',
281
+ distributionType: data.distributionType
282
+ });
283
+ break;
284
+
285
+ case 'FundsClaimed':
286
+ case 'FundsTransferred':
287
+ this._ensureNode(data.userId, 'user', data.userId);
288
+ this._ensureNode(data.beneficiary || data.recipient, 'wallet',
289
+ (data.beneficiary || data.recipient).slice(0, 8) + '...');
290
+ this.sankeyLinks.push({
291
+ source: data.userId,
292
+ target: data.beneficiary || data.recipient,
293
+ value: BigInt(data.amount),
294
+ token: data.tokenAddress,
295
+ type: type === 'FundsClaimed' ? 'claim' : 'transfer'
296
+ });
297
+ break;
298
+
299
+ case 'MemberAdded':
300
+ this._ensureNode(data.userId, 'user', data.userId);
301
+ break;
302
+ }
303
+ }
304
+
305
+ /**
306
+ * Ensure a node exists in the Sankey graph
307
+ */
308
+ _ensureNode(id, type, label) {
309
+ if (!this.sankeyNodes.has(id)) {
310
+ this.sankeyNodes.set(id, { id, type, label });
311
+ }
312
+ }
313
+
314
+ /**
315
+ * Get Sankey-compatible data for visualization
316
+ * @param {Object} options - Filter options
317
+ * @returns {Object} { nodes: [], links: [] }
318
+ */
319
+ getSankeyData(options = {}) {
320
+ const { tokenAddress, fromBlock, toBlock, minValue } = options;
321
+
322
+ let links = [...this.sankeyLinks];
323
+
324
+ // Filter by token
325
+ if (tokenAddress) {
326
+ links = links.filter(l => l.token === tokenAddress);
327
+ }
328
+
329
+ // Filter by minimum value
330
+ if (minValue) {
331
+ const minBigInt = BigInt(minValue);
332
+ links = links.filter(l => l.value >= minBigInt);
333
+ }
334
+
335
+ // Get unique node IDs from filtered links
336
+ const nodeIds = new Set();
337
+ links.forEach(l => {
338
+ nodeIds.add(l.source);
339
+ nodeIds.add(l.target);
340
+ });
341
+
342
+ // Convert nodes to array format
343
+ const nodeArray = [...nodeIds].map(id => {
344
+ const node = this.sankeyNodes.get(id) || { id, type: 'unknown', label: id };
345
+ return {
346
+ id: node.id,
347
+ name: node.label,
348
+ type: node.type
349
+ };
350
+ });
351
+
352
+ // Create node index for links
353
+ const nodeIndex = new Map();
354
+ nodeArray.forEach((n, i) => nodeIndex.set(n.id, i));
355
+
356
+ // Convert links to Sankey format with numeric indices
357
+ const sankeyLinks = links.map(l => ({
358
+ source: nodeIndex.get(l.source),
359
+ target: nodeIndex.get(l.target),
360
+ value: Number(l.value) / 1e18, // Convert from wei to ETH
361
+ type: l.type,
362
+ splitType: l.splitType,
363
+ distributionType: l.distributionType,
364
+ token: l.token
365
+ }));
366
+
367
+ return {
368
+ nodes: nodeArray,
369
+ links: sankeyLinks
370
+ };
371
+ }
372
+
373
+ /**
374
+ * Get aggregated flow summary
375
+ * @returns {Object} Summary statistics
376
+ */
377
+ getFlowSummary() {
378
+ const summary = {
379
+ totalInflow: 0n,
380
+ totalOutflow: 0n,
381
+ byHolon: {},
382
+ byUser: {},
383
+ byDistributionType: {
384
+ appreciation: 0n,
385
+ equal: 0n,
386
+ zone: 0n,
387
+ percentage: 0n,
388
+ peer_appreciation: 0n
389
+ }
390
+ };
391
+
392
+ for (const link of this.sankeyLinks) {
393
+ if (link.type === 'external_inflow') {
394
+ summary.totalInflow += link.value;
395
+ }
396
+ if (link.type === 'claim' || link.type === 'transfer') {
397
+ summary.totalOutflow += link.value;
398
+ }
399
+ if (link.distributionType && summary.byDistributionType[link.distributionType] !== undefined) {
400
+ summary.byDistributionType[link.distributionType] += link.value;
401
+ }
402
+ }
403
+
404
+ // Convert BigInt to strings for JSON serialization
405
+ return {
406
+ totalInflow: summary.totalInflow.toString(),
407
+ totalOutflow: summary.totalOutflow.toString(),
408
+ totalInflowEth: Number(summary.totalInflow) / 1e18,
409
+ totalOutflowEth: Number(summary.totalOutflow) / 1e18,
410
+ byDistributionType: Object.fromEntries(
411
+ Object.entries(summary.byDistributionType).map(([k, v]) => [k, v.toString()])
412
+ )
413
+ };
414
+ }
415
+
416
+ /**
417
+ * Query historical events from blockchain
418
+ * @param {Object} contract - ethers.js contract instance
419
+ * @param {string} eventName - Event name to query
420
+ * @param {Object} options - { fromBlock, toBlock }
421
+ */
422
+ async queryPastEvents(contract, eventName, options = {}) {
423
+ const { fromBlock = 0, toBlock = 'latest' } = options;
424
+
425
+ try {
426
+ const filter = contract.filters[eventName]?.();
427
+ if (!filter) return [];
428
+
429
+ const events = await contract.queryFilter(filter, fromBlock, toBlock);
430
+ return events.map(e => ({
431
+ type: eventName,
432
+ contractAddress: e.address,
433
+ blockNumber: e.blockNumber,
434
+ transactionHash: e.transactionHash,
435
+ data: this._parseEventData(eventName, e.args)
436
+ }));
437
+ } catch (e) {
438
+ console.error(`Error querying ${eventName}:`, e);
439
+ return [];
440
+ }
441
+ }
442
+
443
+ /**
444
+ * Build Sankey data from historical events
445
+ * @param {Object} contract - ethers.js contract instance
446
+ * @param {string} holonId - Holon identifier
447
+ * @param {Object} options - Query options
448
+ */
449
+ async buildFromHistory(contract, holonId, options = {}) {
450
+ const eventTypes = [
451
+ 'FundsReceived',
452
+ 'FundsCascaded',
453
+ 'FundsAllocated',
454
+ 'FundsClaimed',
455
+ 'FundsTransferred',
456
+ 'MemberAdded'
457
+ ];
458
+
459
+ for (const eventName of eventTypes) {
460
+ const events = await this.queryPastEvents(contract, eventName, options);
461
+ for (const event of events) {
462
+ event.holonId = holonId;
463
+ this.eventHistory.push(event);
464
+ this._updateSankeyData(event);
465
+ }
466
+ }
467
+
468
+ return this.getSankeyData();
469
+ }
470
+
471
+ /**
472
+ * Clear all stored data
473
+ */
474
+ clear() {
475
+ this.eventHistory = [];
476
+ this.sankeyNodes.clear();
477
+ this.sankeyLinks = [];
478
+ }
479
+
480
+ /**
481
+ * Export data for persistence
482
+ */
483
+ export() {
484
+ return {
485
+ events: this.eventHistory,
486
+ nodes: Object.fromEntries(this.sankeyNodes),
487
+ links: this.sankeyLinks.map(l => ({
488
+ ...l,
489
+ value: l.value.toString()
490
+ }))
491
+ };
492
+ }
493
+
494
+ /**
495
+ * Import previously exported data
496
+ */
497
+ import(data) {
498
+ this.eventHistory = data.events || [];
499
+ this.sankeyNodes = new Map(Object.entries(data.nodes || {}));
500
+ this.sankeyLinks = (data.links || []).map(l => ({
501
+ ...l,
502
+ value: BigInt(l.value)
503
+ }));
504
+ }
505
+ }
506
+
507
+ export default EventListener;