diff --git a/package-lock.json b/package-lock.json index 6f4213a2..b9fbea3f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2211,11 +2211,6 @@ "check-error": "^1.0.2" } }, - "chai-bn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/chai-bn/-/chai-bn-0.1.1.tgz", - "integrity": "sha512-e1npVXt3cQfZ6oQET9oP38vNj/4HeJ4ojeUpuC8YzhVbTJpIDqANVt7TKi7Dq9yKlHySk2FqbmiMih35iT4DYg==" - }, "chalk": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", diff --git a/package.json b/package.json index 4ab3eeb2..5f0b8f09 100644 --- a/package.json +++ b/package.json @@ -15,11 +15,11 @@ "publish": "npm run clean:all && npm run bootstrap && npm test && npm run clean:3rd-parties && npx lerna publish", "bootstrap": "npx lerna bootstrap --hoist", "ganache:start:ropsten": "npx ganache-cli --fork https://ropsten.infura.io/latest --blockTime 0.1 -m 'beach swap combine paper music cook electric bullet trust actress liquid asthma' --gasLimit 1000000000000 --host 0.0.0.0 > /dev/null 2>&1 &", - "ganache:start": "npx ganache-cli -m 'beach swap combine paper music cook electric bullet trust actress liquid asthma' --gasLimit 1000000000 --host 0.0.0.0 > /dev/null 2>&1 &", + "ganache:start": "npx ganache-cli --noVMErrorsOnRPCResponse true -m 'beach swap combine paper music cook electric bullet trust actress liquid asthma' --gasLimit 1000000000 --host 0.0.0.0 > /dev/null 2>&1 &", "ganache:stop": "kill `ps ax|grep ganache-cli|grep -v grep| awk '{print $1}'` 2> /dev/null; exit 0", - "truffle:migrate": "npx lerna run migrate --scope tasit-contracts", + "truffle:migrate": "npx lerna run migrate --scope tasit-contracts --stream", "pretest": "npm run ganache:stop && npm run ganache:start && npm run truffle:migrate", - "test": "npx lerna run test", + "test": "npx lerna run test --stream --concurrency 1", "posttest": "npm run ganache:stop" }, "repository": { diff --git a/packages/tasit-account/package.json b/packages/tasit-account/package.json index d443bafd..a02258d1 100644 --- a/packages/tasit-account/package.json +++ b/packages/tasit-account/package.json @@ -18,7 +18,7 @@ }, "scripts": { "prepare": "npx babel src --out-dir dist --ignore **/*.test.js", - "test": "npm run lint && npx mocha src/*.test.js --require @babel/register", + "test": "npm run lint && npx mocha src/*.test.js --require @babel/register --file src/testHelpers/mochaSetup.js", "lint": "npx prettier src/* --write" }, "bugs": { @@ -34,6 +34,6 @@ "@babel/preset-env": "^7.1.6", "@babel/register": "^7.0.0", "chai": "^4.2.0", - "mocha": "^6.0.1" + "mocha": "^6.0.2" } } diff --git a/packages/tasit-account/src/TasitAccount.js b/packages/tasit-account/src/TasitAccount.js index 4c2dae60..01574b0e 100644 --- a/packages/tasit-account/src/TasitAccount.js +++ b/packages/tasit-account/src/TasitAccount.js @@ -3,6 +3,10 @@ import "ethers/dist/shims.js"; // shims aren't injected with package import import { ethers } from "ethers"; +// Account creates an ethres.js Wallet, should it create an Account object that encapsulates the wallet? +// TasitAcount.create() +// > Acount { wallet: ..., metaTxInfos..., etc } +// Related to: https://github.com/tasitlabs/TasitSDK/issues/220 const create = () => { try { const wallet = ethers.Wallet.createRandom(); diff --git a/packages/tasit-account/src/ethers.test.js b/packages/tasit-account/src/ethers.test.js index b27183a0..ef394225 100644 --- a/packages/tasit-account/src/ethers.test.js +++ b/packages/tasit-account/src/ethers.test.js @@ -1,23 +1,18 @@ -import { expect, assert } from "chai"; import { ethers } from "ethers"; -const zero = ethers.utils.bigNumberify(0); +const { ZERO } = constants; -let wallet, provider; +let wallet; // Note: We're intentionally not testing the `fromEncryptedJson` or `encrypt` functions // from `ethers.js` because we don't plan to expose that functionality in the Tasit SDK. // For a detailed explanation of why, see this GitHub issue: // https://github.com/tasitlabs/TasitSDK/issues/24#issuecomment-443576993 describe("ethers.js", () => { - beforeEach("instantiate wallet and provider objects", async function() { - provider = new ethers.providers.JsonRpcProvider(); - provider.pollingInterval = 50; + beforeEach("instantiate wallet and provider objects", async () => { + [wallet] = accounts; + wallet = wallet.connect(provider); - const privateKey = - "0x11d943d7649fbdeb146dc57bd9cfc80b086bfab2330c7b25651dbaf382392f60"; - - wallet = new ethers.Wallet(privateKey, provider); expect(wallet.address).to.have.lengthOf(42); expect(wallet.provider).to.be.not.undefined; }); @@ -39,7 +34,7 @@ describe("ethers.js", () => { ); expect(fundedWalletBalance).not.to.be.undefined; - assert(emptyWalletBalance.eq(zero)); + expect(`${emptyWalletBalance}`).to.equal(`${ZERO}`); }); it("should sign a message", async () => { diff --git a/packages/tasit-account/src/testHelpers/mochaSetup.js b/packages/tasit-account/src/testHelpers/mochaSetup.js new file mode 100644 index 00000000..ebbb4145 --- /dev/null +++ b/packages/tasit-account/src/testHelpers/mochaSetup.js @@ -0,0 +1,35 @@ +import { ethers } from "ethers"; + +// Chai +import { expect, assert } from "chai"; +global.expect = expect; +//global.assert = assert; + +// Helpers +import actionHelpers from "../../../tasit-action/dist/testHelpers/helpers"; +global = Object.assign(global, actionHelpers); + +// Global hooks +let snapshotId; + +beforeEach("global beforeEach() hook", async () => { + const provider = new ethers.providers.JsonRpcProvider(); + provider.pollingInterval = 50; + global.provider = provider; + snapshotId = await createSnapshot(provider); + + while (snapshotId > 1) { + await revertFromSnapshot(provider, snapshotId--); + } + + expect(snapshotId).to.equal(1); +}); + +afterEach("global afterEach() hook", async () => { + expect(snapshotId).to.equal(1); + await revertFromSnapshot(provider, snapshotId); + + // Note: Without this the test suite is breaking. + // It is still unclear why + await mineBlocks(provider, 1); +}); diff --git a/packages/tasit-action/package.json b/packages/tasit-action/package.json index 87d788e2..dbe3e79f 100644 --- a/packages/tasit-action/package.json +++ b/packages/tasit-action/package.json @@ -18,7 +18,7 @@ }, "scripts": { "prepare": "rm -rf dist/* && npx babel src --out-dir dist --ignore src/*.test.js,src/**/*.test.js", - "test": "npm run lint && npx mocha \"src/**/*.test.js\" --recursive --require @babel/register --require src/testHelpers/mochaSetup.js --no-timeouts", + "test": "npm run lint && npx mocha \"src/**/*.test.js\" --recursive --require @babel/register --file src/testHelpers/mochaSetup.js", "lint": "npx prettier src/* --write" }, "bugs": { @@ -34,11 +34,9 @@ "@babel/plugin-proposal-class-properties": "^7.2.3", "@babel/preset-env": "^7.1.6", "@babel/register": "^7.0.0", - "bn.js": "^4.11.8", "chai": "^4.2.0", "chai-as-promised": "^7.1.1", - "chai-bn": "^0.1.1", - "mocha": "^6.0.1", + "mocha": "^6.0.2", "sinon": "^7.2.2", "tasit-account": "^0.0.9" } diff --git a/packages/tasit-action/src/TasitAction.js b/packages/tasit-action/src/TasitAction.js index 201bd283..ce6abcf3 100644 --- a/packages/tasit-action/src/TasitAction.js +++ b/packages/tasit-action/src/TasitAction.js @@ -1,15 +1,16 @@ import ConfigLoader from "./ConfigLoader"; import Contract from "./contract/Contract"; -import NFT from "./erc721/NFT"; +import ERC721Full from "./erc721/ERC721Full"; import Land from "./erc721/Land"; import Decentraland from "./marketplace/Decentraland"; import Estate from "./erc721/Estate"; import Mana from "./erc20/Mana"; +import ERC20Full from "./erc20/ERC20Full"; -export { Contract, NFT, Land, Decentraland, Estate, Mana }; +export { Contract, ERC721Full, Land, Decentraland, Estate, Mana }; -export const ERC20 = { Mana }; -export const ERC721 = { Land, Estate, NFT }; +export const ERC20 = { Mana, ERC20Full }; +export const ERC721 = { Land, Estate, ERC721Full }; export const Marketplace = { Decentraland }; export const TasitAction = { diff --git a/packages/tasit-action/src/contract/Contract.js b/packages/tasit-action/src/contract/Contract.js index a8c596ea..235ed975 100644 --- a/packages/tasit-action/src/contract/Contract.js +++ b/packages/tasit-action/src/contract/Contract.js @@ -64,6 +64,10 @@ export class Contract extends Subscription { return this.#ethersContract.address; }; + getABI = () => { + return this.#ethersContract.interface.abi; + }; + // For testing purposes _getProvider = () => { return this.#provider; diff --git a/packages/tasit-action/src/contract/Contract.test.js b/packages/tasit-action/src/contract/Contract.test.js index 08a50248..d74d93f6 100644 --- a/packages/tasit-action/src/contract/Contract.test.js +++ b/packages/tasit-action/src/contract/Contract.test.js @@ -1,8 +1,6 @@ import Contract from "./Contract"; import Account from "tasit-account"; -// Note: SampleContract.json is originally generated by `tasit-contracts` and was pasted here manually -// See https://github.com/tasitlabs/TasitSDK/issues/45 import { abi as contractABI } from "../../../tasit-contracts/build/contracts/SampleContract.json"; // Note: Under the current `tasit-contracts` setup SampleContract aways will deployed with this address @@ -12,8 +10,6 @@ const sampleContractAddress = "0x6C4A015797DDDd87866451914eCe1e8b19261931"; describe("TasitAction.Contract", () => { let sampleContract; let wallet; - let testcaseSnaphotId; - let provider; let action; beforeEach("should connect to an existing contract", async () => { @@ -23,16 +19,9 @@ describe("TasitAction.Contract", () => { sampleContract = undefined; wallet = undefined; - testcaseSnaphotId = undefined; - provider = undefined; action = undefined; - // Account creates a wallet, should it create an account object that encapsulates the wallet? - // TasitAcount.create() - // > Acount { wallet: ..., metaTxInfos..., etc } - wallet = createFromPrivateKey( - "0x11d943d7649fbdeb146dc57bd9cfc80b086bfab2330c7b25651dbaf382392f60" - ); + [wallet] = accounts; sampleContract = new Contract(sampleContractAddress, contractABI); expect(sampleContract).to.exist; @@ -40,14 +29,10 @@ describe("TasitAction.Contract", () => { expect(sampleContract.getValue).to.exist; expect(sampleContract.setValue).to.exist; expect(sampleContract._getProvider()).to.exist; - - provider = sampleContract._getProvider(); - testcaseSnaphotId = await createSnapshot(provider); + expect(sampleContract.getABI()).to.deep.equal(contractABI); }); afterEach("revert blockchain snapshot", async () => { - await mineBlocks(provider, 1); - if (sampleContract) { sampleContract.unsubscribe(); @@ -66,8 +51,6 @@ describe("TasitAction.Contract", () => { "ethers.js should not be listening to any events." ).to.be.empty; } - - await revertFromSnapshot(provider, testcaseSnaphotId); }); describe("should throw error when instantiated with invalid args", () => { diff --git a/packages/tasit-action/src/erc20/ERC20Full.js b/packages/tasit-action/src/erc20/ERC20Full.js new file mode 100644 index 00000000..8042cc29 --- /dev/null +++ b/packages/tasit-action/src/erc20/ERC20Full.js @@ -0,0 +1,8 @@ +import Contract from "../contract/Contract"; +import abi from "../../../tasit-contracts/abi/MyERC20Full.json"; + +export default class ERC20Full extends Contract { + constructor(address, wallet) { + super(address, abi, wallet); + } +} diff --git a/packages/tasit-action/src/erc20/ERC20Full.test.js b/packages/tasit-action/src/erc20/ERC20Full.test.js new file mode 100644 index 00000000..8b4b275c --- /dev/null +++ b/packages/tasit-action/src/erc20/ERC20Full.test.js @@ -0,0 +1,13 @@ +import ERC20Full from "./ERC20Full"; + +// Note: Under the current `tasit-contracts` setup ERC20Detailed aways will deployed with this address +// See https://github.com/tasitlabs/TasitSDK/issues/138 +const ERC20_FULL_ADDRESS = "0x37E1A58dD465D33263D00185D065Ee36DD34CDb4"; + +describe("TasitAction.ERC20.ERC20Full", () => { + it("should get the ERC20Full name", async () => { + const erc20 = new ERC20Full(ERC20_FULL_ADDRESS); + const name = await erc20.name(); + expect(name).to.equal("ERC20Full"); + }); +}); diff --git a/packages/tasit-action/src/erc20/Mana.test.js b/packages/tasit-action/src/erc20/Mana.test.js index 7c0fad5e..68935ea9 100644 --- a/packages/tasit-action/src/erc20/Mana.test.js +++ b/packages/tasit-action/src/erc20/Mana.test.js @@ -1,10 +1,10 @@ import Mana from "./Mana"; -import { local as localAddresses } from "../../../tasit-contracts/decentraland/addresses"; +import { local as localAddresses } from "../../../tasit-contracts/3rd-parties/decentraland/addresses"; const { MANAToken: MANA_ADDRESS } = localAddresses; describe("TasitAction.Decentraland.Mana", () => { - it("should get the MANAToken name", async function() { + it("should get the MANAToken name", async () => { const mana = new Mana(MANA_ADDRESS); const name = await mana.name(); expect(name).to.equal("Decentraland MANA"); diff --git a/packages/tasit-action/src/erc721/ERC721Full.js b/packages/tasit-action/src/erc721/ERC721Full.js new file mode 100644 index 00000000..eee041dc --- /dev/null +++ b/packages/tasit-action/src/erc721/ERC721Full.js @@ -0,0 +1,8 @@ +import Contract from "../contract/Contract"; +import abi from "../../../tasit-contracts/abi/MyERC721Full.json"; + +export default class ERC721Full extends Contract { + constructor(address, wallet) { + super(address, abi, wallet); + } +} diff --git a/packages/tasit-action/src/erc721/NFT.test.js b/packages/tasit-action/src/erc721/ERC721Full.test.js similarity index 64% rename from packages/tasit-action/src/erc721/NFT.test.js rename to packages/tasit-action/src/erc721/ERC721Full.test.js index 5a472c43..135a8a06 100644 --- a/packages/tasit-action/src/erc721/NFT.test.js +++ b/packages/tasit-action/src/erc721/ERC721Full.test.js @@ -1,62 +1,47 @@ -import NFT from "./NFT"; +import ERC721Full from "./ERC721Full"; -// Note: Under the current `tasit-contracts` setup FullNFT aways will deployed with this address +// Note: Under the current `tasit-contracts` setup ERC721Full aways will deployed with this address // See https://github.com/tasitlabs/TasitSDK/issues/138 -const fullNFTAddress = "0x0E86f209729bf54763789CDBcA9E8b94f0FD5333"; +const ERC721_FULL_ADDRESS = "0x0E86f209729bf54763789CDBcA9E8b94f0FD5333"; // Note: This contract is used not because of the particulars of this contract, but // just because we needed a contract to send an NFT to and have it fail // when using safeTransferFrom because this contract doesn't implement // onERC721Received -const sampleContractAddress = "0x6C4A015797DDDd87866451914eCe1e8b19261931"; +const SAMPLE_CONTRACT_ADDRESS = "0x6C4A015797DDDd87866451914eCe1e8b19261931"; -describe("TasitAction.ERC721.NFT", () => { +describe("TasitAction.ERC721.ERC721Full", () => { let owner; let ana; let bob; - let fullNFT; - let provider; - let snapshotId; + let erc721; + let action; before("", async () => { - owner = createFromPrivateKey( - "0x11d943d7649fbdeb146dc57bd9cfc80b086bfab2330c7b25651dbaf382392f60" - ); - - ana = createFromPrivateKey( - "0xc181b6b02c9757f13f5aa15d1342a58970a8a489722dc0608a1d09fea717c181" - ); - - bob = createFromPrivateKey( - "0x4f09311114f0ff4dfad0edaa932a3e01a4ee9f34da2cbd087aa0e6ffcb9eb322" - ); + [owner, ana, bob] = accounts; }); beforeEach("", async () => { action = undefined; - fullNFT = new NFT(fullNFTAddress, owner); - - expect(fullNFT).to.exist; - expect(fullNFT.getAddress()).to.equal(fullNFTAddress); - expect(fullNFT.name).to.exist; - expect(fullNFT.symbol).to.exist; - expect(fullNFT._getProvider()).to.exist; + erc721 = new ERC721Full(ERC721_FULL_ADDRESS, owner); - provider = fullNFT._getProvider(); + expect(erc721).to.exist; + expect(erc721.getAddress()).to.equal(ERC721_FULL_ADDRESS); + expect(erc721.name).to.exist; + expect(erc721.symbol).to.exist; + expect(erc721._getProvider()).to.exist; // This line ensures that a new event listener does not catch an existing event from last the block // Two blocks to minimize the risk that polling doesn't occur. await mineBlocks(provider, 2); await confirmBalances( - fullNFT, + erc721, [owner.address, ana.address, bob.address], [0, 0, 0] ); - - snapshotId = await createSnapshot(provider); }); afterEach("", async () => { @@ -67,13 +52,13 @@ describe("TasitAction.ERC721.NFT", () => { expect(provider._events, "ethers.js should not be listening to any events.") .to.be.empty; - if (fullNFT) { - fullNFT.unsubscribe(); + if (erc721) { + erc721.unsubscribe(); - expect(fullNFT.subscribedEventNames()).to.be.empty; + expect(erc721.subscribedEventNames()).to.be.empty; expect( - fullNFT.getEmitter()._events, + erc721.getEmitter()._events, "ethers.js should not be listening to any events." ).to.be.empty; } @@ -90,18 +75,16 @@ describe("TasitAction.ERC721.NFT", () => { ).to.be.empty; } - if (fullNFT) { - fullNFT.unsubscribe(); + if (erc721) { + erc721.unsubscribe(); - expect(fullNFT.subscribedEventNames()).to.be.empty; + expect(erc721.subscribedEventNames()).to.be.empty; expect( - fullNFT.getEmitter()._events, + erc721.getEmitter()._events, "ethers.js should not be listening to any events." ).to.be.empty; } - - await revertFromSnapshot(provider, snapshotId); }); describe("should throw error when instantiated with invalid args", () => { @@ -119,9 +102,9 @@ describe("TasitAction.ERC721.NFT", () => { }); it("should call a read-only contract method", async () => { - const name = await fullNFT.name(); + const name = await erc721.name(); expect(name).to.exist; - expect(name).to.equal("Full NFT"); + expect(name).to.equal("ERC721Full"); }); describe("ERC721 functions", () => { @@ -129,10 +112,10 @@ describe("TasitAction.ERC721.NFT", () => { const zeroAddress = "0x0000000000000000000000000000000000000000"; beforeEach("should mint one token to ana", async () => { - action = fullNFT.mint(ana.address, tokenId); + action = erc721.mint(ana.address, tokenId); const event = await new Promise(function(resolve, reject) { - fullNFT.on("Transfer", message => { + erc721.on("Transfer", message => { const { data } = message; const { args } = data; resolve(args); @@ -143,24 +126,24 @@ describe("TasitAction.ERC721.NFT", () => { }, 1000); }); - fullNFT.off("Transfer"); + erc721.off("Transfer"); expect(event.from).to.equal(zeroAddress); expect(event.to).to.equal(ana.address); expect(event.tokenId.eq(tokenId)).to.be.true; - await confirmBalances(fullNFT, [ana.address], [1]); + await confirmBalances(erc721, [ana.address], [1]); }); // Non-deterministic // Note: This test failed recently on CI it.skip("should transfer an owned token", async () => { - fullNFT = new NFT(fullNFTAddress, ana); + erc721 = new ERC721Full(ERC721_FULL_ADDRESS, ana); - action = fullNFT.transferFrom(ana.address, bob.address, tokenId); + action = erc721.transferFrom(ana.address, bob.address, tokenId); const event = await new Promise(function(resolve, reject) { - fullNFT.on("Transfer", message => { + erc721.on("Transfer", message => { const { data } = message; const { args } = data; resolve(args); @@ -175,37 +158,37 @@ describe("TasitAction.ERC721.NFT", () => { expect(event.to).to.equal(bob.address); expect(event.tokenId.toNumber()).to.equal(tokenId); - await confirmBalances(fullNFT, [ana.address, bob.address], [0, 1]); + await confirmBalances(erc721, [ana.address, bob.address], [0, 1]); }); it("should transfer an approved token", async () => { - fullNFT = new NFT(fullNFTAddress, ana); - action = fullNFT.approve(bob.address, tokenId); + erc721 = new ERC721Full(ERC721_FULL_ADDRESS, ana); + action = erc721.approve(bob.address, tokenId); await action.waitForNonceToUpdate(); - fullNFT.setWallet(bob); - action = fullNFT.transferFrom(ana.address, bob.address, tokenId); + erc721.setWallet(bob); + action = erc721.transferFrom(ana.address, bob.address, tokenId); await action.waitForNonceToUpdate(); - await confirmBalances(fullNFT, [bob.address], [1]); + await confirmBalances(erc721, [bob.address], [1]); }); it("should transfer an owned token using safeTransferFrom", async () => { - fullNFT = new NFT(fullNFTAddress, ana); + erc721 = new ERC721Full(ERC721_FULL_ADDRESS, ana); - action = fullNFT.safeTransferFrom(ana.address, bob.address, tokenId); + action = erc721.safeTransferFrom(ana.address, bob.address, tokenId); await action.waitForNonceToUpdate(); - await confirmBalances(fullNFT, [ana.address, bob.address], [0, 1]); + await confirmBalances(erc721, [ana.address, bob.address], [0, 1]); }); it("should trigger an error if the user is listening for errors from a contract and tries safeTransferFrom to a contract without onERC721Received", async () => { const contractErrorFakeFn = sinon.fake(); - fullNFT = new NFT(fullNFTAddress, ana); + erc721 = new ERC721Full(ERC721_FULL_ADDRESS, ana); const contractErrorListener = message => { const { error } = message; @@ -215,11 +198,11 @@ describe("TasitAction.ERC721.NFT", () => { contractErrorFakeFn(); }; - fullNFT.on("error", contractErrorListener); + erc721.on("error", contractErrorListener); - action = fullNFT.safeTransferFrom( + action = erc721.safeTransferFrom( ana.address, - sampleContractAddress, + SAMPLE_CONTRACT_ADDRESS, tokenId ); await action.waitForNonceToUpdate(); @@ -227,8 +210,8 @@ describe("TasitAction.ERC721.NFT", () => { expect(contractErrorFakeFn.called).to.be.true; await confirmBalances( - fullNFT, - [ana.address, sampleContractAddress], + erc721, + [ana.address, SAMPLE_CONTRACT_ADDRESS], [1, 0] ); }); @@ -236,7 +219,7 @@ describe("TasitAction.ERC721.NFT", () => { it("should trigger an error if the user is listening for errors for an action and tries safeTransferFrom to a contract without onERC721Received", async () => { const actionErrorFakeFn = sinon.fake(); - fullNFT = new NFT(fullNFTAddress, ana); + erc721 = new ERC721Full(ERC721_FULL_ADDRESS, ana); const actionErrorListener = message => { const { error } = message; @@ -246,9 +229,9 @@ describe("TasitAction.ERC721.NFT", () => { actionErrorFakeFn(); }; - action = fullNFT.safeTransferFrom( + action = erc721.safeTransferFrom( ana.address, - sampleContractAddress, + SAMPLE_CONTRACT_ADDRESS, tokenId ); action.on("error", actionErrorListener); @@ -258,8 +241,8 @@ describe("TasitAction.ERC721.NFT", () => { expect(actionErrorFakeFn.called).to.be.true; await confirmBalances( - fullNFT, - [ana.address, sampleContractAddress], + erc721, + [ana.address, SAMPLE_CONTRACT_ADDRESS], [1, 0] ); }); diff --git a/packages/tasit-action/src/erc721/Estate.test.js b/packages/tasit-action/src/erc721/Estate.test.js index a54185dc..c23666f6 100644 --- a/packages/tasit-action/src/erc721/Estate.test.js +++ b/packages/tasit-action/src/erc721/Estate.test.js @@ -1,12 +1,12 @@ import Estate from "./Estate"; -import { local as localAddresses } from "../../../tasit-contracts/decentraland/addresses"; +import { local as localAddresses } from "../../../tasit-contracts/3rd-parties/decentraland/addresses"; const { EstateRegistry: ESTATE_ADDRESS } = localAddresses; describe("TasitAction.ERC721.Estate", () => { // Note: This test runs against an uninitialized contract. // TODO: Improve that test case when we move to forked from testnet blockchain. - it("should get the Estate owner", async function() { + it("should get the Estate owner", async () => { const estate = new Estate(ESTATE_ADDRESS); let owner = await estate.owner(); expect(owner).to.equal("0x0000000000000000000000000000000000000000"); diff --git a/packages/tasit-action/src/erc721/Land.test.js b/packages/tasit-action/src/erc721/Land.test.js index 02240898..b387be62 100644 --- a/packages/tasit-action/src/erc721/Land.test.js +++ b/packages/tasit-action/src/erc721/Land.test.js @@ -1,10 +1,10 @@ import Land from "./Land"; -import { local as localAddresses } from "../../../tasit-contracts/decentraland/addresses"; +import { local as localAddresses } from "../../../tasit-contracts/3rd-parties/decentraland/addresses"; const { LANDProxy: LAND_PROXY_ADDRESS } = localAddresses; describe("TasitAction.ERC721.Land", () => { - it("should get the Land owner", async function() { + it("should get the Land owner", async () => { const land = new Land(LAND_PROXY_ADDRESS); let owner = await land.owner(); expect(owner).to.equal("0xd68649157A061454e2c63c175236b07e98Bd9512"); diff --git a/packages/tasit-action/src/erc721/NFT.js b/packages/tasit-action/src/erc721/NFT.js deleted file mode 100644 index 46d4378e..00000000 --- a/packages/tasit-action/src/erc721/NFT.js +++ /dev/null @@ -1,9 +0,0 @@ -import Contract from "../contract/Contract"; -import erc721FullABI from "../../../tasit-contracts/abi/ERC721Full.json"; - -export default class NFT extends Contract { - constructor(address, wallet) { - const abi = erc721FullABI; - super(address, abi, wallet); - } -} diff --git a/packages/tasit-action/src/ethers.test.js b/packages/tasit-action/src/ethers.test.js index 03d25802..99663412 100644 --- a/packages/tasit-action/src/ethers.test.js +++ b/packages/tasit-action/src/ethers.test.js @@ -1,8 +1,6 @@ import { ethers } from "ethers"; ethers.errors.setLogLevel("error"); -// Note: This file is originally genarated by `tasit-contracts` and was pasted here manually -// See https://github.com/tasitlabs/TasitSDK/issues/45 import { abi as contractABI } from "../../tasit-contracts/build/contracts/SampleContract.json"; // Note: Under the current `tasit-contracts` setup SampleContract aways will deployed with this address @@ -11,17 +9,11 @@ const sampleContractAddress = "0x6C4A015797DDDd87866451914eCe1e8b19261931"; let wallet; let sampleContract; -let testcaseSnaphotId; describe("ethers.js", () => { - const provider = new ethers.providers.JsonRpcProvider(); - provider.pollingInterval = 50; - beforeEach("instantiate provider, wallet and contract objects", async () => { - const privateKey = - "0x11d943d7649fbdeb146dc57bd9cfc80b086bfab2330c7b25651dbaf382392f60"; - - wallet = new ethers.Wallet(privateKey, provider); + [wallet] = accounts; + wallet = wallet.connect(provider); expect(wallet.address).to.have.lengthOf(42); expect(wallet.provider).to.be.not.undefined; @@ -31,16 +23,6 @@ describe("ethers.js", () => { wallet ); expect(sampleContract.address).to.equal(sampleContractAddress); - - testcaseSnaphotId = await createSnapshot(provider); - }); - - afterEach("revert blockchain snapshot", async () => { - await revertFromSnapshot(provider, testcaseSnaphotId); - - // Note: Without this the test suite is breaking. - // It is still unclear why - await mineBlocks(provider, 1); }); it("should instatiate contract object using human-readable ABI", async () => { diff --git a/packages/tasit-action/src/marketplace/Decentraland.test.js b/packages/tasit-action/src/marketplace/Decentraland.test.js index 9d3c1f27..dafaca3c 100644 --- a/packages/tasit-action/src/marketplace/Decentraland.test.js +++ b/packages/tasit-action/src/marketplace/Decentraland.test.js @@ -1,10 +1,10 @@ import Decentraland from "./Decentraland"; -import { local as localAddresses } from "../../../tasit-contracts/decentraland/addresses"; +import { local as localAddresses } from "../../../tasit-contracts/3rd-parties/decentraland/addresses"; const { Marketplace: MARKETPLACE_ADDRESS } = localAddresses; describe("TasitAction.Marketplace.Decentraland", () => { - it("contract shouldn't be paused", async function() { + it("contract shouldn't be paused", async () => { const marketplace = new Decentraland(MARKETPLACE_ADDRESS); const isPaused = await marketplace.paused(); expect(isPaused).to.equal(false); diff --git a/packages/tasit-action/src/testHelpers/helpers.js b/packages/tasit-action/src/testHelpers/helpers.js index 50526fff..68377129 100644 --- a/packages/tasit-action/src/testHelpers/helpers.js +++ b/packages/tasit-action/src/testHelpers/helpers.js @@ -1,7 +1,16 @@ import { expect } from "chai"; import { ethers } from "ethers"; +import ProviderFactory from "../ProviderFactory"; +import developmentConfig from "../config/default.js"; -export const waitForEthersEvent = async (eventEmitter, eventName, callback) => { +// Note: Using dist file because babel doesn't compile node_modules files. +// Any changes on src should be followed by compilation to avoid unexpected behaviors. +// Note that lerna bootstrap does this for you since it +// runs prepare in all bootstrapped packages. +// Refs: https://github.com/lerna/lerna/tree/master/commands/bootstrap +import { createFromPrivateKey } from "tasit-account/dist/testHelpers/helpers"; + +const waitForEthersEvent = async (eventEmitter, eventName, callback) => { return new Promise(function(resolve, reject) { eventEmitter.on(eventName, (...args) => { const event = args.pop(); @@ -16,7 +25,7 @@ const mineOneBlock = async provider => { await provider.send("evm_mine", []); }; -export const mineBlocks = async (provider, n) => { +const mineBlocks = async (provider, n) => { for (let i = 0; i < n; i++) { await mineOneBlock(provider); @@ -28,19 +37,20 @@ export const mineBlocks = async (provider, n) => { } }; -export const createSnapshot = async provider => { - return await provider.send("evm_snapshot", []); +const createSnapshot = async provider => { + const id = await provider.send("evm_snapshot", []); + return Number(id); }; -export const revertFromSnapshot = async (provider, snapshotId) => { - await provider.send("evm_revert", [snapshotId]); +const revertFromSnapshot = async (provider, snapshotId) => { + return await provider.send("evm_revert", [snapshotId]); }; -export const wait = async ms => { +const wait = async ms => { return new Promise(resolve => setTimeout(resolve, ms)); }; -export const confirmBalances = async (token, addresses, balances) => { +const confirmBalances = async (token, addresses, balances) => { expect(addresses.length).to.equal(balances.length); let index = 0; for (let address of addresses) { @@ -50,22 +60,128 @@ export const confirmBalances = async (token, addresses, balances) => { } }; -// Note: ethers created their own BigNumber type that encapsulates BN.js -// Because of that, exists the need of extra parses between user and our API (see tests) -// Should we: -// - Try to intercept and parse ethers.BigNumber to BN.js (and vice-versa)? -// or -// - Exposes ethers.utils.BigNumber / bigNumberify()? -export const toBN = ethersBN => { - return new BN(ethersBN.toString()); +const etherFaucet = async ( + provider, + fromWallet, + beneficiaryAddress, + amountInWei +) => { + const connectedFromWallet = fromWallet.connect(provider); + const tx = await connectedFromWallet.sendTransaction({ + // ethers.utils.parseEther("1.0") + value: "0x0de0b6b3a7640000", + to: beneficiaryAddress, + }); + await provider.waitForTransaction(tx.hash); +}; + +const erc20Faucet = async ( + tokenContract, + ownerWallet, + toAddress, + amountInWei +) => { + tokenContract.setWallet(ownerWallet); + const mintAction = tokenContract.mint(toAddress, `${amountInWei}`); + await mintAction.waitForNonceToUpdate(); + await confirmBalances(tokenContract, [toAddress], [amountInWei]); +}; + +const erc721Faucet = async (tokenContract, ownerWallet, toAddress, tokenId) => { + tokenContract.setWallet(ownerWallet); + const mintAction = tokenContract.mint(toAddress, tokenId); + await mintAction.waitForNonceToUpdate(); + await confirmBalances(tokenContract, [toAddress], [1]); +}; + +const addressesAreEqual = (address1, address2) => { + return address1.toUpperCase() === address2.toUpperCase(); }; -export default { +const { + utils: ethersUtils, + constants: ethersConstants, + Contract: ethersContract, +} = ethers; +const { WeiPerEther } = ethersConstants; +const { bigNumberify } = ethersUtils; + +// In weis +// Note: ethers.js uses BigNumber internally +// That accepts decimal strings (Ref: https://docs.ethers.io/ethers.js/html/api-utils.html#creating-instances) +// Scientific notation works if the number is small enough (< 1e21) to be converted to string properly +// See more: https://github.com/ethers-io/ethers.js/issues/228 +const ZERO = 0; +const ONE = bigNumberify(1).mul(WeiPerEther); +const TEN = bigNumberify(10).mul(WeiPerEther); +const BILLION = bigNumberify(`${1e9}`).mul(WeiPerEther); + +const constants = { + ZERO, + ONE, + TEN, + BILLION, + WeiPerEther, +}; + +// TODO: Go deep on gas handling. +// Without that, VM returns a revert error instead of out of gas error. +// See: https://github.com/tasitlabs/TasitSDK/issues/173 +const gasParams = { + gasLimit: 7e6, + gasPrice: 1e9, +}; + +const accounts = [ + createFromPrivateKey( + "0x11d943d7649fbdeb146dc57bd9cfc80b086bfab2330c7b25651dbaf382392f60" + ), + createFromPrivateKey( + "0xc181b6b02c9757f13f5aa15d1342a58970a8a489722dc0608a1d09fea717c181" + ), + createFromPrivateKey( + "0x4f09311114f0ff4dfad0edaa932a3e01a4ee9f34da2cbd087aa0e6ffcb9eb322" + ), + createFromPrivateKey( + "0xb52de6b5c3b38277edc6a30db517c719af6c7f0d3743a254cb2e0b54408ecbd8" + ), + createFromPrivateKey( + "0x65a6dacaed00c004c4739a121c2c4908d5da41e4015f9f7cf75f8686a019d419" + ), + createFromPrivateKey( + "0x17f6836e922fde89ca95883631f02ff89787ec0ac593106527f9bd2635080fb6" + ), + createFromPrivateKey( + "0xe28dec48b18fb80369ea651cf703a053b2a5cce868e3450b4e532ca0fb8149b4" + ), + createFromPrivateKey( + "0xd79a1249c9ec1b468a71971fe551358ca4d1f9167f085b87f33c1783839c4d9d" + ), + createFromPrivateKey( + "0x8fb382c5caa48ed928e6f6324e3b8112e43e2aaa9a761b12501321630a512b49" + ), + createFromPrivateKey( + "0xee0c6b1a7adea9f87b1a422eb06b245fc714b8eca4c8c0578d6cf946beba86f1" + ), +]; + +export const helpers = { waitForEthersEvent, mineBlocks, createSnapshot, revertFromSnapshot, wait, - toBN, confirmBalances, + etherFaucet, + erc20Faucet, + erc721Faucet, + addressesAreEqual, + constants, + bigNumberify, + gasParams, + ProviderFactory, + accounts, + developmentConfig, }; + +export default helpers; diff --git a/packages/tasit-action/src/testHelpers/mochaSetup.js b/packages/tasit-action/src/testHelpers/mochaSetup.js index 62cc2514..96ecf9bb 100644 --- a/packages/tasit-action/src/testHelpers/mochaSetup.js +++ b/packages/tasit-action/src/testHelpers/mochaSetup.js @@ -1,44 +1,40 @@ -import BN from "bn.js"; -global.BN = BN; - // Chai import chai, { expect } from "chai"; global.expect = expect; chai.use(require("chai-as-promised")); -chai.use(require("chai-bn")(BN)); // Sinon import sinon from "sinon"; global.sinon = sinon; // Helpers -import { - mineBlocks, - createSnapshot, - revertFromSnapshot, - wait, - waitForEthersEvent, - toBN, - confirmBalances, -} from "./helpers"; -global.mineBlocks = mineBlocks; -global.createSnapshot = createSnapshot; -global.revertFromSnapshot = revertFromSnapshot; -global.wait = wait; -global.waitForEthersEvent = waitForEthersEvent; -global.toBN = toBN; -global.confirmBalances = confirmBalances; - -// External helpers -// -// Note: Using dist file because babel doesn't compile node_modules files. -// Any changes on src should be followed by compilation to avoid unexpected behaviors. -// Note that lerna bootstrap does this for you since it -// runs prepare in all bootstrapped packages. -// Refs: https://github.com/lerna/lerna/tree/master/commands/bootstrap -import { createFromPrivateKey } from "tasit-account/dist/testHelpers/helpers"; -global.createFromPrivateKey = createFromPrivateKey; +import actionHelpers from "./helpers"; +global = Object.assign(global, actionHelpers); import ConfigLoader from "../ConfigLoader"; import config from "../config/default.js"; ConfigLoader.setConfig(config); + +// Global hooks +let snapshotId; + +beforeEach("global beforeEach() hook", async () => { + const provider = ProviderFactory.getProvider(); + global.provider = provider; + snapshotId = await createSnapshot(provider); + + while (snapshotId > 1) { + await revertFromSnapshot(provider, snapshotId--); + } + + expect(snapshotId).to.equal(1); +}); + +afterEach("global afterEach() hook", async () => { + expect(snapshotId).to.equal(1); + await revertFromSnapshot(provider, snapshotId); + + // Note: Without this the test suite is breaking. + // It is still unclear why + await mineBlocks(provider, 1); +}); diff --git a/packages/tasit-contracts/3rd-parties/decentraland/addresses.js b/packages/tasit-contracts/3rd-parties/decentraland/addresses.js new file mode 100644 index 00000000..6dc460da --- /dev/null +++ b/packages/tasit-contracts/3rd-parties/decentraland/addresses.js @@ -0,0 +1,13 @@ +const decentralandAddresses = require("./contracts/addresses.json"); + +const { ropsten } = decentralandAddresses; + +const local = { + MANAToken: "0x332bfb4d705d3ce37c4bf06141c7104984e91e79", + EstateRegistry: "0x6191bc768c2339da9eab9e589fc8bf0b3ab80975", + LANDRegistry: "0x773f11ed472aa43e4ebaa963bcfbbea5a10c1bbd", + LANDProxy: "0x1212f783f11611b0c029d5e6f86a23be621669e0", + Marketplace: "0x70960e803a2bbe90c7db34edfdc2d1e81ed46b79", +}; + +module.exports = { ropsten, local }; diff --git a/packages/tasit-contracts/decentraland/contracts b/packages/tasit-contracts/3rd-parties/decentraland/contracts similarity index 100% rename from packages/tasit-contracts/decentraland/contracts rename to packages/tasit-contracts/3rd-parties/decentraland/contracts diff --git a/packages/tasit-contracts/decentraland/land b/packages/tasit-contracts/3rd-parties/decentraland/land similarity index 100% rename from packages/tasit-contracts/decentraland/land rename to packages/tasit-contracts/3rd-parties/decentraland/land diff --git a/packages/tasit-contracts/decentraland/mana b/packages/tasit-contracts/3rd-parties/decentraland/mana similarity index 100% rename from packages/tasit-contracts/decentraland/mana rename to packages/tasit-contracts/3rd-parties/decentraland/mana diff --git a/packages/tasit-contracts/decentraland/marketplace-contracts b/packages/tasit-contracts/3rd-parties/decentraland/marketplace-contracts similarity index 100% rename from packages/tasit-contracts/decentraland/marketplace-contracts rename to packages/tasit-contracts/3rd-parties/decentraland/marketplace-contracts diff --git a/packages/tasit-contracts/decentraland/scripts/3_land_migrations.js b/packages/tasit-contracts/3rd-parties/decentraland/scripts/3_land_migrations.js similarity index 67% rename from packages/tasit-contracts/decentraland/scripts/3_land_migrations.js rename to packages/tasit-contracts/3rd-parties/decentraland/scripts/3_land_migrations.js index dcf21699..109ec8d7 100644 --- a/packages/tasit-contracts/decentraland/scripts/3_land_migrations.js +++ b/packages/tasit-contracts/3rd-parties/decentraland/scripts/3_land_migrations.js @@ -2,6 +2,8 @@ const LANDRegistry = artifacts.require("./LANDRegistry.sol"); const EstateRegistry = artifacts.require("./EstateRegistry.sol"); const LANDProxy = artifacts.require("./LANDProxy.sol"); +// Note: If you want to change this file, make sure that you are editing +// the original file inside of the `tasit-contracts/3rd-parties/decentraland/scripts` module.exports = function(deployer) { deployer.deploy(EstateRegistry); deployer.deploy(LANDRegistry); diff --git a/packages/tasit-contracts/3rd-parties/decentraland/scripts/3_mana_migrations.js b/packages/tasit-contracts/3rd-parties/decentraland/scripts/3_mana_migrations.js new file mode 100644 index 00000000..3fe76148 --- /dev/null +++ b/packages/tasit-contracts/3rd-parties/decentraland/scripts/3_mana_migrations.js @@ -0,0 +1,7 @@ +const MANAToken = artifacts.require("./MANAToken.sol"); + +// Note: If you want to change this file, make sure that you are editing +// the original file inside of the `tasit-contracts/3rd-parties/decentraland/scripts` +module.exports = function(deployer) { + deployer.deploy(MANAToken); +}; diff --git a/packages/tasit-contracts/3rd-parties/decentraland/scripts/3_marketplace-contracts_migrations.js b/packages/tasit-contracts/3rd-parties/decentraland/scripts/3_marketplace-contracts_migrations.js new file mode 100644 index 00000000..f2a217c6 --- /dev/null +++ b/packages/tasit-contracts/3rd-parties/decentraland/scripts/3_marketplace-contracts_migrations.js @@ -0,0 +1,7 @@ +const Marketplace = artifacts.require("./Marketplace.sol"); + +// Note: If you want to change this file, make sure that you are editing +// the original file inside of the `tasit-contracts/3rd-parties/decentraland/scripts` +module.exports = function(deployer) { + deployer.deploy(Marketplace); +}; diff --git a/packages/tasit-contracts/decentraland/scripts/clean.sh b/packages/tasit-contracts/3rd-parties/decentraland/scripts/clean.sh similarity index 83% rename from packages/tasit-contracts/decentraland/scripts/clean.sh rename to packages/tasit-contracts/3rd-parties/decentraland/scripts/clean.sh index 1297fe01..d7395554 100755 --- a/packages/tasit-contracts/decentraland/scripts/clean.sh +++ b/packages/tasit-contracts/3rd-parties/decentraland/scripts/clean.sh @@ -8,7 +8,7 @@ then fi -DECENTRALAND_DIR="$PROJECT_DIR/decentraland"; +DECENTRALAND_DIR="$PROJECT_DIR/3rd-parties/decentraland"; REPOS="mana land marketplace-contracts" for repo in $REPOS; diff --git a/packages/tasit-contracts/decentraland/scripts/install.sh b/packages/tasit-contracts/3rd-parties/decentraland/scripts/install.sh similarity index 94% rename from packages/tasit-contracts/decentraland/scripts/install.sh rename to packages/tasit-contracts/3rd-parties/decentraland/scripts/install.sh index 85cb0b3e..bed69eec 100755 --- a/packages/tasit-contracts/decentraland/scripts/install.sh +++ b/packages/tasit-contracts/3rd-parties/decentraland/scripts/install.sh @@ -7,7 +7,7 @@ then exit; fi -DECENTRALAND_DIR="$PROJECT_DIR/decentraland"; +DECENTRALAND_DIR="$PROJECT_DIR/3rd-parties/decentraland"; # Use list of repository_name:commit_hash:is_npm REPOS="\ diff --git a/packages/tasit-contracts/decentraland/scripts/migrate.sh b/packages/tasit-contracts/3rd-parties/decentraland/scripts/migrate.sh similarity index 93% rename from packages/tasit-contracts/decentraland/scripts/migrate.sh rename to packages/tasit-contracts/3rd-parties/decentraland/scripts/migrate.sh index 7de42117..ec165924 100755 --- a/packages/tasit-contracts/decentraland/scripts/migrate.sh +++ b/packages/tasit-contracts/3rd-parties/decentraland/scripts/migrate.sh @@ -6,7 +6,7 @@ then exit; fi -DECENTRALAND_DIR="$PROJECT_DIR/decentraland" +DECENTRALAND_DIR="$PROJECT_DIR/3rd-parties/decentraland" # mana cp $DECENTRALAND_DIR/scripts/3_mana_migrations.js $DECENTRALAND_DIR/mana/migrations diff --git a/packages/tasit-contracts/3rd-parties/gnosis/addresses.js b/packages/tasit-contracts/3rd-parties/gnosis/addresses.js new file mode 100644 index 00000000..47a5045b --- /dev/null +++ b/packages/tasit-contracts/3rd-parties/gnosis/addresses.js @@ -0,0 +1,5 @@ +const local = { + GnosisSafe: "0x9a4a2e7ed3ee6d481624f5392d8c6169c62065b7", +}; + +module.exports = { local }; diff --git a/packages/tasit-contracts/3rd-parties/gnosis/safe-contracts b/packages/tasit-contracts/3rd-parties/gnosis/safe-contracts new file mode 160000 index 00000000..427d6f7e --- /dev/null +++ b/packages/tasit-contracts/3rd-parties/gnosis/safe-contracts @@ -0,0 +1 @@ +Subproject commit 427d6f7e779431333c54bcb4d4cde31e4d57ce96 diff --git a/packages/tasit-contracts/3rd-parties/gnosis/scripts/2_deploy_contracts.js b/packages/tasit-contracts/3rd-parties/gnosis/scripts/2_deploy_contracts.js new file mode 100644 index 00000000..4b7689af --- /dev/null +++ b/packages/tasit-contracts/3rd-parties/gnosis/scripts/2_deploy_contracts.js @@ -0,0 +1,21 @@ +var ProxyFactory = artifacts.require("./ProxyFactory.sol"); +var GnosisSafe = artifacts.require("./GnosisSafe.sol"); +var StateChannelModule = artifacts.require("./StateChannelModule.sol"); +var DailyLimitModule = artifacts.require("./DailyLimitModule.sol"); +var SocialRecoveryModule = artifacts.require("./SocialRecoveryModule.sol"); +var WhitelistModule = artifacts.require("./WhitelistModule.sol"); +var CreateAndAddModules = artifacts.require("./CreateAndAddModules.sol"); +var MultiSend = artifacts.require("./MultiSend.sol"); + +// accounts[9] +const johnAddress = "0x8226bcef50b3c76a9eb7eba0c09ebbb2362e5db7"; + +// Note: If you want to change this file, make sure that you are editing +// the original file inside of the `tasit-contracts/3rd-parties/gnosis/scripts` +module.exports = function(deployer) { + deployer.deploy(ProxyFactory); + deployer.deploy(GnosisSafe).then(function(safe) { + safe.setup([johnAddress], 1, 0, 0); + return safe; + }); +}; diff --git a/packages/tasit-contracts/3rd-parties/gnosis/scripts/clean.sh b/packages/tasit-contracts/3rd-parties/gnosis/scripts/clean.sh new file mode 100755 index 00000000..b9246db4 --- /dev/null +++ b/packages/tasit-contracts/3rd-parties/gnosis/scripts/clean.sh @@ -0,0 +1,18 @@ +#!/bin/bash +PROJECT_DIR=$1; + +if [ -z "$PROJECT_DIR" ]; +then + echo "Error! Use: ./$0 "; + exit; +fi + + +GNOSIS_DIR="$PROJECT_DIR/3rd-parties/gnosis"; +REPOS="safe-contracts" + +for repo in $REPOS; +do + REPO_DIR="$GNOSIS_DIR/$repo"; + cd $REPO_DIR && git reset --hard && git clean -f +done diff --git a/packages/tasit-contracts/3rd-parties/gnosis/scripts/install.sh b/packages/tasit-contracts/3rd-parties/gnosis/scripts/install.sh new file mode 100755 index 00000000..1a4a1af4 --- /dev/null +++ b/packages/tasit-contracts/3rd-parties/gnosis/scripts/install.sh @@ -0,0 +1,35 @@ +#!/bin/bash +PROJECT_DIR=$1; + +if [ -z "$PROJECT_DIR" ]; +then + echo "Error! Use: ./$0 "; + exit; +fi + +GNOSIS_DIR="$PROJECT_DIR/3rd-parties/gnosis"; + +# Use list of repository_name:commit_hash:is_npm +REPOS="safe-contracts:427d6f7e779431333c54bcb4d4cde31e4d57ce96:true"; + +for clone in $REPOS; +do + REPO=`echo $clone | awk -F ':' '{print $1}'`; + COMMIT=`echo $clone | awk -F ':' '{print $2}'`; + IS_NPM=`echo $clone | awk -F ':' '{print $3}'`; + + REPO_DIR="$GNOSIS_DIR/$REPO"; + + if [ ! -e "$REPO_DIR/package.json" ]; + then + rm -rf $REPO_DIR; + git clone https://github.com/gnosis/$REPO.git $REPO_DIR; + cd $REPO_DIR && git fetch origin $COMMIT && git reset --hard FETCH_HEAD; + fi + + if [ $IS_NPM ]; + then + npm i --prefix $REPO_DIR; + fi + +done diff --git a/packages/tasit-contracts/3rd-parties/gnosis/scripts/migrate.sh b/packages/tasit-contracts/3rd-parties/gnosis/scripts/migrate.sh new file mode 100755 index 00000000..34caaa10 --- /dev/null +++ b/packages/tasit-contracts/3rd-parties/gnosis/scripts/migrate.sh @@ -0,0 +1,13 @@ +#!/bin/bash +PROJECT_DIR=$1 +if [ -z "$PROJECT_DIR" ]; +then + echo "Error! Use: ./$0 "; + exit; +fi + +GNOSIS_DIR="$PROJECT_DIR/3rd-parties/gnosis" + +# safe-contracts +cp $GNOSIS_DIR/scripts/2_deploy_contracts.js $GNOSIS_DIR/safe-contracts/migrations +cd $GNOSIS_DIR/safe-contracts && npx truffle migrate diff --git a/packages/tasit-contracts/3rd-parties/run_on_all.sh b/packages/tasit-contracts/3rd-parties/run_on_all.sh new file mode 100755 index 00000000..be356ded --- /dev/null +++ b/packages/tasit-contracts/3rd-parties/run_on_all.sh @@ -0,0 +1,21 @@ +#!/bin/bash +SCRIPT_NAME=$1; +PROJECT_DIR=$2; + +if [ -z "$PROJECT_DIR" ]; +then + echo "Error! Use: ./$0 "; + exit; +fi + +THIRD_PARTIES="decentraland gnosis"; + +for party in $THIRD_PARTIES; +do + SCRIPT="$PROJECT_DIR/3rd-parties/$party/scripts/$SCRIPT_NAME.sh" + if [ ! -e $SCRIPT ]; then + echo "WARN: Script $SCRIPT doesn't exist."; + else + bash $SCRIPT $PROJECT_DIR; + fi +done diff --git a/packages/tasit-contracts/abi/GnosisSafe.json b/packages/tasit-contracts/abi/GnosisSafe.json new file mode 100644 index 00000000..d42c2f96 --- /dev/null +++ b/packages/tasit-contracts/abi/GnosisSafe.json @@ -0,0 +1,765 @@ +[ + { + "constant": false, + "inputs": [ + { + "name": "owner", + "type": "address" + }, + { + "name": "_threshold", + "type": "uint256" + } + ], + "name": "addOwnerWithThreshold", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "DOMAIN_SEPARATOR_TYPEHASH", + "outputs": [ + { + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "isOwner", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "to", + "type": "address" + }, + { + "name": "value", + "type": "uint256" + }, + { + "name": "data", + "type": "bytes" + }, + { + "name": "operation", + "type": "uint8" + } + ], + "name": "execTransactionFromModule", + "outputs": [ + { + "name": "success", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "bytes32" + } + ], + "name": "signedMessages", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "module", + "type": "address" + } + ], + "name": "enableModule", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_threshold", + "type": "uint256" + } + ], + "name": "changeThreshold", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + }, + { + "name": "", + "type": "bytes32" + } + ], + "name": "approvedHashes", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_masterCopy", + "type": "address" + } + ], + "name": "changeMasterCopy", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "SENTINEL_MODULES", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "SENTINEL_OWNERS", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getOwners", + "outputs": [ + { + "name": "", + "type": "address[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "NAME", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "nonce", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getModules", + "outputs": [ + { + "name": "", + "type": "address[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "SAFE_MSG_TYPEHASH", + "outputs": [ + { + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "SAFE_TX_TYPEHASH", + "outputs": [ + { + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "prevModule", + "type": "address" + }, + { + "name": "module", + "type": "address" + } + ], + "name": "disableModule", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "prevOwner", + "type": "address" + }, + { + "name": "oldOwner", + "type": "address" + }, + { + "name": "newOwner", + "type": "address" + } + ], + "name": "swapOwner", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getThreshold", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "domainSeparator", + "outputs": [ + { + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "prevOwner", + "type": "address" + }, + { + "name": "owner", + "type": "address" + }, + { + "name": "_threshold", + "type": "uint256" + } + ], + "name": "removeOwner", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "VERSION", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "txHash", + "type": "bytes32" + } + ], + "name": "ExecutionFailed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "owner", + "type": "address" + } + ], + "name": "AddedOwner", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "owner", + "type": "address" + } + ], + "name": "RemovedOwner", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "threshold", + "type": "uint256" + } + ], + "name": "ChangedThreshold", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "module", + "type": "address" + } + ], + "name": "EnabledModule", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "module", + "type": "address" + } + ], + "name": "DisabledModule", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "newContract", + "type": "address" + } + ], + "name": "ContractCreation", + "type": "event" + }, + { + "constant": false, + "inputs": [ + { + "name": "_owners", + "type": "address[]" + }, + { + "name": "_threshold", + "type": "uint256" + }, + { + "name": "to", + "type": "address" + }, + { + "name": "data", + "type": "bytes" + } + ], + "name": "setup", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "to", + "type": "address" + }, + { + "name": "value", + "type": "uint256" + }, + { + "name": "data", + "type": "bytes" + }, + { + "name": "operation", + "type": "uint8" + }, + { + "name": "safeTxGas", + "type": "uint256" + }, + { + "name": "dataGas", + "type": "uint256" + }, + { + "name": "gasPrice", + "type": "uint256" + }, + { + "name": "gasToken", + "type": "address" + }, + { + "name": "refundReceiver", + "type": "address" + }, + { + "name": "signatures", + "type": "bytes" + } + ], + "name": "execTransaction", + "outputs": [ + { + "name": "success", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "to", + "type": "address" + }, + { + "name": "value", + "type": "uint256" + }, + { + "name": "data", + "type": "bytes" + }, + { + "name": "operation", + "type": "uint8" + } + ], + "name": "requiredTxGas", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "hashToApprove", + "type": "bytes32" + } + ], + "name": "approveHash", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_data", + "type": "bytes" + } + ], + "name": "signMessage", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_data", + "type": "bytes" + }, + { + "name": "_signature", + "type": "bytes" + } + ], + "name": "isValidSignature", + "outputs": [ + { + "name": "isValid", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "message", + "type": "bytes" + } + ], + "name": "getMessageHash", + "outputs": [ + { + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "to", + "type": "address" + }, + { + "name": "value", + "type": "uint256" + }, + { + "name": "data", + "type": "bytes" + }, + { + "name": "operation", + "type": "uint8" + }, + { + "name": "safeTxGas", + "type": "uint256" + }, + { + "name": "dataGas", + "type": "uint256" + }, + { + "name": "gasPrice", + "type": "uint256" + }, + { + "name": "gasToken", + "type": "address" + }, + { + "name": "refundReceiver", + "type": "address" + }, + { + "name": "_nonce", + "type": "uint256" + } + ], + "name": "encodeTransactionData", + "outputs": [ + { + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "to", + "type": "address" + }, + { + "name": "value", + "type": "uint256" + }, + { + "name": "data", + "type": "bytes" + }, + { + "name": "operation", + "type": "uint8" + }, + { + "name": "safeTxGas", + "type": "uint256" + }, + { + "name": "dataGas", + "type": "uint256" + }, + { + "name": "gasPrice", + "type": "uint256" + }, + { + "name": "gasToken", + "type": "address" + }, + { + "name": "refundReceiver", + "type": "address" + }, + { + "name": "_nonce", + "type": "uint256" + } + ], + "name": "getTransactionHash", + "outputs": [ + { + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/tasit-contracts/abi/MyERC20Full.json b/packages/tasit-contracts/abi/MyERC20Full.json new file mode 100644 index 00000000..50035b5f --- /dev/null +++ b/packages/tasit-contracts/abi/MyERC20Full.json @@ -0,0 +1,378 @@ +[ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "spender", + "type": "address" + }, + { + "name": "value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": false, + "inputs": [ + { + "name": "from", + "type": "address" + }, + { + "name": "to", + "type": "address" + }, + { + "name": "value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "spender", + "type": "address" + }, + { + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x39509351" + }, + { + "constant": false, + "inputs": [ + { + "name": "to", + "type": "address" + }, + { + "name": "value", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x40c10f19" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": false, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "addMinter", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x983b2d56" + }, + { + "constant": false, + "inputs": [], + "name": "renounceMinter", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x98650275" + }, + { + "constant": false, + "inputs": [ + { + "name": "spender", + "type": "address" + }, + { + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa457c2d7" + }, + { + "constant": false, + "inputs": [ + { + "name": "to", + "type": "address" + }, + { + "name": "value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "isMinter", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xaa271e1a" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + }, + { + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "account", + "type": "address" + } + ], + "name": "MinterAdded", + "type": "event", + "signature": "0x6ae172837ea30b801fbfcdd4108aa1d5bf8ff775444fd70256b44e6bf3dfc3f6" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "account", + "type": "address" + } + ], + "name": "MinterRemoved", + "type": "event", + "signature": "0xe94479a9f7e1952cc78f2d6baab678adc1b772d936c6583def489e524cb66692" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + } + ] diff --git a/packages/tasit-contracts/abi/ERC721Full.json b/packages/tasit-contracts/abi/MyERC721Full.json similarity index 100% rename from packages/tasit-contracts/abi/ERC721Full.json rename to packages/tasit-contracts/abi/MyERC721Full.json diff --git a/packages/tasit-contracts/contracts/MyERC20Full.sol b/packages/tasit-contracts/contracts/MyERC20Full.sol new file mode 100644 index 00000000..69384fad --- /dev/null +++ b/packages/tasit-contracts/contracts/MyERC20Full.sol @@ -0,0 +1,11 @@ +pragma solidity ^0.5.0; + +import "openzeppelin-solidity/contracts/token/ERC20/ERC20Detailed.sol"; +import "openzeppelin-solidity/contracts/token/ERC20/ERC20Mintable.sol"; +import "openzeppelin-solidity/contracts/token/ERC20/ERC20Burnable.sol"; + +contract MyERC20Full is ERC20Detailed, ERC20Mintable, ERC20Burnable { + constructor() public ERC20Detailed("ERC20Full", "ERC20", 18) { + + } +} diff --git a/packages/tasit-contracts/contracts/FullNFT.sol b/packages/tasit-contracts/contracts/MyERC721Full.sol similarity index 60% rename from packages/tasit-contracts/contracts/FullNFT.sol rename to packages/tasit-contracts/contracts/MyERC721Full.sol index d7abe14c..3ddb0d9c 100644 --- a/packages/tasit-contracts/contracts/FullNFT.sol +++ b/packages/tasit-contracts/contracts/MyERC721Full.sol @@ -3,8 +3,8 @@ pragma solidity ^0.5.0; import "openzeppelin-solidity/contracts/token/ERC721/ERC721Full.sol"; import "openzeppelin-solidity/contracts/token/ERC721/ERC721Mintable.sol"; -contract FullNFT is ERC721Full, ERC721Mintable { - constructor() public ERC721Full("Full NFT", "FNFT") { +contract MyERC721Full is ERC721Full, ERC721Mintable { + constructor() public ERC721Full("ERC721Full", "ERC721") { } } diff --git a/packages/tasit-contracts/decentraland/addresses.js b/packages/tasit-contracts/decentraland/addresses.js deleted file mode 100644 index 9e4458f8..00000000 --- a/packages/tasit-contracts/decentraland/addresses.js +++ /dev/null @@ -1,13 +0,0 @@ -const decentralandAddresses = require("./contracts/addresses.json"); - -const { ropsten } = decentralandAddresses; - -const local = { - MANAToken: "0xb32939da0c44bf255b9810421a55be095f9bb3f4", - LANDRegistry: "0x6191bc768c2339da9eab9e589fc8bf0b3ab80975", - LANDProxy: "0x773f11ed472aa43e4ebaa963bcfbbea5a10c1bbd", - EstateRegistry: "0x41b598a2c618b59b74540ac3afffb32f7971b37a", - Marketplace: "0x07c0e972064e5c05f7b3596d81de1afd35457eae", -}; - -module.exports = { ropsten, local }; diff --git a/packages/tasit-contracts/decentraland/scripts/3_mana_migrations.js b/packages/tasit-contracts/decentraland/scripts/3_mana_migrations.js deleted file mode 100644 index 821ab21d..00000000 --- a/packages/tasit-contracts/decentraland/scripts/3_mana_migrations.js +++ /dev/null @@ -1,5 +0,0 @@ -const MANAToken = artifacts.require("./MANAToken.sol"); - -module.exports = function(deployer) { - deployer.deploy(MANAToken); -}; diff --git a/packages/tasit-contracts/decentraland/scripts/3_marketplace-contracts_migrations.js b/packages/tasit-contracts/decentraland/scripts/3_marketplace-contracts_migrations.js deleted file mode 100644 index 5b30df52..00000000 --- a/packages/tasit-contracts/decentraland/scripts/3_marketplace-contracts_migrations.js +++ /dev/null @@ -1,5 +0,0 @@ -const Marketplace = artifacts.require("./Marketplace.sol"); - -module.exports = function(deployer) { - deployer.deploy(Marketplace); -}; diff --git a/packages/tasit-contracts/migrations/2_deploy_contracts.js b/packages/tasit-contracts/migrations/2_deploy_contracts.js index cb829259..bb096868 100644 --- a/packages/tasit-contracts/migrations/2_deploy_contracts.js +++ b/packages/tasit-contracts/migrations/2_deploy_contracts.js @@ -1,7 +1,9 @@ var SampleContract = artifacts.require("./SampleContract.sol"); -var FullNFT = artifacts.require("./FullNFT.sol"); +var MyERC721Full = artifacts.require("./MyERC721Full.sol"); +var MyERC20Full = artifacts.require("./MyERC20Full.sol"); module.exports = function(deployer) { deployer.deploy(SampleContract, "Hello World!"); - deployer.deploy(FullNFT); + deployer.deploy(MyERC721Full); + deployer.deploy(MyERC20Full); }; diff --git a/packages/tasit-contracts/package.json b/packages/tasit-contracts/package.json index 19d6857f..8e214753 100644 --- a/packages/tasit-contracts/package.json +++ b/packages/tasit-contracts/package.json @@ -17,13 +17,12 @@ "url": "git+https://github.com/tasitlabs/tasitsdk.git" }, "scripts": { - "prepare": "npm run install:decentraland", - "migrate": "npx truffle migrate && npm run migrate:decentraland", - "install:decentraland": "./decentraland/scripts/install.sh `pwd`", - "migrate:decentraland": "./decentraland/scripts/migrate.sh `pwd`", - "clean:decentraland": "./decentraland/scripts/clean.sh `pwd`", - "clean:3rd-parties": "npm run clean:decentraland", - "test": "npx truffle test" + "prepare": "npm run install:3rd-parties", + "migrate": "rm -rf ./build && npx truffle migrate && npm run migrate:3rd-parties", + "test": "npx truffle test", + "install:3rd-parties": "./3rd-parties/run_on_all.sh install `pwd`", + "migrate:3rd-parties": "./3rd-parties/run_on_all.sh migrate `pwd`", + "clean:3rd-parties": "./3rd-parties/run_on_all.sh clean `pwd`" }, "bugs": { "url": "https://github.com/tasitlabs/tasitsdk/issues" diff --git a/packages/tasit-contracts/test/EstateRegistry.js b/packages/tasit-contracts/test/EstateRegistry.js index fb3bdc7d..7839a74d 100644 --- a/packages/tasit-contracts/test/EstateRegistry.js +++ b/packages/tasit-contracts/test/EstateRegistry.js @@ -1,6 +1,6 @@ -const abi = require("../decentraland/land/build/contracts/EstateRegistry.json") +const abi = require("../3rd-parties/decentraland/land/build/contracts/EstateRegistry.json") .abi; -const localAddresses = require("../decentraland/addresses").local; +const localAddresses = require("../3rd-parties/decentraland/addresses").local; const { LANDRegistry: landAddress, EstateRegistry: address } = localAddresses; // Note: diff --git a/packages/tasit-contracts/test/GnosisSafe.js b/packages/tasit-contracts/test/GnosisSafe.js new file mode 100644 index 00000000..8fc33eb3 --- /dev/null +++ b/packages/tasit-contracts/test/GnosisSafe.js @@ -0,0 +1,26 @@ +const abi = require("../3rd-parties/gnosis/safe-contracts/build/contracts/GnosisSafe.json") + .abi; +const localAddresses = require("../3rd-parties/gnosis/addresses").local; +const { GnosisSafe: contractAddress } = localAddresses; + +// Note: +// This test suite is using web3.js because contract deployment is made by a 3rd-party repository +// (and most existing 3rd-party contracts tend to use Truffle which uses web3.js) +contract("GnosisSafe", function(accounts) { + const GnosisSafe = new web3.eth.Contract(abi, contractAddress); + const jonh = accounts[9]; + + it("should get the GnosisSafe name", async function() { + const name = await GnosisSafe.methods.NAME().call(); + assert.equal( + name, + "Gnosis Safe", + "'Gnosis Safe' isn't the GnosisSafe name." + ); + }); + + it("should get the GnosisSafe owner", async function() { + const [owner] = await GnosisSafe.methods.getOwners().call(); + assert.equal(owner, jonh, "John isn't the GnosisSafe owner."); + }); +}); diff --git a/packages/tasit-contracts/test/LANDProxy.js b/packages/tasit-contracts/test/LANDProxy.js index 689ddcf4..4c3f54e8 100644 --- a/packages/tasit-contracts/test/LANDProxy.js +++ b/packages/tasit-contracts/test/LANDProxy.js @@ -1,5 +1,6 @@ -const abi = require("../decentraland/land/build/contracts/LANDProxy.json").abi; -const localAddresses = require("../decentraland/addresses").local; +const abi = require("../3rd-parties/decentraland/land/build/contracts/LANDProxy.json") + .abi; +const localAddresses = require("../3rd-parties/decentraland/addresses").local; const { LANDProxy: address } = localAddresses; // Note: diff --git a/packages/tasit-contracts/test/LANDRegistry.js b/packages/tasit-contracts/test/LANDRegistry.js index 6c46c362..315a91e2 100644 --- a/packages/tasit-contracts/test/LANDRegistry.js +++ b/packages/tasit-contracts/test/LANDRegistry.js @@ -1,6 +1,6 @@ -const abi = require("../decentraland/land/build/contracts/LANDRegistry.json") +const abi = require("../3rd-parties/decentraland/land/build/contracts/LANDRegistry.json") .abi; -const localAddresses = require("../decentraland/addresses").local; +const localAddresses = require("../3rd-parties/decentraland/addresses").local; const { LANDRegistry: address } = localAddresses; // Note: diff --git a/packages/tasit-contracts/test/MANAToken.js b/packages/tasit-contracts/test/MANAToken.js index 93830fe1..e6d39527 100644 --- a/packages/tasit-contracts/test/MANAToken.js +++ b/packages/tasit-contracts/test/MANAToken.js @@ -1,5 +1,6 @@ -const abi = require("../decentraland/mana/build/contracts/MANAToken.json").abi; -const localAddresses = require("../decentraland/addresses").local; +const abi = require("../3rd-parties/decentraland/mana/build/contracts/MANAToken.json") + .abi; +const localAddresses = require("../3rd-parties/decentraland/addresses").local; const { MANAToken: address } = localAddresses; // Note: diff --git a/packages/tasit-contracts/test/Marketplace.js b/packages/tasit-contracts/test/Marketplace.js index 151c6eb4..d0415fb0 100644 --- a/packages/tasit-contracts/test/Marketplace.js +++ b/packages/tasit-contracts/test/Marketplace.js @@ -1,6 +1,6 @@ -const abi = require("../decentraland/marketplace-contracts/build/contracts/Marketplace.json") +const abi = require("../3rd-parties/decentraland/marketplace-contracts/build/contracts/Marketplace.json") .abi; -const localAddresses = require("../decentraland/addresses").local; +const localAddresses = require("../3rd-parties/decentraland/addresses").local; const { Marketplace: address } = localAddresses; // Note: diff --git a/packages/tasit-contracts/test/FullNFT.js b/packages/tasit-contracts/test/MyERC20Full.js similarity index 51% rename from packages/tasit-contracts/test/FullNFT.js rename to packages/tasit-contracts/test/MyERC20Full.js index 98eebcfc..195f4e81 100644 --- a/packages/tasit-contracts/test/FullNFT.js +++ b/packages/tasit-contracts/test/MyERC20Full.js @@ -1,4 +1,4 @@ -const FullNFT = artifacts.require("./FullNFT.sol"); +const MyERC20Full = artifacts.require("./MyERC20Full.sol"); // Note: It will probably be a point of confusion for new developers // coming to this project that they'll have to get used to the web3.js // API for writing truffle tests but then use the ethers.js API and our @@ -7,20 +7,16 @@ const FullNFT = artifacts.require("./FullNFT.sol"); // in tasit-contracts testing the same contract. // For that reason, a possible TODO is removing any truffle tests // other than those we directly add from 3rd-party projects -contract("FullNFT", function(accounts) { - it("should get the NFT name", async function() { - const fullNFT = await FullNFT.deployed(); +contract("MyERC20Full", async accounts => { + const erc20 = await MyERC20Full.deployed(); - const name = await fullNFT.name(); - - assert.equal(name, "Full NFT", "Full NFT isn't the NFT name."); + it("should get the contract name", async () => { + const name = await erc20.name(); + assert.equal(name, "ERC20Full", "ERC20Full isn't the contract name."); }); - it("should get the NFT symbol", async function() { - const fullNFT = await FullNFT.deployed(); - - const symbol = await fullNFT.symbol(); - - assert.equal(symbol, "FNFT", "FNFT isn't the NFT symbol."); + it("should get the ERC20 symbol", async () => { + const symbol = await erc20.symbol(); + assert.equal(symbol, "ERC20", "ERC20 isn't the contract symbol."); }); }); diff --git a/packages/tasit-contracts/test/MyERC721Full.js b/packages/tasit-contracts/test/MyERC721Full.js new file mode 100644 index 00000000..e425623f --- /dev/null +++ b/packages/tasit-contracts/test/MyERC721Full.js @@ -0,0 +1,22 @@ +const MyERC721Full = artifacts.require("./MyERC721Full.sol"); +// Note: It will probably be a point of confusion for new developers +// coming to this project that they'll have to get used to the web3.js +// API for writing truffle tests but then use the ethers.js API and our +// own API also in JavaScript for testing our own code. So the +// ethers.js tests in tasit-action will look different than the truffle tests +// in tasit-contracts testing the same contract. +// For that reason, a possible TODO is removing any truffle tests +// other than those we directly add from 3rd-party projects +contract("MyERC721Full", async accounts => { + const erc721 = await MyERC721Full.deployed(); + + it("should get the contract name", async () => { + const name = await erc721.name(); + assert.equal(name, "ERC721Full", "ERC721Full isn't the contract name."); + }); + + it("should get the contract symbol", async () => { + const symbol = await erc721.symbol(); + assert.equal(symbol, "ERC721", "ERC721 isn't the contract symbol."); + }); +}); diff --git a/packages/tasit-identity-contract/.babelrc b/packages/tasit-identity-contract/.babelrc new file mode 100644 index 00000000..99cde555 --- /dev/null +++ b/packages/tasit-identity-contract/.babelrc @@ -0,0 +1,13 @@ +{ + "presets": [ + [ + "@babel/preset-env", + { + "targets": { + "node": "10.13.0" + } + } + ] + ], + "plugins": ["@babel/plugin-proposal-class-properties"] +} diff --git a/packages/tasit-identity-contract/.gitignore b/packages/tasit-identity-contract/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/packages/tasit-identity-contract/.npmignore b/packages/tasit-identity-contract/.npmignore new file mode 100644 index 00000000..eb0d9e59 --- /dev/null +++ b/packages/tasit-identity-contract/.npmignore @@ -0,0 +1 @@ +./src/ diff --git a/packages/tasit-identity-contract/package-lock.json b/packages/tasit-identity-contract/package-lock.json new file mode 100644 index 00000000..b40a2483 --- /dev/null +++ b/packages/tasit-identity-contract/package-lock.json @@ -0,0 +1,394 @@ +{ + "name": "tasit-identity-contract", + "version": "0.0.9", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/code-frame": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/generator": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.3.3.tgz", + "integrity": "sha512-aEADYwRRZjJyMnKN7llGIlircxTCofm3dtV5pmY6ob18MSIuipHpA2yZWkPlycwu5HJcx/pADS3zssd8eY7/6A==", + "dev": true, + "requires": { + "@babel/types": "^7.3.3", + "jsesc": "^2.5.1", + "lodash": "^4.17.11", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" + } + }, + "@babel/helper-create-class-features-plugin": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.3.2.tgz", + "integrity": "sha512-tdW8+V8ceh2US4GsYdNVNoohq5uVwOf9k6krjwW4E1lINcHgttnWcNqgdoessn12dAy8QkbezlbQh2nXISNY+A==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-member-expression-to-functions": "^7.0.0", + "@babel/helper-optimise-call-expression": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-replace-supers": "^7.2.3" + } + }, + "@babel/helper-function-name": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", + "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", + "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.0.0.tgz", + "integrity": "sha512-avo+lm/QmZlv27Zsi0xEor2fKcqWG56D5ae9dzklpIaY7cQMK5N8VSpaNVPPagiqmy7LrEjK1IWdGMOqPu5csg==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.0.0.tgz", + "integrity": "sha512-u8nd9NQePYNQV8iPWu/pLLYBqZBa4ZaY1YWRFMuxrid94wKI1QNt67NEZ7GAe5Kc/0LLScbim05xZFWkAdrj9g==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz", + "integrity": "sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==", + "dev": true + }, + "@babel/helper-replace-supers": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.2.3.tgz", + "integrity": "sha512-GyieIznGUfPXPWu0yLS6U55Mz67AZD9cUk0BfirOWlPrXlBcan9Gz+vHGz+cPfuoweZSnPzPIm67VtQM0OWZbA==", + "dev": true, + "requires": { + "@babel/helper-member-expression-to-functions": "^7.0.0", + "@babel/helper-optimise-call-expression": "^7.0.0", + "@babel/traverse": "^7.2.3", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0.tgz", + "integrity": "sha512-MXkOJqva62dfC0w85mEf/LucPPS/1+04nmmRMPEBUB++hiiThQ2zPtX/mEWQ3mtzCEjIJvPY8nuwxXtQeQwUag==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.3.3.tgz", + "integrity": "sha512-xsH1CJoln2r74hR+y7cg2B5JCPaTh+Hd+EbBRk9nWGSNspuo6krjhX0Om6RnRQuIvFq8wVXCLKH3kwKDYhanSg==", + "dev": true + }, + "@babel/plugin-proposal-class-properties": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.2.3.tgz", + "integrity": "sha512-FVuQngLoN2iDrpW7LmhPZ2sO4DJxf35FOcwidwB9Ru9tMvI5URthnkVHuG14IStV+TzkMTyLMoOUlSTtrdVwqw==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.2.3", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/template": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.2.2.tgz", + "integrity": "sha512-zRL0IMM02AUDwghf5LMSSDEz7sBCO2YnNmpg3uWTZj/v1rcG2BmQUvaGU8GhU8BvfMh1k2KIAYZ7Ji9KXPUg7g==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.2.2", + "@babel/types": "^7.2.2" + } + }, + "@babel/traverse": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.2.3.tgz", + "integrity": "sha512-Z31oUD/fJvEWVR0lNZtfgvVt512ForCTNKYcJBGbPb1QZfve4WGH8Wsy7+Mev33/45fhP/hwQtvgusNdcCMgSw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.2.2", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.0.0", + "@babel/parser": "^7.2.3", + "@babel/types": "^7.2.2", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.10" + } + }, + "@babel/types": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.3.3.tgz", + "integrity": "sha512-2tACZ80Wg09UnPg5uGAOUvvInaqLk3l/IAhQzlxLQOIXacr6bMsra5SH6AWw/hIDRCSbCdHP2KzSOD+cT7TzMQ==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.11", + "to-fast-properties": "^2.0.0" + } + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "globals": { + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.11.0.tgz", + "integrity": "sha512-WHq43gS+6ufNOEqlrDBxVEbb8ntfXrfAUU2ZOpCxrBdGKW3gyv8mCxAfIBD0DroPKGrJ2eSsXsLtY9MPntsyTw==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "dev": true + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "tasit-action": { + "version": "0.0.9", + "requires": { + "@babel/runtime": "^7.1.5", + "ethers": "^4.0.21" + }, + "dependencies": { + "@babel/runtime": { + "version": "7.3.1", + "bundled": true, + "requires": { + "regenerator-runtime": "^0.12.0" + } + }, + "@types/node": { + "version": "10.12.26", + "bundled": true + }, + "aes-js": { + "version": "3.0.0", + "bundled": true + }, + "bn.js": { + "version": "4.11.8", + "bundled": true + }, + "brorand": { + "version": "1.1.0", + "bundled": true + }, + "elliptic": { + "version": "6.3.3", + "bundled": true, + "requires": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "inherits": "^2.0.1" + } + }, + "ethers": { + "version": "4.0.25", + "bundled": true, + "requires": { + "@types/node": "^10.3.2", + "aes-js": "3.0.0", + "bn.js": "^4.4.0", + "elliptic": "6.3.3", + "hash.js": "1.1.3", + "js-sha3": "0.5.7", + "scrypt-js": "2.0.4", + "setimmediate": "1.0.4", + "uuid": "2.0.1", + "xmlhttprequest": "1.8.0" + } + }, + "hash.js": { + "version": "1.1.3", + "bundled": true, + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.0" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true + }, + "js-sha3": { + "version": "0.5.7", + "bundled": true + }, + "minimalistic-assert": { + "version": "1.0.1", + "bundled": true + }, + "regenerator-runtime": { + "version": "0.12.1", + "bundled": true + }, + "scrypt-js": { + "version": "2.0.4", + "bundled": true + }, + "setimmediate": { + "version": "1.0.4", + "bundled": true + }, + "tasit-account": { + "bundled": true + }, + "uuid": { + "version": "2.0.1", + "bundled": true + }, + "xmlhttprequest": { + "version": "1.8.0", + "bundled": true + } + } + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "dev": true + } + } +} diff --git a/packages/tasit-identity-contract/package.json b/packages/tasit-identity-contract/package.json new file mode 100644 index 00000000..6f238bbc --- /dev/null +++ b/packages/tasit-identity-contract/package.json @@ -0,0 +1,41 @@ +{ + "name": "tasit-identity-contract", + "version": "0.0.9", + "description": "Library for onboarding a user using a smart-contract-based identity.", + "main": "dist/index.js", + "keywords": [ + "ethereum", + "dapp", + "react", + "native" + ], + "author": "Tasit Labs", + "homepage": "https://github.com/tasitlabs/TasitSDK#readme", + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/tasitlabs/tasitsdk.git" + }, + "scripts": { + "prepare": "npx babel src --out-dir dist --ignore **/*.test.js", + "test": "npm run lint && npx mocha src/*.test.js --require @babel/register --file src/testHelpers/mochaSetup.js", + "lint": "npx prettier src/* --write" + }, + "bugs": { + "url": "https://github.com/tasitlabs/tasitsdk/issues" + }, + "dependencies": { + "@babel/runtime": "^7.1.5", + "ethers": "^4.0.21", + "tasit-action": "0.0.9" + }, + "devDependencies": { + "@babel/cli": "^7.1.5", + "@babel/core": "^7.1.6", + "@babel/plugin-proposal-class-properties": "^7.2.3", + "@babel/preset-env": "^7.1.6", + "@babel/register": "^7.0.0", + "chai": "^4.2.0", + "mocha": "^6.0.2" + } +} diff --git a/packages/tasit-identity-contract/src/GnosisSafe.js b/packages/tasit-identity-contract/src/GnosisSafe.js new file mode 100644 index 00000000..c83fbb53 --- /dev/null +++ b/packages/tasit-identity-contract/src/GnosisSafe.js @@ -0,0 +1,191 @@ +import Action from "tasit-action"; +const { Contract, ERC20, ERC721 } = Action; +const { ERC20Detailed } = ERC20; +const { ERC721Full } = ERC721; +import GnosisSafeUtils from "./GnosisSafeUtils"; +import ActionUtils from "tasit-action/dist/contract/Utils.js"; + +import gnosisSafeABI from "../../tasit-contracts/abi/GnosisSafe.json"; +import erc20ABI from "../../tasit-contracts/abi/MyERC20Full.json"; +import erc721ABI from "../../tasit-contracts/abi/MyERC721Full.json"; + +// TODO: Go deep on gas handling. +// Without that, VM returns a revert error instead of out of gas error. +// See: https://github.com/tasitlabs/TasitSDK/issues/173 +const gasParams = { + gasLimit: 7e6, + gasPrice: 1e9, +}; + +// Possible Gnosis Safe wallet operations +const operations = { + CALL: 0, + DELEGATE_CALL: 1, + CREATE: 2, +}; + +const { CALL } = operations; + +const areValidSigners = signers => { + const { isEthersJsSigner: isSigner } = ActionUtils; + const { isArray } = Array; + + if (!isArray(signers)) return false; + + const allAreValid = !signers.map(isSigner).includes(false); + + if (!allAreValid) return false; + + return true; +}; + +// Extended Gnosis Safe wallet contract with higher-level functions +export default class GnosisSafe extends Contract { + #utils; + #signers; + + constructor(address, wallet) { + const abi = gnosisSafeABI; + super(address, abi, wallet); + this.#utils = new GnosisSafeUtils(this); + } + + setSigners = signers => { + if (!areValidSigners(signers)) + throw new Error( + `Cannot set invalid signers for the Gnosis Safe contract.` + ); + + this.#signers = signers; + }; + + transferERC20 = async (tokenAddress, toAddress, value) => { + const data = this.#utils.encodeFunctionCall(erc20ABI, "transfer", [ + toAddress, + value, + ]); + const etherValue = "0"; + const action = await this.#executeTransaction( + data, + tokenAddress, + etherValue + ); + return action; + }; + + transferNFT = async (tokenAddress, toAddress, tokenId) => { + const fromAddress = this.getAddress(); + const data = this.#utils.encodeFunctionCall(erc721ABI, "safeTransferFrom", [ + fromAddress, + toAddress, + tokenId, + ]); + const etherValue = "0"; + const action = await this.#executeTransaction( + data, + tokenAddress, + etherValue + ); + return action; + }; + + transferEther = async (toAddress, value) => { + const data = "0x"; + const etherValue = value; + const action = await this.#executeTransaction(data, toAddress, etherValue); + return action; + }; + + addSignerWithThreshold = async (newSignerAddress, newThreshold) => { + const data = this.#utils.encodeFunctionCall( + this.getABI(), + "addOwnerWithThreshold", + [newSignerAddress, newThreshold] + ); + const to = this.getAddress(); + const etherValue = "0"; + const action = await this.#executeTransaction(data, to, etherValue); + return action; + }; + + // Note: Should we move this function to sync to keep same behavior as + // contract's write functions that returns an Action object? + // See more: https://github.com/tasitlabs/TasitSDK/issues/234 + #executeTransaction = async (data, toAddress, etherValue) => { + const signers = this.#signers; + + if (!signers) + throw new Error( + `Cannot send an action to Gnosis Safe contract without signers.` + ); + + const to = toAddress; + + const operation = CALL; + + // Gas that should be used for the Safe transaction. + const safeTxGas = await this.#utils.estimateFromSafeTxGas( + to, + etherValue, + data, + operation + ); + + // Gas price that should be used for the payment calculation. + // Note: If no safeTxGas has been set and the gasPrice is 0 we assume that all available gas can be used (refs GnosisSafe.sol:94) + const gasPrice = 0; + + // Token address (or 0 if ETH) that is used for the payment. + const gasToken = "0x0000000000000000000000000000000000000000"; + + // Address of receiver of gas payment (or 0 if tx.origin) + const refundReceiver = "0x0000000000000000000000000000000000000000"; + + // Gas costs for data used to trigger the safe transaction and to pay for transferring a payment + const { length: signersCount } = signers; + const dataGas = this.#utils.estimateDataGas( + this, + to, + etherValue, + data, + operation, + safeTxGas, + gasToken, + refundReceiver, + signersCount + ); + + const nonce = await this.nonce(); + + const transactionHash = await this.getTransactionHash( + to, + etherValue, + data, + operation, + safeTxGas, + dataGas, + gasPrice, + gasToken, + refundReceiver, + nonce + ); + + const signatures = this.#utils.multiSign(signers, transactionHash); + + const execTxAction = this.execTransaction( + to, + etherValue, + data, + operation, + safeTxGas, + dataGas, + gasPrice, + gasToken, + refundReceiver, + signatures, + gasParams + ); + + return execTxAction; + }; +} diff --git a/packages/tasit-identity-contract/src/GnosisSafe.test.js b/packages/tasit-identity-contract/src/GnosisSafe.test.js new file mode 100644 index 00000000..0f6fa752 --- /dev/null +++ b/packages/tasit-identity-contract/src/GnosisSafe.test.js @@ -0,0 +1,165 @@ +import Action from "tasit-action"; +const { ERC20, ERC721 } = Action; +const { ERC20Full } = ERC20; +const { ERC721Full } = ERC721; +import GnosisSafe from "./GnosisSafe"; +import { local as localAddresses } from "../../tasit-contracts/3rd-parties/gnosis/addresses"; + +import Account from "../../tasit-account/dist/index"; + +const { GnosisSafe: GNOSIS_SAFE_ADDRESS } = localAddresses; +const ERC20_ADDRESS = "0x37E1A58dD465D33263D00185D065Ee36DD34CDb4"; +const NFT_ADDRESS = "0x0E86f209729bf54763789CDBcA9E8b94f0FD5333"; + +// 100 gwei +const GAS_PRICE = bigNumberify(`${1e11}`); + +const { ZERO, ONE } = constants; + +describe("GnosisSafe", () => { + let gnosisSafe; + let root; + let johnWallet; + let ephemeralWallet; + let erc20; + let nft; + + before("", async () => { + // That account is funded with ethers and is owner of all token contracts deployed + [root] = accounts; + johnWallet = accounts[9]; + + ephemeralWallet = Account.create(); + + const signers = [johnWallet]; + + // Contract deployment setup with john (accounts[9]) as the only owner + // To change that, edit the file "tasit-contract/3rd-parties/gnosis/scripts/2_deploy_contracts.js" + gnosisSafe = new GnosisSafe(GNOSIS_SAFE_ADDRESS); + gnosisSafe.setSigners(signers); + + erc20 = new ERC20Full(ERC20_ADDRESS); + + nft = new ERC721Full(NFT_ADDRESS); + }); + + beforeEach("", async () => { + const etherBalance = await provider.getBalance(GNOSIS_SAFE_ADDRESS); + expect(`${etherBalance}`).to.equal(`${ZERO}`); + + const erc20Balance = await erc20.balanceOf(GNOSIS_SAFE_ADDRESS); + expect(`${erc20Balance}`).to.equal(`${ZERO}`); + + gnosisSafe.removeWallet(); + erc20.removeWallet(); + }); + + afterEach("", async () => { + expect(erc20.subscribedEventNames()).to.be.empty; + expect(gnosisSafe.subscribedEventNames()).to.be.empty; + expect(provider._events).to.be.empty; + }); + + describe("test cases that needs ETH deposit to the wallet", async () => { + beforeEach("faucet", async () => { + await etherFaucet(provider, root, GNOSIS_SAFE_ADDRESS, ONE); + const balance = await provider.getBalance(GNOSIS_SAFE_ADDRESS); + expect(`${balance}`).to.equal(`${ONE}`); + }); + + it("contract account should send ethers back to owner", async () => { + const { address: toAddress } = johnWallet; + const value = ONE; + + gnosisSafe.setWallet(johnWallet); + const execTxAction = await gnosisSafe.transferEther(toAddress, value); + await execTxAction.waitForNonceToUpdate(); + + const balance = await provider.getBalance(GNOSIS_SAFE_ADDRESS); + expect(`${balance}`).to.equal(`${ZERO}`); + }); + }); + + describe("test cases that needs ERC20 deposit to the wallet", async () => { + beforeEach("faucet", async () => { + await erc20Faucet(erc20, root, GNOSIS_SAFE_ADDRESS, ONE); + const balance = await erc20.balanceOf(GNOSIS_SAFE_ADDRESS); + expect(`${balance}`).to.equal(`${ONE}`); + }); + + it("contract account should send ERC20 tokens back to owner", async () => { + const tokenAddress = ERC20_ADDRESS; + const { address: toAddress } = johnWallet; + const value = ONE; + + gnosisSafe.setWallet(johnWallet); + const action = await gnosisSafe.transferERC20( + tokenAddress, + toAddress, + value + ); + await action.waitForNonceToUpdate(); + + const balance = await erc20.balanceOf(GNOSIS_SAFE_ADDRESS); + expect(`${balance}`).to.equal(`${ZERO}`); + }); + }); + + describe("test cases that needs NFT deposit to the wallet", async () => { + const tokenId = 1; + + beforeEach("faucet", async () => { + await erc721Faucet(nft, root, GNOSIS_SAFE_ADDRESS, tokenId); + + const balance = await nft.balanceOf(GNOSIS_SAFE_ADDRESS); + expect(`${balance}`).to.equal(`1`); + }); + + it("contract account should send NFT tokens back to owner", async () => { + const tokenAddress = NFT_ADDRESS; + const { address: toAddress } = johnWallet; + + gnosisSafe.setWallet(johnWallet); + const execTxAction = await gnosisSafe.transferNFT( + tokenAddress, + toAddress, + tokenId + ); + await execTxAction.waitForNonceToUpdate(); + + const balance = await erc20.balanceOf(GNOSIS_SAFE_ADDRESS); + expect(`${balance}`).to.equal(`${ZERO}`); + }); + }); + + it("wallet owner should add an account as signer", async () => { + const { address: johnAddress } = johnWallet; + + const ownersBefore = await gnosisSafe.getOwners(); + expect(ownersBefore).deep.equal([johnAddress]); + + const thresholdBefore = await gnosisSafe.getThreshold(); + expect(`${thresholdBefore}`).to.equal(`1`); + + const { address: newSignerAddress } = ephemeralWallet; + const newThreshold = `2`; + + gnosisSafe.setWallet(johnWallet); + const action = await gnosisSafe.addSignerWithThreshold( + newSignerAddress, + newThreshold + ); + await action.waitForNonceToUpdate(); + + const ownersAfter = await gnosisSafe.getOwners(); + expect(ownersAfter).deep.equal([newSignerAddress, johnAddress]); + + const thresholdAdter = await gnosisSafe.getThreshold(); + expect(`${thresholdAdter}`).to.equal(`2`); + }); + + // TODO: + // - Setup DailyLimitModule to the Gnosis Safe Contract + // - Move to tasit-link-wallet + it.skip("wallet owner should approve an ephemeral account to spend funds", async () => {}); +}); diff --git a/packages/tasit-identity-contract/src/GnosisSafeUtils.js b/packages/tasit-identity-contract/src/GnosisSafeUtils.js new file mode 100644 index 00000000..2c117335 --- /dev/null +++ b/packages/tasit-identity-contract/src/GnosisSafeUtils.js @@ -0,0 +1,145 @@ +import Action from "tasit-action"; +const { Contract } = Action; +import { ethers } from "ethers"; + +const { utils: ethersUtils } = ethers; +const { bigNumberify } = ethersUtils; +const { Interface } = ethersUtils; + +// 100 gwei +const GAS_PRICE = bigNumberify(`${1e11}`); + +export default class GnosisSafeUtils { + #contract; + + constructor(contract) { + this.#contract = contract; + } + + // Sign a hash using N signers + // Based on: https://github.com/gnosis/safe-contracts/blob/102e632d051650b7c4b0a822123f449beaf95aed/test/utils.js#L93 + multiSign = (wallets, hash) => { + let signatures = "0x"; + + wallets.forEach(wallet => { + const signingKey = new ethers.utils.SigningKey(wallet.privateKey); + const sig = signingKey.signDigest(hash); + signatures += ethers.utils.joinSignature(sig).slice(2); + }); + + return signatures; + }; + + // Based on: https://github.com/gnosis/safe-contracts/blob/102e632d051650b7c4b0a822123f449beaf95aed/test/utilsPersonalSafe.js#L30 + estimateFromSafeTxGas = async (to, value, data, operation) => { + const provider = this.#contract._getProvider(); + const safeContractAddress = this.#contract.getAddress(); + + // Encode call to the contract's estimate gas function + const callToEstimate = this.encodeFunctionCall( + this.#contract.getABI(), + "requiredTxGas", + [to, value, data, operation] + ); + + // The response will be returned via error message + const estimateResponse = await provider.call({ + to: safeContractAddress, + from: safeContractAddress, + data: callToEstimate, + }); + + // Extract estimation from revert error message + const estimatedGasHex = "0x" + estimateResponse.substring(138); + let estimatedGas = bigNumberify(estimatedGasHex); + + // Extracted from Gnosis Safe test case (Why is it necessary?) + // Add 10k else we will fail in case of nested calls + //estimatedGas = estimatedGas.add(10000); + + return estimatedGas; + }; + + // Based on: https://github.com/gnosis/safe-contracts/blob/102e632d051650b7c4b0a822123f449beaf95aed/test/utilsPersonalSafe.js#L7 + estimateDataGas = ( + safe, + to, + value, + data, + operation, + txGasEstimate, + gasToken, + refundReceiver, + signatureCount + ) => { + const sigRcost = 2176; + const sigScost = 2176; + const sigVcost = 68; + const eachSigCost = sigRcost + sigScost + sigVcost; + const signatureCost = signatureCount * eachSigCost; + + const dataGas = 0; + const gasPrice = GAS_PRICE; + + // Signatures cost will add later + const signatures = "0x"; + + const callToEstimate = this.encodeFunctionCall( + this.#contract.getABI(), + "execTransaction", + [ + to, + value, + data, + operation, + txGasEstimate, + dataGas, + gasPrice, + gasToken, + refundReceiver, + signatures, + ] + ); + + let estimatedGas = + this.#estimateDataGasCosts(callToEstimate) + signatureCost; + + if (estimatedGas > 65536) { + estimatedGas += 64; + } else { + estimatedGas += 128; + } + + // Extracted from Gnosis Safe test case (Why is it necessary?) + // Add aditional gas costs (e.g. base tx costs, transfer costs) + //estimatedGas += 32000; + + return estimatedGas; + }; + + // Calculate data gas + #estimateDataGasCosts = dataString => { + const reducer = (accumulator, currentValue) => + (accumulator += this.#dataGasValue(currentValue)); + + return dataString.match(/.{2}/g).reduce(reducer, 0); + }; + + // Calculate gas for each byte + // Note: No references found + #dataGasValue = hexValue => { + switch (hexValue) { + case "0x": + return 0; + case "00": + return 4; + default: + return 68; + } + }; + + encodeFunctionCall = (abi, functionName, args) => { + const contractInterface = new Interface(abi); + return contractInterface.functions[functionName].encode(args); + }; +} diff --git a/packages/tasit-identity-contract/src/index.js b/packages/tasit-identity-contract/src/index.js new file mode 100644 index 00000000..e69de29b diff --git a/packages/tasit-identity-contract/src/testHelpers/mochaSetup.js b/packages/tasit-identity-contract/src/testHelpers/mochaSetup.js new file mode 100644 index 00000000..e9949327 --- /dev/null +++ b/packages/tasit-identity-contract/src/testHelpers/mochaSetup.js @@ -0,0 +1,35 @@ +// Chai +import { expect } from "chai"; +global.expect = expect; + +// Helpers +import actionHelpers from "tasit-action/dist/testHelpers/helpers"; +global = Object.assign(global, actionHelpers); + +import Action from "tasit-action"; +const { ConfigLoader } = Action; +ConfigLoader.setConfig(developmentConfig); + +// Global hooks +let snapshotId; + +beforeEach("global beforeEach() hook", async () => { + const provider = ProviderFactory.getProvider(); + global.provider = provider; + snapshotId = await createSnapshot(provider); + + while (snapshotId > 1) { + await revertFromSnapshot(provider, snapshotId--); + } + + expect(snapshotId).to.equal(1); +}); + +afterEach("global afterEach() hook", async () => { + expect(snapshotId).to.equal(1); + await revertFromSnapshot(provider, snapshotId); + + // Note: Without this the test suite is breaking. + // It is still unclear why + await mineBlocks(provider, 1); +}); diff --git a/packages/tasit-sdk/package-lock.json b/packages/tasit-sdk/package-lock.json index df6a7eb5..f1a528c1 100644 --- a/packages/tasit-sdk/package-lock.json +++ b/packages/tasit-sdk/package-lock.json @@ -4,789 +4,6 @@ "lockfileVersion": 1, "requires": true, "dependencies": { - "@babel/cli": { - "version": "7.1.5", - "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.1.5.tgz", - "integrity": "sha512-zbO/DtTnaDappBflIU3zYEgATLToRDmW5uN/EGH1GXaes7ydfjqmAoK++xmJIA+8HfDw7UyPZNdM8fhGhfmMhw==", - "dev": true, - "requires": { - "chokidar": "^2.0.3", - "commander": "^2.8.1", - "convert-source-map": "^1.1.0", - "fs-readdir-recursive": "^1.1.0", - "glob": "^7.0.0", - "lodash": "^4.17.10", - "mkdirp": "^0.5.1", - "output-file-sync": "^2.0.0", - "slash": "^2.0.0", - "source-map": "^0.5.0" - } - }, - "@babel/code-frame": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", - "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", - "dev": true, - "requires": { - "@babel/highlight": "^7.0.0" - } - }, - "@babel/core": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.1.6.tgz", - "integrity": "sha512-Hz6PJT6e44iUNpAn8AoyAs6B3bl60g7MJQaI0rZEar6ECzh6+srYO1xlIdssio34mPaUtAb1y+XlkkSJzok3yw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/generator": "^7.1.6", - "@babel/helpers": "^7.1.5", - "@babel/parser": "^7.1.6", - "@babel/template": "^7.1.2", - "@babel/traverse": "^7.1.6", - "@babel/types": "^7.1.6", - "convert-source-map": "^1.1.0", - "debug": "^4.1.0", - "json5": "^2.1.0", - "lodash": "^4.17.10", - "resolve": "^1.3.2", - "semver": "^5.4.1", - "source-map": "^0.5.0" - } - }, - "@babel/generator": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.1.6.tgz", - "integrity": "sha512-brwPBtVvdYdGxtenbQgfCdDPmtkmUBZPjUoK5SXJEBuHaA5BCubh9ly65fzXz7R6o5rA76Rs22ES8Z+HCc0YIQ==", - "dev": true, - "requires": { - "@babel/types": "^7.1.6", - "jsesc": "^2.5.1", - "lodash": "^4.17.10", - "source-map": "^0.5.0", - "trim-right": "^1.0.1" - } - }, - "@babel/helper-annotate-as-pure": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz", - "integrity": "sha512-3UYcJUj9kvSLbLbUIfQTqzcy5VX7GRZ/CCDrnOaZorFFM01aXp1+GJwuFGV4NDDoAS+mOUyHcO6UD/RfqOks3Q==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.1.0.tgz", - "integrity": "sha512-qNSR4jrmJ8M1VMM9tibvyRAHXQs2PmaksQF7c1CGJNipfe3D8p+wgNwgso/P2A2r2mdgBWAXljNWR0QRZAMW8w==", - "dev": true, - "requires": { - "@babel/helper-explode-assignable-expression": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-call-delegate": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.1.0.tgz", - "integrity": "sha512-YEtYZrw3GUK6emQHKthltKNZwszBcHK58Ygcis+gVUrF4/FmTVr5CCqQNSfmvg2y+YDEANyYoaLz/SHsnusCwQ==", - "dev": true, - "requires": { - "@babel/helper-hoist-variables": "^7.0.0", - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-define-map": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.1.0.tgz", - "integrity": "sha512-yPPcW8dc3gZLN+U1mhYV91QU3n5uTbx7DUdf8NnPbjS0RMwBuHi9Xt2MUgppmNz7CJxTBWsGczTiEp1CSOTPRg==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.1.0", - "@babel/types": "^7.0.0", - "lodash": "^4.17.10" - } - }, - "@babel/helper-explode-assignable-expression": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.1.0.tgz", - "integrity": "sha512-NRQpfHrJ1msCHtKjbzs9YcMmJZOg6mQMmGRB+hbamEdG5PNpaSm95275VD92DvJKuyl0s2sFiDmMZ+EnnvufqA==", - "dev": true, - "requires": { - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-function-name": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", - "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "^7.0.0", - "@babel/template": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", - "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-hoist-variables": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.0.0.tgz", - "integrity": "sha512-Ggv5sldXUeSKsuzLkddtyhyHe2YantsxWKNi7A+7LeD12ExRDWTRk29JCXpaHPAbMaIPZSil7n+lq78WY2VY7w==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-member-expression-to-functions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.0.0.tgz", - "integrity": "sha512-avo+lm/QmZlv27Zsi0xEor2fKcqWG56D5ae9dzklpIaY7cQMK5N8VSpaNVPPagiqmy7LrEjK1IWdGMOqPu5csg==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-module-imports": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz", - "integrity": "sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-module-transforms": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.1.0.tgz", - "integrity": "sha512-0JZRd2yhawo79Rcm4w0LwSMILFmFXjugG3yqf+P/UsKsRS1mJCmMwwlHDlMg7Avr9LrvSpp4ZSULO9r8jpCzcw==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/helper-simple-access": "^7.1.0", - "@babel/helper-split-export-declaration": "^7.0.0", - "@babel/template": "^7.1.0", - "@babel/types": "^7.0.0", - "lodash": "^4.17.10" - } - }, - "@babel/helper-optimise-call-expression": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.0.0.tgz", - "integrity": "sha512-u8nd9NQePYNQV8iPWu/pLLYBqZBa4ZaY1YWRFMuxrid94wKI1QNt67NEZ7GAe5Kc/0LLScbim05xZFWkAdrj9g==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-plugin-utils": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz", - "integrity": "sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==", - "dev": true - }, - "@babel/helper-regex": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.0.0.tgz", - "integrity": "sha512-TR0/N0NDCcUIUEbqV6dCO+LptmmSQFQ7q70lfcEB4URsjD0E1HzicrwUH+ap6BAQ2jhCX9Q4UqZy4wilujWlkg==", - "dev": true, - "requires": { - "lodash": "^4.17.10" - } - }, - "@babel/helper-remap-async-to-generator": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.1.0.tgz", - "integrity": "sha512-3fOK0L+Fdlg8S5al8u/hWE6vhufGSn0bN09xm2LXMy//REAF8kDCrYoOBKYmA8m5Nom+sV9LyLCwrFynA8/slg==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.0.0", - "@babel/helper-wrap-function": "^7.1.0", - "@babel/template": "^7.1.0", - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-replace-supers": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.1.0.tgz", - "integrity": "sha512-BvcDWYZRWVuDeXTYZWxekQNO5D4kO55aArwZOTFXw6rlLQA8ZaDicJR1sO47h+HrnCiDFiww0fSPV0d713KBGQ==", - "dev": true, - "requires": { - "@babel/helper-member-expression-to-functions": "^7.0.0", - "@babel/helper-optimise-call-expression": "^7.0.0", - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-simple-access": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz", - "integrity": "sha512-Vk+78hNjRbsiu49zAPALxTb+JUQCz1aolpd8osOF16BGnLtseD21nbHgLPGUwrXEurZgiCOUmvs3ExTu4F5x6w==", - "dev": true, - "requires": { - "@babel/template": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0.tgz", - "integrity": "sha512-MXkOJqva62dfC0w85mEf/LucPPS/1+04nmmRMPEBUB++hiiThQ2zPtX/mEWQ3mtzCEjIJvPY8nuwxXtQeQwUag==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-wrap-function": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.1.0.tgz", - "integrity": "sha512-R6HU3dete+rwsdAfrOzTlE9Mcpk4RjU3aX3gi9grtmugQY0u79X7eogUvfXA5sI81Mfq1cn6AgxihfN33STjJA==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.1.0", - "@babel/template": "^7.1.0", - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@babel/helpers": { - "version": "7.1.5", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.1.5.tgz", - "integrity": "sha512-2jkcdL02ywNBry1YNFAH/fViq4fXG0vdckHqeJk+75fpQ2OH+Az6076tX/M0835zA45E0Cqa6pV5Kiv9YOqjEg==", - "dev": true, - "requires": { - "@babel/template": "^7.1.2", - "@babel/traverse": "^7.1.5", - "@babel/types": "^7.1.5" - } - }, - "@babel/highlight": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", - "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", - "dev": true, - "requires": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^4.0.0" - } - }, - "@babel/node": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/@babel/node/-/node-7.2.2.tgz", - "integrity": "sha512-jPqgTycE26uFsuWpLika9Ohz9dmLQHWjOnMNxBOjYb1HXO+eLKxEr5FfKSXH/tBvFwwaw+pzke3gagnurGOfCA==", - "dev": true, - "requires": { - "@babel/polyfill": "^7.0.0", - "@babel/register": "^7.0.0", - "commander": "^2.8.1", - "lodash": "^4.17.10", - "v8flags": "^3.1.1" - } - }, - "@babel/parser": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.1.6.tgz", - "integrity": "sha512-dWP6LJm9nKT6ALaa+bnL247GHHMWir3vSlZ2+IHgHgktZQx0L3Uvq2uAWcuzIe+fujRsYWBW2q622C5UvGK9iQ==", - "dev": true - }, - "@babel/plugin-proposal-async-generator-functions": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.1.0.tgz", - "integrity": "sha512-Fq803F3Jcxo20MXUSDdmZZXrPe6BWyGcWBPPNB/M7WaUYESKDeKMOGIxEzQOjGSmW/NWb6UaPZrtTB2ekhB/ew==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-remap-async-to-generator": "^7.1.0", - "@babel/plugin-syntax-async-generators": "^7.0.0" - } - }, - "@babel/plugin-proposal-json-strings": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.0.0.tgz", - "integrity": "sha512-kfVdUkIAGJIVmHmtS/40i/fg/AGnw/rsZBCaapY5yjeO5RA9m165Xbw9KMOu2nqXP5dTFjEjHdfNdoVcHv133Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-json-strings": "^7.0.0" - } - }, - "@babel/plugin-proposal-object-rest-spread": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.0.0.tgz", - "integrity": "sha512-14fhfoPcNu7itSen7Py1iGN0gEm87hX/B+8nZPqkdmANyyYWYMY2pjA3r8WXbWVKMzfnSNS0xY8GVS0IjXi/iw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-object-rest-spread": "^7.0.0" - } - }, - "@babel/plugin-proposal-optional-catch-binding": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.0.0.tgz", - "integrity": "sha512-JPqAvLG1s13B/AuoBjdBYvn38RqW6n1TzrQO839/sIpqLpbnXKacsAgpZHzLD83Sm8SDXMkkrAvEnJ25+0yIpw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-optional-catch-binding": "^7.0.0" - } - }, - "@babel/plugin-proposal-unicode-property-regex": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.0.0.tgz", - "integrity": "sha512-tM3icA6GhC3ch2SkmSxv7J/hCWKISzwycub6eGsDrFDgukD4dZ/I+x81XgW0YslS6mzNuQ1Cbzh5osjIMgepPQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.0.0", - "regexpu-core": "^4.2.0" - } - }, - "@babel/plugin-syntax-async-generators": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.0.0.tgz", - "integrity": "sha512-im7ged00ddGKAjcZgewXmp1vxSZQQywuQXe2B1A7kajjZmDeY/ekMPmWr9zJgveSaQH0k7BcGrojQhcK06l0zA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-syntax-json-strings": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.0.0.tgz", - "integrity": "sha512-UlSfNydC+XLj4bw7ijpldc1uZ/HB84vw+U6BTuqMdIEmz/LDe63w/GHtpQMdXWdqQZFeAI9PjnHe/vDhwirhKA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-syntax-object-rest-spread": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.0.0.tgz", - "integrity": "sha512-5A0n4p6bIiVe5OvQPxBnesezsgFJdHhSs3uFSvaPdMqtsovajLZ+G2vZyvNe10EzJBWWo3AcHGKhAFUxqwp2dw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-syntax-optional-catch-binding": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.0.0.tgz", - "integrity": "sha512-Wc+HVvwjcq5qBg1w5RG9o9RVzmCaAg/Vp0erHCKpAYV8La6I94o4GQAmFYNmkzoMO6gzoOSulpKeSSz6mPEoZw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-arrow-functions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.0.0.tgz", - "integrity": "sha512-2EZDBl1WIO/q4DIkIp4s86sdp4ZifL51MoIviLY/gG/mLSuOIEg7J8o6mhbxOTvUJkaN50n+8u41FVsr5KLy/w==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-async-to-generator": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.1.0.tgz", - "integrity": "sha512-rNmcmoQ78IrvNCIt/R9U+cixUHeYAzgusTFgIAv+wQb9HJU4szhpDD6e5GCACmj/JP5KxuCwM96bX3L9v4ZN/g==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-remap-async-to-generator": "^7.1.0" - } - }, - "@babel/plugin-transform-block-scoped-functions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.0.0.tgz", - "integrity": "sha512-AOBiyUp7vYTqz2Jibe1UaAWL0Hl9JUXEgjFvvvcSc9MVDItv46ViXFw2F7SVt1B5k+KWjl44eeXOAk3UDEaJjQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-block-scoping": { - "version": "7.1.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.1.5.tgz", - "integrity": "sha512-jlYcDrz+5ayWC7mxgpn1Wj8zj0mmjCT2w0mPIMSwO926eXBRxpEgoN/uQVRBfjtr8ayjcmS+xk2G1jaP8JjMJQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "lodash": "^4.17.10" - } - }, - "@babel/plugin-transform-classes": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.1.0.tgz", - "integrity": "sha512-rNaqoD+4OCBZjM7VaskladgqnZ1LO6o2UxuWSDzljzW21pN1KXkB7BstAVweZdxQkHAujps5QMNOTWesBciKFg==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.0.0", - "@babel/helper-define-map": "^7.1.0", - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-optimise-call-expression": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.1.0", - "@babel/helper-split-export-declaration": "^7.0.0", - "globals": "^11.1.0" - } - }, - "@babel/plugin-transform-computed-properties": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.0.0.tgz", - "integrity": "sha512-ubouZdChNAv4AAWAgU7QKbB93NU5sHwInEWfp+/OzJKA02E6Woh9RVoX4sZrbRwtybky/d7baTUqwFx+HgbvMA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-destructuring": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.1.3.tgz", - "integrity": "sha512-Mb9M4DGIOspH1ExHOUnn2UUXFOyVTiX84fXCd+6B5iWrQg/QMeeRmSwpZ9lnjYLSXtZwiw80ytVMr3zue0ucYw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-dotall-regex": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.0.0.tgz", - "integrity": "sha512-00THs8eJxOJUFVx1w8i1MBF4XH4PsAjKjQ1eqN/uCH3YKwP21GCKfrn6YZFZswbOk9+0cw1zGQPHVc1KBlSxig==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.0.0", - "regexpu-core": "^4.1.3" - } - }, - "@babel/plugin-transform-duplicate-keys": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.0.0.tgz", - "integrity": "sha512-w2vfPkMqRkdxx+C71ATLJG30PpwtTpW7DDdLqYt2acXU7YjztzeWW2Jk1T6hKqCLYCcEA5UQM/+xTAm+QCSnuQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-exponentiation-operator": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.1.0.tgz", - "integrity": "sha512-uZt9kD1Pp/JubkukOGQml9tqAeI8NkE98oZnHZ2qHRElmeKCodbTZgOEUtujSCSLhHSBWbzNiFSDIMC4/RBTLQ==", - "dev": true, - "requires": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-for-of": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.0.0.tgz", - "integrity": "sha512-TlxKecN20X2tt2UEr2LNE6aqA0oPeMT1Y3cgz8k4Dn1j5ObT8M3nl9aA37LLklx0PBZKETC9ZAf9n/6SujTuXA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-function-name": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.1.0.tgz", - "integrity": "sha512-VxOa1TMlFMtqPW2IDYZQaHsFrq/dDoIjgN098NowhexhZcz3UGlvPgZXuE1jEvNygyWyxRacqDpCZt+par1FNg==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-literals": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.0.0.tgz", - "integrity": "sha512-1NTDBWkeNXgpUcyoVFxbr9hS57EpZYXpje92zv0SUzjdu3enaRwF/l3cmyRnXLtIdyJASyiS6PtybK+CgKf7jA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-modules-amd": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.1.0.tgz", - "integrity": "sha512-wt8P+xQ85rrnGNr2x1iV3DW32W8zrB6ctuBkYBbf5/ZzJY99Ob4MFgsZDFgczNU76iy9PWsy4EuxOliDjdKw6A==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-modules-commonjs": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.1.0.tgz", - "integrity": "sha512-wtNwtMjn1XGwM0AXPspQgvmE6msSJP15CX2RVfpTSTNPLhKhaOjaIfBaVfj4iUZ/VrFSodcFedwtPg/NxwQlPA==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-simple-access": "^7.1.0" - } - }, - "@babel/plugin-transform-modules-systemjs": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.1.3.tgz", - "integrity": "sha512-PvTxgjxQAq4pvVUZF3mD5gEtVDuId8NtWkJsZLEJZMZAW3TvgQl1pmydLLN1bM8huHFVVU43lf0uvjQj9FRkKw==", - "dev": true, - "requires": { - "@babel/helper-hoist-variables": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-modules-umd": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.1.0.tgz", - "integrity": "sha512-enrRtn5TfRhMmbRwm7F8qOj0qEYByqUvTttPEGimcBH4CJHphjyK1Vg7sdU7JjeEmgSpM890IT/efS2nMHwYig==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-new-target": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.0.0.tgz", - "integrity": "sha512-yin069FYjah+LbqfGeTfzIBODex/e++Yfa0rH0fpfam9uTbuEeEOx5GLGr210ggOV77mVRNoeqSYqeuaqSzVSw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-object-super": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.1.0.tgz", - "integrity": "sha512-/O02Je1CRTSk2SSJaq0xjwQ8hG4zhZGNjE8psTsSNPXyLRCODv7/PBozqT5AmQMzp7MI3ndvMhGdqp9c96tTEw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.1.0" - } - }, - "@babel/plugin-transform-parameters": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.1.0.tgz", - "integrity": "sha512-vHV7oxkEJ8IHxTfRr3hNGzV446GAb+0hgbA7o/0Jd76s+YzccdWuTU296FOCOl/xweU4t/Ya4g41yWz80RFCRw==", - "dev": true, - "requires": { - "@babel/helper-call-delegate": "^7.1.0", - "@babel/helper-get-function-arity": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-regenerator": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.0.0.tgz", - "integrity": "sha512-sj2qzsEx8KDVv1QuJc/dEfilkg3RRPvPYx/VnKLtItVQRWt1Wqf5eVCOLZm29CiGFfYYsA3VPjfizTCV0S0Dlw==", - "dev": true, - "requires": { - "regenerator-transform": "^0.13.3" - } - }, - "@babel/plugin-transform-shorthand-properties": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.0.0.tgz", - "integrity": "sha512-g/99LI4vm5iOf5r1Gdxq5Xmu91zvjhEG5+yZDJW268AZELAu4J1EiFLnkSG3yuUsZyOipVOVUKoGPYwfsTymhw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-spread": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.0.0.tgz", - "integrity": "sha512-L702YFy2EvirrR4shTj0g2xQp7aNwZoWNCkNu2mcoU0uyzMl0XRwDSwzB/xp6DSUFiBmEXuyAyEN16LsgVqGGQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-sticky-regex": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.0.0.tgz", - "integrity": "sha512-LFUToxiyS/WD+XEWpkx/XJBrUXKewSZpzX68s+yEOtIbdnsRjpryDw9U06gYc6klYEij/+KQVRnD3nz3AoKmjw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.0.0" - } - }, - "@babel/plugin-transform-template-literals": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.0.0.tgz", - "integrity": "sha512-vA6rkTCabRZu7Nbl9DfLZE1imj4tzdWcg5vtdQGvj+OH9itNNB6hxuRMHuIY8SGnEt1T9g5foqs9LnrHzsqEFg==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-typeof-symbol": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.0.0.tgz", - "integrity": "sha512-1r1X5DO78WnaAIvs5uC48t41LLckxsYklJrZjNKcevyz83sF2l4RHbw29qrCPr/6ksFsdfRpT/ZgxNWHXRnffg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-unicode-regex": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.0.0.tgz", - "integrity": "sha512-uJBrJhBOEa3D033P95nPHu3nbFwFE9ZgXsfEitzoIXIwqAZWk7uXcg06yFKXz9FSxBH5ucgU/cYdX0IV8ldHKw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.0.0", - "regexpu-core": "^4.1.3" - } - }, - "@babel/polyfill": { - "version": "7.2.5", - "resolved": "https://registry.npmjs.org/@babel/polyfill/-/polyfill-7.2.5.tgz", - "integrity": "sha512-8Y/t3MWThtMLYr0YNC/Q76tqN1w30+b0uQMeFUYauG2UGTR19zyUtFrAzT23zNtBxPp+LbE5E/nwV/q/r3y6ug==", - "dev": true, - "requires": { - "core-js": "^2.5.7", - "regenerator-runtime": "^0.12.0" - } - }, - "@babel/preset-env": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.1.6.tgz", - "integrity": "sha512-YIBfpJNQMBkb6MCkjz/A9J76SNCSuGVamOVBgoUkLzpJD/z8ghHi9I42LQ4pulVX68N/MmImz6ZTixt7Azgexw==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-proposal-async-generator-functions": "^7.1.0", - "@babel/plugin-proposal-json-strings": "^7.0.0", - "@babel/plugin-proposal-object-rest-spread": "^7.0.0", - "@babel/plugin-proposal-optional-catch-binding": "^7.0.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.0.0", - "@babel/plugin-syntax-async-generators": "^7.0.0", - "@babel/plugin-syntax-object-rest-spread": "^7.0.0", - "@babel/plugin-syntax-optional-catch-binding": "^7.0.0", - "@babel/plugin-transform-arrow-functions": "^7.0.0", - "@babel/plugin-transform-async-to-generator": "^7.1.0", - "@babel/plugin-transform-block-scoped-functions": "^7.0.0", - "@babel/plugin-transform-block-scoping": "^7.1.5", - "@babel/plugin-transform-classes": "^7.1.0", - "@babel/plugin-transform-computed-properties": "^7.0.0", - "@babel/plugin-transform-destructuring": "^7.0.0", - "@babel/plugin-transform-dotall-regex": "^7.0.0", - "@babel/plugin-transform-duplicate-keys": "^7.0.0", - "@babel/plugin-transform-exponentiation-operator": "^7.1.0", - "@babel/plugin-transform-for-of": "^7.0.0", - "@babel/plugin-transform-function-name": "^7.1.0", - "@babel/plugin-transform-literals": "^7.0.0", - "@babel/plugin-transform-modules-amd": "^7.1.0", - "@babel/plugin-transform-modules-commonjs": "^7.1.0", - "@babel/plugin-transform-modules-systemjs": "^7.0.0", - "@babel/plugin-transform-modules-umd": "^7.1.0", - "@babel/plugin-transform-new-target": "^7.0.0", - "@babel/plugin-transform-object-super": "^7.1.0", - "@babel/plugin-transform-parameters": "^7.1.0", - "@babel/plugin-transform-regenerator": "^7.0.0", - "@babel/plugin-transform-shorthand-properties": "^7.0.0", - "@babel/plugin-transform-spread": "^7.0.0", - "@babel/plugin-transform-sticky-regex": "^7.0.0", - "@babel/plugin-transform-template-literals": "^7.0.0", - "@babel/plugin-transform-typeof-symbol": "^7.0.0", - "@babel/plugin-transform-unicode-regex": "^7.0.0", - "browserslist": "^4.1.0", - "invariant": "^2.2.2", - "js-levenshtein": "^1.1.3", - "semver": "^5.3.0" - } - }, - "@babel/register": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.0.0.tgz", - "integrity": "sha512-f/+CRmaCe7rVEvcvPvxeA8j5aJhHC3aJie7YuqcMDhUOuyWLA7J/aNrTaHIzoWPEhpHA54mec4Mm8fv8KBlv3g==", - "dev": true, - "requires": { - "core-js": "^2.5.7", - "find-cache-dir": "^1.0.0", - "home-or-tmp": "^3.0.0", - "lodash": "^4.17.10", - "mkdirp": "^0.5.1", - "pirates": "^4.0.0", - "source-map-support": "^0.5.9" - } - }, - "@babel/runtime": { - "version": "7.1.5", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.1.5.tgz", - "integrity": "sha512-xKnPpXG/pvK1B90JkwwxSGii90rQGKtzcMt2gI5G6+M0REXaq6rOHsGC2ay6/d0Uje7zzvSzjEzfR3ENhFlrfA==", - "requires": { - "regenerator-runtime": "^0.12.0" - } - }, - "@babel/template": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.1.2.tgz", - "integrity": "sha512-SY1MmplssORfFiLDcOETrW7fCLl+PavlwMh92rrGcikQaRq4iWPVH0MpwPpY3etVMx6RnDjXtr6VZYr/IbP/Ag==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.1.2", - "@babel/types": "^7.1.2" - } - }, - "@babel/traverse": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.1.6.tgz", - "integrity": "sha512-CXedit6GpISz3sC2k2FsGCUpOhUqKdyL0lqNrImQojagnUMXf8hex4AxYFRuMkNGcvJX5QAFGzB5WJQmSv8SiQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/generator": "^7.1.6", - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-split-export-declaration": "^7.0.0", - "@babel/parser": "^7.1.6", - "@babel/types": "^7.1.6", - "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.10" - } - }, - "@babel/types": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.1.6.tgz", - "integrity": "sha512-DMiUzlY9DSjVsOylJssxLHSgj6tWM9PRFJOGW/RaOglVOK9nzTxoOMfTfRQXGUCUQ/HmlG2efwC+XqUEJ5ay4w==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.10", - "to-fast-properties": "^2.0.0" - } - }, - "@types/node": { - "version": "10.12.27", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.27.tgz", - "integrity": "sha512-e9wgeY6gaY21on3ve0xAjgBVjGDWq/xUteK0ujsE53bUoxycMkqfnkUgMt6ffZtykZ5X12Mg3T7Pw4TRCObDKg==" - }, - "aes-js": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz", - "integrity": "sha1-4h3xCtbCBTKVvLuNq0Cwnb6ofk0=" - }, "ansi-colors": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", @@ -808,17 +25,6 @@ "color-convert": "^1.9.0" } }, - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "optional": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - } - }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -852,25 +58,12 @@ "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", "dev": true }, - "assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true - }, "assign-symbols": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", "dev": true }, - "async-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", - "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", - "dev": true, - "optional": true - }, "atob": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", @@ -938,18 +131,6 @@ } } }, - "binary-extensions": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.12.0.tgz", - "integrity": "sha512-DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg==", - "dev": true, - "optional": true - }, - "bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" - }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -989,34 +170,12 @@ } } }, - "brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" - }, "browser-stdout": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, - "browserslist": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.3.4.tgz", - "integrity": "sha512-u5iz+ijIMUlmV8blX82VGFrB9ecnUg5qEt55CMZ/YJEhha+d8qpBfOFuutJ6F/VKRXjZoD33b6uvarpPxcl3RA==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30000899", - "electron-to-chromium": "^1.3.82", - "node-releases": "^1.0.1" - } - }, - "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true - }, "cache-base": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", @@ -1040,26 +199,6 @@ "integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==", "dev": true }, - "caniuse-lite": { - "version": "1.0.30000912", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000912.tgz", - "integrity": "sha512-M3zAtV36U+xw5mMROlTXpAHClmPAor6GPKAMD5Yi7glCB5sbMPFtnQ3rGpk4XqPdUrrTIaVYSJZxREZWNy8QJg==", - "dev": true - }, - "chai": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", - "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", - "dev": true, - "requires": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^3.0.1", - "get-func-name": "^2.0.0", - "pathval": "^1.1.0", - "type-detect": "^4.0.5" - } - }, "chalk": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", @@ -1071,34 +210,6 @@ "supports-color": "^5.3.0" } }, - "check-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", - "dev": true - }, - "chokidar": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", - "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", - "dev": true, - "optional": true, - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.0", - "braces": "^2.3.0", - "fsevents": "^1.2.2", - "glob-parent": "^3.1.0", - "inherits": "^2.0.1", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "lodash.debounce": "^4.0.8", - "normalize-path": "^2.1.1", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.0.0", - "upath": "^1.0.5" - } - }, "class-utils": { "version": "0.3.6", "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", @@ -1164,18 +275,6 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, - "commander": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", - "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", - "dev": true - }, - "commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true - }, "component-emitter": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", @@ -1188,34 +287,12 @@ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, - "convert-source-map": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", - "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.1" - } - }, "copy-descriptor": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", "dev": true }, - "core-js": { - "version": "2.5.7", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz", - "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==", - "dev": true - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true, - "optional": true - }, "cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", @@ -1229,15 +306,6 @@ "which": "^1.2.9" } }, - "debug": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz", - "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", @@ -1250,15 +318,6 @@ "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", "dev": true }, - "deep-eql": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", - "dev": true, - "requires": { - "type-detect": "^4.0.0" - } - }, "define-properties": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", @@ -1321,23 +380,6 @@ "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", "dev": true }, - "electron-to-chromium": { - "version": "1.3.85", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.85.tgz", - "integrity": "sha512-kWSDVVF9t3mft2OHVZy4K85X2beP6c6mFm3teFS/mLSDJpQwuFIWHrULCX+w6H1E55ZYmFRlT+ATAFRwhrYzsw==", - "dev": true - }, - "elliptic": { - "version": "6.3.3", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.3.3.tgz", - "integrity": "sha1-VILZZG1UvLif19mU/J4ulWiHbj8=", - "requires": { - "bn.js": "^4.4.0", - "brorand": "^1.0.1", - "hash.js": "^1.0.0", - "inherits": "^2.0.1" - } - }, "end-of-stream": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", @@ -1381,32 +423,9 @@ "esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, - "esutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true }, - "ethers": { - "version": "4.0.26", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-4.0.26.tgz", - "integrity": "sha512-3hK4S8eAGhuWZ/feip5z17MswjGgjb4lEPJqWO/O0dNqToYLSHhvu6gGQPs8d9f+XfpEB2EYexfF0qjhWiZjUA==", - "requires": { - "@types/node": "^10.3.2", - "aes-js": "3.0.0", - "bn.js": "^4.4.0", - "elliptic": "6.3.3", - "hash.js": "1.1.3", - "js-sha3": "0.5.7", - "scrypt-js": "2.0.4", - "setimmediate": "1.0.4", - "uuid": "2.0.1", - "xmlhttprequest": "1.8.0" - } - }, "execa": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", @@ -1590,26 +609,6 @@ } } }, - "find-cache-dir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz", - "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^1.0.0", - "pkg-dir": "^2.0.0" - } - }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, "findup-sync": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", @@ -1665,560 +664,11 @@ "map-cache": "^0.2.2" } }, - "fs-readdir-recursive": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", - "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", - "dev": true - }, "fs.realpath": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "fsevents": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz", - "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==", - "dev": true, - "optional": true, - "requires": { - "nan": "^2.9.2", - "node-pre-gyp": "^0.10.0" - }, - "dependencies": { - "abbrev": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true, - "dev": true - }, - "aproba": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "balanced-match": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "chownr": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "debug": { - "version": "2.6.9", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ms": "2.0.0" - } - }, - "deep-extend": { - "version": "0.5.1", - "bundled": true, - "dev": true, - "optional": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "detect-libc": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "fs-minipass": { - "version": "1.2.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "glob": { - "version": "7.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "iconv-lite": { - "version": "0.4.21", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safer-buffer": "^2.1.0" - } - }, - "ignore-walk": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "ini": { - "version": "1.3.5", - "bundled": true, - "dev": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "bundled": true, - "dev": true, - "optional": true - }, - "minipass": { - "version": "2.2.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "^5.1.1", - "yallist": "^3.0.0" - } - }, - "minizlib": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "needle": { - "version": "2.2.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "debug": "^2.1.2", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - } - }, - "node-pre-gyp": { - "version": "0.10.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.0", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.1.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4" - } - }, - "nopt": { - "version": "4.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "npm-bundled": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "npm-packlist": { - "version": "1.1.10", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" - } - }, - "npmlog": { - "version": "4.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "wrappy": "1" - } - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "osenv": { - "version": "0.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "process-nextick-args": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "rc": { - "version": "1.2.7", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "deep-extend": "^0.5.1", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "rimraf": { - "version": "2.6.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "glob": "^7.0.5" - } - }, - "safe-buffer": { - "version": "5.1.1", - "bundled": true, - "dev": true - }, - "safer-buffer": { - "version": "2.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "sax": { - "version": "1.2.4", - "bundled": true, - "dev": true, - "optional": true - }, - "semver": { - "version": "5.5.0", - "bundled": true, - "dev": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "tar": { - "version": "4.4.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "chownr": "^1.0.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.2.4", - "minizlib": "^1.1.0", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.1", - "yallist": "^3.0.2" - } - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "wide-align": { - "version": "1.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "string-width": "^1.0.2" - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "yallist": { - "version": "3.0.2", - "bundled": true, - "dev": true - } - } + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true }, "function-bind": { "version": "1.1.1", @@ -2232,12 +682,6 @@ "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", "dev": true }, - "get-func-name": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", - "dev": true - }, "get-stream": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", @@ -2267,29 +711,6 @@ "path-is-absolute": "^1.0.0" } }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "optional": true, - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "optional": true, - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, "global-modules": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", @@ -2314,18 +735,6 @@ "which": "^1.2.14" } }, - "globals": { - "version": "11.9.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.9.0.tgz", - "integrity": "sha512-5cJVtyXWH8PiJPVLZzzoIizXx944O4OmRro5MWKx5fT4MgcN7OfaMutPeaTdJCCURwbWdhhcCWcKIffPnmTzBg==", - "dev": true - }, - "graceful-fs": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", - "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", - "dev": true - }, "growl": { "version": "1.10.5", "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", @@ -2385,27 +794,12 @@ } } }, - "hash.js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", - "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", - "requires": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.0" - } - }, "he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true }, - "home-or-tmp": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-3.0.0.tgz", - "integrity": "sha1-V6j+JM8zzdUkhgoVgh3cJchmcfs=", - "dev": true - }, "homedir-polyfill": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", @@ -2428,7 +822,8 @@ "inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true }, "ini": { "version": "1.3.5", @@ -2436,15 +831,6 @@ "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", "dev": true }, - "invariant": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "dev": true, - "requires": { - "loose-envify": "^1.0.0" - } - }, "invert-kv": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", @@ -2471,16 +857,6 @@ } } }, - "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, - "optional": true, - "requires": { - "binary-extensions": "^1.0.0" - } - }, "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", @@ -2556,16 +932,6 @@ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true }, - "is-glob": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", - "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", - "dev": true, - "optional": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, "is-number": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", @@ -2586,12 +952,6 @@ } } }, - "is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", - "dev": true - }, "is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", @@ -2649,23 +1009,6 @@ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true }, - "js-levenshtein": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.4.tgz", - "integrity": "sha512-PxfGzSs0ztShKrUYPIn5r0MtyAhYcCwmndozzpz8YObbPnD1jFxzlBGbRnX2mIu6Z13xN6+PTu05TQFnZFlzow==", - "dev": true - }, - "js-sha3": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", - "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=" - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, "js-yaml": { "version": "3.12.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", @@ -2676,21 +1019,6 @@ "esprima": "^4.0.0" } }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - }, - "json5": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.0.tgz", - "integrity": "sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - }, "kind-of": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", @@ -2706,29 +1034,12 @@ "invert-kv": "^2.0.0" } }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, "lodash": { "version": "4.17.11", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", "dev": true }, - "lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", - "dev": true, - "optional": true - }, "log-symbols": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", @@ -2738,24 +1049,6 @@ "chalk": "^2.0.1" } }, - "loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, - "requires": { - "js-tokens": "^3.0.0 || ^4.0.0" - } - }, - "make-dir": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", - "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", - "dev": true, - "requires": { - "pify": "^3.0.0" - } - }, "map-age-cleaner": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", @@ -2818,11 +1111,6 @@ "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", "dev": true }, - "minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" - }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -2832,12 +1120,6 @@ "brace-expansion": "^1.1.7" } }, - "minimist": { - "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, "mixin-deep": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", @@ -2933,13 +1215,6 @@ "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", "dev": true }, - "nan": { - "version": "2.11.1", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.11.1.tgz", - "integrity": "sha512-iji6k87OSXa0CcrLl9z+ZiYSuR2o+c0bGuNmXdrhTQTakxytAFsC56SArGYoiHlJlFoHSnvmhpceZJaXkVuOtA==", - "dev": true, - "optional": true - }, "nanomatch": { "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", @@ -2974,31 +1249,6 @@ "object.getownpropertydescriptors": "^2.0.3" } }, - "node-modules-regexp": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz", - "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=", - "dev": true - }, - "node-releases": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.0.5.tgz", - "integrity": "sha512-Ky7q0BO1BBkG/rQz6PkEZ59rwo+aSfhczHP1wwq8IowoVdN/FpiP7qp0XW0P2+BVCWe5fQUBozdbVd54q1RbCQ==", - "dev": true, - "requires": { - "semver": "^5.3.0" - } - }, - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "optional": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - }, "npm-run-path": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", @@ -3111,17 +1361,6 @@ "mem": "^4.0.0" } }, - "output-file-sync": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/output-file-sync/-/output-file-sync-2.0.1.tgz", - "integrity": "sha512-mDho4qm7WgIXIGf4eYU1RHN2UU5tPfVYVSRwDJw0uTmj35DQUt/eNp19N7v6T3SrR0ESTEf2up2CGO73qI35zQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "is-plain-obj": "^1.1.0", - "mkdirp": "^0.5.1" - } - }, "p-defer": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", @@ -3140,30 +1379,6 @@ "integrity": "sha512-pzQPhYMCAgLAKPWD2jC3Se9fEfrD9npNos0y150EeqZll7akhEgGhTW/slB6lHku8AvYGiJ+YJ5hfHKePPgFWg==", "dev": true }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - }, "parse-passwd": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", @@ -3176,13 +1391,6 @@ "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", "dev": true }, - "path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true, - "optional": true - }, "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", @@ -3201,61 +1409,12 @@ "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", "dev": true }, - "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", - "dev": true - }, - "pathval": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", - "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", - "dev": true - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - }, - "pirates": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.0.tgz", - "integrity": "sha512-8t5BsXy1LUIjn3WWOlOuFDuKswhQb/tkak641lvBgmPOBUQHXveORtlMCp6OdPV1dtuTaEahKA8VNz6uLfKBtA==", - "dev": true, - "requires": { - "node-modules-regexp": "^1.0.0" - } - }, - "pkg-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", - "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", - "dev": true, - "requires": { - "find-up": "^2.1.0" - } - }, "posix-character-classes": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", "dev": true }, - "private": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", - "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", - "dev": true - }, - "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", - "dev": true, - "optional": true - }, "pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", @@ -3266,63 +1425,6 @@ "once": "^1.3.1" } }, - "readable-stream": { - "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "dev": true, - "optional": true, - "requires": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - } - }, - "regenerate": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", - "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", - "dev": true - }, - "regenerate-unicode-properties": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-7.0.0.tgz", - "integrity": "sha512-s5NGghCE4itSlUS+0WUj88G6cfMVMmH8boTPNvABf8od+2dhT9WDlWu8n01raQAJZMOK8Ch6jSexaRO7swd6aw==", - "dev": true, - "requires": { - "regenerate": "^1.4.0" - } - }, - "regenerator-runtime": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz", - "integrity": "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg==" - }, - "regenerator-transform": { - "version": "0.13.3", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.13.3.tgz", - "integrity": "sha512-5ipTrZFSq5vU2YoGoww4uaRVAK4wyYC4TSICibbfEPOruUu8FFP7ErV0BjmbIOEpn3O/k9na9UEdYR/3m7N6uA==", - "dev": true, - "requires": { - "private": "^0.1.6" - } - }, "regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", @@ -3333,50 +1435,6 @@ "safe-regex": "^1.1.0" } }, - "regexpu-core": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.2.0.tgz", - "integrity": "sha512-Z835VSnJJ46CNBttalHD/dB+Sj2ezmY6Xp38npwU87peK6mqOzOpV8eYktdkLTEkzzD+JsTcxd84ozd8I14+rw==", - "dev": true, - "requires": { - "regenerate": "^1.4.0", - "regenerate-unicode-properties": "^7.0.0", - "regjsgen": "^0.4.0", - "regjsparser": "^0.3.0", - "unicode-match-property-ecmascript": "^1.0.4", - "unicode-match-property-value-ecmascript": "^1.0.2" - } - }, - "regjsgen": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.4.0.tgz", - "integrity": "sha512-X51Lte1gCYUdlwhF28+2YMO0U6WeN0GLpgpA7LK7mbdDnkQYiwvEpmpe0F/cv5L14EbxgrdayAG3JETBv0dbXA==", - "dev": true - }, - "regjsparser": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.3.0.tgz", - "integrity": "sha512-zza72oZBBHzt64G7DxdqrOo/30bhHkwMUoT0WqfGu98XLd7N+1tsy5MJ96Bk4MD0y74n629RhmrGW6XlnLLwCA==", - "dev": true, - "requires": { - "jsesc": "~0.5.0" - }, - "dependencies": { - "jsesc": { - "version": "0.5.0", - "resolved": "http://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", - "dev": true - } - } - }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true, - "optional": true - }, "repeat-element": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", @@ -3401,15 +1459,6 @@ "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", "dev": true }, - "resolve": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", - "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", - "dev": true, - "requires": { - "path-parse": "^1.0.5" - } - }, "resolve-dir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", @@ -3432,12 +1481,6 @@ "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", "dev": true }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, "safe-regex": { "version": "1.1.0", "resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", @@ -3447,11 +1490,6 @@ "ret": "~0.1.10" } }, - "scrypt-js": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.4.tgz", - "integrity": "sha512-4KsaGcPnuhtCZQCxFxN3GVYIhKFPTdLd8PLC552XwbMndtD0cjRFAhDuuydXQ0h08ZfPgzqe6EKHozpuH74iDw==" - }, "semver": { "version": "5.6.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", @@ -3487,11 +1525,6 @@ } } }, - "setimmediate": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.4.tgz", - "integrity": "sha1-IOgd5iLUoCWIzgyNqJc8vPHTE48=" - }, "shebang-command": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", @@ -3513,12 +1546,6 @@ "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true }, - "slash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", - "dev": true - }, "snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", @@ -3660,24 +1687,6 @@ "urix": "^0.1.0" } }, - "source-map-support": { - "version": "0.5.9", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.9.tgz", - "integrity": "sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, "source-map-url": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", @@ -3730,16 +1739,6 @@ "strip-ansi": "^4.0.0" } }, - "string_decoder": { - "version": "1.1.1", - "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", @@ -3770,30 +1769,6 @@ "has-flag": "^3.0.0" } }, - "tasit-account": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/tasit-account/-/tasit-account-0.0.9.tgz", - "integrity": "sha512-w6F+nYdaVL4Axvlhr64cLGa06JyU7oiehRzi8ufNjI9jaSNcVzv8wXJ1ZHE+wWkWKyUw6rX5ffm6sOkFsiw1IA==", - "requires": { - "@babel/runtime": "^7.1.5", - "ethers": "^4.0.21" - } - }, - "tasit-action": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/tasit-action/-/tasit-action-0.0.9.tgz", - "integrity": "sha512-xBrOGMx3SfHR3I16B5INiBefukmskwNaHWrGbEqOL6bjYv2/vzuYgXj1zN7qB28CphBZIU9x5SSPAuOUL6C2lg==", - "requires": { - "@babel/runtime": "^7.1.5", - "ethers": "^4.0.21" - } - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - }, "to-object-path": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", @@ -3836,46 +1811,6 @@ "repeat-string": "^1.6.1" } }, - "trim-right": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", - "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", - "dev": true - }, - "type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true - }, - "unicode-canonical-property-names-ecmascript": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", - "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==", - "dev": true - }, - "unicode-match-property-ecmascript": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", - "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", - "dev": true, - "requires": { - "unicode-canonical-property-names-ecmascript": "^1.0.4", - "unicode-property-aliases-ecmascript": "^1.0.4" - } - }, - "unicode-match-property-value-ecmascript": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.0.2.tgz", - "integrity": "sha512-Rx7yODZC1L/T8XKo/2kNzVAQaRE88AaMvI1EF/Xnj3GW2wzN6fop9DDWuFAKUVFH7vozkz26DzP0qyWLKLIVPQ==", - "dev": true - }, - "unicode-property-aliases-ecmascript": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.4.tgz", - "integrity": "sha512-2WSLa6OdYd2ng8oqiGIWnJqyFArvhn+5vgx5GTxMbUYjCYKUcuKS62YLFF0R/BDGlB1yzXjQOLtPAfHsgirEpg==", - "dev": true - }, "union-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", @@ -3951,13 +1886,6 @@ } } }, - "upath": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz", - "integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==", - "dev": true, - "optional": true - }, "urix": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", @@ -3970,27 +1898,6 @@ "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", "dev": true }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true, - "optional": true - }, - "uuid": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", - "integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w=" - }, - "v8flags": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.2.tgz", - "integrity": "sha512-MtivA7GF24yMPte9Rp/BWGCYQNaUj86zeYxV/x2RRJMKagImbbv3u8iJC57lNhWLPcGLJmHcHmFWkNsplbbLWw==", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1" - } - }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", @@ -4068,11 +1975,6 @@ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, - "xmlhttprequest": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz", - "integrity": "sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw=" - }, "y18n": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", diff --git a/packages/tasit-sdk/package.json b/packages/tasit-sdk/package.json index abcd18ad..262a7fc5 100644 --- a/packages/tasit-sdk/package.json +++ b/packages/tasit-sdk/package.json @@ -19,8 +19,8 @@ "scripts": { "prepare": "npx babel src --out-dir dist --ignore **/*.test.js", "test": "npm run test:local", - "test:local": "npm run lint && npx mocha src/*.test.js --exclude src/*forkedRopsten.test.js --require @babel/register --no-timeouts", - "test:forkedRopsten": "npm run lint && npx mocha src/*forkedRopsten.test.js --require @babel/register --no-timeouts", + "test:local": "npm run lint && npx mocha src/*.test.js --exclude src/*forkedRopsten.test.js --require @babel/register --file src/testHelpers/mochaSetup.js --no-timeouts", + "test:forkedRopsten": "npm run lint && npx mocha src/*forkedRopsten.test.js --require @babel/register --file src/testHelpers/mochaSetup.js --no-timeouts", "lint": "npx prettier src/* --write" }, "bugs": { diff --git a/packages/tasit-sdk/src/Decentraland.forkedRopsten.test.js b/packages/tasit-sdk/src/Decentraland.forkedRopsten.test.js index 9d56a142..c768861b 100644 --- a/packages/tasit-sdk/src/Decentraland.forkedRopsten.test.js +++ b/packages/tasit-sdk/src/Decentraland.forkedRopsten.test.js @@ -1,13 +1,11 @@ -import { expect, assert } from "chai"; - import { Account, Action } from "./TasitSdk"; -const { ERC20, ERC721, Marketplace, ConfigLoader } = Action; +const { ERC20, ERC721, Marketplace } = Action; const { Mana } = ERC20; const { Estate, Land } = ERC721; const { Decentraland: DecentralandMarketplace } = Marketplace; import config from "./config/default"; -import { ropsten as ropstenAddresses } from "../../tasit-contracts/decentraland/addresses"; +import { ropsten as ropstenAddresses } from "../../tasit-contracts/3rd-parties/decentraland/addresses"; const { MarketplaceProxy: MARKETPLACE_ADDRESS, LANDProxy: LAND_ADDRESS, @@ -15,21 +13,6 @@ const { EstateProxy: ESTATE_ADDRESS, } = ropstenAddresses; -import { - createSnapshot, - revertFromSnapshot, - confirmBalances, - gasParams, - setupWallets, - addressesAreEqual, - bigNumberify, - etherFaucet, - ropstenManaFaucet, - constants, - ProviderFactory, - DecentralandUtils, -} from "./testHelpers/helpers"; - const { ONE, TEN } = constants; const ROPSTEN_NETWORK_ID = 3; @@ -43,14 +26,8 @@ describe("Decentraland tasit app test cases (ropsten)", () => { let marketplaceContract; let landForSale; let estateForSale; - let snapshotId; - let provider; before("", async () => { - ConfigLoader.setConfig(config); - - provider = ProviderFactory.getProvider(); - const network = await provider.getNetwork(); const { chainId } = network; expect(chainId, "The target network isn't ropsten.").to.equal( @@ -101,9 +78,9 @@ describe("Decentraland tasit app test cases (ropsten)", () => { beforeEach( "buyer approves marketplace contract to transfer tokens on their behalf", async () => { - snapshotId = await createSnapshot(provider); + [ownerWallet] = accounts; + ephemeralWallet = Account.create(); - ({ ownerWallet, ephemeralWallet } = setupWallets()); expect(ownerWallet.address).to.have.lengthOf(42); expect(ephemeralWallet.address).to.have.lengthOf(42); @@ -146,10 +123,6 @@ describe("Decentraland tasit app test cases (ropsten)", () => { } ); - afterEach("", async () => { - await revertFromSnapshot(provider, snapshotId); - }); - describe("read-only / without wallet test cases", async () => { it("should get land for sale info", async () => { const { assetId } = landForSale; diff --git a/packages/tasit-sdk/src/Decentraland.test.js b/packages/tasit-sdk/src/Decentraland.test.js index 38bd2ee5..b3752422 100644 --- a/packages/tasit-sdk/src/Decentraland.test.js +++ b/packages/tasit-sdk/src/Decentraland.test.js @@ -1,24 +1,4 @@ -import { Account, Action } from "./TasitSdk"; -const { Contract, ERC721, ConfigLoader } = Action; -import { expect, assert } from "chai"; -import config from "./config/default"; - -import { - mineBlocks, - createSnapshot, - revertFromSnapshot, - confirmBalances, - gasParams, - setupContracts, - setupWallets, - duration, - createEstatesFromParcels, - getEstateSellOrder, - etherFaucet, - ownedManaFaucet, - constants, - ProviderFactory, -} from "./testHelpers/helpers"; +import { Account } from "./TasitSdk"; const { ONE, TEN } = constants; @@ -31,21 +11,11 @@ describe("Decentraland", () => { let landContract; let estateContract; let marketplaceContract; - let snapshotId; - let provider; let estateIds; before("", async () => { - ConfigLoader.setConfig(config); - - provider = ProviderFactory.getProvider(); - - ({ - ownerWallet, - sellerWallet, - buyerWallet, - ephemeralWallet, - } = setupWallets()); + [ownerWallet, sellerWallet, buyerWallet] = accounts; + ephemeralWallet = Account.create(); expect(ownerWallet.address).to.have.lengthOf(42); expect(sellerWallet.address).to.have.lengthOf(42); @@ -54,8 +24,6 @@ describe("Decentraland", () => { }); beforeEach("", async () => { - snapshotId = await createSnapshot(provider); - // Note: In future we can have other ERC20 than Mana to test the Marketplace orders ({ manaContract, @@ -99,16 +67,13 @@ describe("Decentraland", () => { await mineBlocks(provider, 1); }); - afterEach("", async () => { - await revertFromSnapshot(provider, snapshotId); - }); - describe("Marketplace", () => { // TODO: Assign different contract objects for each wallet (avoiding setWallet) beforeEach( "buyer and seller approve marketplace contract to transfer tokens on their behalf", async () => { - ownedManaFaucet(manaContract, ownerWallet, buyerWallet, TEN); + const { address: buyerAddress } = buyerWallet; + erc20Faucet(manaContract, ownerWallet, buyerAddress, TEN); manaContract.setWallet(buyerWallet); const marketplaceApprovalByBuyer = manaContract.approve( @@ -128,9 +93,12 @@ describe("Decentraland", () => { ); it("should execute an order", async () => { + const { address: buyerAddress } = buyerWallet; + const { address: sellerAddress } = sellerWallet; + await confirmBalances( estateContract, - [buyerWallet.address, sellerWallet.address], + [buyerAddress, sellerAddress], [0, estateIds.length] ); @@ -161,7 +129,7 @@ describe("Decentraland", () => { await confirmBalances( estateContract, - [buyerWallet.address, sellerWallet.address], + [buyerAddress, sellerAddress], [1, estateIds.length - 1] ); }); @@ -227,7 +195,8 @@ describe("Decentraland", () => { }); it("should buy an estate", async () => { - await ownedManaFaucet(manaContract, ownerWallet, ephemeralWallet, TEN); + const { address: ephemeralAddress } = ephemeralWallet; + await erc20Faucet(manaContract, ownerWallet, ephemeralAddress, TEN); await etherFaucet(provider, ownerWallet, ephemeralWallet.address, ONE); manaContract.setWallet(ephemeralWallet); @@ -251,7 +220,7 @@ describe("Decentraland", () => { ); await executeOrder.waitForNonceToUpdate(); - await confirmBalances(estateContract, [ephemeralWallet.address], [1]); + await confirmBalances(estateContract, [ephemeralAddress], [1]); }); }); }); diff --git a/packages/tasit-sdk/src/config/default.js b/packages/tasit-sdk/src/config/default.js deleted file mode 100644 index 33623682..00000000 --- a/packages/tasit-sdk/src/config/default.js +++ /dev/null @@ -1,16 +0,0 @@ -const development = { - provider: { - network: "other", - provider: "jsonrpc", - pollingInterval: 50, - jsonRpc: { - url: "http://localhost", - port: 8545, - }, - }, - events: { - timeout: 2000, - }, -}; - -module.exports = development; diff --git a/packages/tasit-sdk/src/testHelpers/DecentralandUtils.js b/packages/tasit-sdk/src/testHelpers/DecentralandUtils.js index 4350fd31..a845ba64 100644 --- a/packages/tasit-sdk/src/testHelpers/DecentralandUtils.js +++ b/packages/tasit-sdk/src/testHelpers/DecentralandUtils.js @@ -1,7 +1,7 @@ import { ethers } from "ethers"; import marketplaceABI from "../../../tasit-contracts/abi/Marketplace.json"; -import { ropsten as ropstenAddresses } from "../../../tasit-contracts/decentraland/addresses"; +import { ropsten as ropstenAddresses } from "../../../tasit-contracts/3rd-parties/decentraland/addresses"; const { MarketplaceProxy: MARKETPLACE_ADDRESS } = ropstenAddresses; // This util class is being used to fetch data from Decentraland Marketplace contract diff --git a/packages/tasit-sdk/src/testHelpers/helpers.js b/packages/tasit-sdk/src/testHelpers/helpers.js index 1b9e00df..a3345374 100644 --- a/packages/tasit-sdk/src/testHelpers/helpers.js +++ b/packages/tasit-sdk/src/testHelpers/helpers.js @@ -1,65 +1,28 @@ import { ethers } from "ethers"; -import { Account, Action } from "../TasitSdk"; +import { Action } from "../TasitSdk"; const { Contract, ERC20, ERC721, Marketplace } = Action; const { Mana } = ERC20; const { Estate, Land } = ERC721; const { Decentraland } = Marketplace; -import { createFromPrivateKey } from "tasit-account/dist/testHelpers/helpers"; - -// The goal of the integration test suite is to use only exposed classes -// from TasitSdk. ProviderFactory is used here as an exception -// as the clearest way to get a provider -// in this test suite. Eventually, maybe ProviderFactory will move to -// some shared helper dir. -import ProviderFactory from "tasit-action/dist/ProviderFactory"; import DecentralandUtils from "./DecentralandUtils"; -import { - mineBlocks, - createSnapshot, - revertFromSnapshot, - confirmBalances, -} from "tasit-action/dist/testHelpers/helpers"; - -import { abi as landProxyABI } from "../../../tasit-contracts/abi/LANDProxy.json"; - -import { - local as localAddresses, - ropsten as ropstenAddresses, -} from "../../../tasit-contracts/decentraland/addresses"; +// Helpers +import actionHelpers from "tasit-action/dist/testHelpers/helpers"; +global = Object.assign(global, actionHelpers); const { utils: ethersUtils, constants: ethersConstants, Contract: ethersContract, } = ethers; -const { WeiPerEther } = ethersConstants; -const { bigNumberify } = ethersUtils; - -const ownerPrivKey = - "0x11d943d7649fbdeb146dc57bd9cfc80b086bfab2330c7b25651dbaf382392f60"; -const sellerPrivKey = - "0xc181b6b02c9757f13f5aa15d1342a58970a8a489722dc0608a1d09fea717c181"; -const buyerPrivKey = - "0x4f09311114f0ff4dfad0edaa932a3e01a4ee9f34da2cbd087aa0e6ffcb9eb322"; - -// TODO: Go deep on gas handling. -// Without that, VM returns a revert error instead of out of gas error. -// See: https://github.com/tasitlabs/TasitSDK/issues/173 -const gasParams = { - gasLimit: 7e6, - gasPrice: 1e9, -}; -const setupWallets = () => { - const ownerWallet = createFromPrivateKey(ownerPrivKey); - const sellerWallet = createFromPrivateKey(sellerPrivKey); - const buyerWallet = createFromPrivateKey(buyerPrivKey); - const ephemeralWallet = Account.create(); +import { abi as landProxyABI } from "../../../tasit-contracts/abi/LANDProxy.json"; - return { ownerWallet, sellerWallet, buyerWallet, ephemeralWallet }; -}; +import { + local as localAddresses, + ropsten as ropstenAddresses, +} from "../../../tasit-contracts/3rd-parties/decentraland/addresses"; const setupContracts = async ownerWallet => { const { @@ -255,40 +218,6 @@ const duration = { }, }; -const etherFaucet = async ( - provider, - fromWallet, - beneficiaryAddress, - amountInWei -) => { - const connectedFromWallet = fromWallet.connect(provider); - const tx = await connectedFromWallet.sendTransaction({ - // ethers.utils.parseEther("1.0") - value: "0x0de0b6b3a7640000", - to: beneficiaryAddress, - }); - await provider.waitForTransaction(tx.hash); -}; - -const ownedManaFaucet = async ( - manaContract, - ownerWallet, - beneficiary, - amountInWei -) => { - manaContract.setWallet(ownerWallet); - const mintManaToBuyer = manaContract.mint( - beneficiary.address, - amountInWei.toString() - ); - await mintManaToBuyer.waitForNonceToUpdate(); - await confirmBalances(manaContract, [beneficiary.address], [amountInWei]); -}; - -const addressesAreEqual = (address1, address2) => { - return address1.toUpperCase() === address2.toUpperCase(); -}; - // The Mana contract deployed on ropsten network has a setBalance function const ropstenManaFaucet = async (provider, walletWithGas, to, amountInWei) => { const { MANAToken: MANA_ADDRESS } = ropstenAddresses; @@ -299,36 +228,19 @@ const ropstenManaFaucet = async (provider, walletWithGas, to, amountInWei) => { await provider.waitForTransaction(tx.hash); }; -// In weis -// Note: ethers.js uses BigNumber internally -// That accepts decimal strings (Ref: https://docs.ethers.io/ethers.js/html/api-utils.html#creating-instances) -// Scientific notation works if the number is small enough (< 1e21) to be converted to string properly -// See more: https://github.com/ethers-io/ethers.js/issues/228 -const ONE = bigNumberify(1).mul(WeiPerEther); -const TEN = bigNumberify(10).mul(WeiPerEther); -const BILLION = bigNumberify(`${1e9}`).mul(WeiPerEther); - -const constants = { - ONE, - TEN, - BILLION, - WeiPerEther, -}; - -export { +export const helpers = { mineBlocks, createSnapshot, revertFromSnapshot, confirmBalances, gasParams, - setupWallets, setupContracts, duration, createParcels, createEstatesFromParcels, getEstateSellOrder, etherFaucet, - ownedManaFaucet, + erc20Faucet, ropstenManaFaucet, addressesAreEqual, bigNumberify, @@ -336,3 +248,5 @@ export { ProviderFactory, DecentralandUtils, }; + +export default helpers; diff --git a/packages/tasit-sdk/src/testHelpers/mochaSetup.js b/packages/tasit-sdk/src/testHelpers/mochaSetup.js new file mode 100644 index 00000000..68bd6ede --- /dev/null +++ b/packages/tasit-sdk/src/testHelpers/mochaSetup.js @@ -0,0 +1,49 @@ +// Chai +import { expect } from "chai"; +global.expect = expect; + +// Helpers +import helpers from "./helpers"; +global = Object.assign(global, helpers); + +// External helpers +// +// Note: Using dist file because babel doesn't compile node_modules files. +// Any changes on src should be followed by compilation to avoid unexpected behaviors. +// Note that lerna bootstrap does this for you since it +// runs prepare in all bootstrapped packages. +// Refs: https://github.com/lerna/lerna/tree/master/commands/bootstrap +import { createFromPrivateKey } from "tasit-account/dist/testHelpers/helpers"; +global.createFromPrivateKey = createFromPrivateKey; + +import { Action } from "../TasitSdk"; +const { ConfigLoader } = Action; +ConfigLoader.setConfig(developmentConfig); + +// Global hooks +let snapshotId; + +before("global before() hook", async () => { + const provider = ProviderFactory.getProvider(); + global.provider = provider; +}); + +beforeEach("global beforeEach() hook", async () => { + provider = ProviderFactory.getProvider(); + snapshotId = await createSnapshot(provider); + + while (snapshotId > 1) { + await revertFromSnapshot(provider, snapshotId--); + } + + expect(snapshotId).to.equal(1); +}); + +afterEach("global afterEach() hook", async () => { + expect(snapshotId).to.equal(1); + await revertFromSnapshot(provider, snapshotId); + + // Note: Without this the test suite is breaking. + // It is still unclear why + await mineBlocks(provider, 1); +});