add instructions on how to run transaction service, tests wip
This commit is contained in:
parent
cb58a4150f
commit
0bf8b3e658
|
@ -104,7 +104,7 @@
|
||||||
"classnames": "^2.2.5",
|
"classnames": "^2.2.5",
|
||||||
"css-loader": "3.0.0",
|
"css-loader": "3.0.0",
|
||||||
"detect-port": "^1.2.2",
|
"detect-port": "^1.2.2",
|
||||||
"eslint": "6.0.1",
|
"eslint": "5.16.0",
|
||||||
"eslint-config-airbnb": "17.1.1",
|
"eslint-config-airbnb": "17.1.1",
|
||||||
"eslint-plugin-flowtype": "3.11.1",
|
"eslint-plugin-flowtype": "3.11.1",
|
||||||
"eslint-plugin-import": "2.18.0",
|
"eslint-plugin-import": "2.18.0",
|
||||||
|
|
12
readme.md
12
readme.md
|
@ -37,7 +37,7 @@ yarn start
|
||||||
|
|
||||||
To run the test, you'll need to migrate contracts `safe-contracts` to the local ganache-cli
|
To run the test, you'll need to migrate contracts `safe-contracts` to the local ganache-cli
|
||||||
|
|
||||||
1. Migrating Safe Contracts:
|
1. Migrate Safe Contracts:
|
||||||
```
|
```
|
||||||
git clone https://github.com/gnosis/safe-contracts.git
|
git clone https://github.com/gnosis/safe-contracts.git
|
||||||
cd safe-contracts
|
cd safe-contracts
|
||||||
|
@ -50,7 +50,15 @@ Inside `safe-react` directory
|
||||||
```
|
```
|
||||||
npx truffle migrate
|
npx truffle migrate
|
||||||
```
|
```
|
||||||
3. Run the tests:
|
3. Run `transaction-history-service`
|
||||||
|
```
|
||||||
|
git clone https://github.com/gnosis/safe-transaction-history.git
|
||||||
|
cd safe-transaction-history
|
||||||
|
git checkout develop
|
||||||
|
docker-compose build
|
||||||
|
docker-compose up -d
|
||||||
|
```
|
||||||
|
4. Run the tests:
|
||||||
```
|
```
|
||||||
yarn test
|
yarn test
|
||||||
```
|
```
|
||||||
|
|
|
@ -1,14 +1,12 @@
|
||||||
// @flow
|
// @flow
|
||||||
import {
|
import {
|
||||||
TX_SERVICE_HOST,
|
TX_SERVICE_HOST,
|
||||||
ENABLED_TX_SERVICE_REMOVAL_SENDER,
|
|
||||||
SIGNATURES_VIA_METAMASK,
|
SIGNATURES_VIA_METAMASK,
|
||||||
RELAY_API_URL,
|
RELAY_API_URL,
|
||||||
} from '~/config/names'
|
} from '~/config/names'
|
||||||
|
|
||||||
const devConfig = {
|
const devConfig = {
|
||||||
[TX_SERVICE_HOST]: 'https://safe-transaction-service.dev.gnosisdev.com/api/v1/',
|
[TX_SERVICE_HOST]: 'https://safe-transaction-service.dev.gnosisdev.com/api/v1/',
|
||||||
[ENABLED_TX_SERVICE_REMOVAL_SENDER]: false,
|
|
||||||
[SIGNATURES_VIA_METAMASK]: false,
|
[SIGNATURES_VIA_METAMASK]: false,
|
||||||
[RELAY_API_URL]: 'https://safe-relay.staging.gnosisdev.com/api/v1/',
|
[RELAY_API_URL]: 'https://safe-relay.staging.gnosisdev.com/api/v1/',
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
import { ensureOnce } from '~/utils/singleton'
|
import { ensureOnce } from '~/utils/singleton'
|
||||||
import {
|
import {
|
||||||
TX_SERVICE_HOST,
|
TX_SERVICE_HOST,
|
||||||
ENABLED_TX_SERVICE_REMOVAL_SENDER,
|
|
||||||
SIGNATURES_VIA_METAMASK,
|
SIGNATURES_VIA_METAMASK,
|
||||||
RELAY_API_URL,
|
RELAY_API_URL,
|
||||||
} from '~/config/names'
|
} from '~/config/names'
|
||||||
|
@ -34,12 +33,6 @@ export const getTxServiceUriFrom = (safeAddress: string) => `safes/${safeAddress
|
||||||
|
|
||||||
export const getRelayUrl = () => getConfig()[RELAY_API_URL]
|
export const getRelayUrl = () => getConfig()[RELAY_API_URL]
|
||||||
|
|
||||||
export const allowedRemoveSenderInTxHistoryService = () => {
|
|
||||||
const config = getConfig()
|
|
||||||
|
|
||||||
return config[ENABLED_TX_SERVICE_REMOVAL_SENDER]
|
|
||||||
}
|
|
||||||
|
|
||||||
export const signaturesViaMetamask = () => {
|
export const signaturesViaMetamask = () => {
|
||||||
const config = getConfig()
|
const config = getConfig()
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
export const TX_SERVICE_HOST = 'tsh'
|
export const TX_SERVICE_HOST = 'tsh'
|
||||||
export const ENABLED_TX_SERVICE_REMOVAL_SENDER = 'trs'
|
|
||||||
export const SIGNATURES_VIA_METAMASK = 'svm'
|
export const SIGNATURES_VIA_METAMASK = 'svm'
|
||||||
export const RELAY_API_URL = 'rau'
|
export const RELAY_API_URL = 'rau'
|
||||||
|
|
|
@ -1,14 +1,12 @@
|
||||||
// @flow
|
// @flow
|
||||||
import {
|
import {
|
||||||
TX_SERVICE_HOST,
|
TX_SERVICE_HOST,
|
||||||
ENABLED_TX_SERVICE_REMOVAL_SENDER,
|
|
||||||
SIGNATURES_VIA_METAMASK,
|
SIGNATURES_VIA_METAMASK,
|
||||||
RELAY_API_URL,
|
RELAY_API_URL,
|
||||||
} from '~/config/names'
|
} from '~/config/names'
|
||||||
|
|
||||||
const prodConfig = {
|
const prodConfig = {
|
||||||
[TX_SERVICE_HOST]: 'https://safe-transaction-service.dev.gnosisdev.com/api/v1/',
|
[TX_SERVICE_HOST]: 'https://safe-transaction-service.dev.gnosisdev.com/api/v1/',
|
||||||
[ENABLED_TX_SERVICE_REMOVAL_SENDER]: false,
|
|
||||||
[SIGNATURES_VIA_METAMASK]: false,
|
[SIGNATURES_VIA_METAMASK]: false,
|
||||||
[RELAY_API_URL]: 'https://safe-relay.staging.gnosisdev.com/api/v1/',
|
[RELAY_API_URL]: 'https://safe-relay.staging.gnosisdev.com/api/v1/',
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,12 @@
|
||||||
// @flow
|
// @flow
|
||||||
import {
|
import {
|
||||||
TX_SERVICE_HOST,
|
TX_SERVICE_HOST,
|
||||||
ENABLED_TX_SERVICE_REMOVAL_SENDER,
|
|
||||||
SIGNATURES_VIA_METAMASK,
|
SIGNATURES_VIA_METAMASK,
|
||||||
RELAY_API_URL,
|
RELAY_API_URL,
|
||||||
} from '~/config/names'
|
} from '~/config/names'
|
||||||
|
|
||||||
const testConfig = {
|
const testConfig = {
|
||||||
[TX_SERVICE_HOST]: 'https://safe-transaction-service.dev.gnosisdev.com/api/v1/',
|
[TX_SERVICE_HOST]: 'http://localhost:8000/api/v1/',
|
||||||
[ENABLED_TX_SERVICE_REMOVAL_SENDER]: false,
|
|
||||||
[SIGNATURES_VIA_METAMASK]: false,
|
[SIGNATURES_VIA_METAMASK]: false,
|
||||||
[RELAY_API_URL]: 'https://safe-relay.staging.gnosisdev.com/api/v1',
|
[RELAY_API_URL]: 'https://safe-relay.staging.gnosisdev.com/api/v1',
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,6 @@ export const approveTransaction = async (
|
||||||
)
|
)
|
||||||
const receipt = await safeInstance.approveHash(contractTxHash, { from: sender })
|
const receipt = await safeInstance.approveHash(contractTxHash, { from: sender })
|
||||||
|
|
||||||
if (process.env.NODE_ENV !== 'test') {
|
|
||||||
await saveTxToHistory(
|
await saveTxToHistory(
|
||||||
safeInstance,
|
safeInstance,
|
||||||
to,
|
to,
|
||||||
|
@ -51,7 +50,6 @@ export const approveTransaction = async (
|
||||||
sender,
|
sender,
|
||||||
TX_TYPE_CONFIRMATION,
|
TX_TYPE_CONFIRMATION,
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
return receipt
|
return receipt
|
||||||
}
|
}
|
||||||
|
@ -91,7 +89,6 @@ export const executeTransaction = async (
|
||||||
{ from: sender },
|
{ from: sender },
|
||||||
)
|
)
|
||||||
|
|
||||||
if (process.env.NODE_ENV !== 'test') {
|
|
||||||
await saveTxToHistory(
|
await saveTxToHistory(
|
||||||
safeInstance,
|
safeInstance,
|
||||||
to,
|
to,
|
||||||
|
@ -103,7 +100,6 @@ export const executeTransaction = async (
|
||||||
sender,
|
sender,
|
||||||
TX_TYPE_EXECUTION,
|
TX_TYPE_EXECUTION,
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
return receipt
|
return receipt
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
|
@ -38,7 +38,7 @@ type TxServiceModel = {
|
||||||
isExecuted: boolean,
|
isExecuted: boolean,
|
||||||
}
|
}
|
||||||
|
|
||||||
const buildTransactionFrom = async (safeAddress: string, tx: TxServiceModel, safeSubjects: Map<string, string>) => {
|
export const buildTransactionFrom = async (safeAddress: string, tx: TxServiceModel, safeSubjects: Map<string, string>) => {
|
||||||
const name = safeSubjects.get(String(tx.nonce)) || 'Unknown'
|
const name = safeSubjects.get(String(tx.nonce)) || 'Unknown'
|
||||||
const storedOwners = await getOwners(safeAddress)
|
const storedOwners = await getOwners(safeAddress)
|
||||||
const confirmations = List(
|
const confirmations = List(
|
||||||
|
|
|
@ -1 +1,80 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
import { fireEvent, cleanup } from '@testing-library/react'
|
||||||
|
import { List } from 'immutable'
|
||||||
|
import { aNewStore } from '~/store'
|
||||||
|
import { aMinedSafe } from '~/test/builder/safe.redux.builder'
|
||||||
|
import { sendTokenTo, sendEtherTo } from '~/test/utils/tokenMovements'
|
||||||
|
import { renderSafeView } from '~/test/builder/safe.dom.utils'
|
||||||
|
import { getWeb3, getBalanceInEtherOf } from '~/logic/wallets/getWeb3'
|
||||||
|
import { dispatchAddTokenToList } from '~/test/utils/transactions/moveTokens.helper'
|
||||||
|
import { sleep } from '~/utils/timer'
|
||||||
|
import TokenBalanceRecord from '~/routes/safe/store/models/tokenBalance'
|
||||||
|
import { calculateBalanceOf } from '~/routes/safe/store/actions/fetchTokenBalances'
|
||||||
|
import updateActiveTokens from '~/routes/safe/store/actions/updateActiveTokens'
|
||||||
|
import { addTransactions } from '~/routes/safe/store/actions/addTransactions'
|
||||||
|
import { buildTransactionFrom } from '~/routes/safe/store/actions/fetchTransactions'
|
||||||
|
import '@testing-library/jest-dom/extend-expect'
|
||||||
|
import updateSafe from '~/routes/safe/store/actions/updateSafe'
|
||||||
|
import { BALANCE_ROW_TEST_ID } from '~/routes/safe/components/Balances'
|
||||||
|
import { fillAndSubmitSendFundsForm } from './utils/transactions'
|
||||||
|
import { EMPTY_DATA } from '~/logic/wallets/ethTransactions';
|
||||||
|
|
||||||
|
afterEach(cleanup)
|
||||||
|
|
||||||
|
describe('DOM > Feature > Sending Funds', () => {
|
||||||
|
let store
|
||||||
|
let safeAddress: string
|
||||||
|
let accounts
|
||||||
|
beforeEach(async () => {
|
||||||
|
store = aNewStore()
|
||||||
|
// using 4th account because other accounts were used in other tests and paid gas
|
||||||
|
safeAddress = await aMinedSafe(store, 2, 2)
|
||||||
|
accounts = await getWeb3().eth.getAccounts()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Sends ETH with threshold = 2', async () => {
|
||||||
|
// GIVEN
|
||||||
|
const ethAmount = '5'
|
||||||
|
await sendEtherTo(safeAddress, ethAmount)
|
||||||
|
const balanceAfterSendingEthToSafe = await getBalanceInEtherOf(accounts[0])
|
||||||
|
|
||||||
|
// WHEN
|
||||||
|
const SafeDom = renderSafeView(store, safeAddress)
|
||||||
|
await sleep(1300)
|
||||||
|
|
||||||
|
// Open send funds modal
|
||||||
|
const balanceRows = SafeDom.getAllByTestId(BALANCE_ROW_TEST_ID)
|
||||||
|
expect(balanceRows[0]).toHaveTextContent(`${ethAmount} ETH`)
|
||||||
|
const sendButton = SafeDom.getByTestId('balance-send-btn')
|
||||||
|
fireEvent.click(sendButton)
|
||||||
|
|
||||||
|
await fillAndSubmitSendFundsForm(SafeDom, sendButton, ethAmount, accounts[0])
|
||||||
|
|
||||||
|
// CONFIRM TX
|
||||||
|
const transaction = {
|
||||||
|
to: accounts[0],
|
||||||
|
value: parseInt(ethAmount, 10) * (10 ** 18),
|
||||||
|
data: EMPTY_DATA,
|
||||||
|
operation: 0,
|
||||||
|
nonce: 0,
|
||||||
|
submissionDate: new Date().toISOString(),
|
||||||
|
executionDate: null,
|
||||||
|
isExecuted: false,
|
||||||
|
confirmations: [
|
||||||
|
owner: accounts[0],
|
||||||
|
submissionDate: new Date().toISOString(),
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
// THEN
|
||||||
|
const safeFunds = await getBalanceInEtherOf(safeAddress)
|
||||||
|
expect(Number(safeFunds)).toBe(0)
|
||||||
|
|
||||||
|
const receiverFunds = await getBalanceInEtherOf(accounts[0])
|
||||||
|
const ESTIMATED_GASCOSTS = 0.3
|
||||||
|
expect(Number(parseInt(receiverFunds, 10) - parseInt(balanceAfterSendingEthToSafe, 10))).toBeGreaterThan(
|
||||||
|
parseInt(ethAmount, 10) - ESTIMATED_GASCOSTS,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
// @flow
|
|
||||||
|
|
||||||
// TBD
|
|
||||||
|
|
||||||
describe('DOM > Feature > SAFE MULTISIG Transactions', () => {
|
|
||||||
it.only('mines correctly all multisig txs in a 1 owner & 1 threshold safe', async () => {})
|
|
||||||
|
|
||||||
it.only('mines withdraw process correctly all multisig txs in a 2 owner & 2 threshold safe', async () => {})
|
|
||||||
|
|
||||||
it.only('approves and executes pending transactions', async () => {})
|
|
||||||
})
|
|
61
yarn.lock
61
yarn.lock
|
@ -4207,14 +4207,14 @@ bignumber.js@^7.2.1:
|
||||||
resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-7.2.1.tgz#80c048759d826800807c4bfd521e50edbba57a5f"
|
resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-7.2.1.tgz#80c048759d826800807c4bfd521e50edbba57a5f"
|
||||||
integrity sha512-S4XzBk5sMB+Rcb/LNcpzXr57VRTxgAvaAEDAl1AwRx27j00hT84O6OkteE7u8UB3NuaaygCRrEpqox4uDOrbdQ==
|
integrity sha512-S4XzBk5sMB+Rcb/LNcpzXr57VRTxgAvaAEDAl1AwRx27j00hT84O6OkteE7u8UB3NuaaygCRrEpqox4uDOrbdQ==
|
||||||
|
|
||||||
|
"bignumber.js@git+https://github.com/debris/bignumber.js#master":
|
||||||
|
version "2.0.7"
|
||||||
|
resolved "git+https://github.com/debris/bignumber.js#c7a38de919ed75e6fb6ba38051986e294b328df9"
|
||||||
|
|
||||||
"bignumber.js@git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2":
|
"bignumber.js@git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2":
|
||||||
version "2.0.7"
|
version "2.0.7"
|
||||||
resolved "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2"
|
resolved "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2"
|
||||||
|
|
||||||
"bignumber.js@git+https://github.com/debris/bignumber.js.git#master":
|
|
||||||
version "2.0.7"
|
|
||||||
resolved "git+https://github.com/debris/bignumber.js.git#c7a38de919ed75e6fb6ba38051986e294b328df9"
|
|
||||||
|
|
||||||
"bignumber.js@git+https://github.com/frozeman/bignumber.js-nolookahead.git":
|
"bignumber.js@git+https://github.com/frozeman/bignumber.js-nolookahead.git":
|
||||||
version "2.0.7"
|
version "2.0.7"
|
||||||
resolved "git+https://github.com/frozeman/bignumber.js-nolookahead.git#57692b3ecfc98bbdd6b3a516cb2353652ea49934"
|
resolved "git+https://github.com/frozeman/bignumber.js-nolookahead.git#57692b3ecfc98bbdd6b3a516cb2353652ea49934"
|
||||||
|
@ -6820,49 +6820,7 @@ eslint-visitor-keys@^1.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d"
|
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d"
|
||||||
integrity sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==
|
integrity sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==
|
||||||
|
|
||||||
eslint@6.0.1:
|
eslint@5.16.0, eslint@^5.0.0, eslint@^5.5.0:
|
||||||
version "6.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.0.1.tgz#4a32181d72cb999d6f54151df7d337131f81cda7"
|
|
||||||
integrity sha512-DyQRaMmORQ+JsWShYsSg4OPTjY56u1nCjAmICrE8vLWqyLKxhFXOthwMj1SA8xwfrv0CofLNVnqbfyhwCkaO0w==
|
|
||||||
dependencies:
|
|
||||||
"@babel/code-frame" "^7.0.0"
|
|
||||||
ajv "^6.10.0"
|
|
||||||
chalk "^2.1.0"
|
|
||||||
cross-spawn "^6.0.5"
|
|
||||||
debug "^4.0.1"
|
|
||||||
doctrine "^3.0.0"
|
|
||||||
eslint-scope "^4.0.3"
|
|
||||||
eslint-utils "^1.3.1"
|
|
||||||
eslint-visitor-keys "^1.0.0"
|
|
||||||
espree "^6.0.0"
|
|
||||||
esquery "^1.0.1"
|
|
||||||
esutils "^2.0.2"
|
|
||||||
file-entry-cache "^5.0.1"
|
|
||||||
functional-red-black-tree "^1.0.1"
|
|
||||||
glob-parent "^3.1.0"
|
|
||||||
globals "^11.7.0"
|
|
||||||
ignore "^4.0.6"
|
|
||||||
import-fresh "^3.0.0"
|
|
||||||
imurmurhash "^0.1.4"
|
|
||||||
inquirer "^6.2.2"
|
|
||||||
is-glob "^4.0.0"
|
|
||||||
js-yaml "^3.13.1"
|
|
||||||
json-stable-stringify-without-jsonify "^1.0.1"
|
|
||||||
levn "^0.3.0"
|
|
||||||
lodash "^4.17.11"
|
|
||||||
minimatch "^3.0.4"
|
|
||||||
mkdirp "^0.5.1"
|
|
||||||
natural-compare "^1.4.0"
|
|
||||||
optionator "^0.8.2"
|
|
||||||
progress "^2.0.0"
|
|
||||||
regexpp "^2.0.1"
|
|
||||||
semver "^5.5.1"
|
|
||||||
strip-ansi "^4.0.0"
|
|
||||||
strip-json-comments "^2.0.1"
|
|
||||||
table "^5.2.3"
|
|
||||||
text-table "^0.2.0"
|
|
||||||
|
|
||||||
eslint@^5.0.0, eslint@^5.5.0:
|
|
||||||
version "5.16.0"
|
version "5.16.0"
|
||||||
resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.16.0.tgz#a1e3ac1aae4a3fbd8296fcf8f7ab7314cbb6abea"
|
resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.16.0.tgz#a1e3ac1aae4a3fbd8296fcf8f7ab7314cbb6abea"
|
||||||
integrity sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg==
|
integrity sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg==
|
||||||
|
@ -6921,15 +6879,6 @@ espree@^5.0.1:
|
||||||
acorn-jsx "^5.0.0"
|
acorn-jsx "^5.0.0"
|
||||||
eslint-visitor-keys "^1.0.0"
|
eslint-visitor-keys "^1.0.0"
|
||||||
|
|
||||||
espree@^6.0.0:
|
|
||||||
version "6.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/espree/-/espree-6.0.0.tgz#716fc1f5a245ef5b9a7fdb1d7b0d3f02322e75f6"
|
|
||||||
integrity sha512-lJvCS6YbCn3ImT3yKkPe0+tJ+mH6ljhGNjHQH9mRtiO6gjhVAOhVXW1yjnwqGwTkK3bGbye+hb00nFNmu0l/1Q==
|
|
||||||
dependencies:
|
|
||||||
acorn "^6.0.7"
|
|
||||||
acorn-jsx "^5.0.0"
|
|
||||||
eslint-visitor-keys "^1.0.0"
|
|
||||||
|
|
||||||
esprima@^3.1.3, esprima@~3.1.0:
|
esprima@^3.1.3, esprima@~3.1.0:
|
||||||
version "3.1.3"
|
version "3.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633"
|
resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633"
|
||||||
|
|
Loading…
Reference in New Issue