@stabilitydao/host 0.2.1 → 0.2.2

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 (62) hide show
  1. package/out/activity/builder.d.ts +135 -0
  2. package/out/activity/builder.d.ts.map +1 -0
  3. package/out/activity/builder.js +17 -0
  4. package/out/activity/builder.js.map +1 -0
  5. package/out/activity/index.d.ts +18 -0
  6. package/out/activity/index.d.ts.map +1 -0
  7. package/out/activity/index.js +31 -0
  8. package/out/activity/index.js.map +1 -0
  9. package/out/agents.d.ts +21 -0
  10. package/out/agents.d.ts.map +1 -0
  11. package/out/agents.js +16 -0
  12. package/out/agents.js.map +1 -0
  13. package/out/api.d.ts +47 -0
  14. package/out/api.d.ts.map +1 -0
  15. package/out/api.js +3 -0
  16. package/out/api.js.map +1 -0
  17. package/out/assets.d.ts +13 -0
  18. package/out/assets.d.ts.map +1 -0
  19. package/out/assets.js +1515 -0
  20. package/out/assets.js.map +1 -0
  21. package/out/chains.d.ts +105 -0
  22. package/out/chains.d.ts.map +1 -0
  23. package/out/chains.js +591 -0
  24. package/out/chains.js.map +1 -0
  25. package/out/host.d.ts +407 -0
  26. package/out/host.d.ts.map +1 -0
  27. package/out/host.js +765 -0
  28. package/out/host.js.map +1 -0
  29. package/out/index.d.ts +10 -0
  30. package/out/index.d.ts.map +1 -0
  31. package/out/index.js.map +1 -0
  32. package/out/storage/daoMetaData.d.ts +5 -0
  33. package/out/storage/daoMetaData.d.ts.map +1 -0
  34. package/out/storage/daoMetaData.js +311 -0
  35. package/out/storage/daoMetaData.js.map +1 -0
  36. package/out/storage/daos.d.ts +3 -0
  37. package/out/storage/daos.d.ts.map +1 -0
  38. package/out/storage/daos.js +303 -0
  39. package/out/storage/daos.js.map +1 -0
  40. package/package.json +7 -1
  41. package/.github/workflows/npm.yml +0 -19
  42. package/.github/workflows/prettier.yml +0 -25
  43. package/.github/workflows/test.yml +0 -29
  44. package/.prettierignore +0 -4
  45. package/.prettierrc +0 -1
  46. package/jest.config.js +0 -9
  47. package/logo.png +0 -0
  48. package/src/activity/builder.ts +0 -141
  49. package/src/activity/index.ts +0 -34
  50. package/src/agents.ts +0 -31
  51. package/src/api.ts +0 -51
  52. package/src/assets.ts +0 -1579
  53. package/src/chains.ts +0 -604
  54. package/src/host.ts +0 -1212
  55. package/src/index.ts +0 -36
  56. package/src/storage/daoMetaData.ts +0 -312
  57. package/src/storage/daos.ts +0 -306
  58. package/tests/assets.test.ts +0 -61
  59. package/tests/chains.test.ts +0 -22
  60. package/tests/host.test.ts +0 -811
  61. package/tsconfig.json +0 -18
  62. /package/{src → out}/tokenlist.json +0 -0
