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.
- package/.openzeppelin/unknown-1337.json +2056 -0
- package/CONTRIBUTING.md +36 -0
- package/README.md +24 -25
- package/_book/README.md +590 -0
- package/_book/core.md +50 -0
- package/_book/gitbook/fonts/fontawesome/FontAwesome.otf +0 -0
- package/_book/gitbook/fonts/fontawesome/fontawesome-webfont.eot +0 -0
- package/_book/gitbook/fonts/fontawesome/fontawesome-webfont.svg +685 -0
- package/_book/gitbook/fonts/fontawesome/fontawesome-webfont.ttf +0 -0
- package/_book/gitbook/fonts/fontawesome/fontawesome-webfont.woff +0 -0
- package/_book/gitbook/fonts/fontawesome/fontawesome-webfont.woff2 +0 -0
- package/_book/gitbook/gitbook-plugin-fontsettings/fontsettings.js +240 -0
- package/_book/gitbook/gitbook-plugin-fontsettings/website.css +291 -0
- package/_book/gitbook/gitbook-plugin-highlight/ebook.css +135 -0
- package/_book/gitbook/gitbook-plugin-highlight/website.css +434 -0
- package/_book/gitbook/gitbook-plugin-lunr/lunr.min.js +7 -0
- package/_book/gitbook/gitbook-plugin-lunr/search-lunr.js +59 -0
- package/_book/gitbook/gitbook-plugin-search/lunr.min.js +7 -0
- package/_book/gitbook/gitbook-plugin-search/search-engine.js +50 -0
- package/_book/gitbook/gitbook-plugin-search/search.css +35 -0
- package/_book/gitbook/gitbook-plugin-search/search.js +213 -0
- package/_book/gitbook/gitbook-plugin-sharing/buttons.js +90 -0
- package/_book/gitbook/gitbook.js +4 -0
- package/_book/gitbook/images/apple-touch-icon-precomposed-152.png +0 -0
- package/_book/gitbook/images/favicon.ico +0 -0
- package/_book/gitbook/style.css +9 -0
- package/_book/gitbook/theme.js +4 -0
- package/_book/index.html +705 -0
- package/_book/intro.md +32 -0
- package/_book/search_index.json +1 -0
- package/book.json +8 -0
- package/build/contracts/AccessControl.json +1 -0
- package/build/contracts/AccessControlEnumerable.json +1 -0
- package/build/contracts/Achievements.json +1 -0
- package/build/contracts/Address.json +1 -0
- package/build/contracts/BalanceHolder.json +1 -0
- package/build/contracts/BalanceHolder_ERC20.json +1 -0
- package/build/contracts/CeilDiv.json +1 -0
- package/build/contracts/Clones.json +1 -0
- package/build/contracts/Context.json +1 -0
- package/build/contracts/Counters.json +1 -0
- package/build/contracts/ERC165.json +1 -0
- package/build/contracts/ERC20.json +1 -0
- package/build/contracts/ERC20Burnable.json +1 -0
- package/build/contracts/ERC20Pausable.json +1 -0
- package/build/contracts/ERC20PresetMinterPauser.json +1 -0
- package/build/contracts/ERC721.json +1 -0
- package/build/contracts/EnumerableMap.json +1 -0
- package/build/contracts/EnumerableSet.json +1 -0
- package/build/contracts/FantasyERC20.json +1 -0
- package/build/contracts/IAccessControl.json +1 -0
- package/build/contracts/IAccessControlEnumerable.json +1 -0
- package/build/contracts/IBalanceHolder_ERC20.json +1 -0
- package/build/contracts/IERC165.json +1 -0
- package/build/contracts/IERC20.json +1 -0
- package/build/contracts/IERC20Metadata.json +1 -0
- package/build/contracts/IERC20Permit.json +1 -0
- package/build/contracts/IERC721.json +1 -0
- package/build/contracts/IERC721Enumerable.json +1 -0
- package/build/contracts/IERC721Metadata.json +1 -0
- package/build/contracts/IERC721Receiver.json +1 -0
- package/build/contracts/IFantasyERC20.json +1 -0
- package/build/contracts/IPredictionMarketV3.json +1 -0
- package/build/contracts/IPredictionMarketV3Factory.json +1 -0
- package/build/contracts/IPredictionMarketV3Manager.json +1 -0
- package/build/contracts/IRealityETH_ERC20.json +1 -0
- package/build/contracts/IRealityETH_IERC20.json +1 -0
- package/build/contracts/IWETH.json +1 -0
- package/build/contracts/LandFactory.json +1 -0
- package/build/contracts/Math.json +1 -0
- package/build/contracts/Migrations.json +1 -0
- package/build/contracts/Ownable.json +1 -0
- package/build/contracts/Pausable.json +1 -0
- package/build/contracts/PredictionMarket.json +1 -0
- package/build/contracts/PredictionMarketV2.json +1 -0
- package/build/contracts/PredictionMarketV3.json +1 -0
- package/build/contracts/PredictionMarketV3Controller.json +1 -0
- package/build/contracts/PredictionMarketV3Factory.json +1 -0
- package/build/contracts/PredictionMarketV3Manager.json +1 -0
- package/build/contracts/PredictionMarketV3Querier.json +1 -0
- package/build/contracts/RealitioERC20.json +1 -0
- package/build/contracts/RealitioForeignArbitrationProxyWithAppeals.json +1 -0
- package/build/contracts/RealitioHomeArbitrationProxy.json +1 -0
- package/build/contracts/RealitioSafeMath256.json +1 -0
- package/build/contracts/RealitioSafeMath32.json +1 -0
- package/build/contracts/RealityETH_ERC20_Factory.json +1 -0
- package/build/contracts/RealityETH_ERC20_v3_0.json +1 -0
- package/build/contracts/ReentrancyGuard.json +1 -0
- package/build/contracts/SafeERC20.json +1 -0
- package/build/contracts/SafeMath.json +1 -0
- package/build/contracts/Strings.json +1 -0
- package/build/contracts/Voting.json +1 -0
- package/build/contracts/WETH9.json +1 -0
- package/build/contracts/test.json +1 -0
- package/cleanContracts.js +22 -0
- package/contracts/FantasyERC20.sol +81 -0
- package/contracts/IFantasyERC20.sol +20 -0
- package/contracts/IPredictionMarketV3.sol +207 -0
- package/contracts/IPredictionMarketV3Factory.sol +10 -0
- package/contracts/IPredictionMarketV3Manager.sol +12 -0
- package/contracts/IRealityETH_ERC20.sol +64 -0
- package/contracts/LandFactory.sol +248 -0
- package/contracts/Migrations.sol +24 -0
- package/contracts/PredictionMarketV3.sol +1332 -0
- package/contracts/PredictionMarketV3Controller.sol +87 -0
- package/contracts/PredictionMarketV3Factory.sol +205 -0
- package/contracts/PredictionMarketV3Manager.sol +45 -0
- package/contracts/PredictionMarketV3Querier.sol +79 -0
- package/contracts/RealityETH_ERC20_Factory.sol +54 -0
- package/contracts/Voting.sol +153 -0
- package/contracts/WETH9.sol +62 -0
- package/help.txt +8 -0
- package/index.js +3 -0
- package/migrations/10_deploy_weth.js +5 -0
- package/migrations/11_deploy_full_flow.js +99 -0
- package/migrations/12_deploy_pm_v3_querier.js +7 -0
- package/migrations/13_deploy_pm_v3_factory.js +14 -0
- package/migrations/1_initial_migration.js +5 -0
- package/migrations/2_deploy_erc20.js +10 -0
- package/migrations/3_deploy_realitio.js +11 -0
- package/migrations/4_deploy_pm.js +20 -0
- package/migrations/5_seed_markets.js +51 -0
- package/migrations/6_deploy_achievements.js +5 -0
- package/migrations/7_deploy_voting.js +14 -0
- package/migrations/8_deploy_pm_v2.js +20 -0
- package/migrations/9_seed_markets_v2.js +68 -0
- package/package.json +106 -13
- package/src/Application.js +421 -0
- package/src/interfaces/index.js +19 -0
- package/src/models/AchievementsContract.js +217 -0
- package/src/models/ArbitrationContract.js +69 -0
- package/src/models/ArbitrationProxyContract.js +32 -0
- package/src/models/ERC20Contract.js +156 -0
- package/src/models/FantasyERC20Contract.js +92 -0
- package/src/models/IContract.js +1002 -0
- package/src/models/PolkamarketsSmartAccount.js +100 -0
- package/src/models/PredictionMarketContract.js +562 -0
- package/src/models/PredictionMarketV2Contract.js +830 -0
- package/src/models/PredictionMarketV3Contract.js +233 -0
- package/src/models/PredictionMarketV3ControllerContract.js +102 -0
- package/src/models/PredictionMarketV3FactoryContract.js +96 -0
- package/src/models/PredictionMarketV3ManagerContract.js +111 -0
- package/src/models/PredictionMarketV3QuerierContract.js +24 -0
- package/src/models/RealitioERC20Contract.js +286 -0
- package/src/models/VotingContract.js +182 -0
- package/src/models/WETH9Contract.js +92 -0
- package/src/models/index.js +33 -0
- package/src/utils/Account.js +40 -0
- package/src/utils/Contract.js +120 -0
- package/src/utils/Numbers.js +94 -0
- package/tests/fantasyERC20Contract.js +225 -0
- package/tests/index.js +10 -0
- package/tests/predictionMarketContract.js +466 -0
- package/tests/predictionMarketV2Contract.js +1042 -0
- package/tests/predictionMarketV3Contract.js +1079 -0
- package/tests/predictionMarketV3ControllerContract.js +613 -0
- package/tests/predictionMarketV3FactoryContract.js +469 -0
- package/tests/predictionMarketV3ManagerContract.js +610 -0
- package/tests/utils.js +16 -0
- package/tests/votingContract.js +490 -0
- package/tooling/docs/jsdoc.json +6 -0
- package/truffle-config.js +134 -0
- package/polkamarkets.js +0 -436
|
@@ -0,0 +1,466 @@
|
|
|
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', async () => {
|
|
10
|
+
require('dotenv').config();
|
|
11
|
+
|
|
12
|
+
let app;
|
|
13
|
+
let predictionMarketContract;
|
|
14
|
+
let realitioERC20Contract
|
|
15
|
+
let ERC20Contract;
|
|
16
|
+
|
|
17
|
+
// market / outcome ids we'll make unit tests with
|
|
18
|
+
let marketId = 0;
|
|
19
|
+
let outcomeIds = [0, 1];
|
|
20
|
+
const ethAmount = 0.01;
|
|
21
|
+
let closeDateTime;
|
|
22
|
+
|
|
23
|
+
context('Contract Deployment', async () => {
|
|
24
|
+
it('should start the Application', mochaAsync(async () => {
|
|
25
|
+
app = new Application({
|
|
26
|
+
web3Provider: process.env.WEB3_PROVIDER,
|
|
27
|
+
web3PrivateKey: process.env.WEB3_PRIVATE_KEY,
|
|
28
|
+
});
|
|
29
|
+
expect(app).to.not.equal(null);
|
|
30
|
+
}));
|
|
31
|
+
|
|
32
|
+
it('should deploy Prediction Market Contract', mochaAsync(async () => {
|
|
33
|
+
// Create Contract
|
|
34
|
+
predictionMarketContract = app.getPredictionMarketContract({});
|
|
35
|
+
realitioERC20Contract = app.getRealitioERC20Contract({});
|
|
36
|
+
ERC20Contract = app.getERC20Contract({});
|
|
37
|
+
// // Deploy
|
|
38
|
+
await realitioERC20Contract.deploy({});
|
|
39
|
+
await ERC20Contract.deploy({ params: ['Polkamarkets', 'POLK'] });
|
|
40
|
+
|
|
41
|
+
const realitioContractAddress = realitioERC20Contract.getAddress();
|
|
42
|
+
const ERC20ContractAddress = ERC20Contract.getAddress();
|
|
43
|
+
const accountAddress = await predictionMarketContract.getMyAccount();
|
|
44
|
+
|
|
45
|
+
await predictionMarketContract.deploy({
|
|
46
|
+
params: [
|
|
47
|
+
0,
|
|
48
|
+
ERC20ContractAddress,
|
|
49
|
+
0,
|
|
50
|
+
realitioContractAddress,
|
|
51
|
+
86400
|
|
52
|
+
]
|
|
53
|
+
});
|
|
54
|
+
const predictionMarketContractAddress = predictionMarketContract.getAddress();
|
|
55
|
+
|
|
56
|
+
expect(predictionMarketContractAddress).to.not.equal(null);
|
|
57
|
+
expect(realitioContractAddress).to.not.equal(null);
|
|
58
|
+
|
|
59
|
+
// setting predictionMarket ownable vars
|
|
60
|
+
// await predictionMarketContract.getContract().methods.initialize().send({ from: accountAddress });
|
|
61
|
+
// // setting realitioERC20 governance vars
|
|
62
|
+
// await predictionMarketContract.getContract().methods.setRealitioERC20(realitioContractAddress).send({ from: accountAddress });
|
|
63
|
+
// await predictionMarketContract.getContract().methods.setRealitioTimeout(86400).send({ from: accountAddress });
|
|
64
|
+
// await predictionMarketContract.getContract().methods.setToken(ERC20ContractAddress).send({ from: accountAddress });
|
|
65
|
+
// await predictionMarketContract.getContract().methods.setRequiredBalance(0).send({ from: accountAddress });
|
|
66
|
+
}));
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
context('Market Creation', async () => {
|
|
70
|
+
it('should create a Market', mochaAsync(async () => {
|
|
71
|
+
closeDateTime = moment().add(1, 'day').startOf('day').format('YYYY-MM-DD HH:mm');
|
|
72
|
+
try {
|
|
73
|
+
const res = await predictionMarketContract.createMarket({
|
|
74
|
+
name: 'Will BTC price close above 100k$ on May 1st 2022',
|
|
75
|
+
image: 'foo-bar',
|
|
76
|
+
category: 'Foo;Bar',
|
|
77
|
+
oracleAddress: '0x0000000000000000000000000000000000000001', // TODO
|
|
78
|
+
duration: moment(closeDateTime).unix(),
|
|
79
|
+
outcomes: ['Yes', 'No'],
|
|
80
|
+
ethAmount: ethAmount
|
|
81
|
+
});
|
|
82
|
+
expect(res.status).to.equal(true);
|
|
83
|
+
} catch (e) {
|
|
84
|
+
// TODO: review this
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const marketIds = await predictionMarketContract.getMarkets();
|
|
88
|
+
marketId = marketIds[marketIds.length - 1];
|
|
89
|
+
expect(marketIds.length).to.equal(1);
|
|
90
|
+
expect(marketIds[marketIds.length - 1]).to.equal(marketId);
|
|
91
|
+
}));
|
|
92
|
+
|
|
93
|
+
it('should create another Market', mochaAsync(async () => {
|
|
94
|
+
const res = await predictionMarketContract.createMarket({
|
|
95
|
+
name: 'Will ETH price close above 10k$ on May 1st 2022',
|
|
96
|
+
image: 'foo-bar',
|
|
97
|
+
category: 'Foo;Bar',
|
|
98
|
+
oracleAddress: '0x0000000000000000000000000000000000000001', // TODO
|
|
99
|
+
duration: moment(closeDateTime).unix(),
|
|
100
|
+
outcomes: ['Yes', 'No'],
|
|
101
|
+
ethAmount: 0.001
|
|
102
|
+
});
|
|
103
|
+
expect(res.status).to.equal(true);
|
|
104
|
+
|
|
105
|
+
const marketIds = await predictionMarketContract.getMarkets();
|
|
106
|
+
expect(marketIds.length).to.equal(2);
|
|
107
|
+
}));
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
context('Market Data', async () => {
|
|
111
|
+
it('should get Market data', mochaAsync(async () => {
|
|
112
|
+
const res = await predictionMarketContract.getMarketData({ marketId: 0 });
|
|
113
|
+
expect(res).to.eql({
|
|
114
|
+
name: '',
|
|
115
|
+
closeDateTime,
|
|
116
|
+
state: 0,
|
|
117
|
+
oracleAddress: '0x0000000000000000000000000000000000000000',
|
|
118
|
+
liquidity: 0.01,
|
|
119
|
+
outcomeIds: [0, 1],
|
|
120
|
+
});
|
|
121
|
+
}));
|
|
122
|
+
|
|
123
|
+
it('should get Market details', mochaAsync(async () => {
|
|
124
|
+
const res = await predictionMarketContract.getMarketDetails({ marketId: 0 });
|
|
125
|
+
expect(res).to.eql({
|
|
126
|
+
name: 'Will BTC price close above 100k$ on May 1st 2022',
|
|
127
|
+
category: 'Foo',
|
|
128
|
+
subcategory: 'Bar',
|
|
129
|
+
outcomes: ['Yes', 'No'],
|
|
130
|
+
image: 'foo-bar'
|
|
131
|
+
});
|
|
132
|
+
}));
|
|
133
|
+
|
|
134
|
+
it('should get Market Outcomes data', mochaAsync(async () => {
|
|
135
|
+
const outcome1Data = await predictionMarketContract.getOutcomeData({ marketId, outcomeId: outcomeIds[0] });
|
|
136
|
+
expect(outcome1Data).to.include({
|
|
137
|
+
price: 0.5,
|
|
138
|
+
shares: 0.01
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
const outcome2Data = await predictionMarketContract.getOutcomeData({ marketId, outcomeId: outcomeIds[1] });
|
|
142
|
+
expect(outcome2Data).to.include({
|
|
143
|
+
price: 0.5,
|
|
144
|
+
shares: 0.01
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
// outcomes share prices should sum to 1
|
|
148
|
+
expect(outcome1Data.price + outcome2Data.price).to.equal(1);
|
|
149
|
+
// outcomes number of shares should dum to ethAmount * 2
|
|
150
|
+
expect(outcome1Data.shares + outcome2Data.shares).to.equal(ethAmount * 2);
|
|
151
|
+
}));
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
context('Market Interaction - Balanced Market (Same Outcome Odds)', async () => {
|
|
155
|
+
it('should add liquidity without changing shares balance', mochaAsync(async () => {
|
|
156
|
+
const myShares = await predictionMarketContract.getMyMarketShares({ marketId });
|
|
157
|
+
const marketData = await predictionMarketContract.getMarketData({ marketId });
|
|
158
|
+
const outcome1Data = await predictionMarketContract.getOutcomeData({ marketId, outcomeId: outcomeIds[0] });
|
|
159
|
+
const outcome2Data = await predictionMarketContract.getOutcomeData({ marketId, outcomeId: outcomeIds[1] });
|
|
160
|
+
|
|
161
|
+
// balanced market - same price in all outcomoes
|
|
162
|
+
expect(outcome1Data.price).to.equal(outcome2Data.price);
|
|
163
|
+
|
|
164
|
+
try {
|
|
165
|
+
const res = await predictionMarketContract.addLiquidity({ marketId, ethAmount })
|
|
166
|
+
expect(res.status).to.equal(true);
|
|
167
|
+
} catch (e) {
|
|
168
|
+
// TODO: review this
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const myNewShares = await predictionMarketContract.getMyMarketShares({ marketId });
|
|
172
|
+
const newMarketData = await predictionMarketContract.getMarketData({ marketId });
|
|
173
|
+
const newOutcome1Data = await predictionMarketContract.getOutcomeData({ marketId, outcomeId: outcomeIds[0] });
|
|
174
|
+
const newOutcome2Data = await predictionMarketContract.getOutcomeData({ marketId, outcomeId: outcomeIds[1] });
|
|
175
|
+
|
|
176
|
+
expect(newMarketData.liquidity).to.above(marketData.liquidity);
|
|
177
|
+
expect(newMarketData.liquidity).to.equal(marketData.liquidity + ethAmount);
|
|
178
|
+
|
|
179
|
+
// Outcome prices shoud remain the same after providing liquidity
|
|
180
|
+
expect(newOutcome1Data.price).to.equal(outcome1Data.price);
|
|
181
|
+
expect(newOutcome2Data.price).to.equal(outcome2Data.price);
|
|
182
|
+
|
|
183
|
+
// Price balances are 0.5-0.5, liquidity will be added solely through liquidity shares
|
|
184
|
+
expect(myNewShares.liquidityShares).to.above(myShares.liquidityShares);
|
|
185
|
+
expect(myNewShares.liquidityShares).to.equal(myShares.liquidityShares + ethAmount);
|
|
186
|
+
// shares balance remains the same
|
|
187
|
+
expect(myNewShares.outcomeShares[0]).to.equal(myShares.outcomeShares[0]);
|
|
188
|
+
expect(myNewShares.outcomeShares[1]).to.equal(myShares.outcomeShares[1]);
|
|
189
|
+
}));
|
|
190
|
+
|
|
191
|
+
it('should remove liquidity without changing shares balance', mochaAsync(async () => {
|
|
192
|
+
const myShares = await predictionMarketContract.getMyMarketShares({ marketId });
|
|
193
|
+
const marketData = await predictionMarketContract.getMarketData({ marketId });
|
|
194
|
+
const outcome1Data = await predictionMarketContract.getOutcomeData({ marketId, outcomeId: outcomeIds[0] });
|
|
195
|
+
const outcome2Data = await predictionMarketContract.getOutcomeData({ marketId, outcomeId: outcomeIds[1] });
|
|
196
|
+
const contractBalance = Number(await predictionMarketContract.getBalance());
|
|
197
|
+
|
|
198
|
+
// balanced market - same price in all outcomoes
|
|
199
|
+
expect(outcome1Data.price).to.equal(outcome2Data.price);
|
|
200
|
+
|
|
201
|
+
try {
|
|
202
|
+
const res = await predictionMarketContract.removeLiquidity({ marketId, shares: ethAmount })
|
|
203
|
+
expect(res.status).to.equal(true);
|
|
204
|
+
} catch (e) {
|
|
205
|
+
// TODO: review this
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const myNewShares = await predictionMarketContract.getMyMarketShares({ marketId });
|
|
209
|
+
const newMarketData = await predictionMarketContract.getMarketData({ marketId });
|
|
210
|
+
const newOutcome1Data = await predictionMarketContract.getOutcomeData({ marketId, outcomeId: outcomeIds[0] });
|
|
211
|
+
const newOutcome2Data = await predictionMarketContract.getOutcomeData({ marketId, outcomeId: outcomeIds[1] });
|
|
212
|
+
const newContractBalance = Number(await predictionMarketContract.getBalance());
|
|
213
|
+
|
|
214
|
+
expect(newMarketData.liquidity).to.below(marketData.liquidity);
|
|
215
|
+
expect(newMarketData.liquidity).to.equal(marketData.liquidity - ethAmount);
|
|
216
|
+
|
|
217
|
+
// Outcome prices shoud remain the same after providing liquidity
|
|
218
|
+
expect(newOutcome1Data.price).to.equal(outcome1Data.price);
|
|
219
|
+
expect(newOutcome2Data.price).to.equal(outcome2Data.price);
|
|
220
|
+
|
|
221
|
+
// Price balances are 0.5-0.5, liquidity will be added solely through liquidity shares
|
|
222
|
+
expect(myNewShares.liquidityShares).to.below(myShares.liquidityShares);
|
|
223
|
+
expect(myNewShares.liquidityShares).to.equal(myShares.liquidityShares - ethAmount);
|
|
224
|
+
// shares balance remains the same
|
|
225
|
+
expect(myNewShares.outcomeShares[0]).to.equal(myShares.outcomeShares[0]);
|
|
226
|
+
expect(myNewShares.outcomeShares[1]).to.equal(myShares.outcomeShares[1]);
|
|
227
|
+
|
|
228
|
+
// User gets liquidity tokens back in ETH
|
|
229
|
+
expect(newContractBalance).to.below(contractBalance);
|
|
230
|
+
// TODO: check amountTransferred from internal transactions
|
|
231
|
+
const amountTransferred = Number((contractBalance - newContractBalance).toFixed(5));
|
|
232
|
+
expect(amountTransferred).to.equal(ethAmount);
|
|
233
|
+
}));
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
context('Market Interaction - Unbalanced Market (Different Outcome Odds)', async () => {
|
|
237
|
+
it('should display my shares', mochaAsync(async () => {
|
|
238
|
+
const res = await predictionMarketContract.getMyMarketShares({ marketId });
|
|
239
|
+
// currently holding liquidity tokens from market creation
|
|
240
|
+
expect(res).to.eql({
|
|
241
|
+
liquidityShares: 0.01,
|
|
242
|
+
outcomeShares: {
|
|
243
|
+
0: 0.00,
|
|
244
|
+
1: 0.00,
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
}));
|
|
248
|
+
|
|
249
|
+
it('should buy outcome shares', mochaAsync(async () => {
|
|
250
|
+
const outcomeId = 0;
|
|
251
|
+
const minOutcomeSharesToBuy = 0.015;
|
|
252
|
+
|
|
253
|
+
const marketData = await predictionMarketContract.getMarketData({ marketId });
|
|
254
|
+
const outcome1Data = await predictionMarketContract.getOutcomeData({ marketId, outcomeId: outcomeIds[0] });
|
|
255
|
+
const outcome2Data = await predictionMarketContract.getOutcomeData({ marketId, outcomeId: outcomeIds[1] });
|
|
256
|
+
const contractBalance = Number(await predictionMarketContract.getBalance());
|
|
257
|
+
|
|
258
|
+
try {
|
|
259
|
+
const res = await predictionMarketContract.buy({ marketId, outcomeId, ethAmount, minOutcomeSharesToBuy });
|
|
260
|
+
expect(res.status).to.equal(true);
|
|
261
|
+
} catch (e) {
|
|
262
|
+
// TODO: review this
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
const newMarketData = await predictionMarketContract.getMarketData({ marketId });
|
|
266
|
+
const newOutcome1Data = await predictionMarketContract.getOutcomeData({ marketId, outcomeId: outcomeIds[0] });
|
|
267
|
+
const newOutcome2Data = await predictionMarketContract.getOutcomeData({ marketId, outcomeId: outcomeIds[1] });
|
|
268
|
+
const newContractBalance = Number(await predictionMarketContract.getBalance());
|
|
269
|
+
|
|
270
|
+
// outcome price should increase
|
|
271
|
+
expect(newOutcome1Data.price).to.above(outcome1Data.price);
|
|
272
|
+
expect(newOutcome1Data.price).to.equal(0.8);
|
|
273
|
+
// opposite outcome price should decrease
|
|
274
|
+
expect(newOutcome2Data.price).to.below(outcome2Data.price);
|
|
275
|
+
expect(newOutcome2Data.price).to.equal(0.2);
|
|
276
|
+
// Prices sum = 1
|
|
277
|
+
// 0.05 + 0.05 = 1
|
|
278
|
+
expect(newOutcome1Data.price + newOutcome2Data.price).to.equal(1);
|
|
279
|
+
|
|
280
|
+
// Liquidity value remains the same
|
|
281
|
+
expect(newMarketData.liquidity).to.equal(marketData.liquidity);
|
|
282
|
+
|
|
283
|
+
// outcome shares should decrease
|
|
284
|
+
expect(newOutcome1Data.shares).to.below(outcome1Data.shares);
|
|
285
|
+
expect(newOutcome1Data.shares).to.equal(0.005);
|
|
286
|
+
// opposite outcome shares should increase
|
|
287
|
+
expect(newOutcome2Data.shares).to.above(outcome2Data.shares);
|
|
288
|
+
expect(newOutcome2Data.shares).to.equal(0.02);
|
|
289
|
+
// # Shares Product = Liquidity^2
|
|
290
|
+
// 0.005 * 0.02 = 0.01^2
|
|
291
|
+
expect(outcome1Data.shares * outcome2Data.shares).to.equal(newMarketData.liquidity ** 2);
|
|
292
|
+
expect(newOutcome1Data.shares * newOutcome2Data.shares).to.equal(newMarketData.liquidity ** 2);
|
|
293
|
+
|
|
294
|
+
const myShares = await predictionMarketContract.getMyMarketShares({ marketId });
|
|
295
|
+
expect(myShares).to.eql({
|
|
296
|
+
liquidityShares: 0.01,
|
|
297
|
+
outcomeShares: {
|
|
298
|
+
0: 0.015,
|
|
299
|
+
1: 0.00,
|
|
300
|
+
}
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
// Contract adds ethAmount to balance
|
|
304
|
+
expect(newContractBalance).to.above(contractBalance);
|
|
305
|
+
// TODO: check amountReceived from internal transactions
|
|
306
|
+
const amountReceived = Number((newContractBalance - contractBalance).toFixed(5));
|
|
307
|
+
expect(amountReceived).to.equal(ethAmount);
|
|
308
|
+
}));
|
|
309
|
+
|
|
310
|
+
it('should add liquidity', mochaAsync(async () => {
|
|
311
|
+
const myShares = await predictionMarketContract.getMyMarketShares({ marketId });
|
|
312
|
+
const marketData = await predictionMarketContract.getMarketData({ marketId });
|
|
313
|
+
const outcome1Data = await predictionMarketContract.getOutcomeData({ marketId, outcomeId: outcomeIds[0] });
|
|
314
|
+
const outcome2Data = await predictionMarketContract.getOutcomeData({ marketId, outcomeId: outcomeIds[1] });
|
|
315
|
+
|
|
316
|
+
try {
|
|
317
|
+
const res = await predictionMarketContract.addLiquidity({ marketId, ethAmount })
|
|
318
|
+
expect(res.status).to.equal(true);
|
|
319
|
+
} catch (e) {
|
|
320
|
+
// TODO: review this
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
const myNewShares = await predictionMarketContract.getMyMarketShares({ marketId });
|
|
324
|
+
const newMarketData = await predictionMarketContract.getMarketData({ marketId });
|
|
325
|
+
const newOutcome1Data = await predictionMarketContract.getOutcomeData({ marketId, outcomeId: outcomeIds[0] });
|
|
326
|
+
const newOutcome2Data = await predictionMarketContract.getOutcomeData({ marketId, outcomeId: outcomeIds[1] });
|
|
327
|
+
|
|
328
|
+
// Outcome prices shoud remain the same after providing liquidity
|
|
329
|
+
expect(newOutcome1Data.price).to.equal(outcome1Data.price);
|
|
330
|
+
expect(newOutcome2Data.price).to.equal(outcome2Data.price);
|
|
331
|
+
|
|
332
|
+
// # Shares Product = Liquidity^2
|
|
333
|
+
// 0.0075 * 0.03 = 0.015^2
|
|
334
|
+
expect(newMarketData.liquidity).to.above(marketData.liquidity);
|
|
335
|
+
expect(newMarketData.liquidity).to.equal(0.015);
|
|
336
|
+
expect(newOutcome1Data.shares).to.above(outcome1Data.shares);
|
|
337
|
+
expect(newOutcome1Data.shares).to.equal(0.0075);
|
|
338
|
+
expect(newOutcome2Data.shares).to.above(outcome2Data.shares);
|
|
339
|
+
expect(newOutcome2Data.shares).to.equal(0.03);
|
|
340
|
+
expect(newOutcome1Data.shares * newOutcome2Data.shares).to.equal(newMarketData.liquidity ** 2);
|
|
341
|
+
|
|
342
|
+
// Price balances are not 0.5-0.5, liquidity will be added through shares + liquidity
|
|
343
|
+
expect(myNewShares.liquidityShares).to.above(myShares.liquidityShares);
|
|
344
|
+
expect(myNewShares.liquidityShares).to.equal(0.015);
|
|
345
|
+
// shares balance of higher odd outcome increases
|
|
346
|
+
expect(myNewShares.outcomeShares[0]).to.above(myShares.outcomeShares[0]);
|
|
347
|
+
expect(myNewShares.outcomeShares[0]).to.equal(0.0225);
|
|
348
|
+
// shares balance of lower odd outcome remains
|
|
349
|
+
expect(myNewShares.outcomeShares[1]).to.equal(myShares.outcomeShares[1]);
|
|
350
|
+
expect(myNewShares.outcomeShares[1]).to.equal(0);
|
|
351
|
+
}));
|
|
352
|
+
|
|
353
|
+
it('should remove liquidity', mochaAsync(async () => {
|
|
354
|
+
const myShares = await predictionMarketContract.getMyMarketShares({ marketId });
|
|
355
|
+
const marketData = await predictionMarketContract.getMarketData({ marketId });
|
|
356
|
+
const outcome1Data = await predictionMarketContract.getOutcomeData({ marketId, outcomeId: outcomeIds[0] });
|
|
357
|
+
const outcome2Data = await predictionMarketContract.getOutcomeData({ marketId, outcomeId: outcomeIds[1] });
|
|
358
|
+
const contractBalance = Number(await predictionMarketContract.getBalance());
|
|
359
|
+
const liquiditySharesToRemove = 0.005;
|
|
360
|
+
|
|
361
|
+
try {
|
|
362
|
+
const res = await predictionMarketContract.removeLiquidity({ marketId, shares: liquiditySharesToRemove });
|
|
363
|
+
expect(res.status).to.equal(true);
|
|
364
|
+
} catch (e) {
|
|
365
|
+
// TODO: review this
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
const myNewShares = await predictionMarketContract.getMyMarketShares({ marketId });
|
|
369
|
+
const newMarketData = await predictionMarketContract.getMarketData({ marketId });
|
|
370
|
+
const newOutcome1Data = await predictionMarketContract.getOutcomeData({ marketId, outcomeId: outcomeIds[0] });
|
|
371
|
+
const newOutcome2Data = await predictionMarketContract.getOutcomeData({ marketId, outcomeId: outcomeIds[1] });
|
|
372
|
+
const newContractBalance = Number(await predictionMarketContract.getBalance());
|
|
373
|
+
|
|
374
|
+
// Outcome prices shoud remain the same after removing liquidity
|
|
375
|
+
expect(newOutcome1Data.price).to.equal(outcome1Data.price);
|
|
376
|
+
expect(newOutcome2Data.price).to.equal(outcome2Data.price);
|
|
377
|
+
|
|
378
|
+
// # Shares Product = Liquidity^2
|
|
379
|
+
// 0.005 * 0.02 = 0.01^2
|
|
380
|
+
expect(newMarketData.liquidity).to.below(marketData.liquidity);
|
|
381
|
+
expect(newMarketData.liquidity).to.equal(0.01);
|
|
382
|
+
expect(newOutcome1Data.shares).to.below(outcome1Data.shares);
|
|
383
|
+
expect(newOutcome1Data.shares).to.equal(0.005);
|
|
384
|
+
expect(newOutcome2Data.shares).to.below(outcome2Data.shares);
|
|
385
|
+
expect(newOutcome2Data.shares).to.equal(0.02);
|
|
386
|
+
expect(newOutcome1Data.shares * newOutcome2Data.shares).to.equal(newMarketData.liquidity ** 2);
|
|
387
|
+
|
|
388
|
+
// Price balances are not 0.5-0.5, liquidity will be added through shares + liquidity
|
|
389
|
+
expect(myNewShares.liquidityShares).to.below(myShares.liquidityShares);
|
|
390
|
+
expect(myNewShares.liquidityShares).to.equal(0.01);
|
|
391
|
+
// shares balance of higher odd outcome remains
|
|
392
|
+
expect(myNewShares.outcomeShares[0]).to.equal(myShares.outcomeShares[0]);
|
|
393
|
+
expect(myNewShares.outcomeShares[0]).to.equal(0.0225);
|
|
394
|
+
// shares balance of lower odd outcome increases
|
|
395
|
+
expect(myNewShares.outcomeShares[1]).to.above(myShares.outcomeShares[1]);
|
|
396
|
+
expect(myNewShares.outcomeShares[1]).to.equal(0.0075);
|
|
397
|
+
|
|
398
|
+
// User gets part of the liquidity tokens back in ETH
|
|
399
|
+
expect(newContractBalance).to.below(contractBalance);
|
|
400
|
+
// TODO: check amountTransferred from internal transactions
|
|
401
|
+
const amountTransferred = Number((contractBalance - newContractBalance).toFixed(5));
|
|
402
|
+
expect(amountTransferred).to.equal(0.0025);
|
|
403
|
+
}));
|
|
404
|
+
|
|
405
|
+
it('should sell outcome shares', mochaAsync(async () => {
|
|
406
|
+
const outcomeId = 0;
|
|
407
|
+
const maxOutcomeSharesToSell = 0.015;
|
|
408
|
+
|
|
409
|
+
const marketData = await predictionMarketContract.getMarketData({ marketId });
|
|
410
|
+
const outcome1Data = await predictionMarketContract.getOutcomeData({ marketId, outcomeId: outcomeIds[0] });
|
|
411
|
+
const outcome2Data = await predictionMarketContract.getOutcomeData({ marketId, outcomeId: outcomeIds[1] });
|
|
412
|
+
const contractBalance = Number(await predictionMarketContract.getBalance());
|
|
413
|
+
|
|
414
|
+
try {
|
|
415
|
+
const res = await predictionMarketContract.sell({ marketId, outcomeId, ethAmount, maxOutcomeSharesToSell });
|
|
416
|
+
expect(res.status).to.equal(true);
|
|
417
|
+
} catch (e) {
|
|
418
|
+
// TODO: review this
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
const newMarketData = await predictionMarketContract.getMarketData({ marketId });
|
|
422
|
+
const newOutcome1Data = await predictionMarketContract.getOutcomeData({ marketId, outcomeId: outcomeIds[0] });
|
|
423
|
+
const newOutcome2Data = await predictionMarketContract.getOutcomeData({ marketId, outcomeId: outcomeIds[1] });
|
|
424
|
+
const newContractBalance = Number(await predictionMarketContract.getBalance());
|
|
425
|
+
|
|
426
|
+
// outcome price should decrease
|
|
427
|
+
expect(newOutcome1Data.price).to.below(outcome1Data.price);
|
|
428
|
+
expect(newOutcome1Data.price).to.equal(0.5);
|
|
429
|
+
// opposite outcome price should increase
|
|
430
|
+
expect(newOutcome2Data.price).to.above(outcome2Data.price);
|
|
431
|
+
expect(newOutcome2Data.price).to.equal(0.5);
|
|
432
|
+
// Prices sum = 1
|
|
433
|
+
// 0.05 + 0.05 = 1
|
|
434
|
+
expect(newOutcome1Data.price + newOutcome2Data.price).to.equal(1);
|
|
435
|
+
|
|
436
|
+
// Liquidity value remains the same
|
|
437
|
+
expect(newMarketData.liquidity).to.equal(marketData.liquidity);
|
|
438
|
+
|
|
439
|
+
// outcome shares should increase
|
|
440
|
+
expect(newOutcome1Data.shares).to.above(outcome1Data.shares);
|
|
441
|
+
expect(newOutcome1Data.shares).to.equal(0.01);
|
|
442
|
+
// opposite outcome shares should increase
|
|
443
|
+
expect(newOutcome2Data.shares).to.below(outcome2Data.shares);
|
|
444
|
+
expect(newOutcome2Data.shares).to.equal(0.01);
|
|
445
|
+
// # Shares Product = Liquidity^2
|
|
446
|
+
// 0.01 * 0.01 = 0.01^2
|
|
447
|
+
expect(outcome1Data.shares * outcome2Data.shares).to.equal(newMarketData.liquidity ** 2);
|
|
448
|
+
expect(newOutcome1Data.shares * newOutcome2Data.shares).to.equal(newMarketData.liquidity ** 2);
|
|
449
|
+
|
|
450
|
+
const myShares = await predictionMarketContract.getMyMarketShares({ marketId });
|
|
451
|
+
expect(myShares).to.eql({
|
|
452
|
+
liquidityShares: 0.01,
|
|
453
|
+
outcomeShares: {
|
|
454
|
+
0: 0.0075,
|
|
455
|
+
1: 0.0075,
|
|
456
|
+
}
|
|
457
|
+
});
|
|
458
|
+
|
|
459
|
+
// User gets shares value back in ETH
|
|
460
|
+
expect(newContractBalance).to.below(contractBalance);
|
|
461
|
+
// TODO: check amountTransferred from internal transactions
|
|
462
|
+
const amountTransferred = Number((contractBalance - newContractBalance).toFixed(5));
|
|
463
|
+
expect(amountTransferred).to.equal(0.01);
|
|
464
|
+
}));
|
|
465
|
+
});
|
|
466
|
+
});
|