Best JavaScript code snippet using wpt
PremiaOption.test.ts
Source:PremiaOption.test.ts
1import { ethers } from 'hardhat';2import { BigNumber } from 'ethers';3import { expect } from 'chai';4import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/dist/src/signer-with-address';5import {6 PremiaOption,7 PremiaOption__factory,8 TestErc20,9 TestErc20__factory,10 TestFlashLoan__factory,11 TestPremiaFeeDiscount,12 TestPremiaFeeDiscount__factory,13 WETH9,14 WETH9__factory,15} from '../contractsTyped';16import { PremiaOptionTestUtil } from './utils/PremiaOptionTestUtil';17import {18 ONE_WEEK,19 TEST_TOKEN_DECIMALS,20 TEST_USE_WETH,21 ZERO_ADDRESS,22} from './utils/constants';23import { resetHardhat, setTimestampPostExpiration } from './utils/evm';24import { deployContracts, IPremiaContracts } from '../scripts/deployContracts';25import { formatUnits, parseEther, parseUnits } from 'ethers/lib/utils';26import { createUniswap, IUniswap } from './utils/uniswap';27import {28 getAmountExceedsBalanceRevertMsg,29 getToken,30 mintTestToken,31 parseTestToken,32} from './utils/token';33let p: IPremiaContracts;34let uniswap: IUniswap;35let weth: WETH9;36let wbtc: TestErc20;37let dai: TestErc20;38let premiaOption: PremiaOption;39let premiaFeeDiscount: TestPremiaFeeDiscount;40let admin: SignerWithAddress;41let writer1: SignerWithAddress;42let writer2: SignerWithAddress;43let user1: SignerWithAddress;44let feeRecipient: SignerWithAddress;45let testToken: WETH9 | TestErc20;46const tax = 100;47let optionTestUtil: PremiaOptionTestUtil;48describe('PremiaOption', () => {49 beforeEach(async () => {50 await resetHardhat();51 [admin, writer1, writer2, user1, feeRecipient] = await ethers.getSigners();52 weth = await new WETH9__factory(admin).deploy();53 dai = await new TestErc20__factory(admin).deploy(18);54 wbtc = await new TestErc20__factory(admin).deploy(TEST_TOKEN_DECIMALS);55 testToken = getToken(weth, wbtc);56 p = await deployContracts(admin, feeRecipient.address, true);57 const premiaOptionFactory = new PremiaOption__factory(admin);58 premiaOption = await premiaOptionFactory.deploy(59 'dummyURI',60 dai.address,61 p.uPremia.address,62 p.feeCalculator.address,63 p.premiaReferral.address,64 feeRecipient.address,65 );66 await p.uPremia.addMinter([premiaOption.address]);67 premiaFeeDiscount = await new TestPremiaFeeDiscount__factory(68 admin,69 ).deploy();70 await p.feeCalculator.setPremiaFeeDiscount(premiaFeeDiscount.address);71 await p.premiaReferral.addWhitelisted([premiaOption.address]);72 optionTestUtil = new PremiaOptionTestUtil({73 testToken,74 dai,75 premiaOption,76 admin,77 writer1,78 writer2,79 user1,80 feeRecipient,81 tax,82 });83 });84 it('should add testToken for trading', async () => {85 await optionTestUtil.addTestToken();86 const strikePriceIncrement = await premiaOption.tokenStrikeIncrement(87 testToken.address,88 );89 expect(strikePriceIncrement.eq(parseEther('10'))).to.true;90 });91 it('should create a new optionId', async () => {92 await optionTestUtil.addTestToken();93 const defaultOption = optionTestUtil.getOptionDefaults();94 await premiaOption.getOptionIdOrCreate(95 testToken.address,96 defaultOption.expiration,97 defaultOption.strikePrice,98 true,99 );100 const option = await premiaOption.optionData(1);101 expect(option.token).to.eq(testToken.address);102 expect(option.expiration).to.eq(defaultOption.expiration);103 expect(option.strikePrice).to.eq(defaultOption.strikePrice);104 expect(option.isCall).to.be.true;105 });106 describe('writeOption', () => {107 it('should fail if token not added', async () => {108 await expect(optionTestUtil.writeOption(writer1)).to.be.revertedWith(109 'Token not supported',110 );111 });112 it('should disable testToken for writing', async () => {113 await optionTestUtil.addTestToken();114 await premiaOption.setTokens([testToken.address], [0]);115 await expect(optionTestUtil.writeOption(writer1)).to.be.revertedWith(116 'Token not supported',117 );118 });119 it('should revert if contract amount <= 0', async () => {120 await optionTestUtil.addTestToken();121 await expect(122 optionTestUtil.writeOption(writer1, { amount: BigNumber.from(0) }),123 ).to.be.revertedWith('Amount <= 0');124 });125 it('should revert if contract strike price <= 0', async () => {126 await optionTestUtil.addTestToken();127 await expect(128 optionTestUtil.writeOption(writer1, { strikePrice: 0 }),129 ).to.be.revertedWith('Strike <= 0');130 });131 it('should revert if strike price increment is wrong', async () => {132 await optionTestUtil.addTestToken();133 await expect(134 optionTestUtil.writeOption(writer1, {135 strikePrice: parseEther('1'),136 }),137 ).to.be.revertedWith('Wrong strike incr');138 });139 it('should revert if timestamp already passed', async () => {140 await optionTestUtil.addTestToken();141 await setTimestampPostExpiration();142 await expect(optionTestUtil.writeOption(writer1)).to.be.revertedWith(143 'Exp passed',144 );145 });146 it('should revert if timestamp increment is wrong', async () => {147 await optionTestUtil.addTestToken();148 await expect(149 optionTestUtil.writeOption(writer1, {150 expiration: optionTestUtil.getNextExpiration() + 200,151 }),152 ).to.be.revertedWith('Wrong exp incr');153 });154 it('should revert if timestamp is beyond max expiration', async () => {155 await optionTestUtil.addTestToken();156 await expect(157 optionTestUtil.writeOption(writer1, {158 expiration: Math.floor(new Date().getTime() / 1000 + 60 * ONE_WEEK),159 }),160 ).to.be.revertedWith('Exp > 1 yr');161 });162 it('should fail if address does not have enough testToken for call', async () => {163 await optionTestUtil.addTestToken();164 await mintTestToken(writer1, testToken, parseTestToken('0.99'));165 await testToken166 .connect(writer1)167 .approve(premiaOption.address, parseTestToken('1'));168 await expect(optionTestUtil.writeOption(writer1)).to.be.revertedWith(169 getAmountExceedsBalanceRevertMsg(),170 );171 });172 it('should fail if address does not have enough dai for put', async () => {173 await optionTestUtil.addTestToken();174 await dai.mint(writer1.address, parseEther('9.99'));175 await dai176 .connect(writer1)177 .increaseAllowance(premiaOption.address, parseEther('10'));178 await expect(179 optionTestUtil.writeOption(writer1, { isCall: false }),180 ).to.be.revertedWith('ERC20: transfer amount exceeds balance');181 });182 it('should successfully mint options for 2 testToken', async () => {183 await optionTestUtil.addTestTokenAndWriteOptions(parseTestToken('2'));184 const balance = await premiaOption.balanceOf(writer1.address, 1);185 expect(balance).to.eq(parseTestToken('2'));186 });187 it('should be optionId 1', async () => {188 await optionTestUtil.addTestTokenAndWriteOptions(parseTestToken('2'));189 const defaults = optionTestUtil.getOptionDefaults();190 const optionId = await premiaOption.getOptionId(191 testToken.address,192 defaults.expiration,193 defaults.strikePrice,194 defaults.isCall,195 );196 expect(optionId).to.eq(1);197 });198 it('should successfully batchWriteOption', async () => {199 await optionTestUtil.addTestToken();200 const defaultOption = optionTestUtil.getOptionDefaults();201 const contractAmount1 = parseTestToken('2');202 const contractAmount2 = parseTestToken('3');203 let amount = contractAmount1.add(contractAmount1.mul(tax).div(1e4));204 await mintTestToken(writer1, testToken, amount);205 await testToken206 .connect(writer1)207 .approve(premiaOption.address, parseTestToken(amount.toString()));208 const baseAmount = contractAmount2.mul(10).mul(3);209 amount = baseAmount.add(baseAmount.mul(tax).div(1e4));210 await dai.mint(writer1.address, parseEther(amount.toString()));211 await dai212 .connect(writer1)213 .increaseAllowance(premiaOption.address, parseEther(amount.toString()));214 await premiaOption215 .connect(writer1)216 .setApprovalForAll(p.premiaOptionBatch.address, true);217 await p.premiaOptionBatch.connect(writer1).batchWriteOption(218 premiaOption.address,219 [220 {221 ...defaultOption,222 token: testToken.address,223 isCall: true,224 amount: contractAmount1,225 },226 {227 ...defaultOption,228 token: testToken.address,229 isCall: false,230 amount: contractAmount2,231 },232 ],233 ZERO_ADDRESS,234 );235 const balance1 = await premiaOption.balanceOf(writer1.address, 1);236 const balance2 = await premiaOption.balanceOf(writer1.address, 2);237 expect(balance1).to.eq(contractAmount1);238 expect(balance2).to.eq(contractAmount2);239 });240 it('should fail writeOptionFrom if not approved', async () => {241 await optionTestUtil.addTestToken();242 const amount = parseTestToken('2');243 const amountWithFee = amount.add(amount.mul(tax).div(1e4));244 await mintTestToken(writer1, testToken, amountWithFee);245 await testToken246 .connect(writer1)247 .approve(premiaOption.address, amountWithFee);248 await expect(249 premiaOption250 .connect(writer2)251 .writeOptionFrom(252 writer1.address,253 { ...optionTestUtil.getOptionDefaults(), amount },254 ZERO_ADDRESS,255 ),256 ).to.be.revertedWith('Not approved');257 });258 it('should successfully writeOptionFrom', async () => {259 await optionTestUtil.addTestToken();260 const amount = parseTestToken('2');261 const amountWithFee = amount.add(amount.mul(tax).div(1e4));262 await mintTestToken(writer1, testToken, amountWithFee);263 await testToken264 .connect(writer1)265 .approve(premiaOption.address, amountWithFee);266 await premiaOption267 .connect(writer1)268 .setApprovalForAll(writer2.address, true);269 await premiaOption270 .connect(writer2)271 .writeOptionFrom(272 writer1.address,273 { ...optionTestUtil.getOptionDefaults(), amount },274 ZERO_ADDRESS,275 );276 expect(await premiaOption.balanceOf(writer1.address, 1)).to.eq(amount);277 expect(await premiaOption.nbWritten(writer1.address, 1)).to.eq(amount);278 });279 });280 describe('cancelOption', () => {281 it('should successfully cancel 1 call option', async () => {282 await optionTestUtil.addTestTokenAndWriteOptions(parseTestToken('2'));283 let optionBalance = await premiaOption.balanceOf(writer1.address, 1);284 let testTokenBalance = await testToken.balanceOf(writer1.address);285 expect(optionBalance).to.eq(parseTestToken('2'));286 expect(testTokenBalance).to.eq(0);287 await premiaOption.connect(writer1).cancelOption(1, parseTestToken('1'));288 optionBalance = await premiaOption.balanceOf(writer1.address, 1);289 testTokenBalance = await testToken.balanceOf(writer1.address);290 expect(optionBalance).to.eq(parseTestToken('1'));291 expect(testTokenBalance.toString()).to.eq(parseTestToken('1'));292 });293 it('should successfully cancel 1 put option', async () => {294 await optionTestUtil.addTestTokenAndWriteOptions(295 parseTestToken('2'),296 false,297 );298 let optionBalance = await premiaOption.balanceOf(writer1.address, 1);299 let daiBalance = await dai.balanceOf(writer1.address);300 expect(optionBalance).to.eq(parseTestToken('2'));301 expect(daiBalance).to.eq(0);302 await premiaOption.connect(writer1).cancelOption(1, parseTestToken('1'));303 optionBalance = await premiaOption.balanceOf(writer1.address, 1);304 daiBalance = await dai.balanceOf(writer1.address);305 expect(optionBalance).to.eq(parseTestToken('1'));306 expect(daiBalance.toString()).to.eq(parseEther('10'));307 });308 it('should fail cancelling option if not a writer', async () => {309 await optionTestUtil.addTestTokenAndWriteOptions(parseTestToken('2'));310 await optionTestUtil.transferOptionToUser1(writer1);311 await expect(312 premiaOption.connect(user1).cancelOption(1, parseTestToken('1')),313 ).to.revertedWith('Not enough written');314 });315 it('should subtract option written after cancelling', async () => {316 await optionTestUtil.addTestTokenAndWriteOptions(parseTestToken('2'));317 await premiaOption.connect(writer1).cancelOption(1, parseTestToken('1'));318 const nbWritten = await premiaOption.nbWritten(writer1.address, 1);319 expect(nbWritten).to.eq(parseTestToken('1'));320 });321 it('should successfully batchCancelOption', async () => {322 await optionTestUtil.addTestTokenAndWriteOptions(parseTestToken('3'));323 await optionTestUtil.addTestTokenAndWriteOptions(324 parseTestToken('3'),325 false,326 );327 let optionBalance1 = await premiaOption.balanceOf(writer1.address, 1);328 let optionBalance2 = await premiaOption.balanceOf(writer1.address, 2);329 let testTokenBalance = await testToken.balanceOf(writer1.address);330 let daiBalance = await dai.balanceOf(writer1.address);331 expect(optionBalance1).to.eq(parseTestToken('3'));332 expect(testTokenBalance).to.eq(0);333 expect(optionBalance2).to.eq(parseTestToken('3'));334 expect(daiBalance).to.eq(0);335 await premiaOption336 .connect(writer1)337 .setApprovalForAll(p.premiaOptionBatch.address, true);338 await p.premiaOptionBatch339 .connect(writer1)340 .batchCancelOption(341 premiaOption.address,342 [1, 2],343 [parseTestToken('2'), parseTestToken('1')],344 );345 optionBalance1 = await premiaOption.balanceOf(writer1.address, 1);346 optionBalance2 = await premiaOption.balanceOf(writer1.address, 2);347 testTokenBalance = await testToken.balanceOf(writer1.address);348 daiBalance = await dai.balanceOf(writer1.address);349 expect(optionBalance1).to.eq(parseTestToken('1'));350 expect(optionBalance2).to.eq(parseTestToken('2'));351 expect(testTokenBalance.toString()).to.eq(parseTestToken('2'));352 expect(daiBalance.toString()).to.eq(parseEther('10'));353 });354 it('should fail cancelOptionFrom if not approved', async () => {355 await optionTestUtil.addTestTokenAndWriteOptions(356 parseTestToken('2'),357 false,358 );359 await expect(360 premiaOption361 .connect(writer2)362 .cancelOptionFrom(writer1.address, 1, parseTestToken('2')),363 ).to.be.revertedWith('Not approved');364 });365 it('should successfully cancelOptionFrom', async () => {366 await optionTestUtil.addTestTokenAndWriteOptions(367 parseTestToken('2'),368 false,369 );370 await premiaOption371 .connect(writer1)372 .setApprovalForAll(writer2.address, true);373 await premiaOption374 .connect(writer2)375 .cancelOptionFrom(writer1.address, 1, parseTestToken('2'));376 expect(await premiaOption.balanceOf(writer1.address, 1)).to.eq(0);377 });378 });379 describe('exerciseOption', () => {380 it('should fail exercising call option if not owned', async () => {381 await optionTestUtil.addTestTokenAndWriteOptions(parseTestToken('2'));382 await expect(383 premiaOption384 .connect(user1)385 .exerciseOption(1, parseTestToken('1'), ZERO_ADDRESS),386 ).to.revertedWith('ERC1155: burn amount exceeds balance');387 });388 it('should fail exercising call option if not enough dai', async () => {389 await optionTestUtil.addTestTokenAndWriteOptions(parseTestToken('2'));390 await optionTestUtil.transferOptionToUser1(writer1);391 await expect(392 premiaOption393 .connect(user1)394 .exerciseOption(1, parseTestToken('1'), ZERO_ADDRESS),395 ).to.revertedWith('ERC20: transfer amount exceeds balance');396 });397 it('should successfully exercise 1 call option', async () => {398 await optionTestUtil.addTestTokenAndWriteOptionsAndExercise(399 true,400 parseTestToken('2'),401 parseTestToken('1'),402 );403 const optionBalance = await premiaOption.balanceOf(user1.address, 1);404 const daiBalance = await dai.balanceOf(user1.address);405 const testTokenBalance = await testToken.balanceOf(user1.address);406 expect(optionBalance).to.eq(parseTestToken('1'));407 expect(daiBalance).to.eq(0);408 expect(testTokenBalance).to.eq(parseTestToken('1'));409 });410 it('should successfully exercise 1 put option', async () => {411 await optionTestUtil.addTestTokenAndWriteOptionsAndExercise(412 false,413 parseTestToken('2'),414 parseTestToken('1'),415 );416 const optionBalance = await premiaOption.balanceOf(user1.address, 1);417 const daiBalance = await dai.balanceOf(user1.address);418 const testTokenBalance = await testToken.balanceOf(user1.address);419 expect(optionBalance).to.eq(parseTestToken('1'));420 expect(daiBalance).to.eq(parseEther('10'));421 expect(testTokenBalance).to.eq(0);422 });423 it('should have 0.01 testToken and 0.1 dai in feeRecipient after 1 option exercised', async () => {424 await optionTestUtil.addTestTokenAndWriteOptionsAndExercise(425 true,426 parseTestToken('1'),427 parseTestToken('1'),428 );429 const daiBalance = await dai.balanceOf(feeRecipient.address);430 const testTokenBalance = await testToken.balanceOf(feeRecipient.address);431 expect(daiBalance).to.eq(parseEther('0.1'));432 expect(testTokenBalance).to.eq(parseTestToken('0.01'));433 });434 it('should have 0 testToken and 0.1 dai in feeRecipient after 1 option exercised if writer is whitelisted', async () => {435 await p.feeCalculator.addWhitelisted([writer1.address]);436 await optionTestUtil.addTestTokenAndWriteOptionsAndExercise(437 true,438 parseTestToken('1'),439 parseTestToken('1'),440 );441 const daiBalance = await dai.balanceOf(feeRecipient.address);442 const testTokenBalance = await testToken.balanceOf(feeRecipient.address);443 expect(daiBalance).to.eq(parseEther('0.1'));444 expect(testTokenBalance).to.eq(parseTestToken('0'));445 });446 it('should have 0.1 testToken and 0 dai in feeRecipient after 1 option exercised if exerciser is whitelisted', async () => {447 await p.feeCalculator.addWhitelisted([user1.address]);448 await optionTestUtil.addTestTokenAndWriteOptionsAndExercise(449 true,450 parseTestToken('1'),451 parseTestToken('1'),452 );453 const daiBalance = await dai.balanceOf(feeRecipient.address);454 const testTokenBalance = await testToken.balanceOf(feeRecipient.address);455 expect(daiBalance).to.eq(parseEther('0'));456 expect(testTokenBalance).to.eq(parseTestToken('0.01'));457 });458 it('should successfully batchExerciseOption', async () => {459 await optionTestUtil.addTestTokenAndWriteOptions(460 parseTestToken('2'),461 true,462 );463 await optionTestUtil.addTestTokenAndWriteOptions(464 parseTestToken('3'),465 false,466 );467 await optionTestUtil.transferOptionToUser1(468 writer1,469 parseTestToken('2'),470 1,471 );472 await optionTestUtil.transferOptionToUser1(473 writer1,474 parseTestToken('3'),475 2,476 );477 let baseAmount = parseEther('10');478 let amount = parseEther('10').add(baseAmount.mul(tax).div(1e4));479 await dai.mint(user1.address, amount);480 await dai.connect(user1).increaseAllowance(premiaOption.address, amount);481 baseAmount = parseTestToken('2');482 amount = baseAmount.add(baseAmount.mul(tax).div(1e4));483 await mintTestToken(user1, testToken, amount);484 await testToken.connect(user1).approve(premiaOption.address, amount);485 await premiaOption486 .connect(user1)487 .setApprovalForAll(p.premiaOptionBatch.address, true);488 await p.premiaOptionBatch489 .connect(user1)490 .batchExerciseOption(491 premiaOption.address,492 [1, 2],493 [parseTestToken('1'), parseTestToken('2')],494 ZERO_ADDRESS,495 );496 const optionBalance1 = await premiaOption.balanceOf(user1.address, 1);497 const optionBalance2 = await premiaOption.balanceOf(user1.address, 2);498 const daiBalance = await dai.balanceOf(user1.address);499 const testTokenBalance = await testToken.balanceOf(user1.address);500 expect(optionBalance1).to.eq(parseTestToken('1'));501 expect(optionBalance2).to.eq(parseTestToken('1'));502 expect(daiBalance).to.eq(parseEther('20'));503 expect(testTokenBalance).to.eq(parseTestToken('1'));504 });505 it('should fail exerciseOptionFrom if not approved', async () => {506 const amount = parseTestToken('2');507 await optionTestUtil.addTestTokenAndWriteOptions(amount, false);508 await optionTestUtil.transferOptionToUser1(writer1, amount);509 const amountTotal = amount.add(amount.mul(tax).div(1e4));510 await mintTestToken(user1, testToken, amountTotal);511 await testToken.connect(user1).approve(premiaOption.address, amountTotal);512 await expect(513 premiaOption514 .connect(writer2)515 .exerciseOptionFrom(user1.address, 1, amount, ZERO_ADDRESS),516 ).to.be.revertedWith('Not approved');517 });518 it('should successfully exerciseOptionFrom', async () => {519 const amount = parseTestToken('2');520 await optionTestUtil.addTestTokenAndWriteOptions(amount, false);521 await optionTestUtil.transferOptionToUser1(writer1, amount);522 const amountTotal = amount.add(amount.mul(tax).div(1e4));523 await mintTestToken(user1, testToken, amountTotal);524 await testToken.connect(user1).approve(premiaOption.address, amountTotal);525 await premiaOption526 .connect(user1)527 .setApprovalForAll(writer2.address, true);528 await premiaOption529 .connect(writer2)530 .exerciseOptionFrom(user1.address, 1, amount, ZERO_ADDRESS);531 expect(await premiaOption.balanceOf(user1.address, 1)).to.eq(0);532 expect(await dai.balanceOf(user1.address)).to.eq(parseEther('20'));533 expect(await testToken.balanceOf(premiaOption.address)).to.eq(534 parseTestToken('2'),535 );536 });537 });538 describe('withdraw', () => {539 it('should fail withdrawing if option not expired', async () => {540 await optionTestUtil.addTestTokenAndWriteOptionsAndExercise(541 true,542 parseTestToken('2'),543 parseTestToken('1'),544 );545 await expect(premiaOption.connect(writer1).withdraw(1)).to.revertedWith(546 'Not expired',547 );548 });549 it('should fail withdrawing from non-writer if option is expired', async () => {550 await optionTestUtil.addTestTokenAndWriteOptions(parseTestToken('2'));551 await optionTestUtil.transferOptionToUser1(writer1);552 await setTimestampPostExpiration();553 await expect(premiaOption.connect(user1).withdraw(1)).to.revertedWith(554 'No option to claim',555 );556 });557 it('should successfully allow writer withdrawal of 2 testToken if 0/2 call option exercised', async () => {558 await optionTestUtil.addTestTokenAndWriteOptions(parseTestToken('2'));559 await optionTestUtil.transferOptionToUser1(writer1, parseTestToken('2'));560 await setTimestampPostExpiration();561 let testTokenBalance = await testToken.balanceOf(writer1.address);562 let daiBalance = await dai.balanceOf(writer1.address);563 expect(testTokenBalance).to.eq(0);564 expect(daiBalance).to.eq(0);565 await premiaOption.connect(writer1).withdraw(1);566 testTokenBalance = await testToken.balanceOf(writer1.address);567 daiBalance = await dai.balanceOf(writer1.address);568 expect(testTokenBalance).to.eq(parseTestToken('2'));569 expect(daiBalance).to.eq(0);570 });571 it('should successfully allow writer withdrawal of 1 testToken and 10 dai if 1/2 call option exercised', async () => {572 await optionTestUtil.addTestTokenAndWriteOptionsAndExercise(573 true,574 parseTestToken('2'),575 parseTestToken('1'),576 );577 await setTimestampPostExpiration();578 let testTokenBalance = await testToken.balanceOf(writer1.address);579 let daiBalance = await dai.balanceOf(writer1.address);580 expect(testTokenBalance).to.eq(0);581 expect(daiBalance).to.eq(0);582 await premiaOption.connect(writer1).withdraw(1);583 testTokenBalance = await testToken.balanceOf(writer1.address);584 daiBalance = await dai.balanceOf(writer1.address);585 expect(testTokenBalance).to.eq(parseTestToken('1'));586 expect(daiBalance).to.eq(parseEther('10'));587 });588 it('should successfully allow writer withdrawal of 20 dai if 2/2 call option exercised', async () => {589 await optionTestUtil.addTestTokenAndWriteOptionsAndExercise(590 true,591 parseTestToken('2'),592 parseTestToken('2'),593 );594 await setTimestampPostExpiration();595 let testTokenBalance = await testToken.balanceOf(writer1.address);596 let daiBalance = await dai.balanceOf(writer1.address);597 expect(testTokenBalance).to.eq(0);598 expect(daiBalance).to.eq(0);599 await premiaOption.connect(writer1).withdraw(1);600 testTokenBalance = await testToken.balanceOf(writer1.address);601 daiBalance = await dai.balanceOf(writer1.address);602 expect(testTokenBalance).to.eq(0);603 expect(daiBalance).to.eq(parseEther('20'));604 });605 it('should successfully allow writer withdrawal of 20 dai if 0/2 put option exercised', async () => {606 await optionTestUtil.addTestTokenAndWriteOptions(607 parseTestToken('2'),608 false,609 );610 await optionTestUtil.transferOptionToUser1(writer1, parseTestToken('2'));611 await setTimestampPostExpiration();612 let testTokenBalance = await testToken.balanceOf(writer1.address);613 let daiBalance = await dai.balanceOf(writer1.address);614 expect(testTokenBalance).to.eq(0);615 expect(daiBalance).to.eq(0);616 await premiaOption.connect(writer1).withdraw(1);617 testTokenBalance = await testToken.balanceOf(writer1.address);618 daiBalance = await dai.balanceOf(writer1.address);619 expect(testTokenBalance).to.eq(0);620 expect(daiBalance).to.eq(parseEther('20'));621 });622 it('should successfully allow writer withdrawal of 1 testToken and 10 dai if 1/2 put option exercised', async () => {623 await optionTestUtil.addTestTokenAndWriteOptionsAndExercise(624 false,625 parseTestToken('2'),626 parseTestToken('1'),627 );628 await setTimestampPostExpiration();629 let testTokenBalance = await testToken.balanceOf(writer1.address);630 let daiBalance = await dai.balanceOf(writer1.address);631 expect(testTokenBalance).to.eq(0);632 expect(daiBalance).to.eq(0);633 await premiaOption.connect(writer1).withdraw(1);634 testTokenBalance = await testToken.balanceOf(writer1.address);635 daiBalance = await dai.balanceOf(writer1.address);636 expect(testTokenBalance).to.eq(parseTestToken('1'));637 expect(daiBalance).to.eq(parseEther('10'));638 });639 it('should successfully allow writer withdrawal of 2 testToken if 2/2 put option exercised', async () => {640 await optionTestUtil.addTestTokenAndWriteOptionsAndExercise(641 false,642 parseTestToken('2'),643 parseTestToken('2'),644 );645 await setTimestampPostExpiration();646 let testTokenBalance = await testToken.balanceOf(writer1.address);647 let daiBalance = await dai.balanceOf(writer1.address);648 expect(testTokenBalance).to.eq(0);649 expect(daiBalance).to.eq(0);650 await premiaOption.connect(writer1).withdraw(1);651 testTokenBalance = await testToken.balanceOf(writer1.address);652 daiBalance = await dai.balanceOf(writer1.address);653 expect(testTokenBalance).to.eq(parseTestToken('2'));654 expect(daiBalance).to.eq(0);655 });656 it('should withdraw 0.5 testToken and 5 dai if 1/2 option exercised and 2 different writers', async () => {657 await optionTestUtil.addTestToken();658 await optionTestUtil.mintAndWriteOption(writer1, parseTestToken('1'));659 await optionTestUtil.mintAndWriteOption(writer2, parseTestToken('1'));660 await optionTestUtil.transferOptionToUser1(writer1);661 await optionTestUtil.transferOptionToUser1(writer2);662 await optionTestUtil.exerciseOption(true, parseTestToken('1'));663 await setTimestampPostExpiration();664 await premiaOption.connect(writer1).withdraw(1);665 await premiaOption.connect(writer2).withdraw(1);666 const writer1TestToken = await testToken.balanceOf(writer1.address);667 const writer1Dai = await dai.balanceOf(writer1.address);668 const writer2TestToken = await testToken.balanceOf(writer2.address);669 const writer2Dai = await dai.balanceOf(writer2.address);670 expect(writer1TestToken).to.eq(parseTestToken('0.5'));671 expect(writer1Dai).to.eq(parseEther('5'));672 expect(writer2TestToken).to.eq(parseTestToken('0.5'));673 expect(writer2Dai).to.eq(parseEther('5'));674 });675 it('should withdraw 1 testToken, if 1/2 call exercised and 1 withdrawPreExpiration', async () => {676 await optionTestUtil.addTestToken();677 await optionTestUtil.mintAndWriteOption(writer1, parseTestToken('1'));678 await optionTestUtil.mintAndWriteOption(writer2, parseTestToken('1'));679 await optionTestUtil.transferOptionToUser1(writer1, parseTestToken('1'));680 await optionTestUtil.transferOptionToUser1(writer2, parseTestToken('1'));681 await optionTestUtil.exerciseOption(true, parseTestToken('1'));682 await premiaOption683 .connect(writer2)684 .withdrawPreExpiration(1, parseTestToken('1'));685 await setTimestampPostExpiration();686 await premiaOption.connect(writer1).withdraw(1);687 const daiBalance = await dai.balanceOf(writer1.address);688 const testTokenBalance = await testToken.balanceOf(writer1.address);689 const nbWritten = await premiaOption.nbWritten(writer1.address, 1);690 expect(daiBalance).to.eq(0);691 expect(testTokenBalance).to.eq(parseTestToken('1'));692 expect(nbWritten).to.eq(0);693 });694 it('should withdraw 10 dai, if 1/2 put exercised and 1 withdrawPreExpiration', async () => {695 await optionTestUtil.addTestToken();696 await optionTestUtil.mintAndWriteOption(697 writer1,698 parseTestToken('1'),699 false,700 );701 await optionTestUtil.mintAndWriteOption(702 writer2,703 parseTestToken('1'),704 false,705 );706 await optionTestUtil.transferOptionToUser1(writer1, parseTestToken('1'));707 await optionTestUtil.transferOptionToUser1(writer2, parseTestToken('1'));708 await optionTestUtil.exerciseOption(false, parseTestToken('1'));709 await premiaOption710 .connect(writer2)711 .withdrawPreExpiration(1, parseTestToken('1'));712 await setTimestampPostExpiration();713 await premiaOption.connect(writer1).withdraw(1);714 const daiBalance = await dai.balanceOf(writer1.address);715 const testTokenBalance = await testToken.balanceOf(writer1.address);716 const nbWritten = await premiaOption.nbWritten(writer1.address, 1);717 expect(daiBalance).to.eq(parseEther('10'));718 expect(testTokenBalance).to.eq(0);719 expect(nbWritten).to.eq(0);720 });721 it('should successfully batchWithdraw', async () => {722 await optionTestUtil.addTestToken();723 await optionTestUtil.mintAndWriteOption(writer1, parseTestToken('1'));724 await optionTestUtil.mintAndWriteOption(writer2, parseTestToken('1'));725 await optionTestUtil.transferOptionToUser1(writer1, parseTestToken('1'));726 await optionTestUtil.transferOptionToUser1(writer2, parseTestToken('1'));727 await optionTestUtil.exerciseOption(true, parseTestToken('1'));728 await premiaOption729 .connect(writer2)730 .withdrawPreExpiration(1, parseTestToken('1'));731 await optionTestUtil.mintAndWriteOption(732 writer1,733 parseTestToken('1'),734 false,735 );736 await optionTestUtil.mintAndWriteOption(737 writer2,738 parseTestToken('1'),739 false,740 );741 await optionTestUtil.transferOptionToUser1(742 writer1,743 parseTestToken('1'),744 2,745 );746 await optionTestUtil.transferOptionToUser1(747 writer2,748 parseTestToken('1'),749 2,750 );751 await optionTestUtil.exerciseOption(752 false,753 parseTestToken('1'),754 undefined,755 2,756 );757 await premiaOption758 .connect(writer2)759 .withdrawPreExpiration(2, parseTestToken('1'));760 await setTimestampPostExpiration();761 await premiaOption762 .connect(writer1)763 .setApprovalForAll(p.premiaOptionBatch.address, true);764 await p.premiaOptionBatch765 .connect(writer1)766 .batchWithdraw(premiaOption.address, [1, 2]);767 const daiBalance = await dai.balanceOf(writer1.address);768 const testTokenBalance = await testToken.balanceOf(writer1.address);769 const nbWritten1 = await premiaOption.nbWritten(writer1.address, 1);770 const nbWritten2 = await premiaOption.nbWritten(writer1.address, 2);771 expect(daiBalance).to.eq(parseEther('10'));772 expect(testTokenBalance).to.eq(parseTestToken('1'));773 expect(nbWritten1).to.eq(0);774 expect(nbWritten2).to.eq(0);775 });776 it('should fail withdrawFrom if not approved', async () => {777 await optionTestUtil.addTestTokenAndWriteOptions(parseTestToken('2'));778 await optionTestUtil.transferOptionToUser1(writer1, parseTestToken('2'));779 await setTimestampPostExpiration();780 let testTokenBalance = await testToken.balanceOf(writer1.address);781 let daiBalance = await dai.balanceOf(writer1.address);782 expect(testTokenBalance).to.eq(0);783 expect(daiBalance).to.eq(0);784 await expect(785 premiaOption.connect(writer2).withdrawFrom(writer1.address, 1),786 ).to.be.revertedWith('Not approved');787 });788 it('should successfully withdrawFrom', async () => {789 await optionTestUtil.addTestTokenAndWriteOptions(parseTestToken('2'));790 await optionTestUtil.transferOptionToUser1(writer1, parseTestToken('2'));791 await setTimestampPostExpiration();792 let testTokenBalance = await testToken.balanceOf(writer1.address);793 let daiBalance = await dai.balanceOf(writer1.address);794 expect(testTokenBalance).to.eq(0);795 expect(daiBalance).to.eq(0);796 await premiaOption797 .connect(writer1)798 .setApprovalForAll(writer2.address, true);799 await premiaOption.connect(writer2).withdrawFrom(writer1.address, 1);800 testTokenBalance = await testToken.balanceOf(writer1.address);801 daiBalance = await dai.balanceOf(writer1.address);802 expect(testTokenBalance).to.eq(parseTestToken('2'));803 expect(daiBalance).to.eq(0);804 });805 });806 describe('withdrawPreExpiration', () => {807 it('should fail withdrawing if option is expired', async () => {808 await optionTestUtil.addTestTokenAndWriteOptionsAndExercise(809 true,810 parseTestToken('2'),811 parseTestToken('1'),812 );813 await setTimestampPostExpiration();814 await expect(815 premiaOption.withdrawPreExpiration(1, parseTestToken('1')),816 ).to.revertedWith('Expired');817 });818 it('should fail withdrawing from non-writer if option is not expired', async () => {819 await optionTestUtil.addTestTokenAndWriteOptions(parseTestToken('2'));820 await optionTestUtil.transferOptionToUser1(writer1);821 await expect(822 premiaOption823 .connect(user1)824 .withdrawPreExpiration(1, parseTestToken('1')),825 ).to.revertedWith('Not enough claims');826 });827 it('should fail withdrawing if no unclaimed exercised options', async () => {828 await optionTestUtil.addTestTokenAndWriteOptions(parseTestToken('2'));829 await optionTestUtil.transferOptionToUser1(writer1, parseTestToken('2'));830 await expect(831 premiaOption832 .connect(writer1)833 .withdrawPreExpiration(1, parseTestToken('2')),834 ).to.revertedWith('Not enough claimable');835 });836 it('should fail withdrawing if not enough unclaimed exercised options', async () => {837 await optionTestUtil.addTestTokenAndWriteOptions(parseTestToken('2'));838 await optionTestUtil.transferOptionToUser1(writer1, parseTestToken('2'));839 await optionTestUtil.exerciseOption(true, parseTestToken('1'));840 await expect(841 premiaOption842 .connect(writer1)843 .withdrawPreExpiration(1, parseTestToken('2')),844 ).to.revertedWith('Not enough claimable');845 });846 it('should successfully withdraw 10 dai for withdrawPreExpiration of call option exercised', async () => {847 await optionTestUtil.addTestTokenAndWriteOptions(parseTestToken('2'));848 await optionTestUtil.transferOptionToUser1(writer1, parseTestToken('2'));849 await optionTestUtil.exerciseOption(true, parseTestToken('1'));850 await premiaOption851 .connect(writer1)852 .withdrawPreExpiration(1, parseTestToken('1'));853 const daiBalance = await dai.balanceOf(writer1.address);854 const testTokenBalance = await testToken.balanceOf(writer1.address);855 const nbWritten = await premiaOption.nbWritten(writer1.address, 1);856 expect(daiBalance).to.eq(parseEther('10'));857 expect(testTokenBalance).to.eq(0);858 expect(nbWritten).to.eq(parseTestToken('1'));859 });860 it('should successfully withdraw 1 testToken for withdrawPreExpiration of put option exercised', async () => {861 await optionTestUtil.addTestTokenAndWriteOptions(862 parseTestToken('2'),863 false,864 );865 await optionTestUtil.transferOptionToUser1(writer1, parseTestToken('2'));866 await optionTestUtil.exerciseOption(false, parseTestToken('1'));867 await premiaOption868 .connect(writer1)869 .withdrawPreExpiration(1, parseTestToken('1'));870 const daiBalance = await dai.balanceOf(writer1.address);871 const testTokenBalance = await testToken.balanceOf(writer1.address);872 const nbWritten = await premiaOption.nbWritten(writer1.address, 1);873 expect(daiBalance).to.eq(0);874 expect(testTokenBalance).to.eq(parseTestToken('1'));875 expect(nbWritten).to.eq(parseTestToken('1'));876 });877 it('should successfully batchWithdrawPreExpiration', async () => {878 await optionTestUtil.addTestToken();879 await optionTestUtil.mintAndWriteOption(880 writer1,881 parseTestToken('3'),882 true,883 );884 await optionTestUtil.mintAndWriteOption(885 writer1,886 parseTestToken('3'),887 false,888 );889 await optionTestUtil.transferOptionToUser1(writer1, parseTestToken('3'));890 await optionTestUtil.transferOptionToUser1(891 writer1,892 parseTestToken('3'),893 2,894 );895 await optionTestUtil.exerciseOption(true, parseTestToken('2'));896 await optionTestUtil.exerciseOption(897 false,898 parseTestToken('1'),899 undefined,900 2,901 );902 await premiaOption903 .connect(writer1)904 .setApprovalForAll(p.premiaOptionBatch.address, true);905 await p.premiaOptionBatch906 .connect(writer1)907 .batchWithdrawPreExpiration(908 premiaOption.address,909 [1, 2],910 [parseTestToken('2'), parseTestToken('1')],911 );912 const daiBalance = await dai.balanceOf(writer1.address);913 const testTokenBalance = await testToken.balanceOf(writer1.address);914 const nbWritten1 = await premiaOption.nbWritten(writer1.address, 1);915 const nbWritten2 = await premiaOption.nbWritten(writer1.address, 2);916 expect(daiBalance).to.eq(parseEther('20'));917 expect(testTokenBalance).to.eq(parseTestToken('1'));918 expect(nbWritten1).to.eq(parseTestToken('1'));919 expect(nbWritten2).to.eq(parseTestToken('2'));920 });921 it('should fail withdrawPreExpirationFrom if not approved', async () => {922 await optionTestUtil.addTestTokenAndWriteOptions(parseTestToken('2'));923 await optionTestUtil.transferOptionToUser1(writer1, parseTestToken('2'));924 await optionTestUtil.exerciseOption(true, parseTestToken('1'));925 await expect(926 premiaOption927 .connect(writer2)928 .withdrawPreExpirationFrom(writer1.address, 1, parseTestToken('1')),929 ).to.be.revertedWith('Not approved');930 });931 it('should successfully withdrawPreExpirationFrom', async () => {932 await optionTestUtil.addTestTokenAndWriteOptions(parseTestToken('2'));933 await optionTestUtil.transferOptionToUser1(writer1, parseTestToken('2'));934 await optionTestUtil.exerciseOption(true, parseTestToken('1'));935 await premiaOption936 .connect(writer1)937 .setApprovalForAll(writer2.address, true);938 await premiaOption939 .connect(writer2)940 .withdrawPreExpirationFrom(writer1.address, 1, parseTestToken('1'));941 const daiBalance = await dai.balanceOf(writer1.address);942 const testTokenBalance = await testToken.balanceOf(writer1.address);943 const nbWritten = await premiaOption.nbWritten(writer1.address, 1);944 expect(daiBalance).to.eq(parseEther('10'));945 expect(testTokenBalance).to.eq(0);946 expect(nbWritten).to.eq(parseTestToken('1'));947 });948 });949 describe('referral', () => {950 it('should register user1 as referrer', async () => {951 await optionTestUtil.addTestTokenAndWriteOptions(952 parseTestToken('2'),953 true,954 user1.address,955 );956 const referrer = await p.premiaReferral.referrals(writer1.address);957 expect(referrer).to.eq(user1.address);958 });959 it('should keep user1 as referrer, if try to set another referrer', async () => {960 await optionTestUtil.addTestTokenAndWriteOptions(961 parseTestToken('2'),962 true,963 user1.address,964 );965 await optionTestUtil.addTestTokenAndWriteOptions(966 parseTestToken('2'),967 true,968 writer2.address,969 );970 const referrer = await p.premiaReferral.referrals(writer1.address);971 expect(referrer).to.eq(user1.address);972 });973 it('should give user with referrer, 10% discount on write fee + give referrer 10% of fee', async () => {974 await optionTestUtil.addTestTokenAndWriteOptions(975 parseTestToken('2'),976 true,977 user1.address,978 );979 const writer1Options = await premiaOption.balanceOf(writer1.address, 1);980 const writer1TestToken = await testToken.balanceOf(writer1.address);981 const referrerTestToken = await testToken.balanceOf(user1.address);982 expect(writer1Options).to.eq(parseTestToken('2'));983 expect(writer1TestToken).to.eq(984 parseTestToken('0.02').div(10), // Expect 10% of tax of 2 options writing985 );986 expect(referrerTestToken).to.eq(987 parseTestToken('0.02').mul(9).div(10).div(10), // Expect 10% of 90% of tax for 2 options988 );989 });990 it('should give user with referrer, 10% discount on exercise fee + give referrer 10% of fee', async () => {991 await optionTestUtil.addTestTokenAndWriteOptionsAndExercise(992 true,993 parseTestToken('2'),994 parseTestToken('2'),995 writer2.address,996 );997 const user1Options = await premiaOption.balanceOf(writer1.address, 1);998 const user1Dai = await dai.balanceOf(user1.address);999 const referrerDai = await dai.balanceOf(writer2.address);1000 expect(user1Options).to.eq(0);1001 expect(user1Dai).to.eq(1002 BigNumber.from(parseEther('0.2')).div(10), // Expect 10% of the 1% tax of 2 options exercised at strike price of 10 DAI1003 );1004 expect(referrerDai).to.eq(1005 parseEther('0.2').mul(9).div(10).div(10), // Expect 10% of 90% of tax1006 );1007 });1008 });1009 describe('fees', () => {1010 it('should calculate total fee correctly without discount', async () => {1011 const fee = await p.feeCalculator.getFeeAmounts(1012 writer1.address,1013 false,1014 parseTestToken('2'),1015 0,1016 );1017 expect(fee[0].add(fee[1])).to.eq(parseTestToken('0.02'));1018 });1019 it('should calculate total fee correctly with a referral', async () => {1020 await optionTestUtil.addTestTokenAndWriteOptions(1021 parseTestToken('2'),1022 true,1023 user1.address,1024 );1025 const fee = await p.feeCalculator.getFeeAmounts(1026 writer1.address,1027 true,1028 parseTestToken('2'),1029 0,1030 );1031 expect(fee[0].add(fee[1])).to.eq(parseTestToken('0.018'));1032 });1033 it('should correctly calculate total fee with a referral + staking discount', async () => {1034 await premiaFeeDiscount.setDiscount(2000);1035 const fee = await p.feeCalculator.getFeeAmounts(1036 writer1.address,1037 true,1038 parseTestToken('2'),1039 0,1040 );1041 expect(fee[0].add(fee[1])).to.eq(parseTestToken('0.0144'));1042 });1043 it('should correctly give a 30% discount from premia staking', async () => {1044 await premiaFeeDiscount.setDiscount(3000);1045 await optionTestUtil.addTestTokenAndWriteOptionsAndExercise(1046 true,1047 parseTestToken('2'),1048 parseTestToken('2'),1049 );1050 const user1Options = await premiaOption.balanceOf(writer1.address, 1);1051 const user1Dai = await dai.balanceOf(user1.address);1052 expect(user1Options).to.eq(0);1053 expect(user1Dai).to.eq(1054 BigNumber.from(parseEther('0.06')), // Expect 30% of the 1% tax of 2 options exercised at strike price of 10 DAI1055 );1056 });1057 it('should correctly give a 30% discount from premia staking + 10% discount from referral', async () => {1058 await premiaFeeDiscount.setDiscount(3000);1059 await optionTestUtil.addTestTokenAndWriteOptionsAndExercise(1060 true,1061 parseTestToken('2'),1062 parseTestToken('2'),1063 writer2.address,1064 );1065 const user1Options = await premiaOption.balanceOf(writer1.address, 1);1066 const user1Dai = await dai.balanceOf(user1.address);1067 const referrerDai = await dai.balanceOf(writer2.address);1068 expect(user1Options).to.eq(0);1069 expect(user1Dai).to.eq(1070 BigNumber.from(parseEther('0.074')), // Expect 30% of the 1% tax of 2 options exercised at strike price of 10 DAI + 10% discount from referral1071 );1072 expect(referrerDai).to.eq(1073 parseEther('0.0126'), // Expect 10% of 90% of tax (After premia staking discount)1074 );1075 });1076 });1077 describe('flashLoan', () => {1078 it('should revert if loan not paid back', async () => {1079 const flashLoanFactory = new TestFlashLoan__factory(writer1);1080 const flashLoan = await flashLoanFactory.deploy();1081 await flashLoan.setMode(2);1082 await optionTestUtil.addTestTokenAndWriteOptions(1083 parseTestToken('2'),1084 true,1085 user1.address,1086 );1087 let testTokenBalance = await testToken.balanceOf(premiaOption.address);1088 expect(testTokenBalance).to.eq(parseTestToken('2'));1089 await expect(1090 premiaOption.flashLoan(1091 testToken.address,1092 parseTestToken('2'),1093 flashLoan.address,1094 ),1095 ).to.be.revertedWith('Failed to pay back');1096 });1097 it('should revert if loan paid back without fee', async () => {1098 const flashLoanFactory = new TestFlashLoan__factory(writer1);1099 const flashLoan = await flashLoanFactory.deploy();1100 await flashLoan.setMode(1);1101 await optionTestUtil.addTestTokenAndWriteOptions(1102 parseTestToken('2'),1103 true,1104 user1.address,1105 );1106 let testTokenBalance = await testToken.balanceOf(premiaOption.address);1107 expect(testTokenBalance).to.eq(parseTestToken('2'));1108 await expect(1109 premiaOption.flashLoan(1110 testToken.address,1111 parseTestToken('2'),1112 flashLoan.address,1113 ),1114 ).to.be.revertedWith('Failed to pay back');1115 });1116 it('should successfully complete flashLoan if paid back with fee', async () => {1117 await p.feeCalculator.setWriteFee(0);1118 const flashLoanFactory = new TestFlashLoan__factory(writer1);1119 const flashLoan = await flashLoanFactory.deploy();1120 await flashLoan.setMode(0);1121 await optionTestUtil.addTestTokenAndWriteOptions(1122 parseTestToken('2'),1123 true,1124 user1.address,1125 );1126 await mintTestToken(admin, testToken, parseTestToken('0.004'));1127 await testToken.transfer(flashLoan.address, parseTestToken('0.004'));1128 let testTokenBalance = await testToken.balanceOf(premiaOption.address);1129 expect(testTokenBalance).to.eq(parseTestToken('2'));1130 await premiaOption.flashLoan(1131 testToken.address,1132 parseTestToken('2'),1133 flashLoan.address,1134 );1135 testTokenBalance = await testToken.balanceOf(premiaOption.address);1136 expect(testTokenBalance).to.eq(parseTestToken('2'));1137 const testTokenBalanceFeeRecipient = await testToken.balanceOf(1138 feeRecipient.address,1139 );1140 expect(testTokenBalanceFeeRecipient).to.eq(parseTestToken('0.004'));1141 });1142 it('should successfully complete flashLoan if paid back without fee and user on fee whitelist', async () => {1143 await p.feeCalculator.setWriteFee(0);1144 const flashLoanFactory = new TestFlashLoan__factory(writer1);1145 const flashLoan = await flashLoanFactory.deploy();1146 await flashLoan.setMode(1);1147 await p.feeCalculator.addWhitelisted([writer1.address]);1148 await optionTestUtil.addTestTokenAndWriteOptions(1149 parseTestToken('2'),1150 true,1151 user1.address,1152 );1153 let testTokenBalance = await testToken.balanceOf(premiaOption.address);1154 expect(testTokenBalance).to.eq(parseTestToken('2'));1155 await premiaOption1156 .connect(writer1)1157 .flashLoan(testToken.address, parseTestToken('2'), flashLoan.address);1158 testTokenBalance = await testToken.balanceOf(premiaOption.address);1159 expect(testTokenBalance).to.eq(parseTestToken('2'));1160 const testTokenBalanceFeeRecipient = await testToken.balanceOf(1161 feeRecipient.address,1162 );1163 expect(testTokenBalanceFeeRecipient).to.eq(0);1164 });1165 });1166 describe('premiaUncut', () => {1167 it('should not reward any uPremia if price not set for token in priceProvider', async () => {1168 await optionTestUtil.addTestTokenAndWriteOptions(parseTestToken('2'));1169 expect(await p.uPremia.balanceOf(writer1.address)).to.eq(0);1170 });1171 it('should reward uPremia on writeOption', async () => {1172 await p.priceProvider.setTokenPrices(1173 [dai.address, testToken.address],1174 [parseEther('1'), parseEther('10')],1175 );1176 await optionTestUtil.addTestTokenAndWriteOptions(parseTestToken('2'));1177 expect(await p.uPremia.balanceOf(writer1.address)).to.eq(1178 parseEther('0.2'),1179 );1180 });1181 it('should reward uPremia on exerciseOption', async () => {1182 await p.priceProvider.setTokenPrices(1183 [dai.address, testToken.address],1184 [parseEther('1'), parseEther('10')],1185 );1186 await optionTestUtil.addTestTokenAndWriteOptionsAndExercise(1187 true,1188 parseTestToken('2'),1189 parseTestToken('1'),1190 );1191 expect(await p.uPremia.balanceOf(writer1.address)).to.eq(1192 parseEther('0.2'),1193 );1194 expect(await p.uPremia.balanceOf(user1.address)).to.eq(parseEther('0.1'));1195 });1196 });1197 describe('flashExercise', () => {1198 beforeEach(async () => {1199 // This test only works when we use WETH (Has been tested directly on testnet with wbtc)1200 if (!TEST_USE_WETH) return;1201 uniswap = await createUniswap(admin, dai, weth);1202 await premiaOption.setWhitelistedUniswapRouters([uniswap.router.address]);1203 });1204 it('should successfully flash exercise if option in the money', async () => {1205 // This test only works when we use WETH (Has been tested directly on testnet with wbtc)1206 if (!TEST_USE_WETH) return;1207 // 1 ETH = 12 DAI1208 await uniswap.dai.mint(uniswap.daiWeth.address, parseEther('1200'));1209 await uniswap.weth.deposit({ value: parseEther('100') });1210 await uniswap.weth.transfer(uniswap.daiWeth.address, parseEther('100'));1211 await uniswap.daiWeth.mint(admin.address);1212 await optionTestUtil.addTestTokenAndWriteOptions(parseEther('2'), true);1213 await optionTestUtil.transferOptionToUser1(writer1, parseEther('2'));1214 await premiaOption1215 .connect(user1)1216 .flashExerciseOption(1217 1,1218 parseEther('1'),1219 ZERO_ADDRESS,1220 uniswap.router.address,1221 parseEther('100000'),1222 testToken.address === weth.address1223 ? [weth.address, dai.address]1224 : [testToken.address, weth.address, dai.address],1225 );1226 const user1Weth = await uniswap.weth.balanceOf(user1.address);1227 expect(1228 user1Weth.gt(parseEther('0.148')) && user1Weth.lt(parseEther('0.149')),1229 ).to.be.true;1230 expect(await uniswap.dai.balanceOf(premiaOption.address)).to.eq(1231 parseEther('10'),1232 );1233 expect(await premiaOption.balanceOf(user1.address, 1)).to.eq(1234 parseEther('1'),1235 );1236 });1237 it('should fail flash exercise if option not in the money', async () => {1238 // This test only works when we use WETH (Has been tested directly on testnet with wbtc)1239 if (!TEST_USE_WETH) return;1240 // 1 ETH = 8 DAI1241 await uniswap.dai.mint(uniswap.daiWeth.address, parseEther('800'));1242 await uniswap.weth.deposit({ value: parseEther('100') });1243 await uniswap.weth.transfer(uniswap.daiWeth.address, parseEther('100'));1244 await uniswap.daiWeth.mint(admin.address);1245 await optionTestUtil.addTestTokenAndWriteOptions(parseEther('2'), true);1246 await optionTestUtil.transferOptionToUser1(writer1, parseEther('2'));1247 await expect(1248 premiaOption1249 .connect(user1)1250 .flashExerciseOption(1251 1,1252 parseEther('1'),1253 ZERO_ADDRESS,1254 uniswap.router.address,1255 parseEther('100000'),1256 testToken.address === weth.address1257 ? [weth.address, dai.address]1258 : [testToken.address, weth.address, dai.address],1259 ),1260 ).to.be.revertedWith('UniswapV2Router: EXCESSIVE_INPUT_AMOUNT');1261 });1262 it('should fail flashExerciseFrom if not approved', async () => {1263 // This test only works when we use WETH (Has been tested directly on testnet with wbtc)1264 if (!TEST_USE_WETH) return;1265 // 1 ETH = 12 DAI1266 await uniswap.dai.mint(uniswap.daiWeth.address, parseEther('1200'));1267 await uniswap.weth.deposit({ value: parseEther('100') });1268 await uniswap.weth.transfer(uniswap.daiWeth.address, parseEther('100'));1269 await uniswap.daiWeth.mint(admin.address);1270 await optionTestUtil.addTestTokenAndWriteOptions(parseEther('2'), true);1271 await optionTestUtil.transferOptionToUser1(writer1, parseEther('2'));1272 await expect(1273 premiaOption1274 .connect(writer2)1275 .flashExerciseOptionFrom(1276 user1.address,1277 1,1278 parseEther('1'),1279 ZERO_ADDRESS,1280 uniswap.router.address,1281 parseEther('100000'),1282 testToken.address === weth.address1283 ? [weth.address, dai.address]1284 : [testToken.address, weth.address, dai.address],1285 ),1286 ).to.be.revertedWith('Not approved');1287 });1288 it('should successfully flashExerciseFrom', async () => {1289 // This test only works when we use WETH (Has been tested directly on testnet with wbtc)1290 if (!TEST_USE_WETH) return;1291 // 1 ETH = 12 DAI1292 await uniswap.dai.mint(uniswap.daiWeth.address, parseEther('1200'));1293 await uniswap.weth.deposit({ value: parseEther('100') });1294 await uniswap.weth.transfer(uniswap.daiWeth.address, parseEther('100'));1295 await uniswap.daiWeth.mint(admin.address);1296 await optionTestUtil.addTestTokenAndWriteOptions(parseEther('2'), true);1297 await optionTestUtil.transferOptionToUser1(writer1, parseEther('2'));1298 await premiaOption1299 .connect(user1)1300 .setApprovalForAll(writer2.address, true);1301 await premiaOption1302 .connect(writer2)1303 .flashExerciseOptionFrom(1304 user1.address,1305 1,1306 parseEther('1'),1307 ZERO_ADDRESS,1308 uniswap.router.address,1309 parseEther('100000'),1310 testToken.address === weth.address1311 ? [weth.address, dai.address]1312 : [testToken.address, weth.address, dai.address],1313 );1314 const user1Weth = await uniswap.weth.balanceOf(user1.address);1315 expect(1316 user1Weth.gt(parseEther('0.148')) && user1Weth.lt(parseEther('0.149')),1317 ).to.be.true;1318 expect(await uniswap.dai.balanceOf(premiaOption.address)).to.eq(1319 parseEther('10'),1320 );1321 expect(await premiaOption.balanceOf(user1.address, 1)).to.eq(1322 parseTestToken('1'),1323 );1324 });1325 });...
textWriter.test.ts
Source:textWriter.test.ts
1import * as assert from "assert"2import * as sourceMap from "../../src/utils/sourceMap"3import * as textWriter from "../../src/utils/textWriter"4export namespace textWriterTest {5 export function writeTest() {6 const writer = new textWriter.TextWriter()7 writer.write("A")8 assert.strictEqual(writer.toString(), "A")9 writer.write("_B_", 1, 2)10 assert.strictEqual(writer.toString(), "AB")11 writer.write("")12 assert.strictEqual(writer.toString(), "AB")13 }14 export function writeSourceMapTest() {15 const writer = new textWriter.SourceMapTextWriter()16 writer.write("A")17 assert.strictEqual(writer.toString(), "A")18 writer.write("_B_", 1, 2)19 assert.strictEqual(writer.toString(), "AB")20 writer.write("C", undefined, undefined, "goo.js", 0, 0)21 assert.strictEqual(writer.toString(), "ABC")22 writer.write("_D_", 1, 2, "hoo.js", 2, 0)23 assert.strictEqual(writer.toString(), "ABCD")24 writer.write("", 0, 0, "empty.js", 0, 0)25 assert.strictEqual(writer.toString(), "ABCD")26 assert.strictEqual(writer.sourceMapBuilder.getSource(0, 0, true, true), null)27 assert.strictEqual(writer.sourceMapBuilder.getSource(0, 1, true, true), null)28 assert.strictEqual(writer.sourceMapBuilder.getSource(0, 2, true, true)!.sourcePath, "goo.js")29 assert.strictEqual(writer.sourceMapBuilder.getSource(0, 2, true, true)!.line, 0)30 assert.strictEqual(writer.sourceMapBuilder.getSource(0, 2, true, true)!.column, 0)31 assert.strictEqual(writer.sourceMapBuilder.getSource(0, 3, true, true)!.sourcePath, "hoo.js")32 assert.strictEqual(writer.sourceMapBuilder.getSource(0, 3, true, true)!.line, 2)33 assert.strictEqual(writer.sourceMapBuilder.getSource(0, 3, true, true)!.column, 0)34 assert.strictEqual(writer.sourceMapBuilder.getSource(0, 4, true, true)!.sourcePath, "hoo.js")35 }36 export function indentTest() {37 const writer = new textWriter.TextWriter()38 writer.indent()39 writer.write("A")40 writer.unindent()41 assert.strictEqual(writer.toString(), "\tA")42 writer.indent()43 writer.write("\nB")44 writer.unindent()45 assert.strictEqual(writer.toString(), "\tA\n\tB")46 writer.indent()47 writer.write("\r\nR")48 writer.unindent()49 assert.strictEqual(writer.toString(), "\tA\n\tB\r\n\tR")50 }51 export function indentSourceMapTest() {52 const writer = new textWriter.SourceMapTextWriter()53 writer.indent()54 writer.write("A")55 writer.unindent()56 assert.strictEqual(writer.toString(), "\tA")57 writer.indent()58 writer.write("\nB")59 writer.unindent()60 assert.strictEqual(writer.toString(), "\tA\n\tB")61 writer.indent()62 writer.write("\r\nR")63 writer.unindent()64 assert.strictEqual(writer.toString(), "\tA\n\tB\r\n\tR")65 }66 export function mergeSourceMapTest1() {67 const map = new sourceMap.SourceMapBuilder()68 map.file = "goo.js"69 map.addMapping(1, 1, "hoo.js", 100, 101, "B")70 map.addMapping(1, 2, "hoo2.js", 200, 201, "C")71 const writer = new textWriter.SourceMapTextWriter()72 writer.write("\r\nABC", undefined, undefined, "goo.js", 0, 0, undefined, map)73 assert.strictEqual(writer.toString(), "\r\nABC")74 assert.strictEqual(writer.sourceMapBuilder.getSource(1, 0, true, true)!.sourcePath, undefined)75 assert.strictEqual(writer.sourceMapBuilder.getSource(1, 1, true, true)!.sourcePath, "hoo.js")76 assert.strictEqual(writer.sourceMapBuilder.getSource(1, 1, true, true)!.line, 100)77 assert.strictEqual(writer.sourceMapBuilder.getSource(1, 1, true, true)!.column, 101)78 assert.strictEqual(writer.sourceMapBuilder.getSource(1, 1, true, true)!.name, "B")79 assert.strictEqual(writer.sourceMapBuilder.getSource(1, 2, true, true)!.sourcePath, "hoo2.js")80 assert.strictEqual(writer.sourceMapBuilder.getSource(1, 2, true, true)!.line, 200)81 assert.strictEqual(writer.sourceMapBuilder.getSource(1, 2, true, true)!.column, 201)82 assert.strictEqual(writer.sourceMapBuilder.getSource(1, 2, true, true)!.name, "C")83 }84 export function mergeSourceMapTest2() {85 const map = new sourceMap.SourceMapBuilder()86 map.file = "goo.js"87 map.addMapping(0, 0, "hoo1.js", 11, 1, "A")88 map.addMapping(0, 1, "hoo2.js", 12, 2, "B")89 map.addMapping(0, 2, "hoo3.js", 13, 3, "C")90 map.addMapping(0, 3, "hoo4.js", 14, 4, "D")91 const writer = new textWriter.SourceMapTextWriter()92 writer.write("ABC", 1, undefined, "goo.js", 0, 1, undefined, map)93 assert.strictEqual(writer.toString(), "BC")94 assert.strictEqual(writer.sourceMapBuilder.getSource(0, 0, true, true)!.sourcePath, "hoo2.js")95 assert.strictEqual(writer.sourceMapBuilder.getSource(0, 0, true, true)!.line, 12)96 assert.strictEqual(writer.sourceMapBuilder.getSource(0, 0, true, true)!.column, 2)97 assert.strictEqual(writer.sourceMapBuilder.getSource(0, 0, true, true)!.name, "B")98 assert.strictEqual(writer.sourceMapBuilder.getSource(0, 1, true, true)!.sourcePath, "hoo3.js")99 assert.strictEqual(writer.sourceMapBuilder.getSource(0, 1, true, true)!.line, 13)100 assert.strictEqual(writer.sourceMapBuilder.getSource(0, 1, true, true)!.column, 3)101 assert.strictEqual(writer.sourceMapBuilder.getSource(0, 1, true, true)!.name, "C")102 writer.write("ABC", 1, undefined, "goo.js", 100, 0, undefined, map)103 assert.strictEqual(writer.toString(), "BCBC")104 }105 export function mergeSourceMapTest3() {106 const map = new sourceMap.SourceMapBuilder()107 map.file = "goo.js"108 map.addMapping(0, 0, "hoo1.js", 11, 1, "A")109 map.addMapping(0, 1, "hoo2.js", 12, 2, "B")110 map.addMapping(0, 2, "hoo3.js", 13, 3, "C")111 map.addMapping(1, 3, "hoo4.js", 14, 4, "D")112 const writer = new textWriter.SourceMapTextWriter()113 writer.write("AB\rC", 1, undefined, "goo.js", 0, 1, undefined, map)114 assert.strictEqual(writer.toString(), "B\rC")115 assert.strictEqual(writer.sourceMapBuilder.getSource(0, 0, true, true)!.sourcePath, "hoo2.js")116 assert.strictEqual(writer.sourceMapBuilder.getSource(0, 0, true, true)!.line, 12)117 assert.strictEqual(writer.sourceMapBuilder.getSource(0, 0, true, true)!.column, 2)118 assert.strictEqual(writer.sourceMapBuilder.getSource(0, 0, true, true)!.name, "B")119 assert.strictEqual(writer.sourceMap.version, 3)120 }121 export function mergeSourceMapTest4() {122 const source = [123 "*/ let variable = 1 + 2\n",124 "function fn() {\r",125 "\t// comment\r\n",126 " return 2\r",127 "}/*\n"128 ].join("")129 const map = new sourceMap.SourceMapBuilder()130 map.addMapping(0, 1)131 map.addMapping(0, 3, "source1", 100, 10)132 map.addMapping(0, 7, "source2", 200, 20, "variable")133 map.addMapping(0, 18, "source3", 300, 30)134 map.addMapping(1, 0, "source1", 400, 40)135 map.addMapping(1, 9, "source4", 500, 50, "fn")136 map.addMapping(2, 1)137 map.addMapping(3, 5, "source1", 200, 20)138 const writer1 = new textWriter.SourceMapTextWriter()139 writer1.write(source, 2, source.length - 2, undefined, 0, 2, undefined, map)140 assert.strictEqual(writer1.toString(), source.slice(2, -2))141 assert.strictEqual(writer1.sourceMapBuilder.getSource(0, 0, true, true)!.sourcePath, undefined)142 assert.strictEqual(writer1.sourceMapBuilder.getSource(0, 0, true, true)!.line, undefined)143 assert.strictEqual(writer1.sourceMapBuilder.getSource(0, 0, true, true)!.column, undefined)144 assert.strictEqual(writer1.sourceMapBuilder.getSource(0, 0, true, true)!.name, undefined)145 assert.strictEqual(writer1.sourceMapBuilder.getSource(0, 1, true, true)!.sourcePath, "source1")146 assert.strictEqual(writer1.sourceMapBuilder.getSource(0, 1, true, true)!.line, 100)147 assert.strictEqual(writer1.sourceMapBuilder.getSource(0, 1, true, true)!.column, 10)148 assert.strictEqual(writer1.sourceMapBuilder.getSource(0, 1, true, true)!.name, undefined)149 assert.strictEqual(writer1.sourceMapBuilder.getSource(0, 2, true, true)!.sourcePath, "source1")150 assert.strictEqual(writer1.sourceMapBuilder.getSource(0, 2, true, true)!.line, 100)151 assert.strictEqual(writer1.sourceMapBuilder.getSource(0, 2, true, true)!.column, 11)152 assert.strictEqual(writer1.sourceMapBuilder.getSource(0, 2, true, true)!.name, undefined)153 assert.strictEqual(writer1.sourceMapBuilder.getSource(0, 3, true, true)!.sourcePath, "source1")154 assert.strictEqual(writer1.sourceMapBuilder.getSource(0, 3, true, true)!.line, 100)155 assert.strictEqual(writer1.sourceMapBuilder.getSource(0, 3, true, true)!.column, 12)156 assert.strictEqual(writer1.sourceMapBuilder.getSource(0, 3, true, true)!.name, undefined)157 assert.strictEqual(writer1.sourceMapBuilder.getSource(0, 4, true, true)!.sourcePath, "source1")158 assert.strictEqual(writer1.sourceMapBuilder.getSource(0, 4, true, true)!.line, 100)159 assert.strictEqual(writer1.sourceMapBuilder.getSource(0, 4, true, true)!.column, 13)160 assert.strictEqual(writer1.sourceMapBuilder.getSource(0, 4, true, true)!.name, undefined)161 assert.strictEqual(writer1.sourceMapBuilder.getSource(0, 5, true, true)!.sourcePath, "source2")162 assert.strictEqual(writer1.sourceMapBuilder.getSource(0, 5, true, true)!.line, 200)163 assert.strictEqual(writer1.sourceMapBuilder.getSource(0, 5, true, true)!.column, 20)164 assert.strictEqual(writer1.sourceMapBuilder.getSource(0, 5, true, true)!.name, "variable")165 assert.strictEqual(writer1.sourceMapBuilder.getSource(0, 6, true, true)!.sourcePath, "source2")166 assert.strictEqual(writer1.sourceMapBuilder.getSource(0, 6, true, true)!.line, 200)167 assert.strictEqual(writer1.sourceMapBuilder.getSource(0, 6, true, true)!.column, 21)168 assert.strictEqual(writer1.sourceMapBuilder.getSource(0, 6, true, true)!.name, "variable")169 assert.strictEqual(writer1.sourceMapBuilder.getSource(0, 7, true, true)!.sourcePath, "source2")170 assert.strictEqual(writer1.sourceMapBuilder.getSource(0, 7, true, true)!.line, 200)171 assert.strictEqual(writer1.sourceMapBuilder.getSource(0, 7, true, true)!.column, 22)172 assert.strictEqual(writer1.sourceMapBuilder.getSource(0, 7, true, true)!.name, "variable")173 assert.strictEqual(writer1.sourceMapBuilder.getSource(1, 9, true, true)!.sourcePath, "source4")174 assert.strictEqual(writer1.sourceMapBuilder.getSource(1, 9, true, true)!.line, 500)175 assert.strictEqual(writer1.sourceMapBuilder.getSource(1, 9, true, true)!.column, 50)176 assert.strictEqual(writer1.sourceMapBuilder.getSource(1, 9, true, true)!.name, "fn")177 assert.strictEqual(writer1.sourceMap.version, 3)178 const writer2 = new textWriter.SourceMapTextWriter()179 writer2.write(source, 6, source.length - 2, undefined, 0, 6, undefined, map)180 assert.strictEqual(writer2.toString(), source.slice(6, -2))181 assert.strictEqual(writer2.sourceMapBuilder.getSource(0, 0, true, true)!.sourcePath, "source1")182 assert.strictEqual(writer2.sourceMapBuilder.getSource(0, 0, true, true)!.line, 100)183 assert.strictEqual(writer2.sourceMapBuilder.getSource(0, 0, true, true)!.column, 13)184 assert.strictEqual(writer2.sourceMapBuilder.getSource(0, 0, true, true)!.name, undefined)185 assert.strictEqual(writer2.sourceMapBuilder.getSource(0, 1, true, true)!.sourcePath, "source2")186 assert.strictEqual(writer2.sourceMapBuilder.getSource(0, 1, true, true)!.line, 200)187 assert.strictEqual(writer2.sourceMapBuilder.getSource(0, 1, true, true)!.column, 20)188 assert.strictEqual(writer2.sourceMapBuilder.getSource(0, 1, true, true)!.name, "variable")189 const writer3 = new textWriter.SourceMapTextWriter()190 writer3.write(source, 17, source.length - 2, undefined, 0, 17, undefined, map)191 assert.strictEqual(writer3.toString(), source.slice(17, -2))192 assert.strictEqual(writer3.sourceMapBuilder.getSource(0, 0, true, true)!.sourcePath, "source2")193 assert.strictEqual(writer3.sourceMapBuilder.getSource(0, 0, true, true)!.line, 200)194 assert.strictEqual(writer3.sourceMapBuilder.getSource(0, 0, true, true)!.column, 30)195 assert.strictEqual(writer3.sourceMapBuilder.getSource(0, 0, true, true)!.name, "variable")196 assert.strictEqual(writer3.sourceMapBuilder.getSource(0, 1, true, true)!.sourcePath, "source3")197 assert.strictEqual(writer3.sourceMapBuilder.getSource(0, 1, true, true)!.line, 300)198 assert.strictEqual(writer3.sourceMapBuilder.getSource(0, 1, true, true)!.column, 30)199 assert.strictEqual(writer3.sourceMapBuilder.getSource(0, 1, true, true)!.name, undefined)200 }201 export function generateEmptySourceMapTest() {202 const lines = [203 ` \taA0_$ä½ å¥½-,;()[]{}+\n`,204 "function fn() {\r",205 "\t// comment\r\n",206 " return 2\r",207 "}/*\n"208 ]209 const writer = new textWriter.SourceMapTextWriter()210 writer.write(lines.join(""), undefined, undefined, "source", 0, 0)211 assert.strictEqual(writer.toString(), lines.join(""))212 for (let i = 0; i < lines[0].length; i++) {213 assert.strictEqual(writer.sourceMapBuilder.getSource(0, i, true, true)!.sourcePath, "source")214 assert.strictEqual(writer.sourceMapBuilder.getSource(0, i, true, true)!.line, 0)215 assert.strictEqual(writer.sourceMapBuilder.getSource(0, i, true, true)!.column, i)216 assert.strictEqual(writer.sourceMapBuilder.getSource(0, i, true, true)!.name, undefined)217 }218 }219 export function noSourceMapTest() {220 const lines = [221 ` \taA0_$ä½ å¥½-,;()[]{}+\n`,222 "function fn() {\r",223 "\t// comment\r\n",224 " return 2\r",225 "}/*\n"226 ]227 const writer1 = new textWriter.TextWriter()228 writer1.indent()229 writer1.write(lines.join(""))230 writer1.unindent()231 assert.strictEqual(writer1.toString(), lines.map(source => `\t${source}`).join(""))232 const writer2 = new textWriter.SourceMapTextWriter()233 writer2.indent()234 writer2.write(lines.join(""))235 writer2.unindent()236 assert.strictEqual(writer2.toString(), lines.map(source => `\t${source}`).join(""))237 }238 export function noColumnsTest() {239 const source = [240 ` \taA0_$ä½ å¥½-,;()[]{}+\n`,241 "function fn() {\r",242 "\t// comment\r\n",243 " return 2\r",244 "}/*\n"245 ].join("")246 const writer1 = new textWriter.TextWriter()247 writer1.write(source)248 assert.strictEqual(writer1.toString(), source)249 const writer2 = new textWriter.SourceMapTextWriter()250 writer2.noColumnMappings = true251 writer2.write(source, undefined, undefined, writer2.sourceMapBuilder.addSource("source"), 0, 0, "foo")252 assert.strictEqual(writer2.toString(), source)253 }...
ydocs.ts
Source:ydocs.ts
1import ava from 'ava'2import { setupOne, setupTwo } from './util/util.js'3import * as Y from 'yjs'4ava('ydoc read/write', async t => {5 const {ws} = await setupOne(t)6 const ydoc1 = new Y.Doc()7 const readFile = async (path: string) => {8 const ydoc2 = new Y.Doc()9 const state = await ws.readAllFileStates(path)10 for (const item of state) {11 Y.applyUpdate(ydoc2, item.data)12 }13 return String(ydoc2.getText())14 }15 // write 116 ydoc1.getText().insert(0, 'Hello, world!')17 await ws.writeFile('/test.txt', Buffer.from(Y.encodeStateAsUpdate(ydoc1)), {noMerge: true})18 t.deepEqual(await readFile('/test.txt'), 'Hello, world!')19 // write 220 ydoc1.getText().delete(7, 13)21 ydoc1.getText().insert(7, 'universe!')22 await ws.writeFile('/test.txt', Buffer.from(Y.encodeStateAsUpdate(ydoc1)), {noMerge: true})23 t.deepEqual(await readFile('/test.txt'), 'Hello, universe!')24})25ava('ydoc read/write two writers', async t => {26 const {ws1, ws2} = await setupTwo(t)27 const writer1 = {ws: ws1, ydoc: new Y.Doc()}28 const writer2 = {ws: ws2, ydoc: new Y.Doc()}29 // write 130 writer1.ydoc.getText().insert(0, 'Hello, world!')31 await writer1.ws.writeFile('/test.txt', Buffer.from(Y.encodeStateAsUpdate(writer1.ydoc)), {noMerge: true})32 for (const writer of [writer1, writer2]) {33 const state = await writer.ws.readAllFileStates('/test.txt')34 for (const item of state) {35 Y.applyUpdate(writer.ydoc, item.data)36 }37 t.deepEqual(String(writer.ydoc.getText()), 'Hello, world!')38 }39 // write 240 writer2.ydoc.getText().delete(7, 13)41 writer2.ydoc.getText().insert(7, 'universe!')42 await writer2.ws.writeFile('/test.txt', Buffer.from(Y.encodeStateAsUpdate(writer2.ydoc)), {noMerge: true})43 for (const writer of [writer1, writer2]) {44 const state = await writer.ws.readAllFileStates('/test.txt')45 for (const item of state) {46 Y.applyUpdate(writer.ydoc, item.data)47 }48 t.deepEqual(String(writer.ydoc.getText()), 'Hello, universe!')49 }50 // write 351 writer2.ydoc.getText().delete(7, 13)52 writer2.ydoc.getText().insert(7, 'UNIVERSE!')53 await writer2.ws.writeFile('/test.txt', Buffer.from(Y.encodeStateAsUpdate(writer2.ydoc)), {noMerge: true})54 for (const writer of [writer1, writer2]) {55 const state = await writer.ws.readAllFileStates('/test.txt')56 for (const item of state) {57 Y.applyUpdate(writer.ydoc, item.data)58 }59 t.deepEqual(String(writer.ydoc.getText()), 'Hello, UNIVERSE!')60 }61 // file noted as "noMerge" rather than "in conflict"62 for (const writer of [writer1, writer2]) {63 const info = await writer.ws.statFile('/test.txt')64 t.is(info?.conflict, false)65 t.is(info?.noMerge, true)66 t.is(info?.otherChanges?.length, 1)67 }68})69ava('conflicted copies and moves not allowed', async t => {70 const {ws1, ws2} = await setupTwo(t)71 const writer1 = {ws: ws1, ydoc: new Y.Doc()}72 const writer2 = {ws: ws2, ydoc: new Y.Doc()}73 // write74 writer1.ydoc.getText().insert(0, 'Hello, world!')75 await writer1.ws.writeFile('/test.txt', Buffer.from(Y.encodeStateAsUpdate(writer1.ydoc)), {noMerge: true})76 writer2.ydoc.getText().insert(0, 'Hello, world!')77 await writer2.ws.writeFile('/test.txt', Buffer.from(Y.encodeStateAsUpdate(writer2.ydoc)), {noMerge: true})78 // copy & write fail79 await t.throwsAsync(() => writer1.ws.moveFile('/test.txt', '/test2.txt'))80 await t.throwsAsync(() => writer1.ws.copyFile('/test.txt', '/test2.txt'))81 await t.throwsAsync(() => writer2.ws.moveFile('/test.txt', '/test2.txt'))82 await t.throwsAsync(() => writer2.ws.copyFile('/test.txt', '/test2.txt'))83})84ava('ydoc read/write during a fork', async t => {85 const {sim, ws1, ws2} = await setupTwo(t)86 const writer1 = {ws: ws1, ydoc: new Y.Doc()}87 const writer2 = {ws: ws2, ydoc: new Y.Doc()}88 const readFile = async (writer: any, path: string) => {89 const state = await writer.ws.readAllFileStates(path)90 for (const item of state) {91 Y.applyUpdate(writer.ydoc, item.data)92 }93 return String(writer.ydoc.getText())94 }95 // forked writes96 // HACK sync state prior to disconnect, works around https://github.com/hypercore-protocol/autobase/issues/797 await ws1.listFiles()98 await ws2.listFiles()99 sim.disconnect(sim.stores[0], sim.stores[1])100 writer1.ydoc.getText().insert(0, 'writer1')101 await writer1.ws.writeFile('/test.txt', Buffer.from(Y.encodeStateAsUpdate(writer1.ydoc)), {noMerge: true})102 writer2.ydoc.getText().insert(0, 'writer2')103 await writer2.ws.writeFile('/test.txt', Buffer.from(Y.encodeStateAsUpdate(writer2.ydoc)), {noMerge: true})104 t.deepEqual(await readFile(writer1, 'test.txt'), 'writer1')105 t.deepEqual(await readFile(writer2, 'test.txt'), 'writer2')106 // merge107 sim.connect(sim.stores[0], sim.stores[1])108 t.deepEqual(await readFile(writer1, 'test.txt'), await readFile(writer2, 'test.txt'))109 // forked writes 2110 // HACK sync state prior to disconnect, works around https://github.com/hypercore-protocol/autobase/issues/7111 await ws1.listFiles()112 await ws2.listFiles()113 sim.disconnect(sim.stores[0], sim.stores[1])114 const orgValue = (await readFile(writer1, 'test.txt'))115 writer1.ydoc.getText().delete(0, orgValue.length)116 await writer1.ws.writeFile('/test.txt', Buffer.from(Y.encodeStateAsUpdate(writer1.ydoc)), {noMerge: true})117 writer2.ydoc.getText().insert(orgValue.length, ' and more text')118 await writer2.ws.writeFile('/test.txt', Buffer.from(Y.encodeStateAsUpdate(writer2.ydoc)), {noMerge: true})119 t.deepEqual(await readFile(writer1, 'test.txt'), '')120 t.deepEqual(await readFile(writer2, 'test.txt'), `${orgValue} and more text`)121 // merge122 sim.connect(sim.stores[0], sim.stores[1])123 t.deepEqual(await readFile(writer1, 'test.txt'), ' and more text')124 t.deepEqual(await readFile(writer2, 'test.txt'), ' and more text')...
Using AI Code Generation
1var writer1 = require('./wpt').writer1;2writer1('hello world');3var writer2 = require('./wpt').writer2;4writer2('hello world');5var writer3 = require('./wpt').writer3;6writer3('hello world');7var writer4 = require('./wpt').writer4;8writer4('hello world');9var writer5 = require('./wpt').writer5;10writer5('hello world');11var writer6 = require('./wpt').writer6;12writer6('hello world');13var writer7 = require('./wpt').writer7;14writer7('hello world');15var writer8 = require('./wpt').writer8;16writer8('hello world');17var writer9 = require('./wpt').writer9;18writer9('hello world');19var writer10 = require('./wpt').writer10;20writer10('hello world');21var writer11 = require('./wpt').writer11;22writer11('hello world');23var writer12 = require('./wpt').writer12;24writer12('hello world');25var writer13 = require('./wpt').writer13;26writer13('hello world');27var writer14 = require('./wpt').writer14;28writer14('hello world');29var writer15 = require('./wpt').writer15;30writer15('hello world');31var writer16 = require('./wpt').writer16;32writer16('hello world');33var writer17 = require('./wpt').writer17;34writer17('hello world
Using AI Code Generation
1var wpt = require('wpt');2wpt.writer1('Hello World, this is a test file', 'test.js');3wpt.writer2('Hello World, this is a test file', 'test2.js');4wpt.writer3('Hello World, this is a test file', 'test3.js');5wpt.writer4('Hello World, this is a test file', 'test4.js');6wpt.writer5('Hello World, this is a test file', 'test5.js');7wpt.writer6('Hello World, this is a test file', 'test6.js');8wpt.writer7('Hello World, this is a test file', 'test7.js');9wpt.writer8('Hello World, this is a test file', 'test8.js');10wpt.writer9('Hello World, this is a test file', 'test9.js');11wpt.writer10('Hello World, this is a test file', 'test10.js');12wpt.writer11('Hello World, this is a test file', 'test11.js');13wpt.writer12('Hello World, this is a test file', 'test12.js');14wpt.writer13('Hello World, this is a test file', 'test13.js');15wpt.writer14('Hello World, this is a test file', 'test14.js');16wpt.writer15('Hello World, this is a test file', 'test15.js');17wpt.writer16('Hello World, this is a test file', 'test16.js');
Using AI Code Generation
1var wpt = require('wpt');2var writer1 = new wpt.Writer('writer1');3writer1.write('Hello World');4writer1.write('Hello World again');5var writer2 = new wpt.Writer('writer2');6writer2.write('Hello World');7writer2.write('Hello World again');
Using AI Code Generation
1const wpt = require('wpt');2var writer1 = wpt.writer1;3const express = require('express');4const app = express();5app.get('/', function (req, res) {6 writer1('Hello World');7 res.send('Hello World!')8});9app.listen(3000, function () {10 console.log('Example app listening on port 3000!')11});12MIT © [Rajat S](
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!