package/out/host.js ADDED
@@ -0,0 +1,765 @@
1
+ "use strict";
2
+ /**
3
+ Host prototype.
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.DAOAction = exports.Host = exports.UnitComponentCategory = exports.UnitStatus = exports.UnitType = exports.FundingType = exports.LifecyclePhase = exports.HOST_DESCRIPTION = void 0;
7
+ exports.getDAOUnit = getDAOUnit;
8
+ exports.getDAOUnitMetaData = getDAOUnitMetaData;
9
+ const chains_1 = require("./chains");
10
+ exports.HOST_DESCRIPTION = "A Cozy Home for DAOs";
11
+ /**
12
+ Lifecycle phase represents DAO tokenomics stage.
13
+ */
14
+ var LifecyclePhase;
15
+ (function (LifecyclePhase) {
16
+ /** Created */
17
+ LifecyclePhase["DRAFT"] = "DRAFT";
18
+ /**
19
+ Initial funding. DAO project passed requirements.
20
+ Since SEED started a DAO become real DAO:
21
+ - noncustodial
22
+ - tokenized share holdings
23
+ - collective management via voting
24
+ */
25
+ LifecyclePhase["SEED"] = "SEED";
26
+ /** Seed was not success. Raised funds sent back to seeders. */
27
+ LifecyclePhase["SEED_FAILED"] = "SEED_FAILED";
28
+ /** Using SEED funds to launch MVP / Unit generating */
29
+ LifecyclePhase["DEVELOPMENT"] = "DEVELOPMENT";
30
+ /** TGE is funding event for token liquidity and DAO developments (optionally) */
31
+ LifecyclePhase["TGE"] = "TGE";
32
+ /** Delay before any vesting allocation started */
33
+ LifecyclePhase["LIVE_CLIFF"] = "LIVE_CLIFF";
34
+ /** Vesting period active */
35
+ LifecyclePhase["LIVE_VESTING"] = "LIVE_VESTING";
36
+ /** Vesting ended - token fully distributed */
37
+ LifecyclePhase["LIVE"] = "LIVE";
38
+ })(LifecyclePhase || (exports.LifecyclePhase = LifecyclePhase = {}));
39
+ var FundingType;
40
+ (function (FundingType) {
41
+ FundingType["SEED"] = "SEED";
42
+ FundingType["TGE"] = "TGE";
43
+ })(FundingType || (exports.FundingType = FundingType = {}));
44
+ /** Supported unit types */
45
+ var UnitType;
46
+ (function (UnitType) {
47
+ /** VE-token early exit fees */
48
+ UnitType["PVP"] = "PVP";
49
+ /** Decentralized finance protocol */
50
+ UnitType["DEFI_PROTOCOL"] = "DEFI_PROTOCOL";
51
+ /** Maximum Extractable Value opportunities searcher and submitter. */
52
+ UnitType["MEV_SEARCHER"] = "MEV_SEARCHER";
53
+ /** Software as a Service business */
54
+ //SAAS = "SAAS",
55
+ })(UnitType || (exports.UnitType = UnitType = {}));
56
+ /** Unit status can be changed automatically on DAO lifecycle phase changes or manually by DAO holders */
57
+ var UnitStatus;
58
+ (function (UnitStatus) {
59
+ UnitStatus["RESEARCH"] = "RESEARCH";
60
+ UnitStatus["BUILDING"] = "BUILDING";
61
+ UnitStatus["LIVE"] = "LIVE";
62
+ })(UnitStatus || (exports.UnitStatus = UnitStatus = {}));
63
+ /** Supported categories of running units. */
64
+ var UnitComponentCategory;
65
+ (function (UnitComponentCategory) {
66
+ UnitComponentCategory["CHAIN_SUPPORT"] = "CHAIN_SUPPORT";
67
+ UnitComponentCategory["ENGINE_SUPPORT"] = "ENGINE_SUPPORT";
68
+ UnitComponentCategory["DEFI_STRATEGY"] = "DEFI_STRATEGY";
69
+ UnitComponentCategory["MEV_STRATEGY"] = "MEV_STRATEGY";
70
+ })(UnitComponentCategory || (exports.UnitComponentCategory = UnitComponentCategory = {}));
71
+ //export type UnitComponent = StrategyShortId | ChainName | LendingEngine;
72
+ /**
73
+ Typescript implementation of the Host
74
+ Object of this class is Host instance deployed on a single blockchain.
75
+
76
+ @class
77
+ */
78
+ class Host {
79
+ constructor(chainId) {
80
+ /** Chain block timestamp */
81
+ this.blockTimestamp = Math.floor(new Date().getTime() / 1000);
82
+ /** Local DAOs storage (in form of a mapping) */
83
+ this.daos = {};
84
+ /** Actual DAO symbols at all blockchains */
85
+ this.usedSymbols = {};
86
+ /** All emitted events */
87
+ this.events = [];
88
+ /** Governance proposals. Can be created only at initialChain of DAO. */
89
+ this.proposals = {};
90
+ /** Current user address */
91
+ this.from = "0x00";
92
+ this.settings = {
93
+ priceDao: 1000,
94
+ priceUnit: 1000,
95
+ priceOracle: 1000,
96
+ priceBridge: 1000,
97
+ minNameLength: 1,
98
+ maxNameLength: 20,
99
+ minSymbolLength: 1,
100
+ maxSymbolLength: 7,
101
+ minVePeriod: 14,
102
+ maxVePeriod: 365 * 4,
103
+ minPvPFee: 10,
104
+ maxPvPFee: 100,
105
+ minFundingDuration: 1,
106
+ maxFundingDuration: 180,
107
+ };
108
+ this.chainId = chainId;
109
+ }
110
+ static getTokensNaming(name, symbol) {
111
+ return {
112
+ seedName: `${name} SEED`,
113
+ seedSymbol: `seed${symbol}`,
114
+ tgeName: `${name} PRESALE`,
115
+ tgeSymbol: `sale${symbol}`,
116
+ tokenName: name,
117
+ tokenSymbol: symbol,
118
+ xName: `x${name}`,
119
+ xSymbol: `x${symbol}`,
120
+ daoName: `${name} DAO`,
121
+ daoSymbol: `${symbol}_DAO`,
122
+ };
123
+ }
124
+ static isLiveDAO(phase) {
125
+ return [
126
+ LifecyclePhase.LIVE_CLIFF,
127
+ LifecyclePhase.LIVE_VESTING,
128
+ LifecyclePhase.LIVE,
129
+ ].includes(phase);
130
+ }
131
+ /**
132
+ * Create new DAO
133
+ * @throws Error
134
+ */
135
+ createDAO(name, symbol, activity, params, funding, metaDataLocation) {
136
+ const dao = {
137
+ phase: LifecyclePhase.DRAFT,
138
+ name,
139
+ symbol,
140
+ activity,
141
+ socials: [],
142
+ images: {},
143
+ deployments: {},
144
+ units: [],
145
+ params,
146
+ chainSettings: {
147
+ bbRate: 50,
148
+ },
149
+ initialChain: chains_1.chains[this.chainId].name,
150
+ funding,
151
+ vesting: [],
152
+ governanceSettings: {},
153
+ deployer: this.from,
154
+ daoMetaDataLocation: metaDataLocation,
155
+ unitsMetaData: [],
156
+ };
157
+ this.validate(dao);
158
+ this.daos[dao.symbol] = dao;
159
+ this.usedSymbols[dao.symbol] = true;
160
+ this._emit("DAO created");
161
+ this._sendCrossChainMessage(CROSS_CHAIN_MESSAGE.NEW_DAO_SYMBOL, {
162
+ symbol,
163
+ });
164
+ return dao;
165
+ }
166
+ /** Add live compatible DAO */
167
+ addLiveDAO(dao) {
168
+ // todo _onlyVerifier
169
+ this.validate(dao);
170
+ this.daos[dao.symbol] = dao;
171
+ this.usedSymbols[dao.symbol] = true;
172
+ this._emit("DAO created");
173
+ this._sendCrossChainMessage(CROSS_CHAIN_MESSAGE.NEW_DAO_SYMBOL, {
174
+ symbol: dao.symbol,
175
+ });
176
+ }
177
+ getDAOMetaData(daoMetaData, symbol) {
178
+ const dao = this.getDAO(symbol);
179
+ if (dao.daoMetaDataLocation === "local") {
180
+ return daoMetaData[symbol.toLowerCase()];
181
+ }
182
+ return {};
183
+ }
184
+ /** Change lifecycle phase of a DAO */
185
+ changePhase(symbol) {
186
+ // anybody can call this
187
+ const dao = this.getDAO(symbol);
188
+ const currentTasks = this.tasks(symbol);
189
+ if (currentTasks.length > 0) {
190
+ throw new Error("SolveTasksFirst");
191
+ }
192
+ if (dao.phase === LifecyclePhase.DRAFT) {
193
+ const seed = dao.funding[this.getFundingIndex(symbol, FundingType.SEED)];
194
+ if (seed.start > this.blockTimestamp) {
195
+ throw new Error("WaitFundingStart");
196
+ }
197
+ // SEED can be started not later than 1 week after must start
198
+ // todo settings.maxSeedStartDelay
199
+ if (seed.start < this.blockTimestamp &&
200
+ this.blockTimestamp - seed.start > 7 * 86400) {
201
+ throw new Error("TooLateSoSetupFundingAgain");
202
+ }
203
+ /*// SEED can be started not later than 1 week before end
204
+ if (seed.end - this.blockTimestamp < 7 * 86400) {
205
+ throw new Error("TooLateSoSetupFundingAgain")
206
+ }*/
207
+ // deploy seedToken
208
+ this.daos[symbol].deployments[this.chainId] = {
209
+ seedToken: "0xProxyDeployed",
210
+ };
211
+ this.daos[symbol].phase = LifecyclePhase.SEED;
212
+ }
213
+ else if (dao.phase === LifecyclePhase.SEED) {
214
+ const seed = dao.funding[this.getFundingIndex(symbol, FundingType.SEED)];
215
+ if (seed.end > this.blockTimestamp) {
216
+ throw new Error("WaitFundingEnd");
217
+ }
218
+ const sucess = seed.raised >= seed.minRaise;
219
+ if (sucess) {
220
+ this.daos[symbol].phase = LifecyclePhase.DEVELOPMENT;
221
+ }
222
+ else {
223
+ // send all raised back to seeders
224
+ this.daos[symbol].phase = LifecyclePhase.SEED_FAILED;
225
+ }
226
+ }
227
+ else if (dao.phase === LifecyclePhase.DEVELOPMENT) {
228
+ const tge = dao.funding[this.getFundingIndex(symbol, FundingType.TGE)];
229
+ if (tge.start > this.blockTimestamp) {
230
+ throw new Error("WaitFundingStart");
231
+ }
232
+ // deploy tgeToken
233
+ this.daos[symbol].deployments[this.chainId].tgeToken =
234
+ "0xProxyDeployedTge";
235
+ this.daos[symbol].phase = LifecyclePhase.TGE;
236
+ }
237
+ else if (dao.phase === LifecyclePhase.TGE) {
238
+ const tge = dao.funding[this.getFundingIndex(symbol, FundingType.TGE)];
239
+ if (tge.end > this.blockTimestamp) {
240
+ throw new Error("WaitFundingEnd");
241
+ }
242
+ const success = tge.raised >= tge.minRaise;
243
+ if (success) {
244
+ // deploy token, xToken, staking, daoToken
245
+ this.daos[symbol].deployments[this.chainId].token = "0xProxyToken";
246
+ this.daos[symbol].deployments[this.chainId].xToken = "0xProxyXToken";
247
+ this.daos[symbol].deployments[this.chainId].staking = "0xProxyStaking";
248
+ this.daos[symbol].deployments[this.chainId].daoToken =
249
+ "0xProxyDAOToken";
250
+ // todo deploy vesting contracts and allocate token
251
+ // todo seedToken holders became xToken holders by predefined rate
252
+ // todo deploy v2 liquidity from TGE funds at predefined price
253
+ this.daos[symbol].phase = LifecyclePhase.LIVE_CLIFF;
254
+ }
255
+ else {
256
+ // send all raised TGE funds back to funders
257
+ this.daos[symbol].phase = LifecyclePhase.DEVELOPMENT;
258
+ }
259
+ }
260
+ else if (dao.phase === LifecyclePhase.LIVE_CLIFF) {
261
+ // if any vesting started then phase changed
262
+ const isVestingStarted = !!dao.vesting?.filter((v) => v.start < this.blockTimestamp).length;
263
+ if (!isVestingStarted) {
264
+ throw new Error("WaitVestingStart");
265
+ }
266
+ this.daos[symbol].phase = LifecyclePhase.LIVE_VESTING;
267
+ }
268
+ else if (dao.phase === LifecyclePhase.LIVE_VESTING) {
269
+ // if any vesting started then phase changed
270
+ const isVestingEnded = !dao.vesting?.filter((v) => v.end > this.blockTimestamp).length;
271
+ if (!isVestingEnded) {
272
+ throw new Error("WaitVestingEnd");
273
+ }
274
+ this.daos[symbol].phase = LifecyclePhase.LIVE;
275
+ }
276
+ else {
277
+ // nothing to change
278
+ throw new Error("ForeverLive");
279
+ }
280
+ }
281
+ /** @throws Error */
282
+ updateImages(symbol, images) {
283
+ // check DAO symbol
284
+ const dao = this.getDAO(symbol);
285
+ // instant execute for DRAFT
286
+ if (dao.phase === LifecyclePhase.DRAFT) {
287
+ this._onlyOwnerOf(symbol);
288
+ this._updateImages(symbol, images);
289
+ return true;
290
+ }
291
+ // create proposal for other phases
292
+ return this._proposeAction(symbol, DAOAction.UPDATE_IMAGES, {
293
+ images,
294
+ });
295
+ }
296
+ /** @throws Error */
297
+ updateSocials(symbol, socials) {
298
+ // check DAO symbol
299
+ const dao = this.getDAO(symbol);
300
+ // instant execute for DRAFT
301
+ if (dao.phase === LifecyclePhase.DRAFT) {
302
+ this._onlyOwnerOf(symbol);
303
+ this._updateSocials(symbol, socials);
304
+ return true;
305
+ }
306
+ // create proposal for other phases
307
+ return this._proposeAction(symbol, DAOAction.UPDATE_SOCIALS, {
308
+ socials,
309
+ });
310
+ }
311
+ /** @throws Error */
312
+ updateUnits(symbol, units, unitsMetaData) {
313
+ // check DAO symbol
314
+ const dao = this.getDAO(symbol);
315
+ // instant execute for DRAFT
316
+ if (dao.phase === LifecyclePhase.DRAFT) {
317
+ this._onlyOwnerOf(symbol);
318
+ this._updateUnits(symbol, units, unitsMetaData);
319
+ return true;
320
+ }
321
+ // create proposal for other phases
322
+ return this._proposeAction(symbol, DAOAction.UPDATE_UNITS, {
323
+ units,
324
+ unitsMetaData,
325
+ });
326
+ }
327
+ /** @throws Error */
328
+ updateFunding(symbol, funding) {
329
+ // check DAO symbol
330
+ const dao = this.getDAO(symbol);
331
+ // validate payload
332
+ this._validateFunding(dao.phase, [funding]);
333
+ // instant execute for DRAFT
334
+ if (dao.phase === LifecyclePhase.DRAFT) {
335
+ this._onlyOwnerOf(symbol);
336
+ this._updateFunding(symbol, funding);
337
+ return true;
338
+ }
339
+ // create proposal for other phases
340
+ return this._proposeAction(symbol, DAOAction.UPDATE_FUNDING, {
341
+ funding,
342
+ });
343
+ }
344
+ _updateSocials(symbol, socials) {
345
+ this.daos[symbol].socials = socials;
346
+ this._emit(`Action ${DAOAction.UPDATE_SOCIALS}`);
347
+ }
348
+ _updateUnits(symbol, units, unitsMetaData) {
349
+ this.daos[symbol].units = units;
350
+ this.daos[symbol].unitsMetaData = unitsMetaData;
351
+ this._emit(`Action ${DAOAction.UPDATE_UNITS}`);
352
+ }
353
+ _updateFunding(symbol, funding) {
354
+ const dao = this.getDAO(symbol);
355
+ const fundingExist = dao.funding.filter((f) => f.type === funding.type).length === 1;
356
+ if (fundingExist) {
357
+ const fundingIndex = this.getFundingIndex(symbol, funding.type);
358
+ this.daos[symbol].funding[fundingIndex] = funding;
359
+ }
360
+ else {
361
+ this.daos[symbol].funding.push(funding);
362
+ }
363
+ this._emit(`Action ${DAOAction.UPDATE_FUNDING}`);
364
+ }
365
+ updateVesting(symbol, vestings) {
366
+ // check DAO symbol
367
+ const dao = this.getDAO(symbol);
368
+ // validate
369
+ this._validateVesting(dao.phase, vestings);
370
+ // instant execute for DRAFT
371
+ if (dao.phase === LifecyclePhase.DRAFT) {
372
+ this._onlyOwnerOf(symbol);
373
+ this._updateVesting(symbol, vestings);
374
+ return true;
375
+ }
376
+ // create proposal for other phases
377
+ return this._proposeAction(symbol, DAOAction.UPDATE_VESTING, {
378
+ vestings,
379
+ });
380
+ }
381
+ fund(symbol, amount) {
382
+ // todo settings.minFunding
383
+ const dao = this.getDAO(symbol);
384
+ if (dao.phase === LifecyclePhase.SEED) {
385
+ const seedIndex = this.getFundingIndex(symbol, FundingType.SEED);
386
+ const seed = dao.funding[seedIndex];
387
+ if (seed.raised + amount >= seed.maxRaise) {
388
+ throw new Error("RaiseMaxExceed");
389
+ }
390
+ // transfer amount of exchangeAsset to seedToken contract
391
+ this.daos[symbol].funding[seedIndex].raised += amount;
392
+ // mint seedToken to user
393
+ return;
394
+ }
395
+ if (dao.phase === LifecyclePhase.TGE) {
396
+ const tgeIndex = this.getFundingIndex(symbol, FundingType.TGE);
397
+ const tge = dao.funding[tgeIndex];
398
+ if (tge.raised + amount >= tge.maxRaise) {
399
+ throw new Error("RaiseMaxExceed");
400
+ }
401
+ // transfer amount of exchangeAsset to tgeToken contract
402
+ this.daos[symbol].funding[tgeIndex].raised += amount;
403
+ // mint tgeToken to user
404
+ return;
405
+ }
406
+ throw new Error("NotFundingPhase");
407
+ }
408
+ receiveVotingResults(proposalId, succeed) {
409
+ const proposal = this.proposals[proposalId];
410
+ if (!proposal) {
411
+ throw new Error("IncorrectProposal");
412
+ }
413
+ if (proposal.status !== VotingStatus.VOTING) {
414
+ throw new Error("AlreadyReceived");
415
+ }
416
+ this.proposals[proposalId].status = succeed
417
+ ? VotingStatus.APPROVED
418
+ : VotingStatus.REJECTED;
419
+ if (succeed) {
420
+ if (proposal.action === DAOAction.UPDATE_IMAGES) {
421
+ this._updateImages(proposal.symbol, proposal.payload.images);
422
+ }
423
+ if (proposal.action === DAOAction.UPDATE_SOCIALS) {
424
+ this._updateSocials(proposal.symbol, proposal.payload.socials);
425
+ }
426
+ if (proposal.action === DAOAction.UPDATE_UNITS) {
427
+ this._updateUnits(proposal.symbol, proposal.payload.units, proposal.payload.unitsMetaData);
428
+ }
429
+ if (proposal.action === DAOAction.UPDATE_FUNDING) {
430
+ this._updateFunding(proposal.symbol, proposal.payload.funding);
431
+ }
432
+ if (proposal.action === DAOAction.UPDATE_VESTING) {
433
+ this._updateVesting(proposal.symbol, proposal.payload.vestings);
434
+ }
435
+ // todo other actions
436
+ }
437
+ }
438
+ /** OFF-CHAIN only **/
439
+ /** @throws Error */
440
+ roadmap(symbol) {
441
+ const dao = this.getDAO(symbol);
442
+ const r = [];
443
+ let tgeRun = 0;
444
+ for (const funding of dao.funding) {
445
+ if (funding.type === FundingType.SEED) {
446
+ r.push({
447
+ phase: LifecyclePhase.SEED,
448
+ start: funding.start,
449
+ end: funding.end,
450
+ });
451
+ }
452
+ if (funding.type === FundingType.TGE) {
453
+ // if SEED was done
454
+ if (r.length > 0) {
455
+ r.push({
456
+ phase: LifecyclePhase.DEVELOPMENT,
457
+ start: r[0].end + 1,
458
+ end: funding.start - 1,
459
+ });
460
+ }
461
+ tgeRun = funding.claim || funding.end;
462
+ r.push({
463
+ phase: LifecyclePhase.TGE,
464
+ start: funding.start,
465
+ end: tgeRun,
466
+ });
467
+ }
468
+ }
469
+ if (dao.vesting.length > 0) {
470
+ let vestingStart = this.blockTimestamp;
471
+ let vestingEnd = this.blockTimestamp;
472
+ for (const vesting of dao.vesting) {
473
+ if (vesting.start < vestingStart) {
474
+ vestingStart = vesting.start;
475
+ }
476
+ if (vesting.end > vestingEnd) {
477
+ vestingEnd = vesting.end;
478
+ }
479
+ }
480
+ r.push({
481
+ phase: LifecyclePhase.LIVE_CLIFF,
482
+ start: tgeRun + 1,
483
+ end: vestingStart - 1,
484
+ });
485
+ r.push({
486
+ phase: LifecyclePhase.LIVE_VESTING,
487
+ start: vestingStart,
488
+ end: vestingEnd,
489
+ });
490
+ r.push({
491
+ phase: LifecyclePhase.LIVE,
492
+ start: vestingEnd + 1,
493
+ });
494
+ }
495
+ return r;
496
+ }
497
+ /** @throws Error */
498
+ tasks(symbol) {
499
+ const dao = this.getDAO(symbol);
500
+ const r = [];
501
+ if (dao.phase === LifecyclePhase.DRAFT) {
502
+ // images
503
+ if (!dao.images.seedToken || !dao.images.token) {
504
+ r.push({
505
+ name: "Need images of token and seedToken",
506
+ });
507
+ }
508
+ // socials
509
+ if (dao.socials.length < 2) {
510
+ r.push({
511
+ name: "Need at least 2 socials",
512
+ });
513
+ }
514
+ // units projected
515
+ if (dao.units.length === 0) {
516
+ r.push({
517
+ name: "Need at least 1 projected unit",
518
+ });
519
+ }
520
+ }
521
+ else if (dao.phase === LifecyclePhase.SEED) {
522
+ const seedIndex = this.getFundingIndex(symbol, FundingType.SEED);
523
+ if (dao.funding[seedIndex].raised < dao.funding[seedIndex].minRaise &&
524
+ dao.funding[seedIndex].end > this.blockTimestamp) {
525
+ r.push({
526
+ name: "Need attract minimal seed funding",
527
+ });
528
+ }
529
+ }
530
+ else if (dao.phase === LifecyclePhase.DEVELOPMENT) {
531
+ // check funding
532
+ const tgeExist = dao.funding.filter((f) => f.type === FundingType.TGE).length === 1;
533
+ if (!tgeExist) {
534
+ r.push({
535
+ name: "Need add pre-TGE funding",
536
+ });
537
+ }
538
+ // images
539
+ if (!dao.images.tgeToken || !dao.images.xToken || !dao.images.daoToken) {
540
+ r.push({
541
+ name: "Need images of all DAO tokens",
542
+ });
543
+ }
544
+ // setup vesting allocations
545
+ if (!dao.vesting?.length) {
546
+ r.push({
547
+ name: "Need vesting allocations",
548
+ });
549
+ }
550
+ if (dao.unitsMetaData?.filter((unitMetaData) => unitMetaData.status === UnitStatus.LIVE).length === 0) {
551
+ r.push({
552
+ name: "Run revenue generating units",
553
+ });
554
+ }
555
+ }
556
+ else if (dao.phase === LifecyclePhase.TGE) {
557
+ const tgeIndex = this.getFundingIndex(symbol, FundingType.TGE);
558
+ if (dao.funding[tgeIndex].raised < dao.funding[tgeIndex].minRaise &&
559
+ dao.funding[tgeIndex].end > this.blockTimestamp) {
560
+ r.push({
561
+ name: "Need attract minimal TGE funding",
562
+ });
563
+ }
564
+ }
565
+ else if (dao.phase === LifecyclePhase.LIVE_CLIFF) {
566
+ // establish and improve
567
+ // build money markets
568
+ // bridge to chains
569
+ }
570
+ else if (dao.phase === LifecyclePhase.LIVE_VESTING) {
571
+ // distribute vesting funds to leverage token
572
+ }
573
+ /*if (dao.phase === LifecyclePhase.LIVE)*/
574
+ // lifetime revenue generating for DAO holders (till ABSORBED proposed feature)
575
+ return r;
576
+ }
577
+ /** Strict on-chain validation */
578
+ /** @throws Error */
579
+ validate(dao) {
580
+ this._validateName(dao.name);
581
+ this._validateSymbol(dao.symbol);
582
+ if (dao.params.vePeriod < this.settings.minVePeriod ||
583
+ dao.params.vePeriod > this.settings.maxVePeriod) {
584
+ throw new Error(`VePeriod(${dao.params.vePeriod})`);
585
+ }
586
+ this._validatePvpFee(dao.params.pvpFee);
587
+ if (!dao.funding.length) {
588
+ throw new Error("NeedFunding");
589
+ }
590
+ // todo: check activity are correct
591
+ // todo: check funding array has unique funding types
592
+ // todo: check funding dates
593
+ // todo: check funding raise goals
594
+ }
595
+ /** @throws Error */
596
+ getDAO(symbol) {
597
+ if (this.daos[symbol]) {
598
+ return this.daos[symbol];
599
+ }
600
+ throw new Error("DAONotFound");
601
+ }
602
+ getDaoOwner(symbol) {
603
+ const dao = this.getDAO(symbol);
604
+ if (dao.phase === LifecyclePhase.DRAFT) {
605
+ return dao.deployer;
606
+ }
607
+ if ([
608
+ LifecyclePhase.SEED,
609
+ LifecyclePhase.DEVELOPMENT,
610
+ LifecyclePhase.TGE,
611
+ ].includes(dao.phase)) {
612
+ return dao.deployments[(0, chains_1.getChainByName)(dao.initialChain).chainId]
613
+ .seedToken;
614
+ }
615
+ return dao.deployments[this.chainId]?.daoToken;
616
+ }
617
+ getFundingIndex(symbol, type) {
618
+ const dao = this.getDAO(symbol);
619
+ for (let i = 0; i < dao.funding.length; i++) {
620
+ if (type === dao.funding[i].type) {
621
+ return i;
622
+ }
623
+ }
624
+ throw new Error("FundingNotFound");
625
+ }
626
+ warpDays(days = 7) {
627
+ this.blockTimestamp += days * 86400;
628
+ }
629
+ /** @throws Error */
630
+ _onlyOwnerOf(symbol) {
631
+ if (this.from != this.getDaoOwner(symbol)) {
632
+ throw new Error(`YouAreNotOwnerOf(${symbol})`);
633
+ }
634
+ }
635
+ _emit(event) {
636
+ this.events.push(event);
637
+ }
638
+ _validateName(name) {
639
+ if (name.length < this.settings.minNameLength ||
640
+ name.length > this.settings.maxNameLength) {
641
+ throw new Error(`NameLength(${name.length})`);
642
+ }
643
+ }
644
+ _validateSymbol(symbol) {
645
+ if (symbol.length < this.settings.minSymbolLength ||
646
+ symbol.length > this.settings.maxSymbolLength) {
647
+ throw new Error(`SymbolLength(${symbol.length})`);
648
+ }
649
+ if (this.usedSymbols[symbol]) {
650
+ throw new Error(`SymbolNotUnique(${symbol})`);
651
+ }
652
+ }
653
+ _validatePvpFee(pvpFee) {
654
+ if (pvpFee < this.settings.minPvPFee || pvpFee > this.settings.maxPvPFee) {
655
+ throw new Error(`PvPFee(${pvpFee})`);
656
+ }
657
+ }
658
+ _validateFunding(daoPhase, fundings) {
659
+ for (const funding of fundings) {
660
+ if (funding.type === FundingType.SEED &&
661
+ daoPhase !== LifecyclePhase.DRAFT) {
662
+ throw new Error("TooLateToUpdateSuchFunding");
663
+ }
664
+ if (funding.type === FundingType.TGE &&
665
+ ![
666
+ LifecyclePhase.DRAFT,
667
+ LifecyclePhase.SEED,
668
+ LifecyclePhase.DEVELOPMENT,
669
+ ].includes(daoPhase)) {
670
+ throw new Error("TooLateToUpdateSuchFunding");
671
+ }
672
+ // todo check min round duration
673
+ // todo check max round duration
674
+ // todo check start date delay
675
+ // todo check min amount
676
+ // todo check max amount
677
+ }
678
+ }
679
+ _validateVesting(daoPhase, vestings) {
680
+ if ([
681
+ LifecyclePhase.LIVE_CLIFF,
682
+ LifecyclePhase.LIVE_VESTING,
683
+ LifecyclePhase.LIVE,
684
+ ].includes(daoPhase)) {
685
+ throw new Error("TooLateToUpdateVesting");
686
+ }
687
+ for (const vesting of vestings) {
688
+ // todo check vesting consistency
689
+ }
690
+ }
691
+ _sendCrossChainMessage(type, payload) {
692
+ // todo some stub
693
+ }
694
+ _proposeAction(symbol, action, payload) {
695
+ const dao = this.getDAO(symbol);
696
+ // todo check for initial chain
697
+ // todo get user power
698
+ // todo check proposalThreshold
699
+ // todo validate payload
700
+ const proposalId = Math.round(Math.random() * Math.random()).toString();
701
+ this.proposals[proposalId] = {
702
+ id: proposalId,
703
+ created: this.blockTimestamp,
704
+ action,
705
+ symbol,
706
+ payload,
707
+ status: VotingStatus.VOTING,
708
+ };
709
+ return proposalId;
710
+ }
711
+ _updateImages(symbol, images) {
712
+ this.daos[symbol].images = images;
713
+ this._emit(`Action ${DAOAction.UPDATE_IMAGES}`);
714
+ }
715
+ _updateVesting(symbol, vestings) {
716
+ this.daos[symbol].vesting = vestings;
717
+ this._emit(`Action ${DAOAction.UPDATE_VESTING}`);
718
+ }
719
+ }
720
+ exports.Host = Host;
721
+ var DAOAction;
722
+ (function (DAOAction) {
723
+ DAOAction[DAOAction["UPDATE_IMAGES"] = 0] = "UPDATE_IMAGES";
724
+ DAOAction[DAOAction["UPDATE_SOCIALS"] = 1] = "UPDATE_SOCIALS";
725
+ DAOAction[DAOAction["UPDATE_NAMING"] = 2] = "UPDATE_NAMING";
726
+ DAOAction[DAOAction["UPDATE_UNITS"] = 3] = "UPDATE_UNITS";
727
+ DAOAction[DAOAction["UPDATE_FUNDING"] = 4] = "UPDATE_FUNDING";
728
+ DAOAction[DAOAction["UPDATE_VESTING"] = 5] = "UPDATE_VESTING";
729
+ })(DAOAction || (exports.DAOAction = DAOAction = {}));
730
+ var VotingStatus;
731
+ (function (VotingStatus) {
732
+ VotingStatus[VotingStatus["VOTING"] = 0] = "VOTING";
733
+ VotingStatus[VotingStatus["APPROVED"] = 1] = "APPROVED";
734
+ VotingStatus[VotingStatus["REJECTED"] = 2] = "REJECTED";
735
+ })(VotingStatus || (VotingStatus = {}));
736
+ var CROSS_CHAIN_MESSAGE;
737
+ (function (CROSS_CHAIN_MESSAGE) {
738
+ CROSS_CHAIN_MESSAGE[CROSS_CHAIN_MESSAGE["NEW_DAO_SYMBOL"] = 0] = "NEW_DAO_SYMBOL";
739
+ CROSS_CHAIN_MESSAGE[CROSS_CHAIN_MESSAGE["DAO_RENAME_SYMBOL"] = 1] = "DAO_RENAME_SYMBOL";
740
+ CROSS_CHAIN_MESSAGE[CROSS_CHAIN_MESSAGE["DAO_BRIDGED"] = 2] = "DAO_BRIDGED";
741
+ })(CROSS_CHAIN_MESSAGE || (CROSS_CHAIN_MESSAGE = {}));
742
+ function getDAOUnit(daos, symbol, unitId) {
743
+ for (const dao of daos) {
744
+ if (dao.symbol.toLowerCase() === symbol.toLowerCase()) {
745
+ for (const unit of dao.units) {
746
+ if (unit.unitId === unitId) {
747
+ return unit;
748
+ }
749
+ }
750
+ }
751
+ }
752
+ }
753
+ function getDAOUnitMetaData(daos, symbol, unitId) {
754
+ for (const dao of daos) {
755
+ if (dao.symbol.toLowerCase() === symbol.toLowerCase()) {
756
+ for (let i = 0; i < dao.units.length; i++) {
757
+ const unit = dao.units[i];
758
+ if (unit.unitId === unitId) {
759
+ return dao.unitsMetaData[i];
760
+ }
761
+ }
762
+ }
763
+ }
764
+ }
765
+ //# sourceMappingURL=host.js.map