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.
- 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 +1 -1
- package/dist/esm/holosphere.js +50 -53
- 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-CMW4qRQS.js → indexeddb-storage-DZaGlY_a.js} +49 -13
- package/dist/indexeddb-storage-DZaGlY_a.js.map +1 -0
- package/dist/{memory-storage-DQzcAZlf.js → memory-storage-BkUi6sZG.js} +6 -2
- package/dist/memory-storage-BkUi6sZG.js.map +1 -0
- package/dist/{memory-storage-DmePEP2q.cjs → memory-storage-C0DuUsdY.cjs} +2 -2
- 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-vOXp40Fx.js → secp256k1-DN4FVXcv.js} +2 -393
- package/dist/secp256k1-DN4FVXcv.js.map +1 -0
- package/docs/CONTRACTS.md +797 -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/dist/index-CDfIuXew.js +0 -15974
- package/dist/index-CDfIuXew.js.map +0 -1
- package/dist/index-ifOgtDvd.cjs +0 -3
- package/dist/index-ifOgtDvd.cjs.map +0 -1
- package/dist/indexeddb-storage-CMW4qRQS.js.map +0 -1
- package/dist/indexeddb-storage-DLZOgetM.cjs +0 -2
- package/dist/indexeddb-storage-DLZOgetM.cjs.map +0 -1
- package/dist/memory-storage-DQzcAZlf.js.map +0 -1
- package/dist/memory-storage-DmePEP2q.cjs.map +0 -1
- package/dist/secp256k1-CP0ZkpAx.cjs +0 -13
- package/dist/secp256k1-CP0ZkpAx.cjs.map +0 -1
- package/dist/secp256k1-vOXp40Fx.js.map +0 -1
|
@@ -0,0 +1,589 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Contract Query Utilities
|
|
3
|
+
*
|
|
4
|
+
* Utility kit for directly querying contract state:
|
|
5
|
+
* zones, splits, appreciation, members, balances, etc.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { ethers } from 'ethers';
|
|
9
|
+
import { ContractABIs } from './index.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Helper to format wei to ETH
|
|
13
|
+
*/
|
|
14
|
+
function formatEth(wei) {
|
|
15
|
+
return ethers.formatEther(wei);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Helper to format wei to ETH as number
|
|
20
|
+
*/
|
|
21
|
+
function formatEthNumber(wei) {
|
|
22
|
+
return Number(ethers.formatEther(wei));
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* ContractQueries - Query utilities for all contract types
|
|
27
|
+
*/
|
|
28
|
+
export class ContractQueries {
|
|
29
|
+
/**
|
|
30
|
+
* @param {ethers.Provider} provider - ethers.js provider
|
|
31
|
+
*/
|
|
32
|
+
constructor(provider) {
|
|
33
|
+
this.provider = provider;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Get a contract instance with the appropriate ABI
|
|
38
|
+
* @param {string} address - Contract address
|
|
39
|
+
* @param {string} flavor - Contract flavor (Splitter, Managed, Zoned, Appreciative, Bundle)
|
|
40
|
+
* @returns {ethers.Contract}
|
|
41
|
+
*/
|
|
42
|
+
getContract(address, flavor) {
|
|
43
|
+
const abi = ContractABIs[flavor];
|
|
44
|
+
if (!abi) {
|
|
45
|
+
throw new Error(`Unknown contract flavor: ${flavor}`);
|
|
46
|
+
}
|
|
47
|
+
return new ethers.Contract(address, abi, this.provider);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Auto-detect contract flavor by calling flavor()
|
|
52
|
+
* @param {string} address - Contract address
|
|
53
|
+
* @returns {Promise<string>} Contract flavor
|
|
54
|
+
*/
|
|
55
|
+
async detectFlavor(address) {
|
|
56
|
+
// Try with a minimal ABI that has flavor()
|
|
57
|
+
const minAbi = [
|
|
58
|
+
'function flavor() view returns (string)',
|
|
59
|
+
'function version() view returns (string)'
|
|
60
|
+
];
|
|
61
|
+
const contract = new ethers.Contract(address, minAbi, this.provider);
|
|
62
|
+
try {
|
|
63
|
+
return await contract.flavor();
|
|
64
|
+
} catch {
|
|
65
|
+
return 'Unknown';
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// ==================== COMMON QUERIES ====================
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Get basic contract info
|
|
73
|
+
*/
|
|
74
|
+
async getContractInfo(address, flavor) {
|
|
75
|
+
const contract = this.getContract(address, flavor);
|
|
76
|
+
const [name, contractFlavor, version, creator, size] = await Promise.all([
|
|
77
|
+
contract.name().catch(() => ''),
|
|
78
|
+
contract.flavor().catch(() => flavor),
|
|
79
|
+
contract.version().catch(() => ''),
|
|
80
|
+
contract.creator().catch(() => ethers.ZeroAddress),
|
|
81
|
+
contract.getSize().catch(() => 0n)
|
|
82
|
+
]);
|
|
83
|
+
|
|
84
|
+
return {
|
|
85
|
+
address,
|
|
86
|
+
name,
|
|
87
|
+
flavor: contractFlavor,
|
|
88
|
+
version,
|
|
89
|
+
creator,
|
|
90
|
+
memberCount: Number(size)
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Get all members (userIds)
|
|
96
|
+
*/
|
|
97
|
+
async getMembers(address, flavor) {
|
|
98
|
+
const contract = this.getContract(address, flavor);
|
|
99
|
+
const size = await contract.getSize();
|
|
100
|
+
const members = [];
|
|
101
|
+
for (let i = 0; i < size; i++) {
|
|
102
|
+
const userId = await contract.userIds(i);
|
|
103
|
+
members.push(userId);
|
|
104
|
+
}
|
|
105
|
+
return members;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Get user's ETH balance
|
|
110
|
+
*/
|
|
111
|
+
async getUserEthBalance(address, flavor, userId) {
|
|
112
|
+
const contract = this.getContract(address, flavor);
|
|
113
|
+
const balance = await contract.etherBalance(userId);
|
|
114
|
+
return {
|
|
115
|
+
wei: balance.toString(),
|
|
116
|
+
eth: formatEthNumber(balance)
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Get user's token balance
|
|
122
|
+
*/
|
|
123
|
+
async getUserTokenBalance(address, flavor, userId, tokenAddress) {
|
|
124
|
+
const contract = this.getContract(address, flavor);
|
|
125
|
+
const balance = await contract.tokenBalance(userId, tokenAddress);
|
|
126
|
+
return {
|
|
127
|
+
wei: balance.toString(),
|
|
128
|
+
formatted: formatEthNumber(balance)
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Get total deposited for a token
|
|
134
|
+
*/
|
|
135
|
+
async getTotalDeposited(address, flavor, tokenAddress) {
|
|
136
|
+
const contract = this.getContract(address, flavor);
|
|
137
|
+
// For ETH, use address(0)
|
|
138
|
+
const token = tokenAddress || ethers.ZeroAddress;
|
|
139
|
+
const total = await contract.totalDeposited(token);
|
|
140
|
+
return {
|
|
141
|
+
wei: total.toString(),
|
|
142
|
+
formatted: formatEthNumber(total)
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Check if user has claimed
|
|
148
|
+
*/
|
|
149
|
+
async hasClaimed(address, flavor, userId) {
|
|
150
|
+
const contract = this.getContract(address, flavor);
|
|
151
|
+
return contract.hasClaimed(userId);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// ==================== SPLITTER QUERIES ====================
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Get Splitter's internal/external split configuration
|
|
158
|
+
*/
|
|
159
|
+
async getSplitterSplit(address) {
|
|
160
|
+
const contract = this.getContract(address, 'Splitter');
|
|
161
|
+
const [internal, external] = await Promise.all([
|
|
162
|
+
contract.internalContractSplitPercentage(),
|
|
163
|
+
contract.externalContractSplitPercentage()
|
|
164
|
+
]);
|
|
165
|
+
return {
|
|
166
|
+
internalPercentage: Number(internal),
|
|
167
|
+
externalPercentage: Number(external),
|
|
168
|
+
internalPercent: Number(internal) / 100,
|
|
169
|
+
externalPercent: Number(external) / 100
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Get Splitter's child contracts
|
|
175
|
+
*/
|
|
176
|
+
async getSplitterChildren(address) {
|
|
177
|
+
const contract = this.getContract(address, 'Splitter');
|
|
178
|
+
const [keys, addresses] = await contract.getContractAddresses();
|
|
179
|
+
const children = [];
|
|
180
|
+
for (let i = 0; i < keys.length; i++) {
|
|
181
|
+
children.push({
|
|
182
|
+
key: keys[i],
|
|
183
|
+
address: addresses[i]
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
return children;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Get user's percentage split in Splitter
|
|
191
|
+
*/
|
|
192
|
+
async getSplitterUserPercentage(address, userId) {
|
|
193
|
+
const contract = this.getContract(address, 'Splitter');
|
|
194
|
+
const pct = await contract.percentages(userId);
|
|
195
|
+
return {
|
|
196
|
+
basisPoints: Number(pct),
|
|
197
|
+
percent: Number(pct) / 100
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Get all member percentages in Splitter
|
|
203
|
+
*/
|
|
204
|
+
async getSplitterAllPercentages(address) {
|
|
205
|
+
const members = await this.getMembers(address, 'Splitter');
|
|
206
|
+
const contract = this.getContract(address, 'Splitter');
|
|
207
|
+
const results = [];
|
|
208
|
+
for (const userId of members) {
|
|
209
|
+
const pct = await contract.percentages(userId);
|
|
210
|
+
results.push({
|
|
211
|
+
userId,
|
|
212
|
+
basisPoints: Number(pct),
|
|
213
|
+
percent: Number(pct) / 100
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
return results;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// ==================== ZONED QUERIES ====================
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Get Zoned contract configuration
|
|
223
|
+
*/
|
|
224
|
+
async getZonedConfig(address) {
|
|
225
|
+
const contract = this.getContract(address, 'Zoned');
|
|
226
|
+
const [nzones, a, b, c] = await Promise.all([
|
|
227
|
+
contract.nzones(),
|
|
228
|
+
contract.a(),
|
|
229
|
+
contract.b(),
|
|
230
|
+
contract.c()
|
|
231
|
+
]);
|
|
232
|
+
return {
|
|
233
|
+
numberOfZones: Number(nzones),
|
|
234
|
+
rewardFunction: {
|
|
235
|
+
a: Number(a),
|
|
236
|
+
b: Number(b),
|
|
237
|
+
c: Number(c)
|
|
238
|
+
}
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Get user's zone assignment
|
|
244
|
+
*/
|
|
245
|
+
async getUserZone(address, userId) {
|
|
246
|
+
const contract = this.getContract(address, 'Zoned');
|
|
247
|
+
const zone = await contract.zone(userId);
|
|
248
|
+
return Number(zone);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Get all members in a specific zone
|
|
253
|
+
*/
|
|
254
|
+
async getZoneMembers(address, zoneNumber) {
|
|
255
|
+
const contract = this.getContract(address, 'Zoned');
|
|
256
|
+
return contract.getZoneMembers(zoneNumber);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Get complete zone breakdown
|
|
261
|
+
*/
|
|
262
|
+
async getZonedBreakdown(address) {
|
|
263
|
+
const config = await this.getZonedConfig(address);
|
|
264
|
+
const contract = this.getContract(address, 'Zoned');
|
|
265
|
+
const zones = [];
|
|
266
|
+
|
|
267
|
+
for (let z = 1; z <= config.numberOfZones; z++) {
|
|
268
|
+
const members = await contract.getZoneMembers(z);
|
|
269
|
+
zones.push({
|
|
270
|
+
zone: z,
|
|
271
|
+
members,
|
|
272
|
+
memberCount: members.length
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// Also get calculated rewards
|
|
277
|
+
const rewards = await contract.calculateRewards();
|
|
278
|
+
const rewardsByZone = rewards.map((r, i) => ({
|
|
279
|
+
zone: i + 1,
|
|
280
|
+
weight: Number(r)
|
|
281
|
+
}));
|
|
282
|
+
|
|
283
|
+
return {
|
|
284
|
+
config,
|
|
285
|
+
zones,
|
|
286
|
+
rewardWeights: rewardsByZone
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// ==================== MANAGED QUERIES ====================
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Get Managed contract appreciation info
|
|
294
|
+
*/
|
|
295
|
+
async getManagedAppreciation(address, userId) {
|
|
296
|
+
const contract = this.getContract(address, 'Managed');
|
|
297
|
+
const appreciation = await contract.appreciation(userId);
|
|
298
|
+
const totalAppreciation = await contract.totalappreciation();
|
|
299
|
+
return {
|
|
300
|
+
userAppreciation: Number(appreciation),
|
|
301
|
+
totalAppreciation: Number(totalAppreciation),
|
|
302
|
+
sharePercent: Number(totalAppreciation) > 0
|
|
303
|
+
? (Number(appreciation) / Number(totalAppreciation)) * 100
|
|
304
|
+
: 0
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Get all member appreciation in Managed contract
|
|
310
|
+
*/
|
|
311
|
+
async getManagedAllAppreciation(address) {
|
|
312
|
+
const members = await this.getMembers(address, 'Managed');
|
|
313
|
+
const contract = this.getContract(address, 'Managed');
|
|
314
|
+
const totalAppreciation = await contract.totalappreciation();
|
|
315
|
+
const maxAppreciation = await contract.maxAppreciation().catch(() => 0n);
|
|
316
|
+
|
|
317
|
+
const results = [];
|
|
318
|
+
for (const userId of members) {
|
|
319
|
+
const appreciation = await contract.appreciation(userId);
|
|
320
|
+
results.push({
|
|
321
|
+
userId,
|
|
322
|
+
appreciation: Number(appreciation),
|
|
323
|
+
sharePercent: Number(totalAppreciation) > 0
|
|
324
|
+
? (Number(appreciation) / Number(totalAppreciation)) * 100
|
|
325
|
+
: 0
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
return {
|
|
330
|
+
members: results,
|
|
331
|
+
totalAppreciation: Number(totalAppreciation),
|
|
332
|
+
maxAppreciation: Number(maxAppreciation)
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// ==================== APPRECIATIVE QUERIES ====================
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Get Appreciative contract peer appreciation
|
|
340
|
+
*/
|
|
341
|
+
async getAppreciativePeer(address, userId) {
|
|
342
|
+
const contract = this.getContract(address, 'Appreciative');
|
|
343
|
+
const [appreciation, remaining, totalAppreciation] = await Promise.all([
|
|
344
|
+
contract.appreciation(userId),
|
|
345
|
+
contract.remainingappreciation(userId),
|
|
346
|
+
contract.totalappreciation()
|
|
347
|
+
]);
|
|
348
|
+
return {
|
|
349
|
+
received: Number(appreciation),
|
|
350
|
+
remainingToGive: Number(remaining),
|
|
351
|
+
totalPool: Number(totalAppreciation),
|
|
352
|
+
sharePercent: Number(totalAppreciation) > 0
|
|
353
|
+
? (Number(appreciation) / Number(totalAppreciation)) * 100
|
|
354
|
+
: 0
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Get all peer appreciation in Appreciative contract
|
|
360
|
+
*/
|
|
361
|
+
async getAppreciativeAll(address) {
|
|
362
|
+
const members = await this.getMembers(address, 'Appreciative');
|
|
363
|
+
const contract = this.getContract(address, 'Appreciative');
|
|
364
|
+
const totalAppreciation = await contract.totalappreciation();
|
|
365
|
+
|
|
366
|
+
const results = [];
|
|
367
|
+
for (const userId of members) {
|
|
368
|
+
const [appreciation, remaining] = await Promise.all([
|
|
369
|
+
contract.appreciation(userId),
|
|
370
|
+
contract.remainingappreciation(userId)
|
|
371
|
+
]);
|
|
372
|
+
results.push({
|
|
373
|
+
userId,
|
|
374
|
+
received: Number(appreciation),
|
|
375
|
+
remainingToGive: Number(remaining),
|
|
376
|
+
sharePercent: Number(totalAppreciation) > 0
|
|
377
|
+
? (Number(appreciation) / Number(totalAppreciation)) * 100
|
|
378
|
+
: 0
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
return {
|
|
383
|
+
members: results,
|
|
384
|
+
totalAppreciation: Number(totalAppreciation)
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// ==================== BUNDLE QUERIES ====================
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Get Bundle contract configuration
|
|
392
|
+
*/
|
|
393
|
+
async getBundleConfig(address) {
|
|
394
|
+
const contract = this.getContract(address, 'Bundle');
|
|
395
|
+
const [steepness, nzones, interiorPct, exteriorPct, electionActive] = await Promise.all([
|
|
396
|
+
contract.steepness(),
|
|
397
|
+
contract.nzones(),
|
|
398
|
+
contract.interiorPercentage(),
|
|
399
|
+
contract.exteriorPercentage(),
|
|
400
|
+
contract.electionActive()
|
|
401
|
+
]);
|
|
402
|
+
|
|
403
|
+
return {
|
|
404
|
+
steepness: Number(steepness),
|
|
405
|
+
numberOfZones: Number(nzones),
|
|
406
|
+
interiorPercentage: Number(interiorPct) / 100, // Basis points to percent
|
|
407
|
+
exteriorPercentage: Number(exteriorPct) / 100,
|
|
408
|
+
electionActive
|
|
409
|
+
};
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* Get Bundle interior/exterior split
|
|
414
|
+
*/
|
|
415
|
+
async getBundleSplit(address) {
|
|
416
|
+
const contract = this.getContract(address, 'Bundle');
|
|
417
|
+
const [interior, exterior] = await Promise.all([
|
|
418
|
+
contract.interiorPercentage(),
|
|
419
|
+
contract.exteriorPercentage()
|
|
420
|
+
]);
|
|
421
|
+
return {
|
|
422
|
+
interiorBasisPoints: Number(interior),
|
|
423
|
+
exteriorBasisPoints: Number(exterior),
|
|
424
|
+
interiorPercent: Number(interior) / 100,
|
|
425
|
+
exteriorPercent: Number(exterior) / 100
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
/**
|
|
430
|
+
* Get Bundle zone weights
|
|
431
|
+
*/
|
|
432
|
+
async getBundleZoneWeights(address) {
|
|
433
|
+
const contract = this.getContract(address, 'Bundle');
|
|
434
|
+
const weights = await contract.getZoneWeights();
|
|
435
|
+
return weights.map((w, i) => ({
|
|
436
|
+
zone: i + 1,
|
|
437
|
+
weight: Number(w)
|
|
438
|
+
}));
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
/**
|
|
442
|
+
* Get Bundle user's zone and interior share
|
|
443
|
+
*/
|
|
444
|
+
async getBundleUserInfo(address, userId) {
|
|
445
|
+
const contract = this.getContract(address, 'Bundle');
|
|
446
|
+
const [zone, interiorShare, isInterior, isExterior, isMember] = await Promise.all([
|
|
447
|
+
contract.zone(userId),
|
|
448
|
+
contract.interiorShare(userId),
|
|
449
|
+
contract.isInteriorMember(userId),
|
|
450
|
+
contract.isExteriorMember(userId),
|
|
451
|
+
contract.isBundleMember(userId)
|
|
452
|
+
]);
|
|
453
|
+
return {
|
|
454
|
+
zone: Number(zone),
|
|
455
|
+
interiorShareBasisPoints: Number(interiorShare),
|
|
456
|
+
interiorSharePercent: Number(interiorShare) / 100,
|
|
457
|
+
isInteriorMember: isInterior,
|
|
458
|
+
isExteriorMember: isExterior,
|
|
459
|
+
isMember
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
/**
|
|
464
|
+
* Get Bundle interior members
|
|
465
|
+
*/
|
|
466
|
+
async getBundleInteriorMembers(address) {
|
|
467
|
+
const contract = this.getContract(address, 'Bundle');
|
|
468
|
+
return contract.getInteriorMembers();
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
/**
|
|
472
|
+
* Get Bundle zone breakdown (exterior)
|
|
473
|
+
*/
|
|
474
|
+
async getBundleZoneBreakdown(address) {
|
|
475
|
+
const config = await this.getBundleConfig(address);
|
|
476
|
+
const contract = this.getContract(address, 'Bundle');
|
|
477
|
+
const zones = [];
|
|
478
|
+
|
|
479
|
+
for (let z = 1; z <= config.numberOfZones; z++) {
|
|
480
|
+
const members = await contract.getZoneMembers(z);
|
|
481
|
+
zones.push({
|
|
482
|
+
zone: z,
|
|
483
|
+
members,
|
|
484
|
+
memberCount: members.length
|
|
485
|
+
});
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
return {
|
|
489
|
+
config,
|
|
490
|
+
zones,
|
|
491
|
+
zoneWeights: await this.getBundleZoneWeights(address)
|
|
492
|
+
};
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
/**
|
|
496
|
+
* Get Bundle election info
|
|
497
|
+
*/
|
|
498
|
+
async getBundleElection(address) {
|
|
499
|
+
const contract = this.getContract(address, 'Bundle');
|
|
500
|
+
const [electionActive, candidates] = await Promise.all([
|
|
501
|
+
contract.electionActive(),
|
|
502
|
+
contract.getCandidates()
|
|
503
|
+
]);
|
|
504
|
+
|
|
505
|
+
if (!electionActive) {
|
|
506
|
+
return { active: false, candidates: [] };
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
const candidateInfo = [];
|
|
510
|
+
for (const candidate of candidates) {
|
|
511
|
+
const votes = await contract.votes(candidate);
|
|
512
|
+
candidateInfo.push({
|
|
513
|
+
userId: candidate,
|
|
514
|
+
votes: Number(votes)
|
|
515
|
+
});
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
return {
|
|
519
|
+
active: true,
|
|
520
|
+
candidates: candidateInfo.sort((a, b) => b.votes - a.votes)
|
|
521
|
+
};
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
// ==================== FULL SNAPSHOT ====================
|
|
525
|
+
|
|
526
|
+
/**
|
|
527
|
+
* Get complete contract state snapshot
|
|
528
|
+
*/
|
|
529
|
+
async getFullSnapshot(address) {
|
|
530
|
+
const flavor = await this.detectFlavor(address);
|
|
531
|
+
const info = await this.getContractInfo(address, flavor);
|
|
532
|
+
const members = await this.getMembers(address, flavor);
|
|
533
|
+
|
|
534
|
+
const snapshot = {
|
|
535
|
+
...info,
|
|
536
|
+
members,
|
|
537
|
+
memberDetails: []
|
|
538
|
+
};
|
|
539
|
+
|
|
540
|
+
// Get member-specific details
|
|
541
|
+
for (const userId of members) {
|
|
542
|
+
const balance = await this.getUserEthBalance(address, flavor, userId);
|
|
543
|
+
const claimed = await this.hasClaimed(address, flavor, userId);
|
|
544
|
+
|
|
545
|
+
const memberDetail = {
|
|
546
|
+
userId,
|
|
547
|
+
ethBalance: balance,
|
|
548
|
+
hasClaimed: claimed
|
|
549
|
+
};
|
|
550
|
+
|
|
551
|
+
// Flavor-specific details
|
|
552
|
+
if (flavor === 'Splitter') {
|
|
553
|
+
const pct = await this.getSplitterUserPercentage(address, userId);
|
|
554
|
+
memberDetail.percentage = pct;
|
|
555
|
+
} else if (flavor === 'Zoned') {
|
|
556
|
+
memberDetail.zone = await this.getUserZone(address, userId);
|
|
557
|
+
} else if (flavor === 'Managed') {
|
|
558
|
+
memberDetail.appreciation = await this.getManagedAppreciation(address, userId);
|
|
559
|
+
} else if (flavor === 'Appreciative') {
|
|
560
|
+
memberDetail.appreciation = await this.getAppreciativePeer(address, userId);
|
|
561
|
+
} else if (flavor === 'Bundle') {
|
|
562
|
+
memberDetail.bundleInfo = await this.getBundleUserInfo(address, userId);
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
snapshot.memberDetails.push(memberDetail);
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
// Add flavor-specific configuration
|
|
569
|
+
if (flavor === 'Splitter') {
|
|
570
|
+
snapshot.split = await this.getSplitterSplit(address);
|
|
571
|
+
snapshot.children = await this.getSplitterChildren(address);
|
|
572
|
+
} else if (flavor === 'Zoned') {
|
|
573
|
+
snapshot.zoneConfig = await this.getZonedBreakdown(address);
|
|
574
|
+
} else if (flavor === 'Managed') {
|
|
575
|
+
snapshot.appreciationSummary = await this.getManagedAllAppreciation(address);
|
|
576
|
+
} else if (flavor === 'Appreciative') {
|
|
577
|
+
snapshot.appreciationSummary = await this.getAppreciativeAll(address);
|
|
578
|
+
} else if (flavor === 'Bundle') {
|
|
579
|
+
snapshot.bundleConfig = await this.getBundleConfig(address);
|
|
580
|
+
snapshot.bundleSplit = await this.getBundleSplit(address);
|
|
581
|
+
snapshot.bundleZones = await this.getBundleZoneBreakdown(address);
|
|
582
|
+
snapshot.election = await this.getBundleElection(address);
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
return snapshot;
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
export default ContractQueries;
|