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 assert = require('assert') |
||||||
const nock = require('nock') |
const nock = require('nock') |
||||||
const NetworkController = require('../../../../app/scripts/controllers/network') |
const NetworkController = require('../../../../../app/scripts/controllers/network') |
||||||
const { |
const { |
||||||
getNetworkDisplayName, |
getNetworkDisplayName, |
||||||
} = require('../../../../app/scripts/controllers/network/util') |
} = require('../../../../../app/scripts/controllers/network/util') |
||||||
|
|
||||||
describe('# Network Controller', function () { |
describe('# Network Controller', function () { |
||||||
let networkController |
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