I#6704 eth_getTransactionByHash will now check metamask's local history for pending transactions (#7327)
* tests - create tests for pending middlewares * transactions - add r,s,v values to the txMeta to match the JSON rpc response * network - add new middleware for eth_getTransactionByHash that the checks pending tx's for a response value * transactions/pending - use getTransactionReceipt for checking if tx is in a block * meta - file renamefeature/default_network_editable
parent
51e5220d5e
commit
514be408f8
@ -0,0 +1,28 @@ |
||||
const { formatTxMetaForRpcResult } = require('../util') |
||||
const createAsyncMiddleware = require('json-rpc-engine/src/createAsyncMiddleware') |
||||
|
||||
function createPendingNonceMiddleware ({ getPendingNonce }) { |
||||
return createAsyncMiddleware(async (req, res, next) => { |
||||
const {method, params} = req |
||||
if (method !== 'eth_getTransactionCount') return next() |
||||
const [param, blockRef] = params |
||||
if (blockRef !== 'pending') return next() |
||||
res.result = await getPendingNonce(param) |
||||
}) |
||||
} |
||||
|
||||
function createPendingTxMiddleware ({ getPendingTransactionByHash }) { |
||||
return createAsyncMiddleware(async (req, res, next) => { |
||||
const {method, params} = req |
||||
if (method !== 'eth_getTransactionByHash') return next() |
||||
const [hash] = params |
||||
const txMeta = getPendingTransactionByHash(hash) |
||||
if (!txMeta) return next() |
||||
res.result = formatTxMetaForRpcResult(txMeta) |
||||
}) |
||||
} |
||||
|
||||
module.exports = { |
||||
createPendingTxMiddleware, |
||||
createPendingNonceMiddleware, |
||||
} |
@ -1,9 +1,9 @@ |
||||
const assert = require('assert') |
||||
const nock = require('nock') |
||||
const NetworkController = require('../../../../app/scripts/controllers/network') |
||||
const NetworkController = require('../../../../../app/scripts/controllers/network') |
||||
const { |
||||
getNetworkDisplayName, |
||||
} = require('../../../../app/scripts/controllers/network/util') |
||||
} = require('../../../../../app/scripts/controllers/network/util') |
||||
|
||||
describe('# Network Controller', function () { |
||||
let networkController |
@ -0,0 +1,81 @@ |
||||
const assert = require('assert') |
||||
const { createPendingNonceMiddleware, createPendingTxMiddleware } = require('../../../../../app/scripts/controllers/network/middleware/pending') |
||||
const txMetaStub = require('./stubs').txMetaStub |
||||
describe('#createPendingNonceMiddleware', function () { |
||||
const getPendingNonce = async () => '0x2' |
||||
const address = '0xF231D46dD78806E1DD93442cf33C7671f8538748' |
||||
const pendingNonceMiddleware = createPendingNonceMiddleware({ getPendingNonce }) |
||||
|
||||
it('should call next if not a eth_getTransactionCount request', (done) => { |
||||
const req = {method: 'eth_getBlockByNumber'} |
||||
const res = {} |
||||
pendingNonceMiddleware(req, res, () => done()) |
||||
}) |
||||
it('should call next if not a "pending" block request', (done) => { |
||||
const req = { method: 'eth_getTransactionCount', params: [address] } |
||||
const res = {} |
||||
pendingNonceMiddleware(req, res, () => done()) |
||||
}) |
||||
it('should fill the result with a the "pending" nonce', (done) => { |
||||
const req = { method: 'eth_getTransactionCount', params: [address, 'pending'] } |
||||
const res = {} |
||||
pendingNonceMiddleware(req, res, () => { done(new Error('should not have called next')) }, () => { |
||||
assert(res.result === '0x2') |
||||
done() |
||||
}) |
||||
}) |
||||
}) |
||||
|
||||
describe('#createPendingTxMiddleware', function () { |
||||
let returnUndefined = true |
||||
const getPendingTransactionByHash = () => returnUndefined ? undefined : txMetaStub |
||||
const address = '0xF231D46dD78806E1DD93442cf33C7671f8538748' |
||||
const pendingTxMiddleware = createPendingTxMiddleware({ getPendingTransactionByHash }) |
||||
const spec = { |
||||
'blockHash': null, |
||||
'blockNumber': null, |
||||
'from': '0xf231d46dd78806e1dd93442cf33c7671f8538748', |
||||
'gas': '0x5208', |
||||
'gasPrice': '0x1e8480', |
||||
'hash': '0x2cc5a25744486f7383edebbf32003e5a66e18135799593d6b5cdd2bb43674f09', |
||||
'input': '0x', |
||||
'nonce': '0x4', |
||||
'to': '0xf231d46dd78806e1dd93442cf33c7671f8538748', |
||||
'transactionIndex': null, |
||||
'value': '0x0', |
||||
'v': '0x2c', |
||||
'r': '0x5f973e540f2d3c2f06d3725a626b75247593cb36477187ae07ecfe0a4db3cf57', |
||||
's': '0x0259b52ee8c58baaa385fb05c3f96116e58de89bcc165cb3bfdfc708672fed8a', |
||||
} |
||||
it('should call next if not a eth_getTransactionByHash request', (done) => { |
||||
const req = {method: 'eth_getBlockByNumber'} |
||||
const res = {} |
||||
pendingTxMiddleware(req, res, () => done()) |
||||
}) |
||||
|
||||
it('should call next if no pending txMeta is in history', (done) => { |
||||
const req = { method: 'eth_getTransactionByHash', params: [address] } |
||||
const res = {} |
||||
pendingTxMiddleware(req, res, () => done()) |
||||
}) |
||||
|
||||
it('should fill the result with a the "pending" tx the result should match the rpc spec', (done) => { |
||||
returnUndefined = false |
||||
const req = { method: 'eth_getTransactionByHash', params: [address, 'pending'] } |
||||
const res = {} |
||||
pendingTxMiddleware(req, res, () => { done(new Error('should not have called next')) }, () => { |
||||
/* |
||||
// uncomment this section for debugging help with non matching keys
|
||||
const coppy = {...res.result} |
||||
Object.keys(spec).forEach((key) => { |
||||
console.log(coppy[key], '===', spec[key], coppy[key] === spec[key], key) |
||||
delete coppy[key] |
||||
}) |
||||
console.log(coppy) |
||||
*/ |
||||
assert.deepStrictEqual(res.result, spec, new Error('result does not match the spec object')) |
||||
done() |
||||
}) |
||||
}) |
||||
|
||||
}) |
@ -0,0 +1,225 @@ |
||||
/* |
||||
this file is for all my big stubs because i don't want to |
||||
to mingle with my tests |
||||
*/ |
||||
|
||||
module.exports = {} |
||||
|
||||
// for pending middlewares test
|
||||
module.exports.txMetaStub = { |
||||
'estimatedGas': '0x5208', |
||||
'firstRetryBlockNumber': '0x51a402', |
||||
'gasLimitSpecified': true, |
||||
'gasPriceSpecified': true, |
||||
'hash': '0x2cc5a25744486f7383edebbf32003e5a66e18135799593d6b5cdd2bb43674f09', |
||||
'history': [ |
||||
{ |
||||
'id': 405984854664302, |
||||
'loadingDefaults': true, |
||||
'metamaskNetworkId': '4', |
||||
'status': 'unapproved', |
||||
'time': 1572395156620, |
||||
'transactionCategory': 'sentEther', |
||||
'txParams': { |
||||
'from': '0xf231d46dd78806e1dd93442cf33c7671f8538748', |
||||
'gas': '0x5208', |
||||
'gasPrice': '0x1e8480', |
||||
'to': '0xf231d46dd78806e1dd93442cf33c7671f8538748', |
||||
'value': '0x0', |
||||
}, |
||||
'type': 'standard', |
||||
}, |
||||
[ |
||||
{ |
||||
'op': 'replace', |
||||
'path': '/loadingDefaults', |
||||
'timestamp': 1572395156645, |
||||
'value': false, |
||||
}, |
||||
{ |
||||
'op': 'add', |
||||
'path': '/gasPriceSpecified', |
||||
'value': true, |
||||
}, |
||||
{ |
||||
'op': 'add', |
||||
'path': '/gasLimitSpecified', |
||||
'value': true, |
||||
}, |
||||
{ |
||||
'op': 'add', |
||||
'path': '/estimatedGas', |
||||
'value': '0x5208', |
||||
}, |
||||
], |
||||
[ |
||||
{ |
||||
'note': '#newUnapprovedTransaction - adding the origin', |
||||
'op': 'add', |
||||
'path': '/origin', |
||||
'timestamp': 1572395156645, |
||||
'value': 'MetaMask', |
||||
}, |
||||
], |
||||
[], |
||||
[ |
||||
{ |
||||
'note': 'txStateManager: setting status to approved', |
||||
'op': 'replace', |
||||
'path': '/status', |
||||
'timestamp': 1572395158240, |
||||
'value': 'approved', |
||||
}, |
||||
], |
||||
[ |
||||
{ |
||||
'note': 'transactions#approveTransaction', |
||||
'op': 'add', |
||||
'path': '/txParams/nonce', |
||||
'timestamp': 1572395158261, |
||||
'value': '0x4', |
||||
}, |
||||
{ |
||||
'op': 'add', |
||||
'path': '/nonceDetails', |
||||
'value': { |
||||
'local': { |
||||
'details': { |
||||
'highest': 4, |
||||
'startPoint': 4, |
||||
}, |
||||
'name': 'local', |
||||
'nonce': 4, |
||||
}, |
||||
'network': { |
||||
'details': { |
||||
'baseCount': 4, |
||||
'blockNumber': '0x51a401', |
||||
}, |
||||
'name': 'network', |
||||
'nonce': 4, |
||||
}, |
||||
'params': { |
||||
'highestLocallyConfirmed': 0, |
||||
'highestSuggested': 4, |
||||
'nextNetworkNonce': 4, |
||||
}, |
||||
}, |
||||
}, |
||||
], |
||||
[ |
||||
{ |
||||
'note': 'transactions#signTransaction: add r, s, v values', |
||||
'op': 'add', |
||||
'path': '/r', |
||||
'timestamp': 1572395158280, |
||||
'value': '0x5f973e540f2d3c2f06d3725a626b75247593cb36477187ae07ecfe0a4db3cf57', |
||||
}, |
||||
{ |
||||
'op': 'add', |
||||
'path': '/s', |
||||
'value': '0x0259b52ee8c58baaa385fb05c3f96116e58de89bcc165cb3bfdfc708672fed8a', |
||||
}, |
||||
{ |
||||
'op': 'add', |
||||
'path': '/v', |
||||
'value': '0x2c', |
||||
}, |
||||
], |
||||
[ |
||||
{ |
||||
'note': 'transactions#publishTransaction', |
||||
'op': 'replace', |
||||
'path': '/status', |
||||
'timestamp': 1572395158281, |
||||
'value': 'signed', |
||||
}, |
||||
{ |
||||
'op': 'add', |
||||
'path': '/rawTx', |
||||
'value': '0xf86204831e848082520894f231d46dd78806e1dd93442cf33c7671f853874880802ca05f973e540f2d3c2f06d3725a626b75247593cb36477187ae07ecfe0a4db3cf57a00259b52ee8c58baaa385fb05c3f96116e58de89bcc165cb3bfdfc708672fed8a', |
||||
}, |
||||
], |
||||
[], |
||||
[ |
||||
{ |
||||
'note': 'transactions#setTxHash', |
||||
'op': 'add', |
||||
'path': '/hash', |
||||
'timestamp': 1572395158570, |
||||
'value': '0x2cc5a25744486f7383edebbf32003e5a66e18135799593d6b5cdd2bb43674f09', |
||||
}, |
||||
], |
||||
[ |
||||
{ |
||||
'note': 'txStateManager - add submitted time stamp', |
||||
'op': 'add', |
||||
'path': '/submittedTime', |
||||
'timestamp': 1572395158571, |
||||
'value': 1572395158570, |
||||
}, |
||||
], |
||||
[ |
||||
{ |
||||
'note': 'txStateManager: setting status to submitted', |
||||
'op': 'replace', |
||||
'path': '/status', |
||||
'timestamp': 1572395158576, |
||||
'value': 'submitted', |
||||
}, |
||||
], |
||||
[ |
||||
{ |
||||
'note': 'transactions/pending-tx-tracker#event: tx:block-update', |
||||
'op': 'add', |
||||
'path': '/firstRetryBlockNumber', |
||||
'timestamp': 1572395168972, |
||||
'value': '0x51a402', |
||||
}, |
||||
], |
||||
], |
||||
'id': 405984854664302, |
||||
'loadingDefaults': false, |
||||
'metamaskNetworkId': '4', |
||||
'nonceDetails': { |
||||
'local': { |
||||
'details': { |
||||
'highest': 4, |
||||
'startPoint': 4, |
||||
}, |
||||
'name': 'local', |
||||
'nonce': 4, |
||||
}, |
||||
'network': { |
||||
'details': { |
||||
'baseCount': 4, |
||||
'blockNumber': '0x51a401', |
||||
}, |
||||
'name': 'network', |
||||
'nonce': 4, |
||||
}, |
||||
'params': { |
||||
'highestLocallyConfirmed': 0, |
||||
'highestSuggested': 4, |
||||
'nextNetworkNonce': 4, |
||||
}, |
||||
}, |
||||
'origin': 'MetaMask', |
||||
'r': '0x5f973e540f2d3c2f06d3725a626b75247593cb36477187ae07ecfe0a4db3cf57', |
||||
'rawTx': '0xf86204831e848082520894f231d46dd78806e1dd93442cf33c7671f853874880802ca05f973e540f2d3c2f06d3725a626b75247593cb36477187ae07ecfe0a4db3cf57a00259b52ee8c58baaa385fb05c3f96116e58de89bcc165cb3bfdfc708672fed8a', |
||||
's': '0x0259b52ee8c58baaa385fb05c3f96116e58de89bcc165cb3bfdfc708672fed8a', |
||||
'status': 'submitted', |
||||
'submittedTime': 1572395158570, |
||||
'time': 1572395156620, |
||||
'transactionCategory': 'sentEther', |
||||
'txParams': { |
||||
'from': '0xf231d46dd78806e1dd93442cf33c7671f8538748', |
||||
'gas': '0x5208', |
||||
'gasPrice': '0x1e8480', |
||||
'nonce': '0x4', |
||||
'to': '0xf231d46dd78806e1dd93442cf33c7671f8538748', |
||||
'value': '0x0', |
||||
}, |
||||
'type': 'standard', |
||||
'v': '0x2c', |
||||
} |
Loading…
Reference in new issue