@daohost/host 0.8.0
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/LICENSE +674 -0
- package/README.md +39 -0
- package/out/activity.d.ts +16 -0
- package/out/activity.d.ts.map +1 -0
- package/out/activity.js +25 -0
- package/out/activity.js.map +1 -0
- package/out/agents.d.ts +15 -0
- package/out/agents.d.ts.map +1 -0
- package/out/agents.js +14 -0
- package/out/agents.js.map +1 -0
- package/out/api.d.ts +115 -0
- package/out/api.d.ts.map +1 -0
- package/out/api.js +3 -0
- package/out/api.js.map +1 -0
- package/out/assets.d.ts +46 -0
- package/out/assets.d.ts.map +1 -0
- package/out/assets.js +1645 -0
- package/out/assets.js.map +1 -0
- package/out/chains.d.ts +106 -0
- package/out/chains.d.ts.map +1 -0
- package/out/chains.js +605 -0
- package/out/chains.js.map +1 -0
- package/out/deployments.d.ts +9 -0
- package/out/deployments.d.ts.map +1 -0
- package/out/deployments.js +18 -0
- package/out/deployments.js.map +1 -0
- package/out/host/types.d.ts +59 -0
- package/out/host/types.d.ts.map +1 -0
- package/out/host/types.js +35 -0
- package/out/host/types.js.map +1 -0
- package/out/host.d.ts +387 -0
- package/out/host.d.ts.map +1 -0
- package/out/host.js +948 -0
- package/out/host.js.map +1 -0
- package/out/index.d.ts +15 -0
- package/out/index.d.ts.map +1 -0
- package/out/index.js +45 -0
- package/out/index.js.map +1 -0
- package/out/storage/daos.d.ts +3 -0
- package/out/storage/daos.d.ts.map +1 -0
- package/out/storage/daos.js +374 -0
- package/out/storage/daos.js.map +1 -0
- package/out/storage/metaData.d.ts +5 -0
- package/out/storage/metaData.d.ts.map +1 -0
- package/out/storage/metaData.js +44 -0
- package/out/storage/metaData.js.map +1 -0
- package/out/tokenlist.json +2098 -0
- package/out/unit.d.ts +75 -0
- package/out/unit.d.ts.map +1 -0
- package/out/unit.js +3 -0
- package/out/unit.js.map +1 -0
- package/out/validation.d.ts +15 -0
- package/out/validation.d.ts.map +1 -0
- package/out/validation.js +105 -0
- package/out/validation.js.map +1 -0
- package/package.json +37 -0
package/out/host.js
ADDED
|
@@ -0,0 +1,948 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
Host prototype.
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.DAOAction = exports.Host = exports.daoContractIndices = exports.ContractIndices = exports.FundingType = exports.LifecyclePhase = exports.STATIC_BASE_URL = exports.DAO_FEATURES = exports.HOST_DESCRIPTION = void 0;
|
|
7
|
+
exports.getUnit = getUnit;
|
|
8
|
+
exports.getDAOUnit = getDAOUnit;
|
|
9
|
+
exports.getDAOUnitMetaData = getDAOUnitMetaData;
|
|
10
|
+
exports.getUnitMetaData = getUnitMetaData;
|
|
11
|
+
exports.getBridgeTokens = getBridgeTokens;
|
|
12
|
+
const chains_1 = require("./chains");
|
|
13
|
+
const assets_1 = require("./assets");
|
|
14
|
+
const validation_1 = require("./validation");
|
|
15
|
+
exports.HOST_DESCRIPTION = "Where True DAOs Live & Work";
|
|
16
|
+
exports.DAO_FEATURES = [
|
|
17
|
+
"True DAO: only holders owns, manage and earn whole value",
|
|
18
|
+
"Inter-chain setup with bridging",
|
|
19
|
+
"Decentralized fundraising",
|
|
20
|
+
"Self-developing via Builder activity",
|
|
21
|
+
"Tokenomics constructor",
|
|
22
|
+
"Proper token launch flow to get cg/cmc and wallets listings",
|
|
23
|
+
"Deterministic managed contract addresses",
|
|
24
|
+
];
|
|
25
|
+
exports.STATIC_BASE_URL = "https://raw.githubusercontent.com/stabilitydao/.github/main";
|
|
26
|
+
/**
|
|
27
|
+
Lifecycle phase represents DAO tokenomics stage.
|
|
28
|
+
*/
|
|
29
|
+
var LifecyclePhase;
|
|
30
|
+
(function (LifecyclePhase) {
|
|
31
|
+
/** Created */
|
|
32
|
+
LifecyclePhase["DRAFT"] = "DRAFT";
|
|
33
|
+
/**
|
|
34
|
+
* DAO ready to attract initial community
|
|
35
|
+
*/
|
|
36
|
+
LifecyclePhase["INCEPTION"] = "INCEPTION";
|
|
37
|
+
/**
|
|
38
|
+
Initial funding. DAO project passed requirements.
|
|
39
|
+
Since SEED started a DAO become real DAO:
|
|
40
|
+
- noncustodial
|
|
41
|
+
- tokenized share holdings
|
|
42
|
+
- collective management via voting
|
|
43
|
+
*/
|
|
44
|
+
LifecyclePhase["SEED"] = "SEED";
|
|
45
|
+
/** Seed was not success. Raised funds sent back to seeders. */
|
|
46
|
+
LifecyclePhase["SEED_FAILED"] = "SEED_FAILED";
|
|
47
|
+
/** Using SEED funds to launch MVP / Unit generating */
|
|
48
|
+
LifecyclePhase["DEVELOPMENT"] = "DEVELOPMENT";
|
|
49
|
+
/** TGE is funding event for token liquidity and DAO developments (optionally) */
|
|
50
|
+
LifecyclePhase["TGE"] = "TGE";
|
|
51
|
+
/** Delay before any vesting allocation started */
|
|
52
|
+
LifecyclePhase["LIVE_CLIFF"] = "LIVE_CLIFF";
|
|
53
|
+
/** Vesting period active */
|
|
54
|
+
LifecyclePhase["LIVE_VESTING"] = "LIVE_VESTING";
|
|
55
|
+
/** Vesting ended - token fully distributed */
|
|
56
|
+
LifecyclePhase["LIVE"] = "LIVE";
|
|
57
|
+
})(LifecyclePhase || (exports.LifecyclePhase = LifecyclePhase = {}));
|
|
58
|
+
var FundingType;
|
|
59
|
+
(function (FundingType) {
|
|
60
|
+
FundingType["SEED"] = "SEED";
|
|
61
|
+
FundingType["TGE"] = "TGE";
|
|
62
|
+
})(FundingType || (exports.FundingType = FundingType = {}));
|
|
63
|
+
/// @notice Indices of all contracts that can be deployed by a DAO. The indices are used to pre-set salts
|
|
64
|
+
var ContractIndices;
|
|
65
|
+
(function (ContractIndices) {
|
|
66
|
+
ContractIndices[ContractIndices["NOT_USED_0"] = 0] = "NOT_USED_0";
|
|
67
|
+
ContractIndices[ContractIndices["SEED_TOKEN_1"] = 1] = "SEED_TOKEN_1";
|
|
68
|
+
ContractIndices[ContractIndices["TGE_TOKEN_2"] = 2] = "TGE_TOKEN_2";
|
|
69
|
+
ContractIndices[ContractIndices["TOKEN_3"] = 3] = "TOKEN_3";
|
|
70
|
+
ContractIndices[ContractIndices["X_TOKEN_4"] = 4] = "X_TOKEN_4";
|
|
71
|
+
ContractIndices[ContractIndices["DAO_TOKEN_5"] = 5] = "DAO_TOKEN_5";
|
|
72
|
+
ContractIndices[ContractIndices["STAKING_6"] = 6] = "STAKING_6";
|
|
73
|
+
ContractIndices[ContractIndices["RECOVERY_7"] = 7] = "RECOVERY_7";
|
|
74
|
+
ContractIndices[ContractIndices["TOKEN_BRIDGE_8"] = 8] = "TOKEN_BRIDGE_8";
|
|
75
|
+
ContractIndices[ContractIndices["X_TOKEN_BRIDGE_9"] = 9] = "X_TOKEN_BRIDGE_9";
|
|
76
|
+
ContractIndices[ContractIndices["DAO_TOKEN_BRIDGE_10"] = 10] = "DAO_TOKEN_BRIDGE_10";
|
|
77
|
+
ContractIndices[ContractIndices["VESTING_1_11"] = 11] = "VESTING_1_11";
|
|
78
|
+
ContractIndices[ContractIndices["VESTING_2_12"] = 12] = "VESTING_2_12";
|
|
79
|
+
ContractIndices[ContractIndices["VESTING_3_13"] = 13] = "VESTING_3_13";
|
|
80
|
+
ContractIndices[ContractIndices["VESTING_4_14"] = 14] = "VESTING_4_14";
|
|
81
|
+
ContractIndices[ContractIndices["VESTING_5_15"] = 15] = "VESTING_5_15";
|
|
82
|
+
ContractIndices[ContractIndices["VESTING_6_16"] = 16] = "VESTING_6_16";
|
|
83
|
+
ContractIndices[ContractIndices["VESTING_7_17"] = 17] = "VESTING_7_17";
|
|
84
|
+
ContractIndices[ContractIndices["VESTING_8_18"] = 18] = "VESTING_8_18";
|
|
85
|
+
ContractIndices[ContractIndices["VESTING_9_19"] = 19] = "VESTING_9_19";
|
|
86
|
+
ContractIndices[ContractIndices["VESTING_10_20"] = 20] = "VESTING_10_20";
|
|
87
|
+
ContractIndices[ContractIndices["REVENUE_ROUTER_21"] = 21] = "REVENUE_ROUTER_21";
|
|
88
|
+
// add new indices here if necessary
|
|
89
|
+
ContractIndices[ContractIndices["COUNT_CONTRACT_INDICES"] = 22] = "COUNT_CONTRACT_INDICES";
|
|
90
|
+
})(ContractIndices || (exports.ContractIndices = ContractIndices = {}));
|
|
91
|
+
exports.daoContractIndices = {
|
|
92
|
+
[ContractIndices.SEED_TOKEN_1]: {
|
|
93
|
+
name: "Seed token",
|
|
94
|
+
description: "Seed round receipt token",
|
|
95
|
+
},
|
|
96
|
+
[ContractIndices.TGE_TOKEN_2]: {
|
|
97
|
+
name: "Presale token",
|
|
98
|
+
description: "TGE pre-sale receipt token",
|
|
99
|
+
},
|
|
100
|
+
[ContractIndices.TOKEN_3]: {
|
|
101
|
+
name: "Token",
|
|
102
|
+
description: "Main tradable DAO token",
|
|
103
|
+
},
|
|
104
|
+
[ContractIndices.X_TOKEN_4]: {
|
|
105
|
+
name: "VE-token",
|
|
106
|
+
description: "VE-tokenomics entry token",
|
|
107
|
+
},
|
|
108
|
+
[ContractIndices.DAO_TOKEN_5]: {
|
|
109
|
+
name: "DAO token",
|
|
110
|
+
description: "Governance token",
|
|
111
|
+
},
|
|
112
|
+
[ContractIndices.STAKING_6]: {
|
|
113
|
+
name: "Staking",
|
|
114
|
+
description: "Staking contract",
|
|
115
|
+
},
|
|
116
|
+
[ContractIndices.RECOVERY_7]: {
|
|
117
|
+
name: "Recovery",
|
|
118
|
+
description: "Accident recovery system contract",
|
|
119
|
+
},
|
|
120
|
+
[ContractIndices.TOKEN_BRIDGE_8]: {
|
|
121
|
+
name: "Token bridge",
|
|
122
|
+
description: "Bridge for main token",
|
|
123
|
+
},
|
|
124
|
+
[ContractIndices.X_TOKEN_BRIDGE_9]: {
|
|
125
|
+
name: "VE-token bridge",
|
|
126
|
+
description: "Bridge for VE-token",
|
|
127
|
+
},
|
|
128
|
+
[ContractIndices.DAO_TOKEN_BRIDGE_10]: {
|
|
129
|
+
name: "DAO token bridge",
|
|
130
|
+
description: "Bridge for Governance token",
|
|
131
|
+
},
|
|
132
|
+
[ContractIndices.VESTING_1_11]: {
|
|
133
|
+
name: "Vesting 1",
|
|
134
|
+
},
|
|
135
|
+
[ContractIndices.VESTING_2_12]: {
|
|
136
|
+
name: "Vesting 2",
|
|
137
|
+
},
|
|
138
|
+
[ContractIndices.VESTING_3_13]: {
|
|
139
|
+
name: "Vesting 3",
|
|
140
|
+
},
|
|
141
|
+
[ContractIndices.VESTING_4_14]: {
|
|
142
|
+
name: "Vesting 4",
|
|
143
|
+
},
|
|
144
|
+
[ContractIndices.VESTING_5_15]: {
|
|
145
|
+
name: "Vesting 5",
|
|
146
|
+
},
|
|
147
|
+
[ContractIndices.VESTING_6_16]: {
|
|
148
|
+
name: "Vesting 6",
|
|
149
|
+
},
|
|
150
|
+
[ContractIndices.VESTING_7_17]: {
|
|
151
|
+
name: "Vesting 7",
|
|
152
|
+
},
|
|
153
|
+
[ContractIndices.VESTING_8_18]: {
|
|
154
|
+
name: "Vesting 8",
|
|
155
|
+
},
|
|
156
|
+
[ContractIndices.VESTING_9_19]: {
|
|
157
|
+
name: "Vesting 9",
|
|
158
|
+
},
|
|
159
|
+
[ContractIndices.VESTING_10_20]: {
|
|
160
|
+
name: "Vesting 10",
|
|
161
|
+
},
|
|
162
|
+
[ContractIndices.REVENUE_ROUTER_21]: {
|
|
163
|
+
name: "Revenue Router",
|
|
164
|
+
description: "Revenue collector and utilizer contract",
|
|
165
|
+
},
|
|
166
|
+
};
|
|
167
|
+
/**
|
|
168
|
+
Typescript implementation of the Host
|
|
169
|
+
Object of this class is Host instance deployed on a single blockchain.
|
|
170
|
+
|
|
171
|
+
@class
|
|
172
|
+
*/
|
|
173
|
+
class Host {
|
|
174
|
+
constructor(chainId) {
|
|
175
|
+
/** Chain block timestamp */
|
|
176
|
+
this.blockTimestamp = Math.floor(new Date().getTime() / 1000);
|
|
177
|
+
/** Local DAOs storage (in form of a mapping) */
|
|
178
|
+
this.daos = {};
|
|
179
|
+
/** Actual DAO symbols at all blockchains */
|
|
180
|
+
this.usedSymbols = {};
|
|
181
|
+
/** All emitted events */
|
|
182
|
+
this.events = [];
|
|
183
|
+
/** Governance proposals. Can be created only at initialChain of DAO. */
|
|
184
|
+
this.proposals = {};
|
|
185
|
+
/** Current user address */
|
|
186
|
+
this.from = "0x00";
|
|
187
|
+
this.settings = {
|
|
188
|
+
priceDao: 1000,
|
|
189
|
+
fundingFee: 1000, // 10%
|
|
190
|
+
minNameLength: 1,
|
|
191
|
+
maxNameLength: 20,
|
|
192
|
+
minSymbolLength: 1,
|
|
193
|
+
maxSymbolLength: 7,
|
|
194
|
+
minVePeriod: 14,
|
|
195
|
+
maxVePeriod: 365 * 4,
|
|
196
|
+
minPvPFee: 10,
|
|
197
|
+
maxPvPFee: 100,
|
|
198
|
+
minFundingDuration: 1,
|
|
199
|
+
maxFundingDuration: 180,
|
|
200
|
+
minFundingRaise: 1000,
|
|
201
|
+
maxFundingRaise: 1e12,
|
|
202
|
+
minVestingNameLen: 1,
|
|
203
|
+
maxVestingNameLen: 20,
|
|
204
|
+
minCliff: 15,
|
|
205
|
+
minVestingDuration: 10,
|
|
206
|
+
maxVestingDuration: 365,
|
|
207
|
+
};
|
|
208
|
+
this.chainId = chainId;
|
|
209
|
+
}
|
|
210
|
+
static getTokensNaming(name, symbol) {
|
|
211
|
+
return {
|
|
212
|
+
seedName: `${name} SEED`,
|
|
213
|
+
seedSymbol: `seed${symbol}`,
|
|
214
|
+
tgeName: `${name} PRESALE`,
|
|
215
|
+
tgeSymbol: `sale${symbol}`,
|
|
216
|
+
tokenName: name,
|
|
217
|
+
tokenSymbol: symbol,
|
|
218
|
+
xName: `x${name}`,
|
|
219
|
+
xSymbol: `x${symbol}`,
|
|
220
|
+
daoName: `${name} DAO`,
|
|
221
|
+
daoSymbol: `${symbol}_DAO`,
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
static isLiveDAO(phase) {
|
|
225
|
+
return [
|
|
226
|
+
LifecyclePhase.LIVE_CLIFF,
|
|
227
|
+
LifecyclePhase.LIVE_VESTING,
|
|
228
|
+
LifecyclePhase.LIVE,
|
|
229
|
+
].includes(phase);
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Create new DAO
|
|
233
|
+
* @throws Error
|
|
234
|
+
*/
|
|
235
|
+
createDAO(name, symbol, activity, params, funding, metaDataLocation) {
|
|
236
|
+
const dao = {
|
|
237
|
+
phase: LifecyclePhase.DRAFT,
|
|
238
|
+
name,
|
|
239
|
+
symbol,
|
|
240
|
+
activity,
|
|
241
|
+
socials: [],
|
|
242
|
+
images: {},
|
|
243
|
+
deployments: {},
|
|
244
|
+
units: [],
|
|
245
|
+
params,
|
|
246
|
+
chainSettings: {
|
|
247
|
+
[this.chainId]: {
|
|
248
|
+
bbRate: 50,
|
|
249
|
+
},
|
|
250
|
+
},
|
|
251
|
+
initialChain: chains_1.chains[this.chainId].name,
|
|
252
|
+
funding,
|
|
253
|
+
vesting: [],
|
|
254
|
+
governanceSettings: {},
|
|
255
|
+
deployer: this.from,
|
|
256
|
+
salts: {},
|
|
257
|
+
metaDataLocation: metaDataLocation,
|
|
258
|
+
unitEmitData: [],
|
|
259
|
+
};
|
|
260
|
+
this.validate(dao);
|
|
261
|
+
this.daos[dao.symbol] = dao;
|
|
262
|
+
this.usedSymbols[dao.symbol] = true;
|
|
263
|
+
this._emit("DAO created");
|
|
264
|
+
this._sendCrossChainMessage(CROSS_CHAIN_MESSAGE.NEW_DAO_SYMBOL, {
|
|
265
|
+
symbol,
|
|
266
|
+
});
|
|
267
|
+
return dao;
|
|
268
|
+
}
|
|
269
|
+
/** Add live compatible DAO */
|
|
270
|
+
addLiveDAO(dao) {
|
|
271
|
+
// todo _onlyVerifier
|
|
272
|
+
this.validate(dao);
|
|
273
|
+
this.daos[dao.symbol] = dao;
|
|
274
|
+
this.usedSymbols[dao.symbol] = true;
|
|
275
|
+
this._emit("DAO created");
|
|
276
|
+
this._sendCrossChainMessage(CROSS_CHAIN_MESSAGE.NEW_DAO_SYMBOL, {
|
|
277
|
+
symbol: dao.symbol,
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
getDAOMetaData(daoMetaData, symbol) {
|
|
281
|
+
const dao = this.getDAO(symbol);
|
|
282
|
+
if (dao.metaDataLocation === "local") {
|
|
283
|
+
return daoMetaData[symbol.toLowerCase()];
|
|
284
|
+
}
|
|
285
|
+
return {};
|
|
286
|
+
}
|
|
287
|
+
/** Change lifecycle phase of a DAO */
|
|
288
|
+
changePhase(symbol) {
|
|
289
|
+
// anybody can call this
|
|
290
|
+
const dao = this.getDAO(symbol);
|
|
291
|
+
const currentTasks = this.tasks(symbol);
|
|
292
|
+
if (currentTasks.length > 0) {
|
|
293
|
+
throw new Error("SolveTasksFirst");
|
|
294
|
+
}
|
|
295
|
+
if (dao.phase === LifecyclePhase.DRAFT) {
|
|
296
|
+
const seed = dao.funding[this.getFundingIndex(symbol, FundingType.SEED)];
|
|
297
|
+
// SEED can be started not later than 1 week after must start
|
|
298
|
+
// todo settings.maxSeedStartDelay
|
|
299
|
+
if (seed.start < this.blockTimestamp &&
|
|
300
|
+
this.blockTimestamp - seed.start > 7 * 86400) {
|
|
301
|
+
throw new Error("TooLateSoSetupFundingAgain");
|
|
302
|
+
}
|
|
303
|
+
/*// SEED can be started not later than 1 week before end
|
|
304
|
+
if (seed.end - this.blockTimestamp < 7 * 86400) {
|
|
305
|
+
throw new Error("TooLateSoSetupFundingAgain")
|
|
306
|
+
}*/
|
|
307
|
+
this.daos[symbol].phase = LifecyclePhase.INCEPTION;
|
|
308
|
+
}
|
|
309
|
+
else if (dao.phase === LifecyclePhase.INCEPTION) {
|
|
310
|
+
const seed = dao.funding[this.getFundingIndex(symbol, FundingType.SEED)];
|
|
311
|
+
if (seed.start > this.blockTimestamp) {
|
|
312
|
+
throw new Error("WaitFundingStart");
|
|
313
|
+
}
|
|
314
|
+
// deploy seedToken
|
|
315
|
+
this.daos[symbol].deployments[this.chainId] = {
|
|
316
|
+
[ContractIndices.SEED_TOKEN_1]: "0xProxyDeployed",
|
|
317
|
+
};
|
|
318
|
+
this.daos[symbol].phase = LifecyclePhase.SEED;
|
|
319
|
+
}
|
|
320
|
+
else if (dao.phase === LifecyclePhase.SEED) {
|
|
321
|
+
const seed = dao.funding[this.getFundingIndex(symbol, FundingType.SEED)];
|
|
322
|
+
if (seed.end > this.blockTimestamp) {
|
|
323
|
+
throw new Error("WaitFundingEnd");
|
|
324
|
+
}
|
|
325
|
+
const success = seed.raised >= seed.minRaise;
|
|
326
|
+
if (success) {
|
|
327
|
+
this.daos[symbol].phase = LifecyclePhase.DEVELOPMENT;
|
|
328
|
+
}
|
|
329
|
+
else {
|
|
330
|
+
// send all raised back to seeders
|
|
331
|
+
this.daos[symbol].phase = LifecyclePhase.SEED_FAILED;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
else if (dao.phase === LifecyclePhase.DEVELOPMENT) {
|
|
335
|
+
const tge = dao.funding[this.getFundingIndex(symbol, FundingType.TGE)];
|
|
336
|
+
if (tge.start > this.blockTimestamp) {
|
|
337
|
+
throw new Error("WaitFundingStart");
|
|
338
|
+
}
|
|
339
|
+
// deploy tgeToken
|
|
340
|
+
this.daos[symbol].deployments[this.chainId][ContractIndices.TGE_TOKEN_2] =
|
|
341
|
+
"0xProxyDeployedTge";
|
|
342
|
+
this.daos[symbol].phase = LifecyclePhase.TGE;
|
|
343
|
+
}
|
|
344
|
+
else if (dao.phase === LifecyclePhase.TGE) {
|
|
345
|
+
const tge = dao.funding[this.getFundingIndex(symbol, FundingType.TGE)];
|
|
346
|
+
if (tge.end > this.blockTimestamp) {
|
|
347
|
+
throw new Error("WaitFundingEnd");
|
|
348
|
+
}
|
|
349
|
+
const success = tge.raised >= tge.minRaise;
|
|
350
|
+
if (success) {
|
|
351
|
+
// deploy token, xToken, staking, daoToken
|
|
352
|
+
this.daos[symbol].deployments[this.chainId][ContractIndices.TOKEN_3] =
|
|
353
|
+
"0xProxyToken";
|
|
354
|
+
this.daos[symbol].deployments[this.chainId][ContractIndices.X_TOKEN_4] =
|
|
355
|
+
"0xProxyXToken";
|
|
356
|
+
this.daos[symbol].deployments[this.chainId][ContractIndices.STAKING_6] =
|
|
357
|
+
"0xProxyStaking";
|
|
358
|
+
this.daos[symbol].deployments[this.chainId][ContractIndices.DAO_TOKEN_5] = "0xProxyDAOToken";
|
|
359
|
+
// todo deploy vesting contracts and allocate token
|
|
360
|
+
// todo seedToken holders became xToken holders by predefined rate
|
|
361
|
+
// todo deploy v2 liquidity from TGE funds at predefined price
|
|
362
|
+
this.daos[symbol].phase = LifecyclePhase.LIVE_CLIFF;
|
|
363
|
+
}
|
|
364
|
+
else {
|
|
365
|
+
// send all raised TGE funds back to funders
|
|
366
|
+
this.daos[symbol].phase = LifecyclePhase.DEVELOPMENT;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
else if (dao.phase === LifecyclePhase.LIVE_CLIFF) {
|
|
370
|
+
// if any vesting started then phase changed
|
|
371
|
+
const isVestingStarted = !!dao.vesting?.filter((v) => v.start < this.blockTimestamp).length;
|
|
372
|
+
if (!isVestingStarted) {
|
|
373
|
+
throw new Error("WaitVestingStart");
|
|
374
|
+
}
|
|
375
|
+
this.daos[symbol].phase = LifecyclePhase.LIVE_VESTING;
|
|
376
|
+
}
|
|
377
|
+
else if (dao.phase === LifecyclePhase.LIVE_VESTING) {
|
|
378
|
+
// if any vesting started then phase changed
|
|
379
|
+
const isVestingEnded = !dao.vesting?.filter((v) => v.end > this.blockTimestamp).length;
|
|
380
|
+
if (!isVestingEnded) {
|
|
381
|
+
throw new Error("WaitVestingEnd");
|
|
382
|
+
}
|
|
383
|
+
this.daos[symbol].phase = LifecyclePhase.LIVE;
|
|
384
|
+
}
|
|
385
|
+
else {
|
|
386
|
+
// nothing to change
|
|
387
|
+
throw new Error("ForeverLive");
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
/** @throws Error */
|
|
391
|
+
updateImages(symbol, images) {
|
|
392
|
+
// check DAO symbol
|
|
393
|
+
const dao = this.getDAO(symbol);
|
|
394
|
+
// instant execute for DRAFT
|
|
395
|
+
if (dao.phase === LifecyclePhase.DRAFT) {
|
|
396
|
+
this._onlyOwnerOf(symbol);
|
|
397
|
+
this._updateImages(symbol, images);
|
|
398
|
+
return true;
|
|
399
|
+
}
|
|
400
|
+
// create proposal for other phases
|
|
401
|
+
return this._proposeAction(symbol, DAOAction.UPDATE_IMAGES, {
|
|
402
|
+
images,
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
/** @throws Error */
|
|
406
|
+
updateSocials(symbol, socials) {
|
|
407
|
+
// check DAO symbol
|
|
408
|
+
const dao = this.getDAO(symbol);
|
|
409
|
+
// instant execute for DRAFT
|
|
410
|
+
if (dao.phase === LifecyclePhase.DRAFT) {
|
|
411
|
+
this._onlyOwnerOf(symbol);
|
|
412
|
+
this._updateSocials(symbol, socials);
|
|
413
|
+
return true;
|
|
414
|
+
}
|
|
415
|
+
// create proposal for other phases
|
|
416
|
+
return this._proposeAction(symbol, DAOAction.UPDATE_SOCIALS, {
|
|
417
|
+
socials,
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
/** @throws Error */
|
|
421
|
+
updateUnits(symbol, units, unitsMetaData) {
|
|
422
|
+
// check DAO symbol
|
|
423
|
+
const dao = this.getDAO(symbol);
|
|
424
|
+
// instant execute for DRAFT
|
|
425
|
+
if (dao.phase === LifecyclePhase.DRAFT) {
|
|
426
|
+
this._onlyOwnerOf(symbol);
|
|
427
|
+
this._updateUnits(symbol, units, unitsMetaData);
|
|
428
|
+
return true;
|
|
429
|
+
}
|
|
430
|
+
// create proposal for other phases
|
|
431
|
+
return this._proposeAction(symbol, DAOAction.UPDATE_UNITS, {
|
|
432
|
+
units,
|
|
433
|
+
unitsMetaData,
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
/** @throws Error */
|
|
437
|
+
updateFunding(symbol, funding) {
|
|
438
|
+
// check DAO symbol
|
|
439
|
+
const dao = this.getDAO(symbol);
|
|
440
|
+
// validate payload
|
|
441
|
+
this.validateFunding(dao.phase, [funding]);
|
|
442
|
+
// instant execute for DRAFT
|
|
443
|
+
if (dao.phase === LifecyclePhase.DRAFT) {
|
|
444
|
+
this._onlyOwnerOf(symbol);
|
|
445
|
+
this._updateFunding(symbol, funding);
|
|
446
|
+
return true;
|
|
447
|
+
}
|
|
448
|
+
// create proposal for other phases
|
|
449
|
+
return this._proposeAction(symbol, DAOAction.UPDATE_FUNDING, {
|
|
450
|
+
funding,
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
_updateSocials(symbol, socials) {
|
|
454
|
+
this.daos[symbol].socials = socials;
|
|
455
|
+
this._emit(`Action ${DAOAction.UPDATE_SOCIALS}`);
|
|
456
|
+
}
|
|
457
|
+
_updateUnits(symbol, units, unitsMetaData) {
|
|
458
|
+
this.daos[symbol].units = units;
|
|
459
|
+
this.daos[symbol].unitEmitData = unitsMetaData;
|
|
460
|
+
this._emit(`Action ${DAOAction.UPDATE_UNITS}`);
|
|
461
|
+
}
|
|
462
|
+
_updateFunding(symbol, funding) {
|
|
463
|
+
const dao = this.getDAO(symbol);
|
|
464
|
+
const fundingExist = dao.funding.filter((f) => f.type === funding.type).length === 1;
|
|
465
|
+
if (fundingExist) {
|
|
466
|
+
const fundingIndex = this.getFundingIndex(symbol, funding.type);
|
|
467
|
+
this.daos[symbol].funding[fundingIndex] = funding;
|
|
468
|
+
}
|
|
469
|
+
else {
|
|
470
|
+
this.daos[symbol].funding.push(funding);
|
|
471
|
+
}
|
|
472
|
+
this._emit(`Action ${DAOAction.UPDATE_FUNDING}`);
|
|
473
|
+
}
|
|
474
|
+
updateVesting(symbol, vestings) {
|
|
475
|
+
// check DAO symbol
|
|
476
|
+
const dao = this.getDAO(symbol);
|
|
477
|
+
// validate
|
|
478
|
+
this.validateVesting(dao.phase, vestings, this.getTgeData(dao));
|
|
479
|
+
// instant execute for DRAFT
|
|
480
|
+
if (dao.phase === LifecyclePhase.DRAFT) {
|
|
481
|
+
this._onlyOwnerOf(symbol);
|
|
482
|
+
this._updateVesting(symbol, vestings);
|
|
483
|
+
return true;
|
|
484
|
+
}
|
|
485
|
+
// create proposal for other phases
|
|
486
|
+
return this._proposeAction(symbol, DAOAction.UPDATE_VESTING, {
|
|
487
|
+
vestings,
|
|
488
|
+
});
|
|
489
|
+
}
|
|
490
|
+
revenue(symbol, unitIndex, asset, amount) {
|
|
491
|
+
// todo implement Host.whitelistedAssets
|
|
492
|
+
// receiving money, calculating usd (can appear later by Host Agent)
|
|
493
|
+
if (this.daos[symbol]) {
|
|
494
|
+
if (!this.daos[symbol].unitRevenue) {
|
|
495
|
+
this.daos[symbol].unitRevenue = [];
|
|
496
|
+
}
|
|
497
|
+
if (!this.daos[symbol].unitRevenue[unitIndex]) {
|
|
498
|
+
this.daos[symbol].unitRevenue[unitIndex] = {};
|
|
499
|
+
}
|
|
500
|
+
if (!this.daos[symbol].unitRevenue[unitIndex][asset]) {
|
|
501
|
+
this.daos[symbol].unitRevenue[unitIndex][asset] = 0n;
|
|
502
|
+
}
|
|
503
|
+
this.daos[symbol].unitRevenue[unitIndex][asset] += amount;
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
fund(symbol, amount) {
|
|
507
|
+
// todo settings.minFunding
|
|
508
|
+
const dao = this.getDAO(symbol);
|
|
509
|
+
if (dao.phase === LifecyclePhase.SEED) {
|
|
510
|
+
const seedIndex = this.getFundingIndex(symbol, FundingType.SEED);
|
|
511
|
+
const seed = dao.funding[seedIndex];
|
|
512
|
+
if (seed.raised + amount >= seed.maxRaise) {
|
|
513
|
+
throw new Error("RaiseMaxExceed");
|
|
514
|
+
}
|
|
515
|
+
// transfer amount of exchangeAsset to seedToken contract
|
|
516
|
+
this.daos[symbol].funding[seedIndex].raised += amount;
|
|
517
|
+
// mint seedToken to user
|
|
518
|
+
return;
|
|
519
|
+
}
|
|
520
|
+
if (dao.phase === LifecyclePhase.TGE) {
|
|
521
|
+
const tgeIndex = this.getFundingIndex(symbol, FundingType.TGE);
|
|
522
|
+
const tge = dao.funding[tgeIndex];
|
|
523
|
+
if (tge.raised + amount >= tge.maxRaise) {
|
|
524
|
+
throw new Error("RaiseMaxExceed");
|
|
525
|
+
}
|
|
526
|
+
// transfer amount of exchangeAsset to tgeToken contract
|
|
527
|
+
this.daos[symbol].funding[tgeIndex].raised += amount;
|
|
528
|
+
// mint tgeToken to user
|
|
529
|
+
return;
|
|
530
|
+
}
|
|
531
|
+
throw new Error("NotFundingPhase");
|
|
532
|
+
}
|
|
533
|
+
receiveVotingResults(proposalId, succeed) {
|
|
534
|
+
const proposal = this.proposals[proposalId];
|
|
535
|
+
if (!proposal) {
|
|
536
|
+
throw new Error("IncorrectProposal");
|
|
537
|
+
}
|
|
538
|
+
if (proposal.status !== VotingStatus.VOTING) {
|
|
539
|
+
throw new Error("AlreadyReceived");
|
|
540
|
+
}
|
|
541
|
+
this.proposals[proposalId].status = succeed
|
|
542
|
+
? VotingStatus.APPROVED
|
|
543
|
+
: VotingStatus.REJECTED;
|
|
544
|
+
if (succeed) {
|
|
545
|
+
if (proposal.action === DAOAction.UPDATE_IMAGES) {
|
|
546
|
+
this._updateImages(proposal.symbol, proposal.payload.images);
|
|
547
|
+
}
|
|
548
|
+
if (proposal.action === DAOAction.UPDATE_SOCIALS) {
|
|
549
|
+
this._updateSocials(proposal.symbol, proposal.payload.socials);
|
|
550
|
+
}
|
|
551
|
+
if (proposal.action === DAOAction.UPDATE_UNITS) {
|
|
552
|
+
this._updateUnits(proposal.symbol, proposal.payload.units, proposal.payload.unitsMetaData);
|
|
553
|
+
}
|
|
554
|
+
if (proposal.action === DAOAction.UPDATE_FUNDING) {
|
|
555
|
+
this._updateFunding(proposal.symbol, proposal.payload.funding);
|
|
556
|
+
}
|
|
557
|
+
if (proposal.action === DAOAction.UPDATE_VESTING) {
|
|
558
|
+
this._updateVesting(proposal.symbol, proposal.payload.vestings);
|
|
559
|
+
}
|
|
560
|
+
// todo other actions
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
/** OFF-CHAIN only **/
|
|
564
|
+
/** @throws Error */
|
|
565
|
+
roadmap(symbol) {
|
|
566
|
+
const dao = this.getDAO(symbol);
|
|
567
|
+
const r = [];
|
|
568
|
+
let tgeRun = 0;
|
|
569
|
+
for (const funding of dao.funding) {
|
|
570
|
+
if (funding.type === FundingType.SEED) {
|
|
571
|
+
r.push({
|
|
572
|
+
phase: LifecyclePhase.INCEPTION,
|
|
573
|
+
});
|
|
574
|
+
r.push({
|
|
575
|
+
phase: LifecyclePhase.SEED,
|
|
576
|
+
start: funding.start,
|
|
577
|
+
end: funding.end,
|
|
578
|
+
});
|
|
579
|
+
}
|
|
580
|
+
if (funding.type === FundingType.TGE) {
|
|
581
|
+
// if SEED was done
|
|
582
|
+
if (r.length > 0) {
|
|
583
|
+
r.push({
|
|
584
|
+
phase: LifecyclePhase.DEVELOPMENT,
|
|
585
|
+
start: r[0].end + 1,
|
|
586
|
+
end: funding.start - 1,
|
|
587
|
+
});
|
|
588
|
+
}
|
|
589
|
+
tgeRun = funding.claim || funding.end;
|
|
590
|
+
r.push({
|
|
591
|
+
phase: LifecyclePhase.TGE,
|
|
592
|
+
start: funding.start,
|
|
593
|
+
end: tgeRun,
|
|
594
|
+
});
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
if (dao.vesting.length > 0) {
|
|
598
|
+
let vestingStart = this.blockTimestamp;
|
|
599
|
+
let vestingEnd = this.blockTimestamp;
|
|
600
|
+
for (const vesting of dao.vesting) {
|
|
601
|
+
if (vesting.start < vestingStart) {
|
|
602
|
+
vestingStart = vesting.start;
|
|
603
|
+
}
|
|
604
|
+
if (vesting.end > vestingEnd) {
|
|
605
|
+
vestingEnd = vesting.end;
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
r.push({
|
|
609
|
+
phase: LifecyclePhase.LIVE_CLIFF,
|
|
610
|
+
start: tgeRun + 1,
|
|
611
|
+
end: vestingStart - 1,
|
|
612
|
+
});
|
|
613
|
+
r.push({
|
|
614
|
+
phase: LifecyclePhase.LIVE_VESTING,
|
|
615
|
+
start: vestingStart,
|
|
616
|
+
end: vestingEnd,
|
|
617
|
+
});
|
|
618
|
+
r.push({
|
|
619
|
+
phase: LifecyclePhase.LIVE,
|
|
620
|
+
start: vestingEnd + 1,
|
|
621
|
+
});
|
|
622
|
+
}
|
|
623
|
+
return r;
|
|
624
|
+
}
|
|
625
|
+
/** @throws Error */
|
|
626
|
+
tasks(symbol) {
|
|
627
|
+
const dao = this.getDAO(symbol);
|
|
628
|
+
const r = [];
|
|
629
|
+
if (dao.phase === LifecyclePhase.DRAFT) {
|
|
630
|
+
// images
|
|
631
|
+
if (!dao.images.seedToken || !dao.images.token) {
|
|
632
|
+
r.push({
|
|
633
|
+
name: "Need images of token and seedToken",
|
|
634
|
+
});
|
|
635
|
+
}
|
|
636
|
+
// socials
|
|
637
|
+
if (dao.socials.length < 2) {
|
|
638
|
+
r.push({
|
|
639
|
+
name: "Need at least 2 socials",
|
|
640
|
+
});
|
|
641
|
+
}
|
|
642
|
+
// units projected
|
|
643
|
+
if (dao.units.length === 0) {
|
|
644
|
+
r.push({
|
|
645
|
+
name: "Need at least 1 projected unit",
|
|
646
|
+
});
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
else if (dao.phase === LifecyclePhase.INCEPTION) {
|
|
650
|
+
// only off-chain tasks, mean SEED will be started anyway
|
|
651
|
+
// todo off-chain tasks like minimal socials users number, units emitted data, etc
|
|
652
|
+
}
|
|
653
|
+
else if (dao.phase === LifecyclePhase.SEED) {
|
|
654
|
+
const seedIndex = this.getFundingIndex(symbol, FundingType.SEED);
|
|
655
|
+
if (dao.funding[seedIndex].raised < dao.funding[seedIndex].minRaise &&
|
|
656
|
+
dao.funding[seedIndex].end > this.blockTimestamp) {
|
|
657
|
+
r.push({
|
|
658
|
+
name: "Need attract minimal seed funding",
|
|
659
|
+
});
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
else if (dao.phase === LifecyclePhase.DEVELOPMENT) {
|
|
663
|
+
// check funding
|
|
664
|
+
const tgeExist = dao.funding.filter((f) => f.type === FundingType.TGE).length === 1;
|
|
665
|
+
if (!tgeExist) {
|
|
666
|
+
r.push({
|
|
667
|
+
name: "Need add pre-TGE funding",
|
|
668
|
+
});
|
|
669
|
+
}
|
|
670
|
+
// images
|
|
671
|
+
if (!dao.images.tgeToken || !dao.images.xToken || !dao.images.daoToken) {
|
|
672
|
+
r.push({
|
|
673
|
+
name: "Need images of all DAO tokens",
|
|
674
|
+
});
|
|
675
|
+
}
|
|
676
|
+
// setup vesting allocations
|
|
677
|
+
if (!dao.vesting?.length) {
|
|
678
|
+
r.push({
|
|
679
|
+
name: "Need vesting allocations",
|
|
680
|
+
});
|
|
681
|
+
}
|
|
682
|
+
if (!this.hasRevenue(dao.symbol)) {
|
|
683
|
+
r.push({
|
|
684
|
+
name: "Start generate revenue",
|
|
685
|
+
});
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
else if (dao.phase === LifecyclePhase.TGE) {
|
|
689
|
+
const tgeIndex = this.getFundingIndex(symbol, FundingType.TGE);
|
|
690
|
+
if (dao.funding[tgeIndex].raised < dao.funding[tgeIndex].minRaise &&
|
|
691
|
+
dao.funding[tgeIndex].end > this.blockTimestamp) {
|
|
692
|
+
r.push({
|
|
693
|
+
name: "Need attract minimal TGE funding",
|
|
694
|
+
});
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
else if (dao.phase === LifecyclePhase.LIVE_CLIFF) {
|
|
698
|
+
// establish and improve
|
|
699
|
+
// build money markets
|
|
700
|
+
// bridge to chains
|
|
701
|
+
}
|
|
702
|
+
else if (dao.phase === LifecyclePhase.LIVE_VESTING) {
|
|
703
|
+
// distribute vesting funds to leverage token
|
|
704
|
+
}
|
|
705
|
+
/*if (dao.phase === LifecyclePhase.LIVE)*/
|
|
706
|
+
// lifetime revenue generating for DAO holders (till ABSORBED proposed feature)
|
|
707
|
+
return r;
|
|
708
|
+
}
|
|
709
|
+
/** Strict on-chain validation */
|
|
710
|
+
/** @throws Error */
|
|
711
|
+
validate(dao) {
|
|
712
|
+
this.validateName(dao.name);
|
|
713
|
+
this.validateSymbol(dao.symbol);
|
|
714
|
+
if (dao.params.vePeriod < this.settings.minVePeriod ||
|
|
715
|
+
dao.params.vePeriod > this.settings.maxVePeriod) {
|
|
716
|
+
throw new Error(`VePeriod(${dao.params.vePeriod})`);
|
|
717
|
+
}
|
|
718
|
+
this.validatePvpFee(dao.params.pvpFee);
|
|
719
|
+
if (!dao.funding.length) {
|
|
720
|
+
throw new Error("NeedFunding");
|
|
721
|
+
}
|
|
722
|
+
// check activity are correct
|
|
723
|
+
this.validateActivity(dao.activity);
|
|
724
|
+
// todo: check funding array has unique funding types
|
|
725
|
+
// todo: check funding dates
|
|
726
|
+
// todo: check funding raise goals
|
|
727
|
+
}
|
|
728
|
+
/** @throws Error */
|
|
729
|
+
getDAO(symbol) {
|
|
730
|
+
if (this.daos[symbol]) {
|
|
731
|
+
return this.daos[symbol];
|
|
732
|
+
}
|
|
733
|
+
throw new Error("DAONotFound");
|
|
734
|
+
}
|
|
735
|
+
getDaoOwner(symbol) {
|
|
736
|
+
const dao = this.getDAO(symbol);
|
|
737
|
+
if (dao.phase === LifecyclePhase.DRAFT) {
|
|
738
|
+
return dao.deployer;
|
|
739
|
+
}
|
|
740
|
+
if ([
|
|
741
|
+
LifecyclePhase.SEED,
|
|
742
|
+
LifecyclePhase.DEVELOPMENT,
|
|
743
|
+
LifecyclePhase.TGE,
|
|
744
|
+
].includes(dao.phase)) {
|
|
745
|
+
return dao.deployments[(0, chains_1.getChainByName)(dao.initialChain).chainId][ContractIndices.SEED_TOKEN_1];
|
|
746
|
+
}
|
|
747
|
+
return dao.deployments[this.chainId][ContractIndices.DAO_TOKEN_5];
|
|
748
|
+
}
|
|
749
|
+
hasRevenue(symbol) {
|
|
750
|
+
const dao = this.getDAO(symbol);
|
|
751
|
+
if (dao.unitRevenue) {
|
|
752
|
+
for (const unitRevenue of dao.unitRevenue) {
|
|
753
|
+
for (const asset of Object.keys(unitRevenue)) {
|
|
754
|
+
if (unitRevenue[asset] > 0n) {
|
|
755
|
+
return true;
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
return false;
|
|
761
|
+
}
|
|
762
|
+
getTgeData(dao) {
|
|
763
|
+
const fundingExist = dao.funding.filter((f) => f.type === FundingType.TGE).length === 1;
|
|
764
|
+
if (fundingExist) {
|
|
765
|
+
const fundingIndex = this.getFundingIndex(dao.symbol, FundingType.TGE);
|
|
766
|
+
return dao.funding[fundingIndex];
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
getFundingIndex(symbol, type) {
|
|
770
|
+
const dao = this.getDAO(symbol);
|
|
771
|
+
for (let i = 0; i < dao.funding.length; i++) {
|
|
772
|
+
if (type === dao.funding[i].type) {
|
|
773
|
+
return i;
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
throw new Error("FundingNotFound");
|
|
777
|
+
}
|
|
778
|
+
warpDays(days = 7) {
|
|
779
|
+
this.blockTimestamp += days * 86400;
|
|
780
|
+
}
|
|
781
|
+
/** @throws Error */
|
|
782
|
+
_onlyOwnerOf(symbol) {
|
|
783
|
+
if (this.from != this.getDaoOwner(symbol)) {
|
|
784
|
+
throw new Error(`YouAreNotOwnerOf(${symbol})`);
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
_emit(event) {
|
|
788
|
+
this.events.push(event);
|
|
789
|
+
}
|
|
790
|
+
validateName(name) {
|
|
791
|
+
if (name.length < this.settings.minNameLength ||
|
|
792
|
+
name.length > this.settings.maxNameLength) {
|
|
793
|
+
throw new Error(`NameLength(${name.length})`);
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
validateSymbol(symbol) {
|
|
797
|
+
if (symbol.length < this.settings.minSymbolLength ||
|
|
798
|
+
symbol.length > this.settings.maxSymbolLength) {
|
|
799
|
+
throw new Error(`SymbolLength(${symbol.length})`);
|
|
800
|
+
}
|
|
801
|
+
if (this.usedSymbols[symbol]) {
|
|
802
|
+
throw new Error(`SymbolNotUnique(${symbol})`);
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
validatePvpFee(pvpFee) {
|
|
806
|
+
if (pvpFee < this.settings.minPvPFee || pvpFee > this.settings.maxPvPFee) {
|
|
807
|
+
throw new Error(`PvPFee(${pvpFee})`);
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
validateFunding(daoPhase, fundings) {
|
|
811
|
+
validation_1.Validation.validateFunding(daoPhase, fundings, this.settings);
|
|
812
|
+
}
|
|
813
|
+
validateActivity(activity) {
|
|
814
|
+
validation_1.Validation.validateActivity(activity);
|
|
815
|
+
}
|
|
816
|
+
validateVesting(daoPhase, vestings, tge) {
|
|
817
|
+
validation_1.Validation.validateVesting(daoPhase, vestings, this.settings, tge);
|
|
818
|
+
}
|
|
819
|
+
_sendCrossChainMessage(type, payload) {
|
|
820
|
+
// todo some stub
|
|
821
|
+
}
|
|
822
|
+
_proposeAction(symbol, action, payload) {
|
|
823
|
+
const dao = this.getDAO(symbol);
|
|
824
|
+
// todo check for initial chain
|
|
825
|
+
// todo get user power
|
|
826
|
+
// todo check proposalThreshold
|
|
827
|
+
// todo validate payload
|
|
828
|
+
const proposalId = Math.round(Math.random() * Math.random()).toString();
|
|
829
|
+
this.proposals[proposalId] = {
|
|
830
|
+
id: proposalId,
|
|
831
|
+
created: this.blockTimestamp,
|
|
832
|
+
action,
|
|
833
|
+
symbol,
|
|
834
|
+
payload,
|
|
835
|
+
status: VotingStatus.VOTING,
|
|
836
|
+
};
|
|
837
|
+
return proposalId;
|
|
838
|
+
}
|
|
839
|
+
_updateImages(symbol, images) {
|
|
840
|
+
this.daos[symbol].images = images;
|
|
841
|
+
this._emit(`Action ${DAOAction.UPDATE_IMAGES}`);
|
|
842
|
+
}
|
|
843
|
+
_updateVesting(symbol, vestings) {
|
|
844
|
+
this.daos[symbol].vesting = vestings;
|
|
845
|
+
this._emit(`Action ${DAOAction.UPDATE_VESTING}`);
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
exports.Host = Host;
|
|
849
|
+
var DAOAction;
|
|
850
|
+
(function (DAOAction) {
|
|
851
|
+
DAOAction[DAOAction["UPDATE_IMAGES"] = 0] = "UPDATE_IMAGES";
|
|
852
|
+
DAOAction[DAOAction["UPDATE_SOCIALS"] = 1] = "UPDATE_SOCIALS";
|
|
853
|
+
DAOAction[DAOAction["UPDATE_NAMING"] = 2] = "UPDATE_NAMING";
|
|
854
|
+
DAOAction[DAOAction["UPDATE_UNITS"] = 3] = "UPDATE_UNITS";
|
|
855
|
+
DAOAction[DAOAction["UPDATE_FUNDING"] = 4] = "UPDATE_FUNDING";
|
|
856
|
+
DAOAction[DAOAction["UPDATE_VESTING"] = 5] = "UPDATE_VESTING";
|
|
857
|
+
})(DAOAction || (exports.DAOAction = DAOAction = {}));
|
|
858
|
+
var VotingStatus;
|
|
859
|
+
(function (VotingStatus) {
|
|
860
|
+
VotingStatus[VotingStatus["VOTING"] = 0] = "VOTING";
|
|
861
|
+
VotingStatus[VotingStatus["APPROVED"] = 1] = "APPROVED";
|
|
862
|
+
VotingStatus[VotingStatus["REJECTED"] = 2] = "REJECTED";
|
|
863
|
+
})(VotingStatus || (VotingStatus = {}));
|
|
864
|
+
var CROSS_CHAIN_MESSAGE;
|
|
865
|
+
(function (CROSS_CHAIN_MESSAGE) {
|
|
866
|
+
CROSS_CHAIN_MESSAGE[CROSS_CHAIN_MESSAGE["NEW_DAO_SYMBOL"] = 0] = "NEW_DAO_SYMBOL";
|
|
867
|
+
CROSS_CHAIN_MESSAGE[CROSS_CHAIN_MESSAGE["DAO_RENAME_SYMBOL"] = 1] = "DAO_RENAME_SYMBOL";
|
|
868
|
+
CROSS_CHAIN_MESSAGE[CROSS_CHAIN_MESSAGE["DAO_BRIDGED"] = 2] = "DAO_BRIDGED";
|
|
869
|
+
})(CROSS_CHAIN_MESSAGE || (CROSS_CHAIN_MESSAGE = {}));
|
|
870
|
+
function getUnit(daos, unitId) {
|
|
871
|
+
for (const dao of daos) {
|
|
872
|
+
for (const unit of dao.units) {
|
|
873
|
+
if (unit.unitId === unitId) {
|
|
874
|
+
return unit;
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
function getDAOUnit(daos, symbol, unitId) {
|
|
880
|
+
for (const dao of daos) {
|
|
881
|
+
if (dao.symbol.toLowerCase() === symbol.toLowerCase()) {
|
|
882
|
+
for (const unit of dao.units) {
|
|
883
|
+
if (unit.unitId === unitId) {
|
|
884
|
+
return unit;
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
function getDAOUnitMetaData(daos, symbol, unitId) {
|
|
891
|
+
for (const dao of daos) {
|
|
892
|
+
if (dao.symbol.toLowerCase() === symbol.toLowerCase()) {
|
|
893
|
+
for (let i = 0; i < dao.units.length; i++) {
|
|
894
|
+
const unit = dao.units[i];
|
|
895
|
+
if (unit.unitId === unitId) {
|
|
896
|
+
return dao.unitEmitData[i];
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
function getUnitMetaData(daos, unitId) {
|
|
903
|
+
for (const dao of daos) {
|
|
904
|
+
for (let i = 0; i < dao.units.length; i++) {
|
|
905
|
+
const unit = dao.units[i];
|
|
906
|
+
if (unit.unitId === unitId) {
|
|
907
|
+
return dao.unitEmitData[i];
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
function getBridgeTokens(daos) {
|
|
913
|
+
const r = {};
|
|
914
|
+
for (const dao of daos) {
|
|
915
|
+
const deploymentChainIds = Object.keys(dao.deployments);
|
|
916
|
+
if (deploymentChainIds.length > 1) {
|
|
917
|
+
for (const chainId of deploymentChainIds) {
|
|
918
|
+
const tokenAddress = dao.deployments[chainId][ContractIndices.TOKEN_3];
|
|
919
|
+
const tokenBridge = dao.deployments[chainId][ContractIndices.TOKEN_BRIDGE_8];
|
|
920
|
+
const xTokenAddress = dao.deployments[chainId][ContractIndices.X_TOKEN_4];
|
|
921
|
+
const xTokenBridge = dao.deployments[chainId][ContractIndices.X_TOKEN_BRIDGE_9];
|
|
922
|
+
if (tokenAddress && tokenBridge) {
|
|
923
|
+
const tokenData = (0, assets_1.getTokenData)(chainId, tokenAddress);
|
|
924
|
+
if (tokenData) {
|
|
925
|
+
if (!r[chainId]) {
|
|
926
|
+
r[chainId] = [];
|
|
927
|
+
}
|
|
928
|
+
r[chainId].push({
|
|
929
|
+
tokenData,
|
|
930
|
+
bridge: tokenBridge,
|
|
931
|
+
});
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
if (xTokenAddress && xTokenBridge) {
|
|
935
|
+
const tokenData = (0, assets_1.getTokenData)(chainId, xTokenAddress);
|
|
936
|
+
if (tokenData) {
|
|
937
|
+
r[chainId].push({
|
|
938
|
+
tokenData,
|
|
939
|
+
bridge: xTokenBridge,
|
|
940
|
+
});
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
return r;
|
|
947
|
+
}
|
|
948
|
+
//# sourceMappingURL=host.js.map
|