mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-26 12:29:06 +01:00
Log web3 usage for functions and nested properties only (#9797)
* Log web3 usage for functions and nested properties only * Change web3 metrics source to legacy * Update web3 metrics properties and event name Co-authored-by: Mark Stacey <markjstacey@gmail.com>
This commit is contained in:
parent
b1b78ff5a5
commit
6426816411
@ -35,18 +35,19 @@ const recordedWeb3Usage = {}
|
||||
* @param {LogWeb3UsageOptions} options
|
||||
*/
|
||||
function logWeb3UsageHandler(req, res, _next, end, { origin, sendMetrics }) {
|
||||
const { action, name } = req.params[0]
|
||||
const { action, path } = req.params[0]
|
||||
|
||||
if (!recordedWeb3Usage[origin]) {
|
||||
recordedWeb3Usage[origin] = {}
|
||||
}
|
||||
if (!recordedWeb3Usage[origin][name]) {
|
||||
recordedWeb3Usage[origin][name] = true
|
||||
if (!recordedWeb3Usage[origin][path]) {
|
||||
recordedWeb3Usage[origin][path] = true
|
||||
|
||||
sendMetrics({
|
||||
event: `Website Accessed window.web3`,
|
||||
matomo: true,
|
||||
event: `Website Used window.web3`,
|
||||
category: 'inpage_provider',
|
||||
properties: { action, web3Property: name },
|
||||
properties: { action, web3Path: path },
|
||||
eventContext: {
|
||||
referrer: {
|
||||
url: origin,
|
||||
|
@ -3,6 +3,7 @@
|
||||
// TODO:deprecate:2020
|
||||
// Delete this file
|
||||
|
||||
import web3Entitites from './web3-entities.json'
|
||||
import 'web3/dist/web3.min'
|
||||
|
||||
const shouldLogUsage = ![
|
||||
@ -11,6 +12,10 @@ const shouldLogUsage = ![
|
||||
'metamask.io',
|
||||
].includes(window.location.hostname)
|
||||
|
||||
/**
|
||||
* To understand how we arrived at this implementation, please see:
|
||||
* https://github.com/ethereum/web3.js/blob/0.20.7/DOCUMENTATION.md
|
||||
*/
|
||||
export default function setupWeb3(log) {
|
||||
// export web3 as a global, checking for usage
|
||||
let reloadInProgress = false
|
||||
@ -31,8 +36,122 @@ export default function setupWeb3(log) {
|
||||
value: web3.eth,
|
||||
})
|
||||
|
||||
// Setup logging of nested property usage
|
||||
if (shouldLogUsage) {
|
||||
// web3 namespaces with common and uncommon dapp actions
|
||||
const includedTopKeys = [
|
||||
'eth',
|
||||
'db',
|
||||
'shh',
|
||||
'net',
|
||||
'personal',
|
||||
'bzz',
|
||||
'version',
|
||||
]
|
||||
|
||||
// For each top-level property, create appropriate Proxy traps for all of
|
||||
// their properties
|
||||
includedTopKeys.forEach((topKey) => {
|
||||
const applyTrapKeys = new Map()
|
||||
const getTrapKeys = new Map()
|
||||
|
||||
Object.keys(web3[topKey]).forEach((key) => {
|
||||
const path = `web3.${topKey}.${key}`
|
||||
|
||||
if (web3Entitites[path]) {
|
||||
if (web3Entitites[path] === 'function') {
|
||||
applyTrapKeys.set(key, path)
|
||||
} else {
|
||||
getTrapKeys.set(key, path)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// Create apply traps for function properties
|
||||
for (const [key, path] of applyTrapKeys) {
|
||||
web3[topKey][key] = new Proxy(web3[topKey][key], {
|
||||
apply: (...params) => {
|
||||
window.ethereum.request({
|
||||
method: 'metamask_logInjectedWeb3Usage',
|
||||
params: [
|
||||
{
|
||||
action: 'apply',
|
||||
path,
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
// Call function normally
|
||||
return Reflect.apply(...params)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// Create get trap for non-function properties
|
||||
web3[topKey] = new Proxy(web3[topKey], {
|
||||
get: (web3Prop, key, ...params) => {
|
||||
const name = stringifyKey(key)
|
||||
|
||||
if (getTrapKeys.has(name)) {
|
||||
window.ethereum.request({
|
||||
method: 'metamask_logInjectedWeb3Usage',
|
||||
params: [
|
||||
{
|
||||
action: 'get',
|
||||
path: getTrapKeys.get(name),
|
||||
},
|
||||
],
|
||||
})
|
||||
}
|
||||
|
||||
// return value normally
|
||||
return Reflect.get(web3Prop, key, ...params)
|
||||
},
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const topLevelFunctions = [
|
||||
'isConnected',
|
||||
'setProvider',
|
||||
'reset',
|
||||
'sha3',
|
||||
'toHex',
|
||||
'toAscii',
|
||||
'fromAscii',
|
||||
'toDecimal',
|
||||
'fromDecimal',
|
||||
'fromWei',
|
||||
'toWei',
|
||||
'toBigNumber',
|
||||
'isAddress',
|
||||
]
|
||||
|
||||
// apply-trap top-level functions
|
||||
topLevelFunctions.forEach((key) => {
|
||||
// This type check is probably redundant, but we've been burned before.
|
||||
if (typeof web3[key] === 'function') {
|
||||
web3[key] = new Proxy(web3[key], {
|
||||
apply: (...params) => {
|
||||
window.ethereum.request({
|
||||
method: 'metamask_logInjectedWeb3Usage',
|
||||
params: [
|
||||
{
|
||||
action: 'apply',
|
||||
path: `web3.${key}`,
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
// Call function normally
|
||||
return Reflect.apply(...params)
|
||||
},
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
const web3Proxy = new Proxy(web3, {
|
||||
get: (_web3, key) => {
|
||||
get: (...params) => {
|
||||
// get the time of use
|
||||
lastTimeUsed = Date.now()
|
||||
|
||||
@ -44,28 +163,8 @@ export default function setupWeb3(log) {
|
||||
hasBeenWarned = true
|
||||
}
|
||||
|
||||
if (shouldLogUsage) {
|
||||
const name = stringifyKey(key)
|
||||
window.ethereum.request({
|
||||
method: 'metamask_logInjectedWeb3Usage',
|
||||
params: [{ action: 'get', name }],
|
||||
})
|
||||
}
|
||||
|
||||
// return value normally
|
||||
return _web3[key]
|
||||
},
|
||||
set: (_web3, key, value) => {
|
||||
const name = stringifyKey(key)
|
||||
if (shouldLogUsage) {
|
||||
window.ethereum.request({
|
||||
method: 'metamask_logInjectedWeb3Usage',
|
||||
params: [{ action: 'set', name }],
|
||||
})
|
||||
}
|
||||
|
||||
// set value normally
|
||||
_web3[key] = value
|
||||
return Reflect.get(...params)
|
||||
},
|
||||
})
|
||||
|
||||
|
101
app/scripts/lib/web3-entities.json
Normal file
101
app/scripts/lib/web3-entities.json
Normal file
@ -0,0 +1,101 @@
|
||||
{
|
||||
"web3.bzz.blockNetworkRead": "function",
|
||||
"web3.bzz.download": "function",
|
||||
"web3.bzz.get": "function",
|
||||
"web3.bzz.getHive": "function",
|
||||
"web3.bzz.getInfo": "function",
|
||||
"web3.bzz.hive": "TRAP",
|
||||
"web3.bzz.info": "TRAP",
|
||||
"web3.bzz.modify": "function",
|
||||
"web3.bzz.put": "function",
|
||||
"web3.bzz.retrieve": "function",
|
||||
"web3.bzz.store": "function",
|
||||
"web3.bzz.swapEnabled": "function",
|
||||
"web3.bzz.syncEnabled": "function",
|
||||
"web3.bzz.upload": "function",
|
||||
"web3.db.getHex": "function",
|
||||
"web3.db.getString": "function",
|
||||
"web3.db.putHex": "function",
|
||||
"web3.db.putString": "function",
|
||||
"web3.eth.accounts": "object",
|
||||
"web3.eth.blockNumber": "TRAP",
|
||||
"web3.eth.call": "function",
|
||||
"web3.eth.coinbase": "object",
|
||||
"web3.eth.compile": "object",
|
||||
"web3.eth.estimateGas": "function",
|
||||
"web3.eth.gasPrice": "TRAP",
|
||||
"web3.eth.getAccounts": "function",
|
||||
"web3.eth.getBalance": "function",
|
||||
"web3.eth.getBlock": "function",
|
||||
"web3.eth.getBlockNumber": "function",
|
||||
"web3.eth.getBlockTransactionCount": "function",
|
||||
"web3.eth.getBlockUncleCount": "function",
|
||||
"web3.eth.getCode": "function",
|
||||
"web3.eth.getCoinbase": "function",
|
||||
"web3.eth.getCompilers": "function",
|
||||
"web3.eth.getGasPrice": "function",
|
||||
"web3.eth.getHashrate": "function",
|
||||
"web3.eth.getMining": "function",
|
||||
"web3.eth.getProtocolVersion": "function",
|
||||
"web3.eth.getStorageAt": "function",
|
||||
"web3.eth.getSyncing": "function",
|
||||
"web3.eth.getTransaction": "function",
|
||||
"web3.eth.getTransactionCount": "function",
|
||||
"web3.eth.getTransactionFromBlock": "function",
|
||||
"web3.eth.getTransactionReceipt": "function",
|
||||
"web3.eth.getUncle": "function",
|
||||
"web3.eth.getWork": "function",
|
||||
"web3.eth.hashrate": "TRAP",
|
||||
"web3.eth.iban": "function",
|
||||
"web3.eth.mining": "TRAP",
|
||||
"web3.eth.protocolVersion": "TRAP",
|
||||
"web3.eth.sendIBANTransaction": "function",
|
||||
"web3.eth.sendRawTransaction": "function",
|
||||
"web3.eth.sendTransaction": "function",
|
||||
"web3.eth.sign": "function",
|
||||
"web3.eth.signTransaction": "function",
|
||||
"web3.eth.submitWork": "function",
|
||||
"web3.eth.syncing": "TRAP",
|
||||
"web3.net.getListening": "function",
|
||||
"web3.net.getPeerCount": "function",
|
||||
"web3.net.listening": "TRAP",
|
||||
"web3.net.peerCount": "TRAP",
|
||||
"web3.personal.ecRecover": "function",
|
||||
"web3.personal.getListAccounts": "function",
|
||||
"web3.personal.importRawKey": "function",
|
||||
"web3.personal.listAccounts": "TRAP",
|
||||
"web3.personal.lockAccount": "function",
|
||||
"web3.personal.newAccount": "function",
|
||||
"web3.personal.sendTransaction": "function",
|
||||
"web3.personal.sign": "function",
|
||||
"web3.personal.unlockAccount": "function",
|
||||
"web3.providers.HttpProvider": "function",
|
||||
"web3.providers.IpcProvider": "function",
|
||||
"web3.shh.addPrivateKey": "function",
|
||||
"web3.shh.addSymKey": "function",
|
||||
"web3.shh.deleteKeyPair": "function",
|
||||
"web3.shh.deleteSymKey": "function",
|
||||
"web3.shh.generateSymKeyFromPassword": "function",
|
||||
"web3.shh.getPrivateKey": "function",
|
||||
"web3.shh.getPublicKey": "function",
|
||||
"web3.shh.getSymKey": "function",
|
||||
"web3.shh.hasKeyPair": "function",
|
||||
"web3.shh.hasSymKey": "function",
|
||||
"web3.shh.info": "function",
|
||||
"web3.shh.markTrustedPeer": "function",
|
||||
"web3.shh.newKeyPair": "function",
|
||||
"web3.shh.newSymKey": "function",
|
||||
"web3.shh.post": "function",
|
||||
"web3.shh.setMaxMessageSize": "function",
|
||||
"web3.shh.setMinPoW": "function",
|
||||
"web3.shh.version": "function",
|
||||
"web3.version.api": "string",
|
||||
"web3.version.ethereum": "TRAP",
|
||||
"web3.version.getEthereum": "function",
|
||||
"web3.version.getNetwork": "function",
|
||||
"web3.version.getNode": "function",
|
||||
"web3.version.getWhisper": "function",
|
||||
"web3.version.network": "string",
|
||||
"web3.version.node": "TRAP",
|
||||
"web3.version.whisper": "TRAP"
|
||||
}
|
Loading…
Reference in New Issue
Block a user