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,344 @@
1
+ /**
2
+ * HolonContracts - Per-holon contract management
3
+ * Links holons to their smart contracts for fractal fund distribution
4
+ */
5
+
6
+ import { ContractDeployer, ABIs } from './deployer.js';
7
+ import { ContractOperations } from './operations.js';
8
+
9
+ export class HolonContracts {
10
+ constructor(chainManager, deployer) {
11
+ this.chainManager = chainManager;
12
+ this.deployer = deployer || new ContractDeployer(chainManager);
13
+
14
+ // Maps holonId -> { address, type, contract, operations }
15
+ this.holonContracts = new Map();
16
+
17
+ // Storage for persistence (can be overridden)
18
+ this.storage = null;
19
+ }
20
+
21
+ /**
22
+ * Set storage adapter for persisting holon-contract mappings
23
+ * @param {Object} storage - Storage adapter with get/set methods
24
+ */
25
+ setStorage(storage) {
26
+ this.storage = storage;
27
+ }
28
+
29
+ /**
30
+ * Deploy a new contract for a holon
31
+ * @param {string} holonId - Holon identifier
32
+ * @param {string} [type='Splitter'] - Contract type (Splitter, Managed, Zoned, Appreciative, Bundle)
33
+ * @param {Object} [options] - Deployment options
34
+ * @returns {Promise<{contract, address, operations}>}
35
+ */
36
+ async deploy(holonId, type = 'Splitter', options = {}) {
37
+ if (this.holonContracts.has(holonId)) {
38
+ throw new Error(`Holon ${holonId} already has a contract. Use unlink() first to remove it.`);
39
+ }
40
+
41
+ const name = options.name || holonId;
42
+ const creatorUserId = options.creatorUserId || holonId;
43
+ let result;
44
+
45
+ switch (type) {
46
+ case 'Splitter':
47
+ result = await this.deployer.deploySplitter(
48
+ holonId,
49
+ name,
50
+ options.splitPercentage || 70,
51
+ { creatorUserId, ...options }
52
+ );
53
+ break;
54
+
55
+ case 'Managed':
56
+ result = await this.deployer.deployManaged(name, options);
57
+ break;
58
+
59
+ case 'Zoned':
60
+ result = await this.deployer.deployZoned(name, options.nZones || 6, options);
61
+ break;
62
+
63
+ case 'Appreciative':
64
+ result = await this.deployer.deployAppreciative(name, creatorUserId, options);
65
+ break;
66
+
67
+ case 'Bundle':
68
+ result = await this.deployer.deployBundle(
69
+ name,
70
+ options.steepness,
71
+ options.nZones || 6,
72
+ { creatorUserId, ...options }
73
+ );
74
+ break;
75
+
76
+ default:
77
+ throw new Error(`Unknown contract type: ${type}`);
78
+ }
79
+
80
+ // Create operations wrapper
81
+ const operations = new ContractOperations(result.contract, type, this.chainManager);
82
+
83
+ // Store mapping
84
+ const holonData = {
85
+ holonId,
86
+ address: result.address,
87
+ type,
88
+ contract: result.contract,
89
+ operations,
90
+ deployedAt: new Date().toISOString(),
91
+ txHash: result.txHash
92
+ };
93
+
94
+ this.holonContracts.set(holonId, holonData);
95
+
96
+ // Persist if storage available
97
+ await this._saveMapping(holonId, holonData);
98
+
99
+ return {
100
+ contract: result.contract,
101
+ address: result.address,
102
+ operations,
103
+ txHash: result.txHash,
104
+ type
105
+ };
106
+ }
107
+
108
+ /**
109
+ * Link a holon to an existing contract
110
+ * @param {string} holonId - Holon identifier
111
+ * @param {string} contractAddress - Existing contract address
112
+ * @param {string} [type='Splitter'] - Contract type
113
+ * @returns {Promise<{contract, address, operations}>}
114
+ */
115
+ async link(holonId, contractAddress, type = 'Splitter') {
116
+ if (this.holonContracts.has(holonId)) {
117
+ throw new Error(`Holon ${holonId} already has a contract. Use unlink() first.`);
118
+ }
119
+
120
+ const abi = ABIs[type];
121
+ if (!abi) {
122
+ throw new Error(`Unknown contract type: ${type}`);
123
+ }
124
+
125
+ // Create contract instance
126
+ const contract = await this.chainManager.getContract(contractAddress, abi.abi);
127
+
128
+ // Verify it's a valid contract by calling a read method
129
+ try {
130
+ await contract.name();
131
+ } catch (error) {
132
+ throw new Error(`Invalid contract at ${contractAddress}: ${error.message}`);
133
+ }
134
+
135
+ // Create operations wrapper
136
+ const operations = new ContractOperations(contract, type, this.chainManager);
137
+
138
+ // Store mapping
139
+ const holonData = {
140
+ holonId,
141
+ address: contractAddress,
142
+ type,
143
+ contract,
144
+ operations,
145
+ linkedAt: new Date().toISOString()
146
+ };
147
+
148
+ this.holonContracts.set(holonId, holonData);
149
+
150
+ // Persist if storage available
151
+ await this._saveMapping(holonId, holonData);
152
+
153
+ return {
154
+ contract,
155
+ address: contractAddress,
156
+ operations,
157
+ type
158
+ };
159
+ }
160
+
161
+ /**
162
+ * Unlink a holon from its contract
163
+ * @param {string} holonId - Holon identifier
164
+ * @returns {boolean} True if unlinked, false if no contract was linked
165
+ */
166
+ async unlink(holonId) {
167
+ if (!this.holonContracts.has(holonId)) {
168
+ return false;
169
+ }
170
+
171
+ this.holonContracts.delete(holonId);
172
+
173
+ // Remove from storage if available
174
+ if (this.storage) {
175
+ await this.storage.delete?.(`holon_contract:${holonId}`);
176
+ }
177
+
178
+ return true;
179
+ }
180
+
181
+ /**
182
+ * Get contract for a holon
183
+ * @param {string} holonId - Holon identifier
184
+ * @returns {Contract|null}
185
+ */
186
+ getContract(holonId) {
187
+ const data = this.holonContracts.get(holonId);
188
+ return data?.contract || null;
189
+ }
190
+
191
+ /**
192
+ * Get contract address for a holon
193
+ * @param {string} holonId - Holon identifier
194
+ * @returns {string|null}
195
+ */
196
+ getAddress(holonId) {
197
+ const data = this.holonContracts.get(holonId);
198
+ return data?.address || null;
199
+ }
200
+
201
+ /**
202
+ * Get operations wrapper for a holon
203
+ * @param {string} holonId - Holon identifier
204
+ * @returns {ContractOperations|null}
205
+ */
206
+ getOperations(holonId) {
207
+ const data = this.holonContracts.get(holonId);
208
+ return data?.operations || null;
209
+ }
210
+
211
+ /**
212
+ * Get contract type for a holon
213
+ * @param {string} holonId - Holon identifier
214
+ * @returns {string|null}
215
+ */
216
+ getType(holonId) {
217
+ const data = this.holonContracts.get(holonId);
218
+ return data?.type || null;
219
+ }
220
+
221
+ /**
222
+ * Check if a holon has a contract
223
+ * @param {string} holonId - Holon identifier
224
+ * @returns {boolean}
225
+ */
226
+ hasContract(holonId) {
227
+ return this.holonContracts.has(holonId);
228
+ }
229
+
230
+ /**
231
+ * Get all holon-contract mappings
232
+ * @returns {Array<{holonId, address, type}>}
233
+ */
234
+ listAll() {
235
+ const result = [];
236
+ for (const [holonId, data] of this.holonContracts) {
237
+ result.push({
238
+ holonId,
239
+ address: data.address,
240
+ type: data.type,
241
+ deployedAt: data.deployedAt,
242
+ linkedAt: data.linkedAt
243
+ });
244
+ }
245
+ return result;
246
+ }
247
+
248
+ /**
249
+ * Get holons by contract type
250
+ * @param {string} type - Contract type
251
+ * @returns {Array<{holonId, address}>}
252
+ */
253
+ getByType(type) {
254
+ const result = [];
255
+ for (const [holonId, data] of this.holonContracts) {
256
+ if (data.type === type) {
257
+ result.push({
258
+ holonId,
259
+ address: data.address
260
+ });
261
+ }
262
+ }
263
+ return result;
264
+ }
265
+
266
+ /**
267
+ * Load holon-contract mappings from storage
268
+ * @returns {Promise<number>} Number of mappings loaded
269
+ */
270
+ async loadFromStorage() {
271
+ if (!this.storage) {
272
+ return 0;
273
+ }
274
+
275
+ const mappings = await this.storage.get?.('holon_contracts_index') || [];
276
+ let loaded = 0;
277
+
278
+ for (const holonId of mappings) {
279
+ try {
280
+ const data = await this.storage.get?.(`holon_contract:${holonId}`);
281
+ if (data && data.address && data.type) {
282
+ // Recreate contract instance
283
+ const abi = ABIs[data.type];
284
+ if (abi) {
285
+ const contract = await this.chainManager.getContract(data.address, abi.abi);
286
+ const operations = new ContractOperations(contract, data.type, this.chainManager);
287
+
288
+ this.holonContracts.set(holonId, {
289
+ ...data,
290
+ contract,
291
+ operations
292
+ });
293
+ loaded++;
294
+ }
295
+ }
296
+ } catch (error) {
297
+ console.warn(`Failed to load contract for holon ${holonId}: ${error.message}`);
298
+ }
299
+ }
300
+
301
+ return loaded;
302
+ }
303
+
304
+ /**
305
+ * Save a holon-contract mapping to storage
306
+ * @private
307
+ */
308
+ async _saveMapping(holonId, data) {
309
+ if (!this.storage) return;
310
+
311
+ // Save the mapping (without contract/operations which can't be serialized)
312
+ await this.storage.set?.(`holon_contract:${holonId}`, {
313
+ holonId: data.holonId,
314
+ address: data.address,
315
+ type: data.type,
316
+ deployedAt: data.deployedAt,
317
+ linkedAt: data.linkedAt,
318
+ txHash: data.txHash
319
+ });
320
+
321
+ // Update index
322
+ const index = await this.storage.get?.('holon_contracts_index') || [];
323
+ if (!index.includes(holonId)) {
324
+ index.push(holonId);
325
+ await this.storage.set?.('holon_contracts_index', index);
326
+ }
327
+ }
328
+
329
+ /**
330
+ * Get required holon operations (throws if not linked)
331
+ * @param {string} holonId - Holon identifier
332
+ * @returns {ContractOperations}
333
+ * @throws {Error} If holon has no contract
334
+ */
335
+ requireOperations(holonId) {
336
+ const ops = this.getOperations(holonId);
337
+ if (!ops) {
338
+ throw new Error(`Holon ${holonId} has no linked contract. Deploy or link one first.`);
339
+ }
340
+ return ops;
341
+ }
342
+ }
343
+
344
+ export default HolonContracts;
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Holosphere Contracts Module
3
+ * Smart contract integration for fractal fund distribution
4
+ *
5
+ * @module contracts
6
+ */
7
+
8
+ // Core classes
9
+ export { ChainManager } from './chain-manager.js';
10
+ export { ContractDeployer, ABIs } from './deployer.js';
11
+ export { HolonContracts } from './holon-contracts.js';
12
+ export { ContractOperations } from './operations.js';
13
+ export { EventListener, SANKEY_EVENTS } from './event-listener.js';
14
+ export { ContractQueries } from './queries.js';
15
+
16
+ // Network utilities
17
+ export {
18
+ NETWORKS,
19
+ getNetwork,
20
+ getNetworksByType,
21
+ listNetworks,
22
+ isNetworkSupported,
23
+ getTxUrl,
24
+ getAddressUrl
25
+ } from './networks.js';
26
+
27
+ // Re-export ABIs for direct access
28
+ import SplitterABI from './abis/Splitter.json' with { type: 'json' };
29
+ import ManagedABI from './abis/Managed.json' with { type: 'json' };
30
+ import ZonedABI from './abis/Zoned.json' with { type: 'json' };
31
+ import AppreciativeABI from './abis/Appreciative.json' with { type: 'json' };
32
+ import BundleABI from './abis/Bundle.json' with { type: 'json' };
33
+ import HolonsABI from './abis/Holons.json' with { type: 'json' };
34
+ import TestTokenABI from './abis/TestToken.json' with { type: 'json' };
35
+
36
+ export const ContractABIs = {
37
+ Splitter: SplitterABI,
38
+ Managed: ManagedABI,
39
+ Zoned: ZonedABI,
40
+ Appreciative: AppreciativeABI,
41
+ Bundle: BundleABI,
42
+ Holons: HolonsABI,
43
+ TestToken: TestTokenABI
44
+ };
45
+
46
+ // Import for default export
47
+ import { ChainManager } from './chain-manager.js';
48
+ import { ContractDeployer } from './deployer.js';
49
+ import { HolonContracts } from './holon-contracts.js';
50
+ import { ContractOperations } from './operations.js';
51
+ import { EventListener, SANKEY_EVENTS } from './event-listener.js';
52
+ import { ContractQueries } from './queries.js';
53
+ import { NETWORKS } from './networks.js';
54
+
55
+ /**
56
+ * Create a complete contracts module instance
57
+ * @param {Object} [config] - Configuration options
58
+ * @returns {Promise<Object>} Contracts module with all components
59
+ */
60
+ export async function createContractsModule(config = {}) {
61
+ const chainManager = new ChainManager(config);
62
+ const deployer = new ContractDeployer(chainManager);
63
+ const holonContracts = new HolonContracts(chainManager, deployer);
64
+
65
+ return {
66
+ chainManager,
67
+ deployer,
68
+ holonContracts
69
+ };
70
+ }
71
+
72
+ export default {
73
+ ChainManager,
74
+ ContractDeployer,
75
+ HolonContracts,
76
+ ContractOperations,
77
+ EventListener,
78
+ ContractQueries,
79
+ SANKEY_EVENTS,
80
+ NETWORKS,
81
+ ABIs: ContractABIs,
82
+ createContractsModule
83
+ };
@@ -0,0 +1,224 @@
1
+ /**
2
+ * Multi-chain network configurations for Holosphere contracts
3
+ * Supports Ethereum, Polygon, Arbitrum, Base, Optimism and testnets
4
+ */
5
+
6
+ export const NETWORKS = {
7
+ // ========== MAINNETS ==========
8
+ ethereum: {
9
+ name: 'Ethereum Mainnet',
10
+ chainId: 1,
11
+ rpc: 'https://eth.llamarpc.com',
12
+ explorer: 'https://etherscan.io',
13
+ currency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
14
+ type: 'mainnet'
15
+ },
16
+ polygon: {
17
+ name: 'Polygon Mainnet',
18
+ chainId: 137,
19
+ rpc: 'https://polygon-rpc.com',
20
+ explorer: 'https://polygonscan.com',
21
+ currency: { name: 'MATIC', symbol: 'MATIC', decimals: 18 },
22
+ type: 'mainnet'
23
+ },
24
+ arbitrum: {
25
+ name: 'Arbitrum One',
26
+ chainId: 42161,
27
+ rpc: 'https://arb1.arbitrum.io/rpc',
28
+ explorer: 'https://arbiscan.io',
29
+ currency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
30
+ type: 'mainnet'
31
+ },
32
+ base: {
33
+ name: 'Base',
34
+ chainId: 8453,
35
+ rpc: 'https://mainnet.base.org',
36
+ explorer: 'https://basescan.org',
37
+ currency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
38
+ type: 'mainnet'
39
+ },
40
+ optimism: {
41
+ name: 'Optimism',
42
+ chainId: 10,
43
+ rpc: 'https://mainnet.optimism.io',
44
+ explorer: 'https://optimistic.etherscan.io',
45
+ currency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
46
+ type: 'mainnet'
47
+ },
48
+ avalanche: {
49
+ name: 'Avalanche C-Chain',
50
+ chainId: 43114,
51
+ rpc: 'https://api.avax.network/ext/bc/C/rpc',
52
+ explorer: 'https://snowtrace.io',
53
+ currency: { name: 'AVAX', symbol: 'AVAX', decimals: 18 },
54
+ type: 'mainnet'
55
+ },
56
+ bsc: {
57
+ name: 'BNB Smart Chain',
58
+ chainId: 56,
59
+ rpc: 'https://bsc-dataseed.binance.org',
60
+ explorer: 'https://bscscan.com',
61
+ currency: { name: 'BNB', symbol: 'BNB', decimals: 18 },
62
+ type: 'mainnet'
63
+ },
64
+
65
+ // ========== TESTNETS ==========
66
+ sepolia: {
67
+ name: 'Sepolia',
68
+ chainId: 11155111,
69
+ rpc: 'https://rpc.sepolia.org',
70
+ explorer: 'https://sepolia.etherscan.io',
71
+ currency: { name: 'Sepolia ETH', symbol: 'ETH', decimals: 18 },
72
+ type: 'testnet',
73
+ faucet: 'https://sepoliafaucet.com'
74
+ },
75
+ goerli: {
76
+ name: 'Goerli',
77
+ chainId: 5,
78
+ rpc: 'https://rpc.goerli.eth.gateway.fm',
79
+ explorer: 'https://goerli.etherscan.io',
80
+ currency: { name: 'Goerli ETH', symbol: 'ETH', decimals: 18 },
81
+ type: 'testnet',
82
+ faucet: 'https://goerlifaucet.com'
83
+ },
84
+ mumbai: {
85
+ name: 'Polygon Mumbai',
86
+ chainId: 80001,
87
+ rpc: 'https://rpc-mumbai.maticvigil.com',
88
+ explorer: 'https://mumbai.polygonscan.com',
89
+ currency: { name: 'MATIC', symbol: 'MATIC', decimals: 18 },
90
+ type: 'testnet',
91
+ faucet: 'https://faucet.polygon.technology'
92
+ },
93
+ amoy: {
94
+ name: 'Polygon Amoy',
95
+ chainId: 80002,
96
+ rpc: 'https://rpc-amoy.polygon.technology',
97
+ explorer: 'https://amoy.polygonscan.com',
98
+ currency: { name: 'MATIC', symbol: 'MATIC', decimals: 18 },
99
+ type: 'testnet',
100
+ faucet: 'https://faucet.polygon.technology'
101
+ },
102
+ arbitrumSepolia: {
103
+ name: 'Arbitrum Sepolia',
104
+ chainId: 421614,
105
+ rpc: 'https://sepolia-rollup.arbitrum.io/rpc',
106
+ explorer: 'https://sepolia.arbiscan.io',
107
+ currency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
108
+ type: 'testnet'
109
+ },
110
+ baseSepolia: {
111
+ name: 'Base Sepolia',
112
+ chainId: 84532,
113
+ rpc: 'https://sepolia.base.org',
114
+ explorer: 'https://sepolia.basescan.org',
115
+ currency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
116
+ type: 'testnet'
117
+ },
118
+ optimismSepolia: {
119
+ name: 'Optimism Sepolia',
120
+ chainId: 11155420,
121
+ rpc: 'https://sepolia.optimism.io',
122
+ explorer: 'https://sepolia-optimism.etherscan.io',
123
+ currency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
124
+ type: 'testnet'
125
+ },
126
+
127
+ // ========== LOCAL ==========
128
+ hardhat: {
129
+ name: 'Hardhat Local',
130
+ chainId: 31337,
131
+ rpc: 'http://127.0.0.1:8545',
132
+ explorer: null,
133
+ currency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
134
+ type: 'local'
135
+ },
136
+ anvil: {
137
+ name: 'Anvil Local',
138
+ chainId: 31337,
139
+ rpc: 'http://127.0.0.1:8545',
140
+ explorer: null,
141
+ currency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
142
+ type: 'local'
143
+ },
144
+ ganache: {
145
+ name: 'Ganache Local',
146
+ chainId: 1337,
147
+ rpc: 'http://127.0.0.1:7545',
148
+ explorer: null,
149
+ currency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
150
+ type: 'local'
151
+ }
152
+ };
153
+
154
+ /**
155
+ * Get network configuration by name or chain ID
156
+ * @param {string|number} networkOrChainId - Network name or chain ID
157
+ * @returns {Object|null} Network configuration or null if not found
158
+ */
159
+ export function getNetwork(networkOrChainId) {
160
+ if (typeof networkOrChainId === 'string') {
161
+ return NETWORKS[networkOrChainId] || null;
162
+ }
163
+ // Search by chain ID
164
+ for (const [name, config] of Object.entries(NETWORKS)) {
165
+ if (config.chainId === networkOrChainId) {
166
+ return { ...config, key: name };
167
+ }
168
+ }
169
+ return null;
170
+ }
171
+
172
+ /**
173
+ * Get all networks of a specific type
174
+ * @param {'mainnet'|'testnet'|'local'} type - Network type
175
+ * @returns {Object} Networks of the specified type
176
+ */
177
+ export function getNetworksByType(type) {
178
+ return Object.fromEntries(
179
+ Object.entries(NETWORKS).filter(([_, config]) => config.type === type)
180
+ );
181
+ }
182
+
183
+ /**
184
+ * List all available network names
185
+ * @returns {string[]} Array of network names
186
+ */
187
+ export function listNetworks() {
188
+ return Object.keys(NETWORKS);
189
+ }
190
+
191
+ /**
192
+ * Check if a network is supported
193
+ * @param {string} network - Network name
194
+ * @returns {boolean}
195
+ */
196
+ export function isNetworkSupported(network) {
197
+ return network in NETWORKS;
198
+ }
199
+
200
+ /**
201
+ * Get explorer URL for a transaction
202
+ * @param {string} network - Network name
203
+ * @param {string} txHash - Transaction hash
204
+ * @returns {string|null} Explorer URL or null
205
+ */
206
+ export function getTxUrl(network, txHash) {
207
+ const config = NETWORKS[network];
208
+ if (!config?.explorer) return null;
209
+ return `${config.explorer}/tx/${txHash}`;
210
+ }
211
+
212
+ /**
213
+ * Get explorer URL for an address
214
+ * @param {string} network - Network name
215
+ * @param {string} address - Contract or wallet address
216
+ * @returns {string|null} Explorer URL or null
217
+ */
218
+ export function getAddressUrl(network, address) {
219
+ const config = NETWORKS[network];
220
+ if (!config?.explorer) return null;
221
+ return `${config.explorer}/address/${address}`;
222
+ }
223
+
224
+ export default NETWORKS;