polkamarkets-js 1.0.2 → 3.1.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.
Files changed (163) hide show
  1. package/.openzeppelin/unknown-1337.json +2056 -0
  2. package/CONTRIBUTING.md +36 -0
  3. package/README.md +24 -25
  4. package/_book/README.md +590 -0
  5. package/_book/core.md +50 -0
  6. package/_book/gitbook/fonts/fontawesome/FontAwesome.otf +0 -0
  7. package/_book/gitbook/fonts/fontawesome/fontawesome-webfont.eot +0 -0
  8. package/_book/gitbook/fonts/fontawesome/fontawesome-webfont.svg +685 -0
  9. package/_book/gitbook/fonts/fontawesome/fontawesome-webfont.ttf +0 -0
  10. package/_book/gitbook/fonts/fontawesome/fontawesome-webfont.woff +0 -0
  11. package/_book/gitbook/fonts/fontawesome/fontawesome-webfont.woff2 +0 -0
  12. package/_book/gitbook/gitbook-plugin-fontsettings/fontsettings.js +240 -0
  13. package/_book/gitbook/gitbook-plugin-fontsettings/website.css +291 -0
  14. package/_book/gitbook/gitbook-plugin-highlight/ebook.css +135 -0
  15. package/_book/gitbook/gitbook-plugin-highlight/website.css +434 -0
  16. package/_book/gitbook/gitbook-plugin-lunr/lunr.min.js +7 -0
  17. package/_book/gitbook/gitbook-plugin-lunr/search-lunr.js +59 -0
  18. package/_book/gitbook/gitbook-plugin-search/lunr.min.js +7 -0
  19. package/_book/gitbook/gitbook-plugin-search/search-engine.js +50 -0
  20. package/_book/gitbook/gitbook-plugin-search/search.css +35 -0
  21. package/_book/gitbook/gitbook-plugin-search/search.js +213 -0
  22. package/_book/gitbook/gitbook-plugin-sharing/buttons.js +90 -0
  23. package/_book/gitbook/gitbook.js +4 -0
  24. package/_book/gitbook/images/apple-touch-icon-precomposed-152.png +0 -0
  25. package/_book/gitbook/images/favicon.ico +0 -0
  26. package/_book/gitbook/style.css +9 -0
  27. package/_book/gitbook/theme.js +4 -0
  28. package/_book/index.html +705 -0
  29. package/_book/intro.md +32 -0
  30. package/_book/search_index.json +1 -0
  31. package/book.json +8 -0
  32. package/build/contracts/AccessControl.json +1 -0
  33. package/build/contracts/AccessControlEnumerable.json +1 -0
  34. package/build/contracts/Achievements.json +1 -0
  35. package/build/contracts/Address.json +1 -0
  36. package/build/contracts/BalanceHolder.json +1 -0
  37. package/build/contracts/BalanceHolder_ERC20.json +1 -0
  38. package/build/contracts/CeilDiv.json +1 -0
  39. package/build/contracts/Clones.json +1 -0
  40. package/build/contracts/Context.json +1 -0
  41. package/build/contracts/Counters.json +1 -0
  42. package/build/contracts/ERC165.json +1 -0
  43. package/build/contracts/ERC20.json +1 -0
  44. package/build/contracts/ERC20Burnable.json +1 -0
  45. package/build/contracts/ERC20Pausable.json +1 -0
  46. package/build/contracts/ERC20PresetMinterPauser.json +1 -0
  47. package/build/contracts/ERC721.json +1 -0
  48. package/build/contracts/EnumerableMap.json +1 -0
  49. package/build/contracts/EnumerableSet.json +1 -0
  50. package/build/contracts/FantasyERC20.json +1 -0
  51. package/build/contracts/IAccessControl.json +1 -0
  52. package/build/contracts/IAccessControlEnumerable.json +1 -0
  53. package/build/contracts/IBalanceHolder_ERC20.json +1 -0
  54. package/build/contracts/IERC165.json +1 -0
  55. package/build/contracts/IERC20.json +1 -0
  56. package/build/contracts/IERC20Metadata.json +1 -0
  57. package/build/contracts/IERC20Permit.json +1 -0
  58. package/build/contracts/IERC721.json +1 -0
  59. package/build/contracts/IERC721Enumerable.json +1 -0
  60. package/build/contracts/IERC721Metadata.json +1 -0
  61. package/build/contracts/IERC721Receiver.json +1 -0
  62. package/build/contracts/IFantasyERC20.json +1 -0
  63. package/build/contracts/IPredictionMarketV3.json +1 -0
  64. package/build/contracts/IPredictionMarketV3Factory.json +1 -0
  65. package/build/contracts/IPredictionMarketV3Manager.json +1 -0
  66. package/build/contracts/IRealityETH_ERC20.json +1 -0
  67. package/build/contracts/IRealityETH_IERC20.json +1 -0
  68. package/build/contracts/IWETH.json +1 -0
  69. package/build/contracts/LandFactory.json +1 -0
  70. package/build/contracts/Math.json +1 -0
  71. package/build/contracts/Migrations.json +1 -0
  72. package/build/contracts/Ownable.json +1 -0
  73. package/build/contracts/Pausable.json +1 -0
  74. package/build/contracts/PredictionMarket.json +1 -0
  75. package/build/contracts/PredictionMarketV2.json +1 -0
  76. package/build/contracts/PredictionMarketV3.json +1 -0
  77. package/build/contracts/PredictionMarketV3Controller.json +1 -0
  78. package/build/contracts/PredictionMarketV3Factory.json +1 -0
  79. package/build/contracts/PredictionMarketV3Manager.json +1 -0
  80. package/build/contracts/PredictionMarketV3Querier.json +1 -0
  81. package/build/contracts/RealitioERC20.json +1 -0
  82. package/build/contracts/RealitioForeignArbitrationProxyWithAppeals.json +1 -0
  83. package/build/contracts/RealitioHomeArbitrationProxy.json +1 -0
  84. package/build/contracts/RealitioSafeMath256.json +1 -0
  85. package/build/contracts/RealitioSafeMath32.json +1 -0
  86. package/build/contracts/RealityETH_ERC20_Factory.json +1 -0
  87. package/build/contracts/RealityETH_ERC20_v3_0.json +1 -0
  88. package/build/contracts/ReentrancyGuard.json +1 -0
  89. package/build/contracts/SafeERC20.json +1 -0
  90. package/build/contracts/SafeMath.json +1 -0
  91. package/build/contracts/Strings.json +1 -0
  92. package/build/contracts/Voting.json +1 -0
  93. package/build/contracts/WETH9.json +1 -0
  94. package/build/contracts/test.json +1 -0
  95. package/cleanContracts.js +22 -0
  96. package/contracts/FantasyERC20.sol +81 -0
  97. package/contracts/IFantasyERC20.sol +20 -0
  98. package/contracts/IPredictionMarketV3.sol +207 -0
  99. package/contracts/IPredictionMarketV3Factory.sol +10 -0
  100. package/contracts/IPredictionMarketV3Manager.sol +12 -0
  101. package/contracts/IRealityETH_ERC20.sol +64 -0
  102. package/contracts/LandFactory.sol +248 -0
  103. package/contracts/Migrations.sol +24 -0
  104. package/contracts/PredictionMarketV3.sol +1332 -0
  105. package/contracts/PredictionMarketV3Controller.sol +87 -0
  106. package/contracts/PredictionMarketV3Factory.sol +205 -0
  107. package/contracts/PredictionMarketV3Manager.sol +45 -0
  108. package/contracts/PredictionMarketV3Querier.sol +79 -0
  109. package/contracts/RealityETH_ERC20_Factory.sol +54 -0
  110. package/contracts/Voting.sol +153 -0
  111. package/contracts/WETH9.sol +62 -0
  112. package/help.txt +8 -0
  113. package/index.js +3 -0
  114. package/migrations/10_deploy_weth.js +5 -0
  115. package/migrations/11_deploy_full_flow.js +99 -0
  116. package/migrations/12_deploy_pm_v3_querier.js +7 -0
  117. package/migrations/13_deploy_pm_v3_factory.js +14 -0
  118. package/migrations/1_initial_migration.js +5 -0
  119. package/migrations/2_deploy_erc20.js +10 -0
  120. package/migrations/3_deploy_realitio.js +11 -0
  121. package/migrations/4_deploy_pm.js +20 -0
  122. package/migrations/5_seed_markets.js +51 -0
  123. package/migrations/6_deploy_achievements.js +5 -0
  124. package/migrations/7_deploy_voting.js +14 -0
  125. package/migrations/8_deploy_pm_v2.js +20 -0
  126. package/migrations/9_seed_markets_v2.js +68 -0
  127. package/package.json +106 -13
  128. package/src/Application.js +421 -0
  129. package/src/interfaces/index.js +19 -0
  130. package/src/models/AchievementsContract.js +217 -0
  131. package/src/models/ArbitrationContract.js +69 -0
  132. package/src/models/ArbitrationProxyContract.js +32 -0
  133. package/src/models/ERC20Contract.js +156 -0
  134. package/src/models/FantasyERC20Contract.js +92 -0
  135. package/src/models/IContract.js +1002 -0
  136. package/src/models/PolkamarketsSmartAccount.js +100 -0
  137. package/src/models/PredictionMarketContract.js +562 -0
  138. package/src/models/PredictionMarketV2Contract.js +830 -0
  139. package/src/models/PredictionMarketV3Contract.js +233 -0
  140. package/src/models/PredictionMarketV3ControllerContract.js +102 -0
  141. package/src/models/PredictionMarketV3FactoryContract.js +96 -0
  142. package/src/models/PredictionMarketV3ManagerContract.js +111 -0
  143. package/src/models/PredictionMarketV3QuerierContract.js +24 -0
  144. package/src/models/RealitioERC20Contract.js +286 -0
  145. package/src/models/VotingContract.js +182 -0
  146. package/src/models/WETH9Contract.js +92 -0
  147. package/src/models/index.js +33 -0
  148. package/src/utils/Account.js +40 -0
  149. package/src/utils/Contract.js +120 -0
  150. package/src/utils/Numbers.js +94 -0
  151. package/tests/fantasyERC20Contract.js +225 -0
  152. package/tests/index.js +10 -0
  153. package/tests/predictionMarketContract.js +466 -0
  154. package/tests/predictionMarketV2Contract.js +1042 -0
  155. package/tests/predictionMarketV3Contract.js +1079 -0
  156. package/tests/predictionMarketV3ControllerContract.js +613 -0
  157. package/tests/predictionMarketV3FactoryContract.js +469 -0
  158. package/tests/predictionMarketV3ManagerContract.js +610 -0
  159. package/tests/utils.js +16 -0
  160. package/tests/votingContract.js +490 -0
  161. package/tooling/docs/jsdoc.json +6 -0
  162. package/truffle-config.js +134 -0
  163. package/polkamarkets.js +0 -436
