mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-29 07:16:36 +01:00
Persist transactions to config-manager
Transactions are now stored, and are never deleted, they only have their status updated. We can add deleting later if we'd like. I've hacked on emitting the new unconfirmedTx key to the UI in the format it received before, I want Aaron's opinion on where I should actually do that.
This commit is contained in:
parent
65d73d7bb4
commit
a441e635bd
@ -117,6 +117,7 @@ function storeSetFromObj(store, obj){
|
|||||||
Object.keys(obj).forEach(function(key){
|
Object.keys(obj).forEach(function(key){
|
||||||
store.set(key, obj[key])
|
store.set(key, obj[key])
|
||||||
})
|
})
|
||||||
|
store.set('unconfTxs', configManager.unconfirmedTxs())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -191,7 +192,8 @@ idStore.on('update', updateBadge)
|
|||||||
|
|
||||||
function updateBadge(state){
|
function updateBadge(state){
|
||||||
var label = ''
|
var label = ''
|
||||||
var count = Object.keys(state.unconfTxs).length
|
var unconfTxs = configManager.unconfirmedTxs()
|
||||||
|
var count = Object.keys(unconfTxs).length
|
||||||
if (count) {
|
if (count) {
|
||||||
label = String(count)
|
label = String(count)
|
||||||
}
|
}
|
||||||
|
@ -134,6 +134,56 @@ ConfigManager.prototype.setData = function(data) {
|
|||||||
this.migrator.saveData(data)
|
this.migrator.saveData(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ConfigManager.prototype.getTxList = function() {
|
||||||
|
var data = this.migrator.getData()
|
||||||
|
if ('transactions' in data) {
|
||||||
|
return data.transactions
|
||||||
|
} else {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigManager.prototype._saveTxList = function(txList) {
|
||||||
|
var data = this.migrator.getData()
|
||||||
|
data.transactions = txList
|
||||||
|
this.setData(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigManager.prototype.addTx = function(tx) {
|
||||||
|
var transactions = this.getTxList()
|
||||||
|
transactions.push(tx)
|
||||||
|
this._saveTxList(transactions)
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigManager.prototype.getTx = function(txId) {
|
||||||
|
var transactions = this.getTxList()
|
||||||
|
var matching = transactions.filter(tx => tx.id === txId)
|
||||||
|
return matching.length > 0 ? matching[0] : null
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigManager.prototype.confirmTx = function(txId) {
|
||||||
|
this._setTxStatus(txId, 'confirmed')
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigManager.prototype.rejectTx = function(txId) {
|
||||||
|
this._setTxStatus(txId, 'rejected')
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigManager.prototype._setTxStatus = function(txId, status) {
|
||||||
|
var transactions = this.getTxList()
|
||||||
|
transactions.forEach((tx) => {
|
||||||
|
if (tx.id === txId) {
|
||||||
|
tx.status = status
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this._saveTxList(transactions)
|
||||||
|
}
|
||||||
|
ConfigManager.prototype.unconfirmedTxs = function() {
|
||||||
|
var transactions = this.getTxList()
|
||||||
|
return transactions.filter(tx => tx.status === 'unconfirmed')
|
||||||
|
.reduce((result, tx) => { result[tx.id] = tx; return result }, {})
|
||||||
|
}
|
||||||
|
|
||||||
// observable
|
// observable
|
||||||
|
|
||||||
ConfigManager.prototype.subscribe = function(fn){
|
ConfigManager.prototype.subscribe = function(fn){
|
||||||
|
@ -31,7 +31,6 @@ function IdentityStore(ethStore) {
|
|||||||
this._currentState = {
|
this._currentState = {
|
||||||
selectedAddress: null,
|
selectedAddress: null,
|
||||||
identities: {},
|
identities: {},
|
||||||
unconfTxs: {},
|
|
||||||
}
|
}
|
||||||
// not part of serilized metamask state - only kept in memory
|
// not part of serilized metamask state - only kept in memory
|
||||||
this._unconfTxCbs = {}
|
this._unconfTxCbs = {}
|
||||||
@ -140,10 +139,11 @@ IdentityStore.prototype.addUnconfirmedTransaction = function(txParams, cb){
|
|||||||
time: time,
|
time: time,
|
||||||
status: 'unconfirmed',
|
status: 'unconfirmed',
|
||||||
}
|
}
|
||||||
this._currentState.unconfTxs[txId] = txData
|
configManager.addTx(txData)
|
||||||
console.log('addUnconfirmedTransaction:', txData)
|
console.log('addUnconfirmedTransaction:', txData)
|
||||||
|
|
||||||
// keep the cb around for after approval (requires user interaction)
|
// keep the cb around for after approval (requires user interaction)
|
||||||
|
// This cb fires completion to the Dapp's write operation.
|
||||||
this._unconfTxCbs[txId] = cb
|
this._unconfTxCbs[txId] = cb
|
||||||
|
|
||||||
// signal update
|
// signal update
|
||||||
@ -154,7 +154,7 @@ IdentityStore.prototype.addUnconfirmedTransaction = function(txParams, cb){
|
|||||||
|
|
||||||
// comes from metamask ui
|
// comes from metamask ui
|
||||||
IdentityStore.prototype.approveTransaction = function(txId, cb){
|
IdentityStore.prototype.approveTransaction = function(txId, cb){
|
||||||
var txData = this._currentState.unconfTxs[txId]
|
var txData = configManager.getTx(txId)
|
||||||
var txParams = txData.txParams
|
var txParams = txData.txParams
|
||||||
var approvalCb = this._unconfTxCbs[txId] || noop
|
var approvalCb = this._unconfTxCbs[txId] || noop
|
||||||
|
|
||||||
@ -162,20 +162,20 @@ IdentityStore.prototype.approveTransaction = function(txId, cb){
|
|||||||
cb()
|
cb()
|
||||||
approvalCb(null, true)
|
approvalCb(null, true)
|
||||||
// clean up
|
// clean up
|
||||||
delete this._currentState.unconfTxs[txId]
|
configManager.confirmTx(txId)
|
||||||
delete this._unconfTxCbs[txId]
|
delete this._unconfTxCbs[txId]
|
||||||
this._didUpdate()
|
this._didUpdate()
|
||||||
}
|
}
|
||||||
|
|
||||||
// comes from metamask ui
|
// comes from metamask ui
|
||||||
IdentityStore.prototype.cancelTransaction = function(txId){
|
IdentityStore.prototype.cancelTransaction = function(txId){
|
||||||
var txData = this._currentState.unconfTxs[txId]
|
var txData = configManager.getTx(txId)
|
||||||
var approvalCb = this._unconfTxCbs[txId] || noop
|
var approvalCb = this._unconfTxCbs[txId] || noop
|
||||||
|
|
||||||
// reject tx
|
// reject tx
|
||||||
approvalCb(null, false)
|
approvalCb(null, false)
|
||||||
// clean up
|
// clean up
|
||||||
delete this._currentState.unconfTxs[txId]
|
configManager.rejectTx(txId)
|
||||||
delete this._unconfTxCbs[txId]
|
delete this._unconfTxCbs[txId]
|
||||||
this._didUpdate()
|
this._didUpdate()
|
||||||
}
|
}
|
||||||
|
@ -68,4 +68,83 @@ describe('config-manager', function() {
|
|||||||
assert.equal(secondResult, secondRpc)
|
assert.equal(secondResult, secondRpc)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('transactions', function() {
|
||||||
|
beforeEach(function() {
|
||||||
|
configManager._saveTxList([])
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('#getTxList', function() {
|
||||||
|
it('when new should return empty array', function() {
|
||||||
|
var result = configManager.getTxList()
|
||||||
|
assert.ok(Array.isArray(result))
|
||||||
|
assert.equal(result.length, 0)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('#_saveTxList', function() {
|
||||||
|
it('saves the submitted data to the tx list', function() {
|
||||||
|
var target = [{ foo: 'bar' }]
|
||||||
|
configManager._saveTxList(target)
|
||||||
|
var result = configManager.getTxList()
|
||||||
|
assert.equal(result[0].foo, 'bar')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('#addTx', function() {
|
||||||
|
it('adds a tx returned in getTxList', function() {
|
||||||
|
var tx = { id: 1 }
|
||||||
|
configManager.addTx(tx)
|
||||||
|
var result = configManager.getTxList()
|
||||||
|
assert.ok(Array.isArray(result))
|
||||||
|
assert.equal(result.length, 1)
|
||||||
|
assert.equal(result[0].id, 1)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('#confirmTx', function() {
|
||||||
|
it('sets the tx status to confirmed', function() {
|
||||||
|
var tx = { id: 1, status: 'unconfirmed' }
|
||||||
|
configManager.addTx(tx)
|
||||||
|
configManager.confirmTx(1)
|
||||||
|
var result = configManager.getTxList()
|
||||||
|
assert.ok(Array.isArray(result))
|
||||||
|
assert.equal(result.length, 1)
|
||||||
|
assert.equal(result[0].status, 'confirmed')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('#rejectTx', function() {
|
||||||
|
it('sets the tx status to rejected', function() {
|
||||||
|
var tx = { id: 1, status: 'unconfirmed' }
|
||||||
|
configManager.addTx(tx)
|
||||||
|
configManager.rejectTx(1)
|
||||||
|
var result = configManager.getTxList()
|
||||||
|
assert.ok(Array.isArray(result))
|
||||||
|
assert.equal(result.length, 1)
|
||||||
|
assert.equal(result[0].status, 'rejected')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('#unconfirmedTxs', function() {
|
||||||
|
it('returns unconfirmed txs in a hash', function() {
|
||||||
|
configManager.addTx({ id: '1', status: 'unconfirmed' })
|
||||||
|
configManager.addTx({ id: '2', status: 'confirmed' })
|
||||||
|
let result = configManager.unconfirmedTxs()
|
||||||
|
assert.equal(typeof result, 'object')
|
||||||
|
assert.equal(result['1'].status, 'unconfirmed')
|
||||||
|
assert.equal(result['0'], undefined)
|
||||||
|
assert.equal(result['2'], undefined)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('#getTx', function() {
|
||||||
|
it('returns a tx with the requested id', function() {
|
||||||
|
configManager.addTx({ id: '1', status: 'unconfirmed' })
|
||||||
|
configManager.addTx({ id: '2', status: 'confirmed' })
|
||||||
|
assert.equal(configManager.getTx('1').status, 'unconfirmed')
|
||||||
|
assert.equal(configManager.getTx('2').status, 'confirmed')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user