mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
Merge remote-tracking branch 'origin/develop' into Version-v8.0.0
* origin/develop: Fix signing method bugs (#8833) replace icons with Checkbox component (#8830) Use gulp-cli@2.3.0 (#8845) Use node-sass@4.14.1 (#8844) Call getMethodDataAsync when knownMethodData[fourBytePrefix] object is empty (#8836) Update connected status popover content (#8834) Use @metamask/controllers@2.0.1 (#8832) ParseInt nextworkNextNonce correction (#8827) Fix first time onboarding popup position (#8829) fix overflowing contract names and origins (#8823) Hide 'Expand view' button in fullscreen (#8826)
This commit is contained in:
commit
cee773e1b5
@ -909,10 +909,13 @@
|
|||||||
"message": "Message"
|
"message": "Message"
|
||||||
},
|
},
|
||||||
"metaMaskConnectStatusParagraphOne": {
|
"metaMaskConnectStatusParagraphOne": {
|
||||||
"message": "This is the new MetaMask Connect status indicator. From here you can easily see and manage sites you’ve connected to with your MetaMask wallet."
|
"message": "You now have more control over your account connections in MetaMask."
|
||||||
},
|
},
|
||||||
"metaMaskConnectStatusParagraphTwo": {
|
"metaMaskConnectStatusParagraphTwo": {
|
||||||
"message": "Click the Connect status to see your connected sites and their permissions."
|
"message": "The connection status button shows if the website you’re visiting is connected to your currently selected account."
|
||||||
|
},
|
||||||
|
"metaMaskConnectStatusParagraphThree": {
|
||||||
|
"message": "Click it to manage your connected accounts."
|
||||||
},
|
},
|
||||||
"metamaskDescription": {
|
"metamaskDescription": {
|
||||||
"message": "Connecting you to Ethereum and the Decentralized Web."
|
"message": "Connecting you to Ethereum and the Decentralized Web."
|
||||||
|
@ -75,6 +75,7 @@ export const SAFE_METHODS = [
|
|||||||
'eth_sendTransaction',
|
'eth_sendTransaction',
|
||||||
'eth_sign',
|
'eth_sign',
|
||||||
'personal_sign',
|
'personal_sign',
|
||||||
|
'personal_ecRecover',
|
||||||
'eth_signTypedData',
|
'eth_signTypedData',
|
||||||
'eth_signTypedData_v1',
|
'eth_signTypedData_v1',
|
||||||
'eth_signTypedData_v3',
|
'eth_signTypedData_v3',
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { addHexPrefix, isValidAddress } from 'ethereumjs-util'
|
import { addHexPrefix, isValidAddress } from 'ethereumjs-util'
|
||||||
|
|
||||||
const normalizers = {
|
const normalizers = {
|
||||||
from: (from, lowerCase = true) => (lowerCase ? addHexPrefix(from).toLowerCase() : addHexPrefix(from)),
|
from: (from) => addHexPrefix(from),
|
||||||
to: (to, lowerCase = true) => (lowerCase ? addHexPrefix(to).toLowerCase() : addHexPrefix(to)),
|
to: (to, lowerCase) => (lowerCase ? addHexPrefix(to).toLowerCase() : addHexPrefix(to)),
|
||||||
nonce: (nonce) => addHexPrefix(nonce),
|
nonce: (nonce) => addHexPrefix(nonce),
|
||||||
value: (value) => addHexPrefix(value),
|
value: (value) => addHexPrefix(value),
|
||||||
data: (data) => addHexPrefix(data),
|
data: (data) => addHexPrefix(data),
|
||||||
@ -12,11 +12,12 @@ const normalizers = {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Normalizes the given txParams
|
* Normalizes the given txParams
|
||||||
* @param {Object} txParams - the tx params
|
* @param {Object} txParams - The transaction params
|
||||||
* @param {boolean} lowerCase - whether to return the addresses lower cased
|
* @param {boolean} [lowerCase] - Whether to lowercase the 'to' address.
|
||||||
|
* Default: true
|
||||||
* @returns {Object} the normalized tx params
|
* @returns {Object} the normalized tx params
|
||||||
*/
|
*/
|
||||||
export function normalizeTxParams (txParams, lowerCase) {
|
export function normalizeTxParams (txParams, lowerCase = true) {
|
||||||
// apply only keys in the normalizers
|
// apply only keys in the normalizers
|
||||||
const normalizedTxParams = {}
|
const normalizedTxParams = {}
|
||||||
for (const key in normalizers) {
|
for (const key in normalizers) {
|
||||||
|
@ -211,7 +211,7 @@ export default class PendingTransactionTracker extends EventEmitter {
|
|||||||
const { hash: txHash, txParams: { nonce, from } } = txMeta
|
const { hash: txHash, txParams: { nonce, from } } = txMeta
|
||||||
const networkNextNonce = await this.query.getTransactionCount(from)
|
const networkNextNonce = await this.query.getTransactionCount(from)
|
||||||
|
|
||||||
if (parseInt(nonce, 16) >= parseInt(networkNextNonce, 16)) {
|
if (parseInt(nonce, 16) >= networkNextNonce.toNumber()) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,5 +283,4 @@ export default class EncryptionPublicKeyManager extends EventEmitter {
|
|||||||
this.memStore.updateState({ unapprovedEncryptionPublicKeyMsgs, unapprovedEncryptionPublicKeyMsgCount })
|
this.memStore.updateState({ unapprovedEncryptionPublicKeyMsgs, unapprovedEncryptionPublicKeyMsgCount })
|
||||||
this.emit('updateBadge')
|
this.emit('updateBadge')
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -4,9 +4,11 @@ import createId from './random-id'
|
|||||||
import assert from 'assert'
|
import assert from 'assert'
|
||||||
import { ethErrors } from 'eth-json-rpc-errors'
|
import { ethErrors } from 'eth-json-rpc-errors'
|
||||||
import sigUtil from 'eth-sig-util'
|
import sigUtil from 'eth-sig-util'
|
||||||
|
import { isValidAddress } from 'ethereumjs-util'
|
||||||
import log from 'loglevel'
|
import log from 'loglevel'
|
||||||
import jsonschema from 'jsonschema'
|
import jsonschema from 'jsonschema'
|
||||||
import { MESSAGE_TYPE } from './enums'
|
import { MESSAGE_TYPE } from './enums'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents, and contains data about, an 'eth_signTypedData' type signature request. These are created when a
|
* Represents, and contains data about, an 'eth_signTypedData' type signature request. These are created when a
|
||||||
* signature for an eth_signTypedData call is requested.
|
* signature for an eth_signTypedData call is requested.
|
||||||
@ -102,14 +104,15 @@ export default class TypedMessageManager extends EventEmitter {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
addUnapprovedMessage (msgParams, req, version) {
|
addUnapprovedMessage (msgParams, req, version) {
|
||||||
|
|
||||||
msgParams.version = version
|
msgParams.version = version
|
||||||
this.validateParams(msgParams)
|
|
||||||
// add origin from request
|
|
||||||
if (req) {
|
if (req) {
|
||||||
msgParams.origin = req.origin
|
msgParams.origin = req.origin
|
||||||
}
|
}
|
||||||
|
this.validateParams(msgParams)
|
||||||
|
|
||||||
log.debug(`TypedMessageManager addUnapprovedMessage: ${JSON.stringify(msgParams)}`)
|
log.debug(`TypedMessageManager addUnapprovedMessage: ${JSON.stringify(msgParams)}`)
|
||||||
|
|
||||||
// create txData obj with parameters and meta data
|
// create txData obj with parameters and meta data
|
||||||
const time = (new Date()).getTime()
|
const time = (new Date()).getTime()
|
||||||
const msgId = createId()
|
const msgId = createId()
|
||||||
@ -134,37 +137,38 @@ export default class TypedMessageManager extends EventEmitter {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
validateParams (params) {
|
validateParams (params) {
|
||||||
|
|
||||||
|
assert.ok(params && typeof params === 'object', 'Params must be an object.')
|
||||||
|
assert.ok('data' in params, 'Params must include a "data" field.')
|
||||||
|
assert.ok('from' in params, 'Params must include a "from" field.')
|
||||||
|
assert.ok(
|
||||||
|
typeof params.from === 'string' && isValidAddress(params.from),
|
||||||
|
'"from" field must be a valid, lowercase, hexadecimal Ethereum address string.'
|
||||||
|
)
|
||||||
|
|
||||||
switch (params.version) {
|
switch (params.version) {
|
||||||
case 'V1':
|
case 'V1':
|
||||||
assert.equal(typeof params, 'object', 'Params should ben an object.')
|
assert.ok(Array.isArray(params.data), '"params.data" must be an array.')
|
||||||
assert.ok('data' in params, 'Params must include a data field.')
|
|
||||||
assert.ok('from' in params, 'Params must include a from field.')
|
|
||||||
assert.ok(Array.isArray(params.data), 'Data should be an array.')
|
|
||||||
assert.equal(typeof params.from, 'string', 'From field must be a string.')
|
|
||||||
assert.doesNotThrow(() => {
|
assert.doesNotThrow(() => {
|
||||||
sigUtil.typedSignatureHash(params.data)
|
sigUtil.typedSignatureHash(params.data)
|
||||||
}, 'Expected EIP712 typed data')
|
}, 'Signing data must be valid EIP-712 typed data.')
|
||||||
break
|
break
|
||||||
case 'V3':
|
case 'V3':
|
||||||
case 'V4':
|
case 'V4':
|
||||||
|
assert.equal(typeof params.data, 'string', '"params.data" must be a string.')
|
||||||
let data
|
let data
|
||||||
assert.equal(typeof params, 'object', 'Params should be an object.')
|
|
||||||
assert.ok('data' in params, 'Params must include a data field.')
|
|
||||||
assert.ok('from' in params, 'Params must include a from field.')
|
|
||||||
assert.equal(typeof params.from, 'string', 'From field must be a string.')
|
|
||||||
assert.equal(typeof params.data, 'string', 'Data must be passed as a valid JSON string.')
|
|
||||||
assert.doesNotThrow(() => {
|
assert.doesNotThrow(() => {
|
||||||
data = JSON.parse(params.data)
|
data = JSON.parse(params.data)
|
||||||
}, 'Data must be passed as a valid JSON string.')
|
}, '"data" must be a valid JSON string.')
|
||||||
const validation = jsonschema.validate(data, sigUtil.TYPED_MESSAGE_SCHEMA)
|
const validation = jsonschema.validate(data, sigUtil.TYPED_MESSAGE_SCHEMA)
|
||||||
assert.ok(data.primaryType in data.types, `Primary type of "${data.primaryType}" has no type definition.`)
|
assert.ok(data.primaryType in data.types, `Primary type of "${data.primaryType}" has no type definition.`)
|
||||||
assert.equal(validation.errors.length, 0, 'Data must conform to EIP-712 schema. See https://git.io/fNtcx.')
|
assert.equal(validation.errors.length, 0, 'Signing data must conform to EIP-712 schema. See https://git.io/fNtcx.')
|
||||||
const chainId = data.domain.chainId
|
const chainId = data.domain.chainId
|
||||||
const activeChainId = parseInt(this.networkController.getNetworkState())
|
const activeChainId = parseInt(this.networkController.getNetworkState())
|
||||||
chainId && assert.equal(chainId, activeChainId, `Provided chainId (${chainId}) must match the active chainId (${activeChainId})`)
|
chainId && assert.equal(chainId, activeChainId, `Provided chainId "${chainId}" must match the active chainId "${activeChainId}"`)
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
assert.fail(`Unknown params.version ${params.version}`)
|
assert.fail(`Unknown typed data version "${params.version}"`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@
|
|||||||
"@formatjs/intl-relativetimeformat": "^5.2.6",
|
"@formatjs/intl-relativetimeformat": "^5.2.6",
|
||||||
"@fortawesome/fontawesome-free": "^5.13.0",
|
"@fortawesome/fontawesome-free": "^5.13.0",
|
||||||
"@material-ui/core": "1.0.0",
|
"@material-ui/core": "1.0.0",
|
||||||
"@metamask/controllers": "^2.0.0",
|
"@metamask/controllers": "^2.0.1",
|
||||||
"@metamask/eth-ledger-bridge-keyring": "^0.2.6",
|
"@metamask/eth-ledger-bridge-keyring": "^0.2.6",
|
||||||
"@metamask/eth-token-tracker": "^2.0.0",
|
"@metamask/eth-token-tracker": "^2.0.0",
|
||||||
"@metamask/etherscan-link": "^1.1.0",
|
"@metamask/etherscan-link": "^1.1.0",
|
||||||
@ -106,7 +106,7 @@
|
|||||||
"eth-json-rpc-errors": "^2.0.2",
|
"eth-json-rpc-errors": "^2.0.2",
|
||||||
"eth-json-rpc-filters": "^4.1.1",
|
"eth-json-rpc-filters": "^4.1.1",
|
||||||
"eth-json-rpc-infura": "^4.0.2",
|
"eth-json-rpc-infura": "^4.0.2",
|
||||||
"eth-json-rpc-middleware": "^4.4.1",
|
"eth-json-rpc-middleware": "^5.0.0",
|
||||||
"eth-keyring-controller": "^6.0.0",
|
"eth-keyring-controller": "^6.0.0",
|
||||||
"eth-method-registry": "^1.2.0",
|
"eth-method-registry": "^1.2.0",
|
||||||
"eth-phishing-detect": "^1.1.4",
|
"eth-phishing-detect": "^1.1.4",
|
||||||
@ -260,7 +260,7 @@
|
|||||||
"mocha": "^7.2.0",
|
"mocha": "^7.2.0",
|
||||||
"nock": "^9.0.14",
|
"nock": "^9.0.14",
|
||||||
"node-fetch": "^2.6.0",
|
"node-fetch": "^2.6.0",
|
||||||
"node-sass": "^4.12.0",
|
"node-sass": "^4.14.1",
|
||||||
"nyc": "^15.0.0",
|
"nyc": "^15.0.0",
|
||||||
"polyfill-crypto.getrandomvalues": "^1.0.0",
|
"polyfill-crypto.getrandomvalues": "^1.0.0",
|
||||||
"proxyquire": "^2.1.3",
|
"proxyquire": "^2.1.3",
|
||||||
|
@ -119,7 +119,7 @@ describe('MetaMask', function () {
|
|||||||
it('show account details dropdown menu', async function () {
|
it('show account details dropdown menu', async function () {
|
||||||
await driver.clickElement(By.css('[data-testid="account-options-menu-button"]'))
|
await driver.clickElement(By.css('[data-testid="account-options-menu-button"]'))
|
||||||
const options = await driver.findElements(By.css('.account-options-menu .menu-item'))
|
const options = await driver.findElements(By.css('.account-options-menu .menu-item'))
|
||||||
assert.equal(options.length, 4) // HD Wallet type does not have to show the Remove Account option
|
assert.equal(options.length, 3) // HD Wallet type does not have to show the Remove Account option
|
||||||
// click outside of menu to dismiss
|
// click outside of menu to dismiss
|
||||||
// account menu button chosen because the menu never covers it.
|
// account menu button chosen because the menu never covers it.
|
||||||
await driver.clickPoint(By.css('.account-menu__icon'), 0, 0)
|
await driver.clickPoint(By.css('.account-menu__icon'), 0, 0)
|
||||||
|
@ -35,9 +35,33 @@ const ExtensionizerMock = {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let loggerMiddlewareMock
|
||||||
|
const initializeMockMiddlewareLog = () => {
|
||||||
|
loggerMiddlewareMock = {
|
||||||
|
requests: [],
|
||||||
|
responses: [],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const tearDownMockMiddlewareLog = () => {
|
||||||
|
loggerMiddlewareMock = undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
const createLoggerMiddlewareMock = () => (req, res, next) => {
|
||||||
|
if (loggerMiddlewareMock) {
|
||||||
|
loggerMiddlewareMock.requests.push(req)
|
||||||
|
next((cb) => {
|
||||||
|
loggerMiddlewareMock.responses.push(res)
|
||||||
|
cb()
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const MetaMaskController = proxyquire('../../../../app/scripts/metamask-controller', {
|
const MetaMaskController = proxyquire('../../../../app/scripts/metamask-controller', {
|
||||||
'./controllers/threebox': { default: ThreeBoxControllerMock },
|
'./controllers/threebox': { default: ThreeBoxControllerMock },
|
||||||
'extensionizer': ExtensionizerMock,
|
'extensionizer': ExtensionizerMock,
|
||||||
|
'./lib/createLoggerMiddleware': { default: createLoggerMiddlewareMock },
|
||||||
}).default
|
}).default
|
||||||
|
|
||||||
const currentNetworkId = 42
|
const currentNetworkId = 42
|
||||||
@ -96,7 +120,6 @@ describe('MetaMaskController', function () {
|
|||||||
// add sinon method spies
|
// add sinon method spies
|
||||||
sandbox.spy(metamaskController.keyringController, 'createNewVaultAndKeychain')
|
sandbox.spy(metamaskController.keyringController, 'createNewVaultAndKeychain')
|
||||||
sandbox.spy(metamaskController.keyringController, 'createNewVaultAndRestore')
|
sandbox.spy(metamaskController.keyringController, 'createNewVaultAndRestore')
|
||||||
sandbox.spy(metamaskController.txController, 'newUnapprovedTransaction')
|
|
||||||
})
|
})
|
||||||
|
|
||||||
afterEach(function () {
|
afterEach(function () {
|
||||||
@ -776,6 +799,17 @@ describe('MetaMaskController', function () {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('#setupUntrustedCommunication', function () {
|
describe('#setupUntrustedCommunication', function () {
|
||||||
|
|
||||||
|
const mockTxParams = { from: TEST_ADDRESS }
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
initializeMockMiddlewareLog()
|
||||||
|
})
|
||||||
|
|
||||||
|
after(function () {
|
||||||
|
tearDownMockMiddlewareLog()
|
||||||
|
})
|
||||||
|
|
||||||
it('sets up phishing stream for untrusted communication', async function () {
|
it('sets up phishing stream for untrusted communication', async function () {
|
||||||
const phishingMessageSender = {
|
const phishingMessageSender = {
|
||||||
url: 'http://myethereumwalletntw.com',
|
url: 'http://myethereumwalletntw.com',
|
||||||
@ -815,7 +849,7 @@ describe('MetaMaskController', function () {
|
|||||||
const message = {
|
const message = {
|
||||||
id: 1999133338649204,
|
id: 1999133338649204,
|
||||||
jsonrpc: '2.0',
|
jsonrpc: '2.0',
|
||||||
params: ['mock tx params'],
|
params: [{ ...mockTxParams }],
|
||||||
method: 'eth_sendTransaction',
|
method: 'eth_sendTransaction',
|
||||||
}
|
}
|
||||||
streamTest.write({
|
streamTest.write({
|
||||||
@ -824,15 +858,12 @@ describe('MetaMaskController', function () {
|
|||||||
}, null, () => {
|
}, null, () => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
assert.deepStrictEqual(
|
assert.deepStrictEqual(
|
||||||
metamaskController.txController.newUnapprovedTransaction.getCall(0).args,
|
loggerMiddlewareMock.requests[0],
|
||||||
[
|
|
||||||
'mock tx params',
|
|
||||||
{
|
{
|
||||||
...message,
|
...message,
|
||||||
origin: 'http://mycrypto.com',
|
origin: 'http://mycrypto.com',
|
||||||
tabId: 456,
|
tabId: 456,
|
||||||
},
|
},
|
||||||
]
|
|
||||||
)
|
)
|
||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
@ -856,7 +887,7 @@ describe('MetaMaskController', function () {
|
|||||||
const message = {
|
const message = {
|
||||||
id: 1999133338649204,
|
id: 1999133338649204,
|
||||||
jsonrpc: '2.0',
|
jsonrpc: '2.0',
|
||||||
params: ['mock tx params'],
|
params: [{ ...mockTxParams }],
|
||||||
method: 'eth_sendTransaction',
|
method: 'eth_sendTransaction',
|
||||||
}
|
}
|
||||||
streamTest.write({
|
streamTest.write({
|
||||||
@ -865,14 +896,11 @@ describe('MetaMaskController', function () {
|
|||||||
}, null, () => {
|
}, null, () => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
assert.deepStrictEqual(
|
assert.deepStrictEqual(
|
||||||
metamaskController.txController.newUnapprovedTransaction.getCall(0).args,
|
loggerMiddlewareMock.requests[0],
|
||||||
[
|
|
||||||
'mock tx params',
|
|
||||||
{
|
{
|
||||||
...message,
|
...message,
|
||||||
origin: 'http://mycrypto.com',
|
origin: 'http://mycrypto.com',
|
||||||
},
|
},
|
||||||
]
|
|
||||||
)
|
)
|
||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import sinon from 'sinon'
|
import sinon from 'sinon'
|
||||||
import { strict as assert } from 'assert'
|
import { strict as assert } from 'assert'
|
||||||
|
import BN from 'bn.js'
|
||||||
import PendingTransactionTracker from '../../../../../app/scripts/controllers/transactions/pending-tx-tracker'
|
import PendingTransactionTracker from '../../../../../app/scripts/controllers/transactions/pending-tx-tracker'
|
||||||
|
|
||||||
describe('PendingTransactionTracker', function () {
|
describe('PendingTransactionTracker', function () {
|
||||||
@ -311,10 +312,11 @@ describe('PendingTransactionTracker', function () {
|
|||||||
|
|
||||||
describe('#_checkIfTxWasDropped', function () {
|
describe('#_checkIfTxWasDropped', function () {
|
||||||
it('should return true when the given nonce is lower than the network nonce', async function () {
|
it('should return true when the given nonce is lower than the network nonce', async function () {
|
||||||
|
const nonceBN = new BN(2)
|
||||||
const pendingTxTracker = new PendingTransactionTracker({
|
const pendingTxTracker = new PendingTransactionTracker({
|
||||||
query: {
|
query: {
|
||||||
getTransactionReceipt: sinon.stub(),
|
getTransactionReceipt: sinon.stub(),
|
||||||
getTransactionCount: sinon.stub().resolves('0x02'),
|
getTransactionCount: sinon.stub().resolves(nonceBN),
|
||||||
},
|
},
|
||||||
nonceTracker: {
|
nonceTracker: {
|
||||||
getGlobalLock: sinon.stub().resolves({
|
getGlobalLock: sinon.stub().resolves({
|
||||||
@ -343,10 +345,11 @@ describe('PendingTransactionTracker', function () {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should return false when the given nonce is the network nonce', async function () {
|
it('should return false when the given nonce is the network nonce', async function () {
|
||||||
|
const nonceBN = new BN(1)
|
||||||
const pendingTxTracker = new PendingTransactionTracker({
|
const pendingTxTracker = new PendingTransactionTracker({
|
||||||
query: {
|
query: {
|
||||||
getTransactionReceipt: sinon.stub(),
|
getTransactionReceipt: sinon.stub(),
|
||||||
getTransactionCount: sinon.stub().resolves('0x01'),
|
getTransactionCount: sinon.stub().resolves(nonceBN),
|
||||||
},
|
},
|
||||||
nonceTracker: {
|
nonceTracker: {
|
||||||
getGlobalLock: sinon.stub().resolves({
|
getGlobalLock: sinon.stub().resolves({
|
||||||
@ -487,10 +490,11 @@ describe('PendingTransactionTracker', function () {
|
|||||||
history: [{}],
|
history: [{}],
|
||||||
rawTx: '0xf86c808504a817c80082471d',
|
rawTx: '0xf86c808504a817c80082471d',
|
||||||
}
|
}
|
||||||
|
const nonceBN = new BN(2)
|
||||||
const pendingTxTracker = new PendingTransactionTracker({
|
const pendingTxTracker = new PendingTransactionTracker({
|
||||||
query: {
|
query: {
|
||||||
getTransactionReceipt: sinon.stub().rejects(),
|
getTransactionReceipt: sinon.stub().rejects(),
|
||||||
getTransactionCount: sinon.stub().resolves('0x02'),
|
getTransactionCount: sinon.stub().resolves(nonceBN),
|
||||||
},
|
},
|
||||||
nonceTracker: {
|
nonceTracker: {
|
||||||
getGlobalLock: sinon.stub().resolves({
|
getGlobalLock: sinon.stub().resolves({
|
||||||
@ -647,6 +651,7 @@ describe('PendingTransactionTracker', function () {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it("should emit 'tx:dropped' with the txMetas id only after the fourth call", async function () {
|
it("should emit 'tx:dropped' with the txMetas id only after the fourth call", async function () {
|
||||||
|
const nonceBN = new BN(2)
|
||||||
const txMeta = {
|
const txMeta = {
|
||||||
id: 1,
|
id: 1,
|
||||||
hash: '0x0593ee121b92e10d63150ad08b4b8f9c7857d1bd160195ee648fb9a0f8d00eeb',
|
hash: '0x0593ee121b92e10d63150ad08b4b8f9c7857d1bd160195ee648fb9a0f8d00eeb',
|
||||||
@ -662,7 +667,7 @@ describe('PendingTransactionTracker', function () {
|
|||||||
const pendingTxTracker = new PendingTransactionTracker({
|
const pendingTxTracker = new PendingTransactionTracker({
|
||||||
query: {
|
query: {
|
||||||
getTransactionReceipt: sinon.stub().resolves(null),
|
getTransactionReceipt: sinon.stub().resolves(null),
|
||||||
getTransactionCount: sinon.stub().resolves('0x02'),
|
getTransactionCount: sinon.stub().resolves(nonceBN),
|
||||||
},
|
},
|
||||||
nonceTracker: {
|
nonceTracker: {
|
||||||
getGlobalLock: sinon.stub().resolves({
|
getGlobalLock: sinon.stub().resolves({
|
||||||
|
@ -97,7 +97,7 @@ const AssetListItem = ({
|
|||||||
data-testid={dataTestId}
|
data-testid={dataTestId}
|
||||||
title={primary}
|
title={primary}
|
||||||
titleIcon={titleIcon}
|
titleIcon={titleIcon}
|
||||||
subtitle={secondary}
|
subtitle={<h3>{secondary}</h3>}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
icon={(
|
icon={(
|
||||||
<Identicon
|
<Identicon
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import React, { PureComponent } from 'react'
|
import React, { PureComponent } from 'react'
|
||||||
|
import CheckBox from '../../ui/check-box'
|
||||||
|
|
||||||
export default class ConnectedAccountsPermissions extends PureComponent {
|
export default class ConnectedAccountsPermissions extends PureComponent {
|
||||||
static contextTypes = {
|
static contextTypes = {
|
||||||
@ -57,7 +58,8 @@ export default class ConnectedAccountsPermissions extends PureComponent {
|
|||||||
<ul className="connected-accounts-permissions__list">
|
<ul className="connected-accounts-permissions__list">
|
||||||
{permissions.map(({ key: permissionName }) => (
|
{permissions.map(({ key: permissionName }) => (
|
||||||
<li key={permissionName} className="connected-accounts-permissions__list-item">
|
<li key={permissionName} className="connected-accounts-permissions__list-item">
|
||||||
<i className="fas fa-check-square" />{t(permissionName)}
|
<CheckBox checked disabled id={permissionName} className="connected-accounts-permissions__checkbox" />
|
||||||
|
<label htmlFor={permissionName}>{t(permissionName)}</label>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -41,13 +41,11 @@
|
|||||||
|
|
||||||
&__list-item {
|
&__list-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
i {
|
|
||||||
display: block;
|
|
||||||
padding-right: 8px;
|
|
||||||
font-size: 18px;
|
|
||||||
color: $Grey-800;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
& &__checkbox {
|
||||||
|
margin: 0 8px 0 0;
|
||||||
|
font-size: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__list-container {
|
&__list-container {
|
||||||
|
@ -10,6 +10,8 @@ import genAccountLink from '../../../../lib/account-link'
|
|||||||
import { getCurrentKeyring, getCurrentNetwork, getRpcPrefsForCurrentProvider, getSelectedIdentity } from '../../../selectors'
|
import { getCurrentKeyring, getCurrentNetwork, getRpcPrefsForCurrentProvider, getSelectedIdentity } from '../../../selectors'
|
||||||
import { useI18nContext } from '../../../hooks/useI18nContext'
|
import { useI18nContext } from '../../../hooks/useI18nContext'
|
||||||
import { useMetricEvent } from '../../../hooks/useMetricEvent'
|
import { useMetricEvent } from '../../../hooks/useMetricEvent'
|
||||||
|
import { getEnvironmentType } from '../../../../../app/scripts/lib/util'
|
||||||
|
import { ENVIRONMENT_TYPE_FULLSCREEN } from '../../../../../app/scripts/lib/enums'
|
||||||
|
|
||||||
export default function AccountOptionsMenu ({ anchorElement, onClose }) {
|
export default function AccountOptionsMenu ({ anchorElement, onClose }) {
|
||||||
const t = useI18nContext()
|
const t = useI18nContext()
|
||||||
@ -58,6 +60,10 @@ export default function AccountOptionsMenu ({ anchorElement, onClose }) {
|
|||||||
className="account-options-menu"
|
className="account-options-menu"
|
||||||
onHide={onClose}
|
onHide={onClose}
|
||||||
>
|
>
|
||||||
|
{
|
||||||
|
getEnvironmentType() === ENVIRONMENT_TYPE_FULLSCREEN
|
||||||
|
? null
|
||||||
|
: (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
openFullscreenEvent()
|
openFullscreenEvent()
|
||||||
@ -68,6 +74,8 @@ export default function AccountOptionsMenu ({ anchorElement, onClose }) {
|
|||||||
>
|
>
|
||||||
{ t('expandView') }
|
{ t('expandView') }
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
)
|
||||||
|
}
|
||||||
<MenuItem
|
<MenuItem
|
||||||
data-testid="account-options-menu__account-details"
|
data-testid="account-options-menu__account-details"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
@ -62,11 +62,6 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
i {
|
|
||||||
font-size: 1.4rem;
|
|
||||||
color: $Grey-200;
|
|
||||||
}
|
|
||||||
|
|
||||||
label {
|
label {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
margin-left: 16px;
|
margin-left: 16px;
|
||||||
@ -75,6 +70,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
& &__checkbox {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
&__content-container {
|
&__content-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
@ -2,6 +2,7 @@ import PropTypes from 'prop-types'
|
|||||||
import React, { PureComponent } from 'react'
|
import React, { PureComponent } from 'react'
|
||||||
import PermissionsConnectHeader from '../../permissions-connect-header'
|
import PermissionsConnectHeader from '../../permissions-connect-header'
|
||||||
import Tooltip from '../../../ui/tooltip-v2'
|
import Tooltip from '../../../ui/tooltip-v2'
|
||||||
|
import CheckBox from '../../../ui/check-box'
|
||||||
|
|
||||||
export default class PermissionPageContainerContent extends PureComponent {
|
export default class PermissionPageContainerContent extends PureComponent {
|
||||||
|
|
||||||
@ -33,6 +34,8 @@ export default class PermissionPageContainerContent extends PureComponent {
|
|||||||
const description = t(permissionName)
|
const description = t(permissionName)
|
||||||
// don't allow deselecting eth_accounts
|
// don't allow deselecting eth_accounts
|
||||||
const isDisabled = permissionName === 'eth_accounts'
|
const isDisabled = permissionName === 'eth_accounts'
|
||||||
|
const isChecked = Boolean(selectedPermissions[permissionName])
|
||||||
|
const title = isChecked ? t('permissionCheckedIconDescription') : t('permissionUncheckedIconDescription')
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@ -44,11 +47,14 @@ export default class PermissionPageContainerContent extends PureComponent {
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{ selectedPermissions[permissionName]
|
<CheckBox
|
||||||
? <i title={t('permissionCheckedIconDescription')} className="fa fa-check-square" />
|
disabled={isDisabled}
|
||||||
: <i title={t('permissionUncheckedIconDescription')} className="fa fa-square" />
|
id={permissionName}
|
||||||
}
|
className="permission-approval-container__checkbox"
|
||||||
<label>{description}</label>
|
checked={isChecked}
|
||||||
|
title={title}
|
||||||
|
/>
|
||||||
|
<label htmlFor={permissionName}>{description}</label>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -69,7 +69,7 @@ describe('Token Cell', function () {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('renders token balance and symbol', function () {
|
it('renders token balance and symbol', function () {
|
||||||
assert.equal(wrapper.find('.list-item__heading').text(), '5.000 TEST ')
|
assert.equal(wrapper.find('.list-item__heading').text(), '5.000 TEST')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('renders converted fiat amount', function () {
|
it('renders converted fiat amount', function () {
|
||||||
|
@ -31,4 +31,27 @@
|
|||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.list-item__subheading > h3 {
|
||||||
|
overflow: visible;
|
||||||
|
display: flex;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: initial;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transaction-status:after {
|
||||||
|
content: "·";
|
||||||
|
margin: 0 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__origin, &__address {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__origin {
|
||||||
|
/*rtl:ignore*/
|
||||||
|
direction: rtl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,7 @@ export default function TransactionListItem ({ transactionGroup, isEarliestNonce
|
|||||||
const {
|
const {
|
||||||
title,
|
title,
|
||||||
subtitle,
|
subtitle,
|
||||||
|
subtitleContainsOrigin,
|
||||||
date,
|
date,
|
||||||
category,
|
category,
|
||||||
primaryCurrency,
|
primaryCurrency,
|
||||||
@ -122,8 +123,8 @@ export default function TransactionListItem ({ transactionGroup, isEarliestNonce
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
icon={<TransactionIcon category={category} status={status} />}
|
icon={<TransactionIcon category={category} status={status} />}
|
||||||
subtitle={subtitle}
|
subtitle={(
|
||||||
subtitleStatus={(
|
<h3>
|
||||||
<TransactionStatus
|
<TransactionStatus
|
||||||
isPending={isPending}
|
isPending={isPending}
|
||||||
isEarliestNonce={isEarliestNonce}
|
isEarliestNonce={isEarliestNonce}
|
||||||
@ -131,6 +132,10 @@ export default function TransactionListItem ({ transactionGroup, isEarliestNonce
|
|||||||
date={date}
|
date={date}
|
||||||
status={status}
|
status={status}
|
||||||
/>
|
/>
|
||||||
|
<span className={subtitleContainsOrigin ? 'transaction-list-item__origin' : 'transaction-list-item__address'}>
|
||||||
|
{subtitle}
|
||||||
|
</span>
|
||||||
|
</h3>
|
||||||
)}
|
)}
|
||||||
rightContent={!isSignatureReq && (
|
rightContent={!isSignatureReq && (
|
||||||
<>
|
<>
|
||||||
|
@ -20,7 +20,7 @@ describe('TransactionStatus Component', function () {
|
|||||||
)
|
)
|
||||||
|
|
||||||
assert.ok(wrapper)
|
assert.ok(wrapper)
|
||||||
assert.equal(wrapper.text(), 'June 1 · ')
|
assert.equal(wrapper.text(), 'June 1')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should render PENDING properly when status is APPROVED', function () {
|
it('should render PENDING properly when status is APPROVED', function () {
|
||||||
@ -33,7 +33,7 @@ describe('TransactionStatus Component', function () {
|
|||||||
)
|
)
|
||||||
|
|
||||||
assert.ok(wrapper)
|
assert.ok(wrapper)
|
||||||
assert.equal(wrapper.text(), 'PENDING · ')
|
assert.equal(wrapper.text(), 'PENDING')
|
||||||
assert.equal(wrapper.find(Tooltip).props().title, 'test-title')
|
assert.equal(wrapper.find(Tooltip).props().title, 'test-title')
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -47,7 +47,7 @@ describe('TransactionStatus Component', function () {
|
|||||||
)
|
)
|
||||||
|
|
||||||
assert.ok(wrapper)
|
assert.ok(wrapper)
|
||||||
assert.equal(wrapper.text(), 'PENDING · ')
|
assert.equal(wrapper.text(), 'PENDING')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should render QUEUED properly', function () {
|
it('should render QUEUED properly', function () {
|
||||||
@ -59,7 +59,7 @@ describe('TransactionStatus Component', function () {
|
|||||||
|
|
||||||
assert.ok(wrapper)
|
assert.ok(wrapper)
|
||||||
assert.ok(wrapper.find('.transaction-status--queued').length, 'queued className not found')
|
assert.ok(wrapper.find('.transaction-status--queued').length, 'queued className not found')
|
||||||
assert.equal(wrapper.text(), 'QUEUED · ')
|
assert.equal(wrapper.text(), 'QUEUED')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should render UNAPPROVED properly', function () {
|
it('should render UNAPPROVED properly', function () {
|
||||||
@ -71,7 +71,7 @@ describe('TransactionStatus Component', function () {
|
|||||||
|
|
||||||
assert.ok(wrapper)
|
assert.ok(wrapper)
|
||||||
assert.ok(wrapper.find('.transaction-status--unapproved').length, 'unapproved className not found')
|
assert.ok(wrapper.find('.transaction-status--unapproved').length, 'unapproved className not found')
|
||||||
assert.equal(wrapper.text(), 'UNAPPROVED · ')
|
assert.equal(wrapper.text(), 'UNAPPROVED')
|
||||||
})
|
})
|
||||||
|
|
||||||
after(function () {
|
after(function () {
|
||||||
|
@ -56,7 +56,6 @@ export default function TransactionStatus ({ status, date, error, isEarliestNonc
|
|||||||
const statusText = statusKey === CONFIRMED_STATUS ? date : t(statusKey)
|
const statusText = statusKey === CONFIRMED_STATUS ? date : t(statusKey)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span>
|
|
||||||
<Tooltip
|
<Tooltip
|
||||||
position="top"
|
position="top"
|
||||||
title={tooltipText}
|
title={tooltipText}
|
||||||
@ -64,8 +63,6 @@ export default function TransactionStatus ({ status, date, error, isEarliestNonc
|
|||||||
>
|
>
|
||||||
{ statusText }
|
{ statusText }
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
{' · '}
|
|
||||||
</span>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ const CHECKBOX_STATE = {
|
|||||||
|
|
||||||
export const { CHECKED, INDETERMINATE, UNCHECKED } = CHECKBOX_STATE
|
export const { CHECKED, INDETERMINATE, UNCHECKED } = CHECKBOX_STATE
|
||||||
|
|
||||||
const CheckBox = ({ className, disabled, id, onClick, checked }) => {
|
const CheckBox = ({ className, disabled, id, onClick, checked, title }) => {
|
||||||
if (typeof checked === 'boolean') {
|
if (typeof checked === 'boolean') {
|
||||||
checked = checked
|
checked = checked
|
||||||
? CHECKBOX_STATE.CHECKED
|
? CHECKBOX_STATE.CHECKED
|
||||||
@ -41,6 +41,7 @@ const CheckBox = ({ className, disabled, id, onClick, checked }) => {
|
|||||||
}
|
}
|
||||||
readOnly
|
readOnly
|
||||||
ref={ref}
|
ref={ref}
|
||||||
|
title={title}
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
@ -52,6 +53,7 @@ CheckBox.propTypes = {
|
|||||||
id: PropTypes.string,
|
id: PropTypes.string,
|
||||||
onClick: PropTypes.func,
|
onClick: PropTypes.func,
|
||||||
checked: PropTypes.oneOf([...Object.keys(CHECKBOX_STATE), true, false]).isRequired,
|
checked: PropTypes.oneOf([...Object.keys(CHECKBOX_STATE), true, false]).isRequired,
|
||||||
|
title: PropTypes.string,
|
||||||
}
|
}
|
||||||
|
|
||||||
CheckBox.defaultProps = {
|
CheckBox.defaultProps = {
|
||||||
|
@ -18,6 +18,5 @@
|
|||||||
&:disabled {
|
&:disabled {
|
||||||
color: $Grey-100;
|
color: $Grey-100;
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
opacity: 0.5;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,11 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
|
> h2 {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
&-wrap {
|
&-wrap {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
@ -53,6 +58,13 @@
|
|||||||
line-height: 14px;
|
line-height: 14px;
|
||||||
color: $Grey-500;
|
color: $Grey-500;
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
|
// all direct descendants should be truncated with ellipses
|
||||||
|
// allows flexibility in consuming components to use h3/other tag
|
||||||
|
> * {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
&:empty {
|
&:empty {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,6 @@ export default function ListItem ({
|
|||||||
title,
|
title,
|
||||||
subtitle,
|
subtitle,
|
||||||
onClick,
|
onClick,
|
||||||
subtitleStatus,
|
|
||||||
children,
|
children,
|
||||||
titleIcon,
|
titleIcon,
|
||||||
icon,
|
icon,
|
||||||
@ -24,16 +23,19 @@ export default function ListItem ({
|
|||||||
{icon}
|
{icon}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<h2 className="list-item__heading">
|
<div className="list-item__heading">
|
||||||
{ title } {titleIcon && (
|
<h2>{ title }</h2>
|
||||||
|
{titleIcon && (
|
||||||
<div className="list-item__heading-wrap">
|
<div className="list-item__heading-wrap">
|
||||||
{titleIcon}
|
{titleIcon}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</h2>
|
</div>
|
||||||
<h3 className="list-item__subheading">
|
{subtitle && (
|
||||||
{subtitleStatus}{subtitle}
|
<div className="list-item__subheading">
|
||||||
</h3>
|
{subtitle}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
{children && (
|
{children && (
|
||||||
<div className="list-item__actions">
|
<div className="list-item__actions">
|
||||||
{ children }
|
{ children }
|
||||||
@ -56,8 +58,7 @@ export default function ListItem ({
|
|||||||
ListItem.propTypes = {
|
ListItem.propTypes = {
|
||||||
title: PropTypes.string.isRequired,
|
title: PropTypes.string.isRequired,
|
||||||
titleIcon: PropTypes.node,
|
titleIcon: PropTypes.node,
|
||||||
subtitle: PropTypes.string,
|
subtitle: PropTypes.node,
|
||||||
subtitleStatus: PropTypes.node,
|
|
||||||
children: PropTypes.node,
|
children: PropTypes.node,
|
||||||
icon: PropTypes.node,
|
icon: PropTypes.node,
|
||||||
rightContent: PropTypes.node,
|
rightContent: PropTypes.node,
|
||||||
|
@ -16,6 +16,7 @@ const expectedResults = [
|
|||||||
{ title: 'Send ETH',
|
{ title: 'Send ETH',
|
||||||
category: 'send',
|
category: 'send',
|
||||||
subtitle: 'To: 0xffe5...1a97',
|
subtitle: 'To: 0xffe5...1a97',
|
||||||
|
subtitleContainsOrigin: false,
|
||||||
date: 'May 12',
|
date: 'May 12',
|
||||||
primaryCurrency: '-1 ETH',
|
primaryCurrency: '-1 ETH',
|
||||||
senderAddress: '0x9eca64466f257793eaa52fcfff5066894b76a149',
|
senderAddress: '0x9eca64466f257793eaa52fcfff5066894b76a149',
|
||||||
@ -26,6 +27,7 @@ const expectedResults = [
|
|||||||
{ title: 'Send ETH',
|
{ title: 'Send ETH',
|
||||||
category: 'send',
|
category: 'send',
|
||||||
subtitle: 'To: 0x0ccc...8848',
|
subtitle: 'To: 0x0ccc...8848',
|
||||||
|
subtitleContainsOrigin: false,
|
||||||
date: 'May 12',
|
date: 'May 12',
|
||||||
primaryCurrency: '-2 ETH',
|
primaryCurrency: '-2 ETH',
|
||||||
senderAddress: '0x9eca64466f257793eaa52fcfff5066894b76a149',
|
senderAddress: '0x9eca64466f257793eaa52fcfff5066894b76a149',
|
||||||
@ -36,6 +38,7 @@ const expectedResults = [
|
|||||||
{ title: 'Send ETH',
|
{ title: 'Send ETH',
|
||||||
category: 'send',
|
category: 'send',
|
||||||
subtitle: 'To: 0xffe5...1a97',
|
subtitle: 'To: 0xffe5...1a97',
|
||||||
|
subtitleContainsOrigin: false,
|
||||||
date: 'May 12',
|
date: 'May 12',
|
||||||
primaryCurrency: '-2 ETH',
|
primaryCurrency: '-2 ETH',
|
||||||
senderAddress: '0x9eca64466f257793eaa52fcfff5066894b76a149',
|
senderAddress: '0x9eca64466f257793eaa52fcfff5066894b76a149',
|
||||||
@ -46,6 +49,7 @@ const expectedResults = [
|
|||||||
{ title: 'Receive',
|
{ title: 'Receive',
|
||||||
category: 'receive',
|
category: 'receive',
|
||||||
subtitle: 'From: 0x31b9...4523',
|
subtitle: 'From: 0x31b9...4523',
|
||||||
|
subtitleContainsOrigin: false,
|
||||||
date: 'May 12',
|
date: 'May 12',
|
||||||
primaryCurrency: '18.75 ETH',
|
primaryCurrency: '18.75 ETH',
|
||||||
senderAddress: '0x31b98d14007bdee637298086988a0bbd31184523',
|
senderAddress: '0x31b98d14007bdee637298086988a0bbd31184523',
|
||||||
@ -56,6 +60,7 @@ const expectedResults = [
|
|||||||
{ title: 'Receive',
|
{ title: 'Receive',
|
||||||
category: 'receive',
|
category: 'receive',
|
||||||
subtitle: 'From: 0x9eca...a149',
|
subtitle: 'From: 0x9eca...a149',
|
||||||
|
subtitleContainsOrigin: false,
|
||||||
date: 'May 8',
|
date: 'May 8',
|
||||||
primaryCurrency: '0 ETH',
|
primaryCurrency: '0 ETH',
|
||||||
senderAddress: '0x9eca64466f257793eaa52fcfff5066894b76a149',
|
senderAddress: '0x9eca64466f257793eaa52fcfff5066894b76a149',
|
||||||
@ -66,6 +71,7 @@ const expectedResults = [
|
|||||||
{ title: 'Receive',
|
{ title: 'Receive',
|
||||||
category: 'receive',
|
category: 'receive',
|
||||||
subtitle: 'From: 0xee01...febb',
|
subtitle: 'From: 0xee01...febb',
|
||||||
|
subtitleContainsOrigin: false,
|
||||||
date: 'May 24',
|
date: 'May 24',
|
||||||
primaryCurrency: '1 ETH',
|
primaryCurrency: '1 ETH',
|
||||||
senderAddress: '0xee014609ef9e09776ac5fe00bdbfef57bcdefebb',
|
senderAddress: '0xee014609ef9e09776ac5fe00bdbfef57bcdefebb',
|
||||||
|
@ -7,7 +7,7 @@ import { useTokenFiatAmount } from './useTokenFiatAmount'
|
|||||||
import { PRIMARY, SECONDARY } from '../helpers/constants/common'
|
import { PRIMARY, SECONDARY } from '../helpers/constants/common'
|
||||||
import { getTokenToAddress } from '../helpers/utils/token-util'
|
import { getTokenToAddress } from '../helpers/utils/token-util'
|
||||||
import { useUserPreferencedCurrency } from './useUserPreferencedCurrency'
|
import { useUserPreferencedCurrency } from './useUserPreferencedCurrency'
|
||||||
import { formatDateWithYearContext, shortenAddress } from '../helpers/utils/util'
|
import { formatDateWithYearContext, shortenAddress, stripHttpSchemes } from '../helpers/utils/util'
|
||||||
import {
|
import {
|
||||||
CONTRACT_INTERACTION_KEY,
|
CONTRACT_INTERACTION_KEY,
|
||||||
DEPLOY_CONTRACT_ACTION_KEY,
|
DEPLOY_CONTRACT_ACTION_KEY,
|
||||||
@ -33,6 +33,7 @@ import { getTokens } from '../ducks/metamask/metamask'
|
|||||||
* @typedef {Object} TransactionDisplayData
|
* @typedef {Object} TransactionDisplayData
|
||||||
* @property {string} title - primary description of the transaction
|
* @property {string} title - primary description of the transaction
|
||||||
* @property {string} subtitle - supporting text describing the transaction
|
* @property {string} subtitle - supporting text describing the transaction
|
||||||
|
* @property {bool} subtitleContainsOrigin - true if the subtitle includes the origin of the tx
|
||||||
* @property {string} category - the transaction category
|
* @property {string} category - the transaction category
|
||||||
* @property {string} primaryCurrency - the currency string to display in the primary position
|
* @property {string} primaryCurrency - the currency string to display in the primary position
|
||||||
* @property {string} [secondaryCurrency] - the currency string to display in the secondary position
|
* @property {string} [secondaryCurrency] - the currency string to display in the secondary position
|
||||||
@ -70,6 +71,7 @@ export function useTransactionDisplayData (transactionGroup) {
|
|||||||
let prefix = '-'
|
let prefix = '-'
|
||||||
const date = formatDateWithYearContext(initialTransaction.time || 0)
|
const date = formatDateWithYearContext(initialTransaction.time || 0)
|
||||||
let subtitle
|
let subtitle
|
||||||
|
let subtitleContainsOrigin = false
|
||||||
let recipientAddress = to
|
let recipientAddress = to
|
||||||
|
|
||||||
// This value is used to determine whether we should look inside txParams.data
|
// This value is used to determine whether we should look inside txParams.data
|
||||||
@ -87,27 +89,31 @@ export function useTransactionDisplayData (transactionGroup) {
|
|||||||
const tokenDisplayValue = useTokenDisplayValue(initialTransaction?.txParams?.data, token, isTokenCategory)
|
const tokenDisplayValue = useTokenDisplayValue(initialTransaction?.txParams?.data, token, isTokenCategory)
|
||||||
const tokenFiatAmount = useTokenFiatAmount(token?.address, tokenDisplayValue, token?.symbol)
|
const tokenFiatAmount = useTokenFiatAmount(token?.address, tokenDisplayValue, token?.symbol)
|
||||||
|
|
||||||
|
const origin = stripHttpSchemes(initialTransaction.origin || initialTransaction.msgParams?.origin || '')
|
||||||
|
|
||||||
let category
|
let category
|
||||||
let title
|
let title
|
||||||
// There are four types of transaction entries that are currently differentiated in the design
|
// There are four types of transaction entries that are currently differentiated in the design
|
||||||
// 1. (PENDING DESIGN) signature request
|
// 1. signature request
|
||||||
// 2. Send (sendEth sendTokens)
|
// 2. Send (sendEth sendTokens)
|
||||||
// 3. Deposit
|
// 3. Deposit
|
||||||
// 4. Site interaction
|
// 4. Site interaction
|
||||||
// 5. Approval
|
// 5. Approval
|
||||||
if (transactionCategory == null) {
|
if (transactionCategory == null) {
|
||||||
const origin = initialTransaction.msgParams?.origin || initialTransaction.origin
|
|
||||||
category = TRANSACTION_CATEGORY_SIGNATURE_REQUEST
|
category = TRANSACTION_CATEGORY_SIGNATURE_REQUEST
|
||||||
title = t('signatureRequest')
|
title = t('signatureRequest')
|
||||||
subtitle = origin || ''
|
subtitle = origin
|
||||||
|
subtitleContainsOrigin = true
|
||||||
} else if (transactionCategory === TOKEN_METHOD_APPROVE) {
|
} else if (transactionCategory === TOKEN_METHOD_APPROVE) {
|
||||||
category = TRANSACTION_CATEGORY_APPROVAL
|
category = TRANSACTION_CATEGORY_APPROVAL
|
||||||
title = t('approve')
|
title = t('approve')
|
||||||
subtitle = initialTransaction.origin
|
subtitle = origin
|
||||||
|
subtitleContainsOrigin = true
|
||||||
} else if (transactionCategory === DEPLOY_CONTRACT_ACTION_KEY || transactionCategory === CONTRACT_INTERACTION_KEY) {
|
} else if (transactionCategory === DEPLOY_CONTRACT_ACTION_KEY || transactionCategory === CONTRACT_INTERACTION_KEY) {
|
||||||
category = TRANSACTION_CATEGORY_INTERACTION
|
category = TRANSACTION_CATEGORY_INTERACTION
|
||||||
title = (methodData?.name && camelCaseToCapitalize(methodData.name)) || (actionKey && t(actionKey)) || ''
|
title = (methodData?.name && camelCaseToCapitalize(methodData.name)) || (actionKey && t(actionKey)) || ''
|
||||||
subtitle = initialTransaction.origin
|
subtitle = origin
|
||||||
|
subtitleContainsOrigin = true
|
||||||
} else if (transactionCategory === INCOMING_TRANSACTION) {
|
} else if (transactionCategory === INCOMING_TRANSACTION) {
|
||||||
category = TRANSACTION_CATEGORY_RECEIVE
|
category = TRANSACTION_CATEGORY_RECEIVE
|
||||||
title = t('receive')
|
title = t('receive')
|
||||||
@ -146,6 +152,7 @@ export function useTransactionDisplayData (transactionGroup) {
|
|||||||
category,
|
category,
|
||||||
date,
|
date,
|
||||||
subtitle,
|
subtitle,
|
||||||
|
subtitleContainsOrigin,
|
||||||
primaryCurrency,
|
primaryCurrency,
|
||||||
senderAddress,
|
senderAddress,
|
||||||
recipientAddress,
|
recipientAddress,
|
||||||
|
@ -25,6 +25,8 @@ import {
|
|||||||
CONNECTED_ACCOUNTS_ROUTE,
|
CONNECTED_ACCOUNTS_ROUTE,
|
||||||
} from '../../helpers/constants/routes'
|
} from '../../helpers/constants/routes'
|
||||||
|
|
||||||
|
const LEARN_MORE_URL = 'https://metamask.zendesk.com/hc/en-us/articles/360045129011-Intro-to-MetaMask-v8-extension'
|
||||||
|
|
||||||
export default class Home extends PureComponent {
|
export default class Home extends PureComponent {
|
||||||
static contextTypes = {
|
static contextTypes = {
|
||||||
t: PropTypes.func,
|
t: PropTypes.func,
|
||||||
@ -187,17 +189,27 @@ export default class Home extends PureComponent {
|
|||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
footer={(
|
footer={(
|
||||||
|
<>
|
||||||
|
<a
|
||||||
|
href={LEARN_MORE_URL}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
{ t('learnMore') }
|
||||||
|
</a>
|
||||||
<Button
|
<Button
|
||||||
type="primary"
|
type="primary"
|
||||||
onClick={setConnectedStatusPopoverHasBeenShown}
|
onClick={setConnectedStatusPopoverHasBeenShown}
|
||||||
>
|
>
|
||||||
{ t('dismiss') }
|
{ t('dismiss') }
|
||||||
</Button>
|
</Button>
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<main className="home__connect-status-text">
|
<main className="home__connect-status-text">
|
||||||
<div>{ t('metaMaskConnectStatusParagraphOne') }</div>
|
<div>{ t('metaMaskConnectStatusParagraphOne') }</div>
|
||||||
<div>{ t('metaMaskConnectStatusParagraphTwo') }</div>
|
<div>{ t('metaMaskConnectStatusParagraphTwo') }</div>
|
||||||
|
<div>{ t('metaMaskConnectStatusParagraphThree') }</div>
|
||||||
</main>
|
</main>
|
||||||
</Popover>
|
</Popover>
|
||||||
)
|
)
|
||||||
|
@ -47,19 +47,24 @@
|
|||||||
padding-right: 24px;
|
padding-right: 24px;
|
||||||
|
|
||||||
div {
|
div {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
|
||||||
&:last-child {
|
&:last-child {
|
||||||
margin-top: 26px;
|
margin-bottom: 0px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__connected-status-popover {
|
&__connected-status-popover {
|
||||||
width: 329px;
|
width: 329px;
|
||||||
height: 295px;
|
margin-top: -15px;
|
||||||
margin-top: -12px;
|
|
||||||
|
|
||||||
.popover-header {
|
.popover-header {
|
||||||
padding-bottom: 4px;
|
padding-bottom: 20px;
|
||||||
|
|
||||||
|
&__title {
|
||||||
|
padding-bottom: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.popover-content {
|
.popover-content {
|
||||||
@ -72,7 +77,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.popover-footer {
|
.popover-footer {
|
||||||
justify-content: flex-end;
|
border-top: 0;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding-top: 20px;
|
||||||
|
font-size: 14px;
|
||||||
|
|
||||||
& :only-child {
|
& :only-child {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
@ -84,16 +93,20 @@
|
|||||||
border-radius: 39px;
|
border-radius: 39px;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a, a:hover {
|
||||||
|
color: $dodger-blue;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__connected-status-popover-bg {
|
&__connected-status-popover-bg {
|
||||||
height: 34px;
|
height: 55px;
|
||||||
width: 110px;
|
width: 120px;
|
||||||
border-radius: 34px;
|
border-radius: 34px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 82px;
|
top: 73px;
|
||||||
left: 12px;
|
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.2);
|
box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.2);
|
||||||
background: none;
|
background: none;
|
||||||
|
@ -2160,7 +2160,7 @@ export function getContractMethodData (data = '') {
|
|||||||
const prefixedData = ethUtil.addHexPrefix(data)
|
const prefixedData = ethUtil.addHexPrefix(data)
|
||||||
const fourBytePrefix = prefixedData.slice(0, 10)
|
const fourBytePrefix = prefixedData.slice(0, 10)
|
||||||
const { knownMethodData } = getState().metamask
|
const { knownMethodData } = getState().metamask
|
||||||
if (knownMethodData && knownMethodData[fourBytePrefix]) {
|
if (knownMethodData && knownMethodData[fourBytePrefix] && Object.keys(knownMethodData[fourBytePrefix]).length !== 0) {
|
||||||
return Promise.resolve(knownMethodData[fourBytePrefix])
|
return Promise.resolve(knownMethodData[fourBytePrefix])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
87
yarn.lock
87
yarn.lock
@ -1629,10 +1629,10 @@
|
|||||||
scroll "^2.0.3"
|
scroll "^2.0.3"
|
||||||
warning "^3.0.0"
|
warning "^3.0.0"
|
||||||
|
|
||||||
"@metamask/controllers@^2.0.0":
|
"@metamask/controllers@^2.0.1":
|
||||||
version "2.0.0"
|
version "2.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/@metamask/controllers/-/controllers-2.0.0.tgz#e57762c213d2722fd178d4c5c288ad98a2ee8bdf"
|
resolved "https://registry.yarnpkg.com/@metamask/controllers/-/controllers-2.0.1.tgz#33b0e2826fb6d4aa582acaff6b347e6abe0f54f5"
|
||||||
integrity sha512-J2DSoyyPRAilTdohl43O5tZdqOSMvB94Kx1ApRpkPZxQwtDUIzWHRpTXptyCEwkhaOdkNz9BvWMoaRQxjktfKw==
|
integrity sha512-xioh4h+4D2pUSJ9H2CaffxKGmlg0kUK2bbRJ8c9GXPVTo8KhRHryvNKfkVCyoSt35FLROzzwTEdVJ4dmUFuELQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
await-semaphore "^0.1.3"
|
await-semaphore "^0.1.3"
|
||||||
eth-contract-metadata "^1.11.0"
|
eth-contract-metadata "^1.11.0"
|
||||||
@ -10174,7 +10174,7 @@ eth-json-rpc-middleware@^1.5.0:
|
|||||||
promise-to-callback "^1.0.0"
|
promise-to-callback "^1.0.0"
|
||||||
tape "^4.6.3"
|
tape "^4.6.3"
|
||||||
|
|
||||||
eth-json-rpc-middleware@^4.1.4, eth-json-rpc-middleware@^4.1.5, eth-json-rpc-middleware@^4.4.1:
|
eth-json-rpc-middleware@^4.1.4, eth-json-rpc-middleware@^4.1.5:
|
||||||
version "4.4.1"
|
version "4.4.1"
|
||||||
resolved "https://registry.yarnpkg.com/eth-json-rpc-middleware/-/eth-json-rpc-middleware-4.4.1.tgz#07d3dd0724c24a8d31e4a172ee96271da71b4228"
|
resolved "https://registry.yarnpkg.com/eth-json-rpc-middleware/-/eth-json-rpc-middleware-4.4.1.tgz#07d3dd0724c24a8d31e4a172ee96271da71b4228"
|
||||||
integrity sha512-yoSuRgEYYGFdVeZg3poWOwAlRI+MoBIltmOB86MtpoZjvLbou9EB/qWMOWSmH2ryCWLW97VYY6NWsmWm3OAA7A==
|
integrity sha512-yoSuRgEYYGFdVeZg3poWOwAlRI+MoBIltmOB86MtpoZjvLbou9EB/qWMOWSmH2ryCWLW97VYY6NWsmWm3OAA7A==
|
||||||
@ -10194,6 +10194,26 @@ eth-json-rpc-middleware@^4.1.4, eth-json-rpc-middleware@^4.1.5, eth-json-rpc-mid
|
|||||||
pify "^3.0.0"
|
pify "^3.0.0"
|
||||||
safe-event-emitter "^1.0.1"
|
safe-event-emitter "^1.0.1"
|
||||||
|
|
||||||
|
eth-json-rpc-middleware@^5.0.0:
|
||||||
|
version "5.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/eth-json-rpc-middleware/-/eth-json-rpc-middleware-5.0.0.tgz#9a202a41a2b1678c094cbffd0db0da619ec86f7b"
|
||||||
|
integrity sha512-31zLHvElrQV7opFZs47UqjMGFM4QCgMms7HJSQAZ3wjPuE3rFLxFUTeGHXwM3fAp9zh7n0M+B2gK7Ds4OUKfog==
|
||||||
|
dependencies:
|
||||||
|
btoa "^1.2.1"
|
||||||
|
clone "^2.1.1"
|
||||||
|
eth-query "^2.1.2"
|
||||||
|
eth-rpc-errors "^2.1.1"
|
||||||
|
eth-sig-util "^1.4.2"
|
||||||
|
ethereumjs-block "^1.6.0"
|
||||||
|
ethereumjs-tx "^1.3.7"
|
||||||
|
ethereumjs-util "^5.1.2"
|
||||||
|
ethereumjs-vm "^2.6.0"
|
||||||
|
fetch-ponyfill "^4.0.0"
|
||||||
|
json-rpc-engine "^5.1.3"
|
||||||
|
json-stable-stringify "^1.0.1"
|
||||||
|
pify "^3.0.0"
|
||||||
|
safe-event-emitter "^1.0.1"
|
||||||
|
|
||||||
eth-keyring-controller@^5.3.0, eth-keyring-controller@^5.6.1:
|
eth-keyring-controller@^5.3.0, eth-keyring-controller@^5.6.1:
|
||||||
version "5.6.1"
|
version "5.6.1"
|
||||||
resolved "https://registry.yarnpkg.com/eth-keyring-controller/-/eth-keyring-controller-5.6.1.tgz#7b7268400704c8f5ce98a055910341177dd207ca"
|
resolved "https://registry.yarnpkg.com/eth-keyring-controller/-/eth-keyring-controller-5.6.1.tgz#7b7268400704c8f5ce98a055910341177dd207ca"
|
||||||
@ -10275,6 +10295,13 @@ eth-query@^2.0.2, eth-query@^2.1.0, eth-query@^2.1.2:
|
|||||||
json-rpc-random-id "^1.0.0"
|
json-rpc-random-id "^1.0.0"
|
||||||
xtend "^4.0.1"
|
xtend "^4.0.1"
|
||||||
|
|
||||||
|
eth-rpc-errors@^2.1.1:
|
||||||
|
version "2.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/eth-rpc-errors/-/eth-rpc-errors-2.1.1.tgz#00a7d6c8a9c864a8ab7d0356be20964e5bee4b13"
|
||||||
|
integrity sha512-MY3zAa5ZF8hvgQu1HOF9agaK5GgigBRGpTJ8H0oVlE0NqMu13CW6syyjLXdeIDCGQTbUeHliU1z9dVmvMKx1Tg==
|
||||||
|
dependencies:
|
||||||
|
fast-safe-stringify "^2.0.6"
|
||||||
|
|
||||||
eth-sig-util@2.3.0, eth-sig-util@^2.3.0:
|
eth-sig-util@2.3.0, eth-sig-util@^2.3.0:
|
||||||
version "2.3.0"
|
version "2.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-2.3.0.tgz#c54a6ac8e8796f7e25f59cf436982a930e645231"
|
resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-2.3.0.tgz#c54a6ac8e8796f7e25f59cf436982a930e645231"
|
||||||
@ -13060,9 +13087,9 @@ gulp-babel@^8.0.0:
|
|||||||
vinyl-sourcemaps-apply "^0.2.0"
|
vinyl-sourcemaps-apply "^0.2.0"
|
||||||
|
|
||||||
gulp-cli@^2.2.0:
|
gulp-cli@^2.2.0:
|
||||||
version "2.2.0"
|
version "2.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/gulp-cli/-/gulp-cli-2.2.0.tgz#5533126eeb7fe415a7e3e84a297d334d5cf70ebc"
|
resolved "https://registry.yarnpkg.com/gulp-cli/-/gulp-cli-2.3.0.tgz#ec0d380e29e52aa45e47977f0d32e18fd161122f"
|
||||||
integrity sha512-rGs3bVYHdyJpLqR0TUBnlcZ1O5O++Zs4bA0ajm+zr3WFCfiSLjGwoCBqFs18wzN+ZxahT9DkOK5nDf26iDsWjA==
|
integrity sha512-zzGBl5fHo0EKSXsHzjspp3y5CONegCm8ErO5Qh0UzFzk2y4tMvzLWhoDokADbarfZRL2pGpRp7yt6gfJX4ph7A==
|
||||||
dependencies:
|
dependencies:
|
||||||
ansi-colors "^1.0.1"
|
ansi-colors "^1.0.1"
|
||||||
archy "^1.0.0"
|
archy "^1.0.0"
|
||||||
@ -13072,7 +13099,7 @@ gulp-cli@^2.2.0:
|
|||||||
copy-props "^2.0.1"
|
copy-props "^2.0.1"
|
||||||
fancy-log "^1.3.2"
|
fancy-log "^1.3.2"
|
||||||
gulplog "^1.0.0"
|
gulplog "^1.0.0"
|
||||||
interpret "^1.1.0"
|
interpret "^1.4.0"
|
||||||
isobject "^3.0.1"
|
isobject "^3.0.1"
|
||||||
liftoff "^3.1.0"
|
liftoff "^3.1.0"
|
||||||
matchdep "^2.0.0"
|
matchdep "^2.0.0"
|
||||||
@ -13080,7 +13107,7 @@ gulp-cli@^2.2.0:
|
|||||||
pretty-hrtime "^1.0.0"
|
pretty-hrtime "^1.0.0"
|
||||||
replace-homedir "^1.0.0"
|
replace-homedir "^1.0.0"
|
||||||
semver-greatest-satisfied-range "^1.1.0"
|
semver-greatest-satisfied-range "^1.1.0"
|
||||||
v8flags "^3.0.1"
|
v8flags "^3.2.0"
|
||||||
yargs "^7.1.0"
|
yargs "^7.1.0"
|
||||||
|
|
||||||
gulp-debug@^3.2.0:
|
gulp-debug@^3.2.0:
|
||||||
@ -14269,10 +14296,10 @@ internal-slot@^1.0.2:
|
|||||||
has "^1.0.3"
|
has "^1.0.3"
|
||||||
side-channel "^1.0.2"
|
side-channel "^1.0.2"
|
||||||
|
|
||||||
interpret@^1.0.0, interpret@^1.1.0:
|
interpret@^1.0.0, interpret@^1.1.0, interpret@^1.4.0:
|
||||||
version "1.1.0"
|
version "1.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614"
|
resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e"
|
||||||
integrity sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=
|
integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==
|
||||||
|
|
||||||
interpret@^2.0.0:
|
interpret@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
@ -19345,10 +19372,10 @@ node-releases@^1.1.46:
|
|||||||
dependencies:
|
dependencies:
|
||||||
semver "^6.3.0"
|
semver "^6.3.0"
|
||||||
|
|
||||||
node-sass@^4.12.0, node-sass@^4.8.3:
|
node-sass@^4.14.1, node-sass@^4.8.3:
|
||||||
version "4.13.1"
|
version "4.14.1"
|
||||||
resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.13.1.tgz#9db5689696bb2eec2c32b98bfea4c7a2e992d0a3"
|
resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.14.1.tgz#99c87ec2efb7047ed638fb4c9db7f3a42e2217b5"
|
||||||
integrity sha512-TTWFx+ZhyDx1Biiez2nB0L3YrCZ/8oHagaDalbuBSlqXgUPsdkUSzJsVxeDO9LtPB49+Fh3WQl3slABo6AotNw==
|
integrity sha512-sjCuOlvGyCJS40R8BscF5vhVlQjNN069NtQ1gSxyK1u9iqvn6tf7O1R4GNowVZfiZUCRt5MmMs1xd+4V/7Yr0g==
|
||||||
dependencies:
|
dependencies:
|
||||||
async-foreach "^0.1.3"
|
async-foreach "^0.1.3"
|
||||||
chalk "^1.1.1"
|
chalk "^1.1.1"
|
||||||
@ -19364,7 +19391,7 @@ node-sass@^4.12.0, node-sass@^4.8.3:
|
|||||||
node-gyp "^3.8.0"
|
node-gyp "^3.8.0"
|
||||||
npmlog "^4.0.0"
|
npmlog "^4.0.0"
|
||||||
request "^2.88.0"
|
request "^2.88.0"
|
||||||
sass-graph "^2.2.4"
|
sass-graph "2.2.5"
|
||||||
stdout-stream "^1.4.0"
|
stdout-stream "^1.4.0"
|
||||||
"true-case-path" "^1.0.2"
|
"true-case-path" "^1.0.2"
|
||||||
|
|
||||||
@ -24044,15 +24071,15 @@ sanitize-filename@^1.6.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
truncate-utf8-bytes "^1.0.0"
|
truncate-utf8-bytes "^1.0.0"
|
||||||
|
|
||||||
sass-graph@^2.2.4:
|
sass-graph@2.2.5:
|
||||||
version "2.2.4"
|
version "2.2.5"
|
||||||
resolved "https://registry.yarnpkg.com/sass-graph/-/sass-graph-2.2.4.tgz#13fbd63cd1caf0908b9fd93476ad43a51d1e0b49"
|
resolved "https://registry.yarnpkg.com/sass-graph/-/sass-graph-2.2.5.tgz#a981c87446b8319d96dce0671e487879bd24c2e8"
|
||||||
integrity sha1-E/vWPNHK8JCLn9k0dq1DpR0eC0k=
|
integrity sha512-VFWDAHOe6mRuT4mZRd4eKE+d8Uedrk6Xnh7Sh9b4NGufQLQjOrvf/MQoOdx+0s92L89FeyUUNfU597j/3uNpag==
|
||||||
dependencies:
|
dependencies:
|
||||||
glob "^7.0.0"
|
glob "^7.0.0"
|
||||||
lodash "^4.0.0"
|
lodash "^4.0.0"
|
||||||
scss-tokenizer "^0.2.3"
|
scss-tokenizer "^0.2.3"
|
||||||
yargs "^7.0.0"
|
yargs "^13.3.2"
|
||||||
|
|
||||||
sass-loader@^7.0.1:
|
sass-loader@^7.0.1:
|
||||||
version "7.0.1"
|
version "7.0.1"
|
||||||
@ -27548,10 +27575,10 @@ uuid@^3.3.2, uuid@^3.3.3:
|
|||||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.3.tgz#4568f0216e78760ee1dbf3a4d2cf53e224112866"
|
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.3.tgz#4568f0216e78760ee1dbf3a4d2cf53e224112866"
|
||||||
integrity sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==
|
integrity sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==
|
||||||
|
|
||||||
v8flags@^3.0.1, v8flags@^3.1.1:
|
v8flags@^3.1.1, v8flags@^3.2.0:
|
||||||
version "3.1.1"
|
version "3.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-3.1.1.tgz#42259a1461c08397e37fe1d4f1cfb59cad85a053"
|
resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-3.2.0.tgz#b243e3b4dfd731fa774e7492128109a0fe66d656"
|
||||||
integrity sha512-iw/1ViSEaff8NJ3HLyEjawk/8hjJib3E7pvG4pddVXfUg1983s3VGsiClDjhK64MQVDGqc1Q8r18S4VKQZS9EQ==
|
integrity sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==
|
||||||
dependencies:
|
dependencies:
|
||||||
homedir-polyfill "^1.0.1"
|
homedir-polyfill "^1.0.1"
|
||||||
|
|
||||||
@ -28795,7 +28822,7 @@ yargs@13.2.4:
|
|||||||
y18n "^4.0.0"
|
y18n "^4.0.0"
|
||||||
yargs-parser "^13.1.0"
|
yargs-parser "^13.1.0"
|
||||||
|
|
||||||
yargs@13.3.2, yargs@^13.2.2, yargs@^13.2.4, yargs@^13.3.0:
|
yargs@13.3.2, yargs@^13.2.2, yargs@^13.2.4, yargs@^13.3.0, yargs@^13.3.2:
|
||||||
version "13.3.2"
|
version "13.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd"
|
resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd"
|
||||||
integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==
|
integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==
|
||||||
@ -28864,7 +28891,7 @@ yargs@^15.0.0, yargs@^15.0.2:
|
|||||||
y18n "^4.0.0"
|
y18n "^4.0.0"
|
||||||
yargs-parser "^18.1.1"
|
yargs-parser "^18.1.1"
|
||||||
|
|
||||||
yargs@^7.0.0, yargs@^7.1.0:
|
yargs@^7.1.0:
|
||||||
version "7.1.0"
|
version "7.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8"
|
resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8"
|
||||||
integrity sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=
|
integrity sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=
|
||||||
|
Loading…
Reference in New Issue
Block a user