@@ -0,0 +1,613 @@
1
+
2
+
3
+ import { expect } from 'chai';
4
+ import moment from 'moment';
5
+
6
+ import { mochaAsync } from './utils';
7
+ import { Application } from '..';
8
+
9
+ context('Prediction Market Contract V3 Controller', async () => {
10
+ require('dotenv').config();
11
+
12
+ const TOKEN_AMOUNT_TO_CLAIM = 10;
13
+ const LOCK_AMOUNT = 5;
14
+
15
+ const USER1_ADDRESS = process.env.TEST_USER1_ADDRESS;
16
+ const USER1_PRIVATE_KEY = process.env.TEST_USER1_PRIVATE_KEY;
17
+ const USER2_ADDRESS = process.env.TEST_USER2_ADDRESS;
18
+
19
+ let app;
20
+ let accountAddress;
21
+ let predictionMarketContract;
22
+ let predictionMarketFactoryContract;
23
+ let predictionMarketControllerContract;
24
+ let realitioERC20Contract
25
+ let pmfTokenContract;
26
+
27
+ context('Contract Deployment', async () => {
28
+ it('should start the Application', mochaAsync(async () => {
29
+ app = new Application({
30
+ web3Provider: process.env.WEB3_PROVIDER,
31
+ web3PrivateKey: process.env.WEB3_PRIVATE_KEY
32
+ });
33
+ expect(app).to.not.equal(null);
34
+ }));
35
+
36
+ it('should deploy Prediction Market Controller Contract', mochaAsync(async () => {
37
+ accountAddress = await app.getAddress();
38
+
39
+ // Create Contract
40
+ predictionMarketContract = app.getPredictionMarketV3Contract({});
41
+ pmfTokenContract = app.getERC20Contract({});
42
+ realitioERC20Contract = app.getRealitioERC20Contract({});
43
+
44
+ await realitioERC20Contract.deploy({});
45
+
46
+ // Deploy
47
+ await pmfTokenContract.deploy({ params: ['Polkamarkets', 'POLK'] });
48
+ const pmfTokenContractAddress = pmfTokenContract.getAddress();
49
+
50
+ predictionMarketFactoryContract = app.getPredictionMarketV3FactoryContract({});
51
+ // Deploy
52
+ await predictionMarketContract.deploy({
53
+ params: [
54
+ '0x0000000000000000000000000000000000000000'
55
+ ]
56
+ });
57
+ const predictionMarketContractAddress = predictionMarketContract.getAddress();
58
+
59
+ await predictionMarketFactoryContract.deploy({
60
+ params:
61
+ [
62
+ pmfTokenContractAddress,
63
+ (LOCK_AMOUNT * 10 ** 18).toString(), // TODO: improve this
64
+ predictionMarketContractAddress,
65
+ realitioERC20Contract.getAddress()
66
+ ]
67
+ });
68
+ const predictionMarketFactoryContractAddress = predictionMarketFactoryContract.getAddress();
69
+
70
+ await pmfTokenContract.mint({
71
+ address: accountAddress,
72
+ amount: '1000'
73
+ });
74
+ await pmfTokenContract.approve({
75
+ address: predictionMarketFactoryContractAddress,
76
+ amount: '1000000'
77
+ });
78
+
79
+ await predictionMarketFactoryContract.createPMController({
80
+ PMV3: predictionMarketContract.getAddress(),
81
+ WETH: '0x0000000000000000000000000000000000000000',
82
+ realitioLibraryAddress: realitioERC20Contract.getAddress(),
83
+ });
84
+
85
+ const predictionMarketControllerAddress = await predictionMarketFactoryContract.getPMControllerAddressById({
86
+ id: 0
87
+ });
88
+
89
+ expect(predictionMarketControllerAddress).to.not.equal(null);
90
+
91
+ predictionMarketControllerContract = app.getPredictionMarketV3ControllerContract({ contractAddress: predictionMarketControllerAddress });
92
+
93
+ expect(predictionMarketControllerContract).to.not.equal(null);
94
+ expect(predictionMarketContractAddress).to.not.equal(null);
95
+ expect(pmfTokenContractAddress).to.not.equal(null);
96
+ }));
97
+ });
98
+
99
+ context('Land Management', async () => {
100
+ context('Land Creation', async () => {
101
+ it('should create a Land', mochaAsync(async () => {
102
+ const currentLandIndex = await predictionMarketControllerContract.getLandTokensLength();
103
+
104
+ await predictionMarketControllerContract.createLand({
105
+ name: 'Token',
106
+ symbol: 'TOKEN',
107
+ tokenAmountToClaim: TOKEN_AMOUNT_TO_CLAIM,
108
+ tokenToAnswer: pmfTokenContract.getAddress(),
109
+ everyoneCanCreateMarkets: false
110
+ });
111
+
112
+ const land = await predictionMarketControllerContract.getLandById({ id: currentLandIndex });
113
+ const newLandIndex = await predictionMarketControllerContract.getLandTokensLength();
114
+
115
+ expect(newLandIndex).to.equal(currentLandIndex + 1);
116
+ expect(land.token).to.not.equal('0x0000000000000000000000000000000000000000');
117
+ expect(land.active).to.equal(true);
118
+ expect(land.everyoneCanCreateMarkets).to.equal(false);
119
+ expect(land.realitio).to.not.equal('0x0000000000000000000000000000000000000000');
120
+ }));
121
+
122
+ it('should create another Land', mochaAsync(async () => {
123
+ const currentLandIndex = await predictionMarketControllerContract.getLandTokensLength();
124
+
125
+ await predictionMarketControllerContract.createLand({
126
+ name: 'Token 2',
127
+ symbol: 'TOKEN2',
128
+ tokenAmountToClaim: TOKEN_AMOUNT_TO_CLAIM,
129
+ tokenToAnswer: pmfTokenContract.getAddress(),
130
+ everyoneCanCreateMarkets: true
131
+ });
132
+ const land = await predictionMarketControllerContract.getLandById({ id: currentLandIndex });
133
+ const newLandIndex = await predictionMarketControllerContract.getLandTokensLength();
134
+
135
+ expect(newLandIndex).to.equal(currentLandIndex + 1);
136
+ expect(land.token).to.not.equal('0x0000000000000000000000000000000000000000');
137
+ expect(land.active).to.equal(true);
138
+ expect(land.everyoneCanCreateMarkets).to.equal(true);
139
+ expect(land.realitio).to.not.equal('0x0000000000000000000000000000000000000000');
140
+ }));
141
+ });
142
+
143
+ context('Land Admins', async () => {
144
+ let landId = 0;
145
+ let token;
146
+
147
+ const user1 = USER1_ADDRESS;
148
+ const user2 = USER2_ADDRESS;
149
+
150
+ let user1App;
151
+ let user1PredictionMarketControllerContract;
152
+
153
+ before(mochaAsync(async () => {
154
+ const land = await predictionMarketControllerContract.getLandById({ id: landId });
155
+ token = land.token;
156
+
157
+ user1App = new Application({
158
+ web3Provider: process.env.WEB3_PROVIDER,
159
+ web3PrivateKey: USER1_PRIVATE_KEY
160
+ });
161
+ user1PredictionMarketControllerContract = user1App.getPredictionMarketV3ControllerContract({
162
+ contractAddress: predictionMarketControllerContract.getAddress()
163
+ });
164
+ }));
165
+
166
+ it('should add an admin to a Land', mochaAsync(async () => {
167
+ const currentIsAdmin = await predictionMarketControllerContract.isLandAdmin({ token, user: user2 });
168
+ await predictionMarketControllerContract.addAdminToLand({
169
+ token,
170
+ user: user2
171
+ });
172
+ const newIsAdmin = await predictionMarketControllerContract.isLandAdmin({ token, user: user2 });
173
+
174
+ expect(currentIsAdmin).to.equal(false);
175
+ expect(newIsAdmin).to.equal(true);
176
+ }));
177
+
178
+ it('should remove an admin from a Land', mochaAsync(async () => {
179
+ const currentIsAdmin = await predictionMarketControllerContract.isLandAdmin({ token, user: user2 });
180
+ await predictionMarketControllerContract.removeAdminFromLand({
181
+ token,
182
+ user: user2
183
+ });
184
+ const newIsAdmin = await predictionMarketControllerContract.isLandAdmin({ token, user: user2 });
185
+
186
+ expect(currentIsAdmin).to.equal(true);
187
+ expect(newIsAdmin).to.equal(false);
188
+ }));
189
+
190
+ it('should not be able to add an admin to a Land if not an admin making the call', mochaAsync(async () => {
191
+ const currentIsAdmin = await predictionMarketControllerContract.isLandAdmin({ token, user: user2 });
192
+ try {
193
+ await user1PredictionMarketControllerContract.addAdminToLand({
194
+ token,
195
+ user: user2
196
+ });
197
+ } catch(e) {
198
+ // not logging error, as tx is expected to fail
199
+ }
200
+ const newIsAdmin = await predictionMarketControllerContract.isLandAdmin({ token, user: user2 });
201
+
202
+ expect(currentIsAdmin).to.equal(false);
203
+ expect(newIsAdmin).to.equal(false);
204
+ }));
205
+
206
+ it('should be able to add/remove an admin to a Land after being made admin', mochaAsync(async () => {
207
+ await predictionMarketControllerContract.addAdminToLand({
208
+ token,
209
+ user: user1
210
+ });
211
+
212
+ const currentIsAdmin = await predictionMarketControllerContract.isLandAdmin({ token, user: user2 });
213
+ await user1PredictionMarketControllerContract.addAdminToLand({
214
+ token,
215
+ user: user2
216
+ });
217
+ const newIsAdmin = await predictionMarketControllerContract.isLandAdmin({ token, user: user2 });
218
+
219
+ expect(currentIsAdmin).to.equal(false);
220
+ expect(newIsAdmin).to.equal(true);
221
+
222
+ await user1PredictionMarketControllerContract.removeAdminFromLand({
223
+ token,
224
+ user: user2
225
+ });
226
+ const lastNewIsAdmin = await predictionMarketControllerContract.isLandAdmin({ token, user: user2 });
227
+
228
+ expect(lastNewIsAdmin).to.equal(false);
229
+
230
+ // resetting user1 admin status
231
+ await predictionMarketControllerContract.removeAdminFromLand({
232
+ token,
233
+ user: user1
234
+ });
235
+ }));
236
+
237
+ it ('should be land admin if is a controller admin', mochaAsync(async () => {
238
+ const currentIsAdmin = await predictionMarketControllerContract.isLandAdmin({ token, user: user1 });
239
+ expect(currentIsAdmin).to.equal(false);
240
+
241
+ await predictionMarketFactoryContract.addAdminToPMController({
242
+ controllerAddress: predictionMarketControllerContract.getAddress(),
243
+ user: user1
244
+ });
245
+
246
+ const newIsAdmin = await predictionMarketControllerContract.isLandAdmin({ token, user: user1 });
247
+ expect(newIsAdmin).to.equal(true);
248
+
249
+ // new admin should be able to add another admin to a land
250
+ await user1PredictionMarketControllerContract.addAdminToLand({
251
+ token,
252
+ user: user2
253
+ });
254
+
255
+ const user2IsAdmin = await predictionMarketControllerContract.isLandAdmin({ token, user: user2 });
256
+ expect(user2IsAdmin).to.equal(true);
257
+
258
+ // removing user2 as admin
259
+ await user1PredictionMarketControllerContract.removeAdminFromLand({
260
+ token,
261
+ user: user2
262
+ });
263
+
264
+ const user2IsAdminAfter = await predictionMarketControllerContract.isLandAdmin({ token, user: user2 });
265
+ expect(user2IsAdminAfter).to.equal(false);
266
+
267
+ await predictionMarketFactoryContract.removeAdminFromPMController({
268
+ controllerAddress: predictionMarketControllerContract.getAddress(),
269
+ user: user1
270
+ });
271
+
272
+ const lastNewIsAdmin = await predictionMarketControllerContract.isLandAdmin({ token, user: user1 });
273
+ expect(lastNewIsAdmin).to.equal(false);
274
+ }));
275
+ });
276
+
277
+ context('Land Disabling + Enabling + Offset', async () => {
278
+ let landId = 0;
279
+ let land;
280
+ let token;
281
+
282
+ let user1App;
283
+ let user1PredictionMarketControllerContract;
284
+
285
+ let landTokenContract;
286
+
287
+ before(mochaAsync(async () => {
288
+ land = await predictionMarketControllerContract.getLandById({ id: landId });
289
+ landTokenContract = app.getFantasyERC20Contract({contractAddress: land.token});
290
+ token = land.token;
291
+
292
+ user1App = new Application({
293
+ web3Provider: process.env.WEB3_PROVIDER,
294
+ web3PrivateKey: USER1_PRIVATE_KEY
295
+ });
296
+ user1PredictionMarketControllerContract = user1App.getPredictionMarketV3ControllerContract({
297
+ contractAddress: predictionMarketControllerContract.getAddress()
298
+ });
299
+ }));
300
+
301
+ it('should not be able to disable a Land if not an admin making the call', mochaAsync(async () => {
302
+ try {
303
+ await user1PredictionMarketControllerContract.disableLand({
304
+ token
305
+ });
306
+ } catch(e) {
307
+ // not logging error, as tx is expected to fail
308
+ }
309
+
310
+ const refreshedLand = await predictionMarketControllerContract.getLandById({ id: landId });
311
+
312
+ expect(land.active).to.equal(true);
313
+ expect(refreshedLand.active).to.equal(true);
314
+ }));
315
+
316
+ it('should disable a Land', mochaAsync(async () => {
317
+ const currentPaused = await landTokenContract.paused();
318
+ await predictionMarketControllerContract.disableLand({
319
+ token: land.token
320
+ });
321
+
322
+ const refreshedLand = await predictionMarketControllerContract.getLandById({ id: landId });
323
+ const newPaused = await landTokenContract.paused();
324
+
325
+ expect(land.active).to.equal(true);
326
+ expect(currentPaused).to.equal(false);
327
+ expect(newPaused).to.equal(true);
328
+ expect(refreshedLand.token).to.equal(land.token);
329
+ expect(refreshedLand.active).to.equal(false);
330
+ expect(refreshedLand.realitio).to.equal(land.realitio);
331
+ }));
332
+
333
+ it('should not be able to disable a Land if already disabled', mochaAsync(async () => {
334
+ try {
335
+ await predictionMarketControllerContract.disableLand({
336
+ token
337
+ });
338
+ } catch(e) {
339
+ // not logging error, as tx is expected to fail
340
+ }
341
+
342
+ const refreshedLand = await predictionMarketControllerContract.getLandById({ id: landId });
343
+
344
+ expect(refreshedLand.active).to.equal(false);
345
+ }));
346
+
347
+ it('should enable a Land', mochaAsync(async () => {
348
+ const currentPaused = await landTokenContract.paused();
349
+ await predictionMarketControllerContract.enableLand({
350
+ token: land.token
351
+ });
352
+
353
+ const refreshedLand = await predictionMarketControllerContract.getLandById({ id: landId });
354
+ const newPaused = await landTokenContract.paused();
355
+
356
+ expect(currentPaused).to.equal(true);
357
+ expect(newPaused).to.equal(false);
358
+ expect(refreshedLand.token).to.equal(land.token);
359
+ expect(refreshedLand.active).to.equal(true);
360
+ expect(refreshedLand.realitio).to.equal(land.realitio);
361
+ }));
362
+ });
363
+ });
364
+
365
+ context('Land Markets', async () => {
366
+ let landId = 0;
367
+ let marketId = 0;
368
+ let outcomeId = 0;
369
+ let value = 0.01;
370
+ let land;
371
+ let land2;
372
+
373
+ let user1;
374
+ let user1App;
375
+ let user1PredictionMarketContract;
376
+
377
+ let landTokenContract;
378
+ let land2TokenContract;
379
+ let user1LandTokenContract;
380
+ let user1Land2TokenContract;
381
+
382
+ before(mochaAsync(async () => {
383
+ land = await predictionMarketControllerContract.getLandById({ id: landId });
384
+ land2 = await predictionMarketControllerContract.getLandById({ id: landId + 1});
385
+
386
+ user1 = USER1_ADDRESS;
387
+ user1App = new Application({
388
+ web3Provider: process.env.WEB3_PROVIDER,
389
+ web3PrivateKey: USER1_PRIVATE_KEY
390
+ });
391
+ user1PredictionMarketContract = user1App.getPredictionMarketV3Contract({
392
+ contractAddress: predictionMarketContract.getAddress()
393
+ });
394
+
395
+ landTokenContract = app.getFantasyERC20Contract({contractAddress: land.token});
396
+ land2TokenContract = app.getFantasyERC20Contract({contractAddress: land2.token});
397
+ user1LandTokenContract = user1App.getFantasyERC20Contract({contractAddress: land.token});
398
+ user1Land2TokenContract = user1App.getFantasyERC20Contract({contractAddress: land2.token});
399
+ // approving land token to spend tokens
400
+ await landTokenContract.claimAndApproveTokens();
401
+ await land2TokenContract.claimAndApproveTokens();
402
+ await user1LandTokenContract.claimAndApproveTokens();
403
+ await user1Land2TokenContract.claimAndApproveTokens();
404
+ }));
405
+
406
+ context('Market Creation', async () => {
407
+ it('should not be able to create a Market if not an admin making the call and everyoneCanCreateMarkets is not active', mochaAsync(async () => {
408
+ const currentMarketIds = await predictionMarketContract.getMarkets();
409
+ const currentLandTokenBalance = await landTokenContract.balanceOf({ address: user1 });
410
+ expect(currentLandTokenBalance).to.equal(TOKEN_AMOUNT_TO_CLAIM);
411
+ expect(land.everyoneCanCreateMarkets).to.equal(false);
412
+
413
+ try {
414
+ await user1PredictionMarketContract.mintAndCreateMarket({
415
+ value,
416
+ name: 'Will BTC price close above 100k$ on May 1st 2025',
417
+ description: 'This is a description',
418
+ image: 'foo-bar',
419
+ category: 'Foo;Bar',
420
+ oracleAddress: '0x0000000000000000000000000000000000000001', // TODO
421
+ duration: moment('2025-05-01').unix(),
422
+ outcomes: ['Yes', 'No'],
423
+ token: landTokenContract.getAddress(),
424
+ realitioAddress: land.realitio,
425
+ realitioTimeout: 300,
426
+ PM3ManagerAddress: predictionMarketControllerContract.getAddress()
427
+ });
428
+ } catch(e) {
429
+ // not logging error, as tx is expected to fail
430
+ }
431
+
432
+ const newMarketIds = await predictionMarketContract.getMarkets();
433
+ expect(newMarketIds.length).to.equal(currentMarketIds.length);
434
+ }));
435
+
436
+ it('should create a Market if admin', mochaAsync(async () => {
437
+ const currentMarketIds = await predictionMarketContract.getMarkets();
438
+ const currentLandTokenBalance = await landTokenContract.balanceOf({ address: accountAddress });
439
+ expect(currentLandTokenBalance).to.equal(TOKEN_AMOUNT_TO_CLAIM);
440
+
441
+
442
+ const res = await predictionMarketContract.mintAndCreateMarket({
443
+ value,
444
+ name: 'Will BTC price close above 100k$ on May 1st 2025',
445
+ description: 'This is a description',
446
+ image: 'foo-bar',
447
+ category: 'Foo;Bar',
448
+ oracleAddress: '0x0000000000000000000000000000000000000001', // TODO
449
+ duration: moment('2025-05-01').unix(),
450
+ outcomes: ['Yes', 'No'],
451
+ token: landTokenContract.getAddress(),
452
+ realitioAddress: land.realitio,
453
+ realitioTimeout: 300,
454
+ PM3ManagerAddress: predictionMarketControllerContract.getAddress()
455
+ });
456
+ expect(res.status).to.equal(true);
457
+
458
+
459
+ const newLandTokenBalance = await landTokenContract.balanceOf({ address: accountAddress });
460
+ const newMarketIds = await predictionMarketContract.getMarkets();
461
+ expect(newMarketIds.length).to.equal(currentMarketIds.length + 1);
462
+ // balance remains the same since tokens were minted
463
+ expect(newLandTokenBalance).to.equal(currentLandTokenBalance);
464
+ }));
465
+
466
+ it('should be able to create a Market if not an admin making the call and everyoneCanCreateMarkets is active', mochaAsync(async () => {
467
+ const currentMarketIds = await predictionMarketContract.getMarkets();
468
+ const currentLandTokenBalance = await land2TokenContract.balanceOf({ address: user1 });
469
+ expect(currentLandTokenBalance).to.equal(TOKEN_AMOUNT_TO_CLAIM);
470
+ expect(await predictionMarketControllerContract.isLandAdmin({ token: land2TokenContract.getAddress(), user: user1 })).to.equal(false);
471
+ expect(land2.everyoneCanCreateMarkets).to.equal(true);
472
+
473
+ const res = await predictionMarketContract.mintAndCreateMarket({
474
+ value,
475
+ name: 'Will Something Happen tomorrow?',
476
+ description: 'This is a description',
477
+ image: 'foo-bar',
478
+ category: 'Foo;Bar',
479
+ oracleAddress: '0x0000000000000000000000000000000000000001', // TODO
480
+ duration: moment('2026-05-01').unix(),
481
+ outcomes: ['Yes', 'No'],
482
+ token: land2TokenContract.getAddress(),
483
+ realitioAddress: land2.realitio,
484
+ realitioTimeout: 300,
485
+ PM3ManagerAddress: predictionMarketControllerContract.getAddress()
486
+ });
487
+ expect(res.status).to.equal(true);
488
+
489
+ const newLandTokenBalance = await land2TokenContract.balanceOf({ address: accountAddress });
490
+ const newMarketIds = await predictionMarketContract.getMarkets();
491
+ expect(newMarketIds.length).to.equal(currentMarketIds.length + 1);
492
+ // balance remains the same since tokens were minted
493
+ expect(newLandTokenBalance).to.equal(currentLandTokenBalance);
494
+ }));
495
+ });
496
+
497
+ context('Market Interaction', async () => {
498
+ it('should be able to buy shares when land enabled', mochaAsync(async () => {
499
+ const minOutcomeSharesToBuy = 0.015;
500
+ const currentLandTokenBalance = await landTokenContract.balanceOf({ address: accountAddress });
501
+
502
+ try {
503
+ const res = await predictionMarketContract.buy({marketId, outcomeId, value, minOutcomeSharesToBuy});
504
+ expect(res.status).to.equal(true);
505
+ } catch(e) {
506
+ console.log(e);
507
+ }
508
+
509
+ const newLandTokenBalance = await landTokenContract.balanceOf({ address: accountAddress });
510
+ const amountTransferred = Number((currentLandTokenBalance - newLandTokenBalance).toFixed(5));
511
+
512
+ expect(amountTransferred).to.equal(value);
513
+ }));
514
+
515
+ it('should sell outcome shares', mochaAsync(async () => {
516
+ const outcomeId = 0;
517
+ const maxOutcomeSharesToSell = 0.015;
518
+
519
+ const currentLandTokenBalance = await landTokenContract.balanceOf({ address: accountAddress });
520
+
521
+ try {
522
+ const res = await predictionMarketContract.sell({marketId, outcomeId, value, maxOutcomeSharesToSell});
523
+ expect(res.status).to.equal(true);
524
+ } catch(e) {
525
+ console.log(e);
526
+ }
527
+
528
+ const newLandTokenBalance = await landTokenContract.balanceOf({ address: accountAddress });
529
+ const amountTransferred = Number((newLandTokenBalance - currentLandTokenBalance).toFixed(5));
530
+
531
+ expect(amountTransferred).to.equal(value);
532
+ }));
533
+
534
+ it('should not be able to buy shares when land disabled', mochaAsync(async () => {
535
+ const minOutcomeSharesToBuy = 0.015;
536
+ const currentLandTokenBalance = await landTokenContract.balanceOf({ address: accountAddress });
537
+
538
+ await predictionMarketControllerContract.disableLand({
539
+ token: land.token
540
+ });
541
+
542
+ try {
543
+ const res = await predictionMarketContract.buy({marketId, outcomeId, value, minOutcomeSharesToBuy});
544
+ expect(res.status).to.equal(true);
545
+ } catch(e) {
546
+ // not logging error, as tx is expected to fail
547
+ }
548
+
549
+ const newLandTokenBalance = await landTokenContract.balanceOf({ address: accountAddress });
550
+ const amountTransferred = currentLandTokenBalance - newLandTokenBalance;
551
+
552
+ expect(amountTransferred).to.equal(0);
553
+ }));
554
+
555
+ it('should be able to buy shares when land enabled again', mochaAsync(async () => {
556
+ const minOutcomeSharesToBuy = 0.015;
557
+ const currentLandTokenBalance = await landTokenContract.balanceOf({ address: accountAddress });
558
+
559
+ await predictionMarketControllerContract.enableLand({
560
+ token: land.token
561
+ });
562
+
563
+ try {
564
+ const res = await predictionMarketContract.buy({marketId, outcomeId, value, minOutcomeSharesToBuy});
565
+ expect(res.status).to.equal(true);
566
+ } catch(e) {
567
+ console.log(e);
568
+ }
569
+
570
+ const newLandTokenBalance = await landTokenContract.balanceOf({ address: accountAddress });
571
+ const amountTransferred = Number((currentLandTokenBalance - newLandTokenBalance).toFixed(5));
572
+
573
+ expect(amountTransferred).to.equal(value);
574
+ }));
575
+ });
576
+
577
+ context('Market Resolution', async () => {
578
+ let outcomeId = 1;
579
+
580
+ it('should not be able to resolve a Market if not an admin making the call', mochaAsync(async () => {
581
+ try {
582
+ await user1PredictionMarketContract.adminResolveMarketOutcome({
583
+ marketId,
584
+ outcomeId
585
+ });
586
+ } catch(e) {
587
+ // not logging error, as tx is expected to fail
588
+ }
589
+
590
+ const market = await predictionMarketContract.getMarketData({ marketId });
591
+ expect(market.state).to.equal(0);
592
+ }));
593
+
594
+ it('should be able to resolve a Market', mochaAsync(async () => {
595
+ try {
596
+ const res = await predictionMarketContract.adminResolveMarketOutcome({
597
+ marketId,
598
+ outcomeId
599
+ });
600
+ expect(res.status).to.equal(true);
601
+ } catch(e) {
602
+ console.log(e);
603
+ }
604
+
605
+ // doing dummy transaction to get the latest block
606
+ await landTokenContract.approve({ address: '0x000000000000000000000000000000000000dead', amount: 0 });
607
+
608
+ const market = await predictionMarketContract.getMarketData({ marketId });
609
+ expect(market.state).to.equal(2);
610
+ }));
611
+ });
612
+ });
613
+ });