mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 01:47:00 +01:00
feature: integrate gaba/ShapeShiftController (#6569)
This commit is contained in:
parent
b81c4e5c98
commit
e57ffbed59
@ -1,180 +0,0 @@
|
||||
const ObservableStore = require('obs-store')
|
||||
const extend = require('xtend')
|
||||
const log = require('loglevel')
|
||||
|
||||
// every three seconds when an incomplete tx is waiting
|
||||
const POLLING_INTERVAL = 3000
|
||||
|
||||
class ShapeshiftController {
|
||||
|
||||
/**
|
||||
* Controller responsible for managing the list of shapeshift transactions. On construction, it initiates a poll
|
||||
* that queries a shapeshift.io API for updates to any pending shapeshift transactions
|
||||
*
|
||||
* @typedef {Object} ShapeshiftController
|
||||
* @param {object} opts Overrides the defaults for the initial state of this.store
|
||||
* @property {array} opts.initState initializes the the state of the ShapeshiftController. Can contain an
|
||||
* shapeShiftTxList array.
|
||||
* @property {array} shapeShiftTxList An array of ShapeShiftTx objects
|
||||
*
|
||||
*/
|
||||
constructor (opts = {}) {
|
||||
const initState = extend({
|
||||
shapeShiftTxList: [],
|
||||
}, opts.initState)
|
||||
this.store = new ObservableStore(initState)
|
||||
this.pollForUpdates()
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents, and contains data about, a single shapeshift transaction.
|
||||
* @typedef {Object} ShapeShiftTx
|
||||
* @property {string} depositAddress - An address at which to send a crypto deposit, so that eth can be sent to the
|
||||
* user's Metamask account
|
||||
* @property {string} depositType - An abbreviation of the type of crypto currency to be deposited.
|
||||
* @property {string} key - The 'shapeshift' key differentiates this from other types of txs in Metamask
|
||||
* @property {number} time - The time at which the tx was created
|
||||
* @property {object} response - Initiated as an empty object, which will be replaced by a Response object. @see {@link
|
||||
* https://developer.mozilla.org/en-US/docs/Web/API/Response}
|
||||
*/
|
||||
|
||||
//
|
||||
// PUBLIC METHODS
|
||||
//
|
||||
|
||||
/**
|
||||
* A getter for the shapeShiftTxList property
|
||||
*
|
||||
* @returns {array<ShapeShiftTx>}
|
||||
*
|
||||
*/
|
||||
getShapeShiftTxList () {
|
||||
const shapeShiftTxList = this.store.getState().shapeShiftTxList
|
||||
return shapeShiftTxList
|
||||
}
|
||||
|
||||
/**
|
||||
* A getter for all ShapeShiftTx in the shapeShiftTxList that have not successfully completed a deposit.
|
||||
*
|
||||
* @returns {array<ShapeShiftTx>} Only includes ShapeShiftTx which has a response property with a status !== complete
|
||||
*
|
||||
*/
|
||||
getPendingTxs () {
|
||||
const txs = this.getShapeShiftTxList()
|
||||
const pending = txs.filter(tx => tx.response && tx.response.status !== 'complete')
|
||||
return pending
|
||||
}
|
||||
|
||||
/**
|
||||
* A poll that exists as long as there are pending transactions. Each call attempts to update the data of any
|
||||
* pendingTxs, and then calls itself again. If there are no pending txs, the recursive call is not made and
|
||||
* the polling stops.
|
||||
*
|
||||
* this.updateTx is used to attempt the update to the pendingTxs in the ShapeShiftTxList, and that updated data
|
||||
* is saved with saveTx.
|
||||
*
|
||||
*/
|
||||
pollForUpdates () {
|
||||
const pendingTxs = this.getPendingTxs()
|
||||
|
||||
if (pendingTxs.length === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
Promise.all(pendingTxs.map((tx) => {
|
||||
return this.updateTx(tx)
|
||||
}))
|
||||
.then((results) => {
|
||||
results.forEach(tx => this.saveTx(tx))
|
||||
this.timeout = setTimeout(this.pollForUpdates.bind(this), POLLING_INTERVAL)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to update a ShapeShiftTx with data from a shapeshift.io API. Both the response and time properties
|
||||
* can be updated. The response property is updated with every call, but the time property is only updated when
|
||||
* the response status updates to 'complete'. This will occur once the user makes a deposit as the ShapeShiftTx
|
||||
* depositAddress
|
||||
*
|
||||
* @param {ShapeShiftTx} tx The tx to update
|
||||
*
|
||||
*/
|
||||
async updateTx (tx) {
|
||||
try {
|
||||
const url = `https://shapeshift.io/txStat/${tx.depositAddress}`
|
||||
const response = await fetch(url)
|
||||
const json = await response.json()
|
||||
tx.response = json
|
||||
if (tx.response.status === 'complete') {
|
||||
tx.time = new Date().getTime()
|
||||
}
|
||||
return tx
|
||||
} catch (err) {
|
||||
log.warn(err)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves an updated to a ShapeShiftTx in the shapeShiftTxList. If the passed ShapeShiftTx is not in the
|
||||
* shapeShiftTxList, nothing happens.
|
||||
*
|
||||
* @param {ShapeShiftTx} tx The updated tx to save, if it exists in the current shapeShiftTxList
|
||||
*
|
||||
*/
|
||||
saveTx (tx) {
|
||||
const { shapeShiftTxList } = this.store.getState()
|
||||
const index = shapeShiftTxList.indexOf(tx)
|
||||
if (index !== -1) {
|
||||
shapeShiftTxList[index] = tx
|
||||
this.store.updateState({ shapeShiftTxList })
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a ShapeShiftTx from the shapeShiftTxList
|
||||
*
|
||||
* @param {ShapeShiftTx} tx The tx to remove
|
||||
*
|
||||
*/
|
||||
removeShapeShiftTx () {
|
||||
const { shapeShiftTxList } = this.store.getState()
|
||||
const index = shapeShiftTxList.indexOf(index)
|
||||
if (index !== -1) {
|
||||
shapeShiftTxList.splice(index, 1)
|
||||
}
|
||||
this.updateState({ shapeShiftTxList })
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ShapeShiftTx, adds it to the shapeShiftTxList, and initiates a new poll for updates of pending txs
|
||||
*
|
||||
* @param {string} depositAddress - An address at which to send a crypto deposit, so that eth can be sent to the
|
||||
* user's Metamask account
|
||||
* @param {string} depositType - An abbreviation of the type of crypto currency to be deposited.
|
||||
*
|
||||
*/
|
||||
createShapeShiftTx (depositAddress, depositType) {
|
||||
const state = this.store.getState()
|
||||
let { shapeShiftTxList } = state
|
||||
|
||||
var shapeShiftTx = {
|
||||
depositAddress,
|
||||
depositType,
|
||||
key: 'shapeshift',
|
||||
time: new Date().getTime(),
|
||||
response: {},
|
||||
}
|
||||
|
||||
if (!shapeShiftTxList) {
|
||||
shapeShiftTxList = [shapeShiftTx]
|
||||
} else {
|
||||
shapeShiftTxList.push(shapeShiftTx)
|
||||
}
|
||||
|
||||
this.store.updateState({ shapeShiftTxList })
|
||||
this.pollForUpdates()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = ShapeshiftController
|
@ -27,7 +27,6 @@ const NetworkController = require('./controllers/network')
|
||||
const PreferencesController = require('./controllers/preferences')
|
||||
const AppStateController = require('./controllers/app-state')
|
||||
const CurrencyController = require('./controllers/currency')
|
||||
const ShapeShiftController = require('./controllers/shapeshift')
|
||||
const InfuraController = require('./controllers/infura')
|
||||
const CachedBalancesController = require('./controllers/cached-balances')
|
||||
const RecentBlocksController = require('./controllers/recent-blocks')
|
||||
@ -57,6 +56,7 @@ const ethUtil = require('ethereumjs-util')
|
||||
const sigUtil = require('eth-sig-util')
|
||||
const {
|
||||
AddressBookController,
|
||||
ShapeShiftController,
|
||||
PhishingController,
|
||||
} = require('gaba')
|
||||
const backEndMetaMetricsEvent = require('./lib/backend-metametrics')
|
||||
@ -237,9 +237,7 @@ module.exports = class MetamaskController extends EventEmitter {
|
||||
})
|
||||
this.balancesController.updateAllBalances()
|
||||
|
||||
this.shapeshiftController = new ShapeShiftController({
|
||||
initState: initState.ShapeShiftController,
|
||||
})
|
||||
this.shapeshiftController = new ShapeShiftController(undefined, initState.ShapeShiftController)
|
||||
|
||||
this.networkController.lookupNetwork()
|
||||
this.messageManager = new MessageManager()
|
||||
@ -265,7 +263,7 @@ module.exports = class MetamaskController extends EventEmitter {
|
||||
PreferencesController: this.preferencesController.store,
|
||||
AddressBookController: this.addressBookController,
|
||||
CurrencyController: this.currencyController.store,
|
||||
ShapeShiftController: this.shapeshiftController.store,
|
||||
ShapeShiftController: this.shapeshiftController,
|
||||
NetworkController: this.networkController.store,
|
||||
InfuraController: this.infuraController.store,
|
||||
CachedBalancesController: this.cachedBalancesController.store,
|
||||
@ -287,7 +285,7 @@ module.exports = class MetamaskController extends EventEmitter {
|
||||
RecentBlocksController: this.recentBlocksController.store,
|
||||
AddressBookController: this.addressBookController,
|
||||
CurrencyController: this.currencyController.store,
|
||||
ShapeshiftController: this.shapeshiftController.store,
|
||||
ShapeshiftController: this.shapeshiftController,
|
||||
InfuraController: this.infuraController.store,
|
||||
ProviderApprovalController: this.providerApprovalController.store,
|
||||
})
|
||||
@ -1633,7 +1631,7 @@ module.exports = class MetamaskController extends EventEmitter {
|
||||
* @property {string} depositType - An abbreviation of the type of crypto currency to be deposited.
|
||||
*/
|
||||
createShapeShiftTx (depositAddress, depositType) {
|
||||
this.shapeshiftController.createShapeShiftTx(depositAddress, depositType)
|
||||
this.shapeshiftController.createTransaction(depositAddress, depositType)
|
||||
}
|
||||
|
||||
// network
|
||||
|
@ -464,7 +464,7 @@ describe('MetaMaskController', function () {
|
||||
|
||||
depositAddress = '3EevLFfB4H4XMWQwYCgjLie1qCAGpd2WBc'
|
||||
depositType = 'ETH'
|
||||
shapeShiftTxList = metamaskController.shapeshiftController.store.getState().shapeShiftTxList
|
||||
shapeShiftTxList = metamaskController.shapeshiftController.state.shapeShiftTxList
|
||||
})
|
||||
|
||||
it('creates a shapeshift tx', async function () {
|
||||
|
Loading…
Reference in New Issue
Block a user