Skip to content
This repository has been archived by the owner on Feb 18, 2020. It is now read-only.

Feature/upgrade to web3 1.0 websockets #311

Open
wants to merge 27 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
ecbb2b2
Changed order of pre-render app functions
W3stside Jul 23, 2018
95d747f
moved getTokenList thunk into blockchain.ts
W3stside Jul 23, 2018
a2a1b78
Moved fns out of walletIntegrations + initialize removed
W3stside Jul 23, 2018
fa14d09
exported out fireListeners + linting
W3stside Jul 23, 2018
5874e41
created AppValidator to check top level app states + insrted in App comp
W3stside Jul 23, 2018
d3ebec4
added block mining in add_token_pair ts for local + lint + glob declare
W3stside Jul 23, 2018
c28eda8
upgrading to web3 1.0 beta + declare module globally
W3stside Jul 23, 2018
1171927
added types + changed toBigNumber to correct module + stories
W3stside Jul 23, 2018
d9d9bac
added ws provider init param + types
W3stside Jul 23, 2018
620fd2e
web3 1.0 beta hack for contract sendAsync
W3stside Jul 23, 2018
c1c30bf
fixed web3Prov + walletInt fns w/1.0 beta Web3
W3stside Jul 23, 2018
e592ba2
Created reducer/actions for saving TXs, types, middleware to updateState
W3stside Jul 26, 2018
2563b80
Updated AppValidator logic
W3stside Jul 26, 2018
f341fc5
use bignumber library from old web3, logging for testing in API
W3stside Jul 26, 2018
a3bf22b
New test filters for watching events and logs in new WS web3
W3stside Jul 26, 2018
0c3ce9b
Update watcher to use 1.0beta Web3 functions
W3stside Jul 26, 2018
1bbd988
Hacky fix to walletIntegrations to work with new Web3 1.0beta
W3stside Jul 26, 2018
a74e395
Change getTokenList to update avail auctions + added txSaving actions
W3stside Jul 26, 2018
4d79c1d
changed MMInit to use web31.0 beta + ability to subscribe to WS
W3stside Jul 26, 2018
b2381a1
added WS global var
W3stside Jul 26, 2018
f399846
updated Package to use bignumber from 0.20 web3 + linting
W3stside Jul 26, 2018
b2d4dd9
Fixed merge conflicts
W3stside Aug 7, 2018
baf9d98
fixed providerWatcher fns
W3stside Aug 7, 2018
c5a20dd
moved events from integrations/events to actions/events
W3stside Aug 7, 2018
1eea7a4
removed push to AuctionStatus
W3stside Aug 7, 2018
847ef6b
added contract listening to AppValidator container
W3stside Aug 7, 2018
746a26a
added TX panel + SCSS to track TXs
W3stside Aug 8, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28,584 changes: 0 additions & 28,584 deletions package-lock.json

This file was deleted.

6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@
"@gnosis.pm/util-contracts": "^1.0.1",
"autobind-decorator": "^2.1.0",
"await-delay": "^1.0.0",
"bignumber.js": "^5.0.0",
"bignumber.js": "git+https://github.com/frozeman/bignumber.js-nolookahead.git",
"blockies": "0.0.2",
"classnames": "^2.2.5",
"connected-react-router": "^4.2.3",
Expand Down Expand Up @@ -127,7 +127,7 @@
"truffle-contract": "^3.0.1",
"uglifyjs-webpack-plugin": "^1.2.5",
"uuid": "^3.1.0",
"web3": "^0.20.2",
"web3": "^1.0.0-beta.34",
"webpack": "^3.12.0",
"whatwg-fetch": "^2.0.3"
},
Expand All @@ -147,6 +147,7 @@
"@storybook/addon-links": "^3.3.14",
"@storybook/react": "^3.3.14",
"@types/bignumber.js": "^4.0.3",
"@types/bn.js": "^4.11.1",
"@types/decimal.js": "0.0.31",
"@types/expect": "^1.20.2",
"@types/history": "^4.6.0",
Expand All @@ -165,6 +166,7 @@
"@types/storybook__addon-actions": "^3.0.1",
"@types/storybook__addon-knobs": "^3.2.1",
"@types/storybook__react": "^3.0.5",
"@types/underscore": "^1.8.8",
"@types/webpack-env": "^1.13.1",
"autoprefixer": "7.1.5",
"awesome-typescript-loader": "^4.0.1",
Expand Down
64 changes: 39 additions & 25 deletions src/actions/blockchain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ import {
openModal,
closeModal,
setTokenBalance,
setSellTokenAmount,
setClosingPrice,
setOngoingAuctions,
selectTokenPair,
Expand All @@ -54,7 +53,9 @@ import {
setTokenListType,
setApprovedTokens,
setAvailableAuctions,
saveTransaction,
setTokenListVersion,
setSellTokenAmount,
} from 'actions'

import { timeoutCondition } from '../utils/helpers'
Expand Down Expand Up @@ -246,7 +247,6 @@ export const getTokenList = (network?: number | string) => async (dispatch: Disp
localForage.getItem('customTokens'),
localForage.getItem('customListHash'),
])

const { ipfsFetchFromHash } = await promisedIPFS

// when switching Networks, NetworkListeners in events.js should delete localForage tokenList
Expand Down Expand Up @@ -432,9 +432,12 @@ export const checkUserStateAndSell = () => async (dispatch: Dispatch<any>, getSt
console.log('PROMPTING to start depositETH tx')
const depositHash = await depositETH.sendTransaction(ETHToWrap.toString(), currentAccount)
console.log('​depositETH tx hash: ', depositHash)
dispatch(saveTransaction({ txName: 'Deposit ETH', txHash: depositHash }))
}

// if sell or buy is unwrapped ETH replace token with previously WETH
changeETHforWETH(dispatch, getState, TokenETH.address)

// Check allowance amount for SELLTOKEN
// if allowance is ok, skip
const [needSellTokenAllowance, OWLBalance] = await promisedTokensAndOWLBalance
Expand Down Expand Up @@ -468,7 +471,6 @@ export const checkUserStateAndSell = () => async (dispatch: Dispatch<any>, getSt
const choice = await promisedChoice

await dispatch(approveTokens(choice, 'SELLTOKEN'))
// Go straight to sell order if deposit && allowance both good
}

if (OWLBalance.gt(0)) {
Expand Down Expand Up @@ -503,6 +505,7 @@ export const checkUserStateAndSell = () => async (dispatch: Dispatch<any>, getSt
await dispatch(approveTokens(choice, 'OWLTOKEN'))
}
}

return dispatch(submitSellOrder())
} catch (e) {
dispatch(errorHandling(e))
Expand All @@ -513,6 +516,7 @@ export const submitSellOrder = () => async (dispatch: any, getState: () => State
const {
tokenPair: { sell, buy, sellAmount, index = 0 },
blockchain: { activeProvider, currentAccount, providers: { [activeProvider]: { network } } },
// LOGS_AND_EVENTS: { DX_Events },
}: State = getState(),
sellName = getTokenName(sell),
buyName = getTokenName(buy),
Expand Down Expand Up @@ -548,49 +552,54 @@ export const submitSellOrder = () => async (dispatch: any, getState: () => State
console.log('PROMPTING to start depositAndSell tx')
hash = await depositAndSell.sendTransaction(sell, buy, nativeSellAmt.toString(), currentAccount)
console.log('depositAndSell tx hash', hash)
dispatch(saveTransaction({ txName: 'Deposit and Sell Order', txHash: hash }))
// else User has enough balance on DX for Token and can sell w/o deposit
} else {

console.log('PROMPTING to start depositAndSell tx')
hash = await postSellOrder.sendTransaction(sell, buy, nativeSellAmt.toString(), index as number, currentAccount)
console.log('postSellOrder tx hash', hash)
dispatch(saveTransaction({ txName: 'Sell Order', txHash: hash }))
}
const receipt = await waitForTx(hash)
console.log('postSellOrder tx receipt: ', receipt)

const { DutchExchange } = contractsMap
const decoder = getDecoderForABI(DutchExchange.abi)
const logs = decoder(receipt.logs)
console.log('postSellOrder tx logs', logs)
const { auctionIndex } = logs.find((log: Web3EventLog) => log._eventName === 'NewSellOrder')
dispatch(closeModal())

dispatch(push('/'))

// wait here for sellOrder to complete
// const sellReceipt = await waitForEvent(hash, 'NewSellOrder')
// console.log('PostSellOrder tx receipt: ', sellReceipt)

// const { returnValues: { auctionIndex } } = sellReceipt

// let receipt
// const [nativeSellAmt, userDXBalance] = await promisedAmtAndDXBalance
// if (nativeSellAmt.greaterThan(userDXBalance)) {
// // api/DutchX functions
// receipt = await depositAndSell(sell, buy, nativeSellAmt.toString(), currentAccount)
// console.log('depositAndSell receipt', receipt)
// // else User has enough balance on DX for Token and can sell w/o deposit
// } else {
// // api/DutchX functions
// receipt = await postSellOrder(sell, buy, nativeSellAmt.toString(), index as number, currentAccount)
// console.log('postSellOrder receipt', receipt)
// }
// const { args: { auctionIndex } } = receipt.logs.find((log: any) => log.event === 'NewSellOrder')

console.log(`Sell order went to ${sellName.symbol}-${buyName.symbol}-${auctionIndex.toString()}`)
dispatch(closeModal())
// console.log(`Sell order went to ${sellName.symbol}-${buyName.symbol}-${auctionIndex.toString()}`)
// dispatch(closeModal())
// jump to Auction Page
dispatch(push(`auction/${sellName.symbol}-${buyName.symbol}-${auctionIndex.toString()}`))

// grab balance of sold token after sale
const balance = await getTokenBalance(sell.address, currentAccount)

// dispatch Actions
dispatch(batchActions([
setTokenBalance({ address: sell.address, balance }),
// set sellAmount back to 0
setSellTokenAmount({ sellAmount: '0' }),
], 'SUBMIT_SELL_ORDER_STATE_UPDATE'))
// indicate that submission worked
// dispatch(push(`auction/${sellName.symbol}-${buyName.symbol}-${auctionIndex.toString()}`))

// // grab balance of sold token after sale
// const balance = await getTokenBalance(sell.address, currentAccount)

// // dispatch Actions
// dispatch(batchActions([
// setTokenBalance({ address: sell.address, balance }),
// // set sellAmount back to 0
// setSellTokenAmount({ sellAmount: '0' }),
// ], 'SUBMIT_SELL_ORDER_STATE_UPDATE'))
// // indicate that submission worked
return true
} catch (error) {
dispatch(errorHandling(error))
Expand Down Expand Up @@ -627,6 +636,7 @@ export const approveTokens = (choice: string, tokenType: 'SELLTOKEN' | 'OWLTOKEN
console.log('PROMPTING to start tokenApproval tx for MIN', sellName)
const tokenApprovalHash = await tokenApproval.sendTransaction(sell.address, nativeSellAmt.toString())
console.log('tokenApproval tx hash', tokenApprovalHash)
dispatch(saveTransaction({ txName: `${sellName} Approval`, txHash: tokenApprovalHash }))
} else {
dispatch(openModal({
modalName: 'TransactionModal',
Expand All @@ -642,6 +652,7 @@ export const approveTokens = (choice: string, tokenType: 'SELLTOKEN' | 'OWLTOKEN
console.log('PROMPTING to start tokenApproval tx for MAX', sellName)
const tokenApprovalHash = await tokenApproval.sendTransaction(sell.address, ((2 ** 255) - allowanceLeft).toString())
console.log('tokenApproval tx hash', tokenApprovalHash)
dispatch(saveTransaction({ txName: `${sellName} Approval`, txHash: tokenApprovalHash }))
}
// OWL APPROVAL
} else {
Expand All @@ -661,6 +672,7 @@ export const approveTokens = (choice: string, tokenType: 'SELLTOKEN' | 'OWLTOKEN
console.log('PROMPTING to start tokenApproval tx for OWL')
const tokenApprovalHash = await tokenApproval.sendTransaction(TokenOWL.address, ((2 ** 255) - allowanceLeft).toString())
console.log('tokenApproval for OWL tx hash', tokenApprovalHash)
dispatch(saveTransaction({ txName: 'OWL Approval', txHash: tokenApprovalHash }))
} else {
console.log('Disallowing OWL')
dispatch(closeModal())
Expand Down Expand Up @@ -775,6 +787,7 @@ export const claimSellerFundsFromSeveral = (

const claimHash = await claimSellerFundsFromSeveralAuctions.sendTransaction(sell, buy, currentAccount, lastNIndex)
console.log('ClaimSellerFundsFromSeveralAuctions TX HASH: ', claimHash)
dispatch(saveTransaction({ txName: 'Claiming Seller Funds', txHash: claimHash }))

// >>> ============= >>>
// END CLAIMING TX
Expand All @@ -797,6 +810,7 @@ export const claimSellerFundsFromSeveral = (
await waitForTx(claimHash)

const withdrawHash = await withdraw.sendTransaction(buy.address)
dispatch(saveTransaction({ txName: 'Withdraw Funds', txHash: withdrawHash }))
// get receipt or throw TIMEOUT
const withdrawReceipt = await Promise.race([waitForTx(withdrawHash), timeoutCondition(120000, 'TIMEOUT')]).catch(() => { throw new Error('SAFETY NETWORK TIMEOUT - PLEASE REFRESH YOUR PAGE') })
console.log('Withdraw TX receipt: ', withdrawReceipt)
Expand Down
106 changes: 106 additions & 0 deletions src/actions/events.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { createAction, handleActions } from 'redux-actions'
import { Dispatch } from 'redux'
import { State } from 'types'

import Web3 from 'web3'
import { RINKEBY_WEBSOCKET } from 'globals'
import { contractsMap, HumanFriendlyToken } from 'api/contracts'

export const saveEvent = createAction<{ eventType: string, event: any }>('SAVE_EVENT')
export const saveLogs = createAction<{ log: any }>('SAVE_LOG')
export const saveTransaction = createAction<{ txName: string, txHash: any }>('SAVE_TRANSACTION')
export const removeTransaction = createAction<{ txHash: string }>('REMOVE_TRANSACTION')

export const setupContractEventListening = () => async (dispatch: Dispatch<any>, getState: () => State) => {
console.log('​exportsetupContractEventListening -> ')

const { tokenList: { combinedTokenList } } = getState()

const WSweb3 = new Web3(new Web3.providers.WebsocketProvider(RINKEBY_WEBSOCKET))
const { DutchExchange } = contractsMap

const defaultCB = (e: Error) => {
if (e) throw (e)
}

const createFilter = (type: string, options: any = [defaultCB]) => WSweb3.eth.subscribe(type, ...options)

// New Data filter
createFilter('newBlockHeaders', [defaultCB]).on('data', (log: any) => {
console.log('Block update:', log)
dispatch(saveLogs({ log }))
})

// Logs Filter
// createFilter('logs', [{ fromBlock: 'latest', address: '0xc778417e063141139fce010982780140aa0cd5ab' }, defaultCB])
// .on('data', (log: any) => {
// console.log('logs', log)
// })
// .on('confirmation', (res: any) => console.log('CONFIRMATION CONFIRMATION', res))

// listen to DX events

const DX = new WSweb3.eth.Contract(DutchExchange.abi, '0x2ade4c3d9fd649ff6e97dcb50b684984bc8f6375')

DX.events.allEvents({ fromBlock: 'latest' }, (err: Error) => {
if (err) console.error(err)
})
.on('data', (event: any) => {
console.log(event)
// dispatch event here
dispatch(saveEvent({ eventType: 'DX_Events', event }))
})
.on('error', (err: Error) => console.error(err))

combinedTokenList.forEach((token: any) => {
if (token.address === '0x0') return
const Token = new WSweb3.eth.Contract(HumanFriendlyToken.abi, token.address)

Token.events.allEvents({ fromBlock: 'latest' }, (err: Error) => { if (err) console.error(err) })
.on('data', (event: any) => {
console.log(`>>==> ${token.symbol || token.name} TOKEN EVENT: `, event)
// dispatch event here
dispatch(saveEvent({ eventType: 'TOKEN_Events', event }))
})
.on('error', (err: Error) => console.error(err))
})
}

export const reducer = handleActions({
[saveEvent.toString()]: (state, action) => {
// @ts-ignore
const { eventType, event } = action.payload
return {
...state,
events: {
...state.events,
[eventType]: [...state.events[eventType], event],
},
transactionsPending: state.transactionsPending.filter((tx: any) => tx.txHash !== event.transactionHash),
}
},
[saveLogs.toString()]: (state, action) => ({
...state,
logs: {
all: state.logs.all.length <= 10 ? [...state.logs.all, action.payload] : [action.payload],
},
}),
[saveTransaction.toString()]: (state, action) => ({
...state,
transactionsPending: [...state.transactionsPending, action.payload],
}),
[removeTransaction.toString()]: (state, action: any) => ({
...state,
transactionsPending: state.transactionsPending.filter((tx: any) => tx.txHash !== action.payload.txHash),
}),
},
{
events: {
DX_Events: [],
TOKEN_Events: [],
},
logs: {
all: [],
},
transactionsPending: [],
})
1 change: 1 addition & 0 deletions src/actions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ export * from './tokenPair'
export * from './modal'
export * from './approvedTokens'
export * from './settings'
export * from './events'
13 changes: 8 additions & 5 deletions src/api/contracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,9 @@ export const contractsMap = contractNames.reduce((acc, name, i) => {

export const setProvider = (provider: any) => Contracts.concat(HumanFriendlyToken).forEach((contract) => {
contract.setProvider(provider)
if (typeof contract.currentProvider.sendAsync !== 'function') {
contract.currentProvider.sendAsync = function () { return contract.currentProvider.send.apply(contract.currentProvider, arguments) }
}
})

const getPromisedIntances = () => Promise.all(Contracts.map(contr => contr.deployed()))
Expand All @@ -143,13 +146,13 @@ async function init() {
// name => contract instance mapping
// e.g. TokenETH => deployed TokenETH contract
const deployedContracts = contractNames.reduce((acc, name, i) => {
if (name === 'TokenFRT') {
if (name === 'TokenFRT') {
acc['TokenMGN'] = instances[i]
} else {
acc[filename2ContractNameMap[name] || name] = instances[i]
}
return acc
}, {}) as ContractsMapWProxy
return acc
}, {}) as ContractsMapWProxy

const { address: proxyAddress } = deployedContracts.DutchExchangeProxy
deployedContracts.DutchExchange = contractsMap.DutchExchange.at(proxyAddress)
Expand All @@ -160,8 +163,8 @@ async function init() {
delete deployedContracts.TokenOWLProxy

if (process.env.NODE_ENV !== 'production') {
console.log(deployedContracts)
}
console.log(deployedContracts)
}
return deployedContracts as ContractsMap
} catch (err) {
console.error('Contract initialisation error: ', err)
Expand Down
4 changes: 4 additions & 0 deletions src/api/dutchx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,10 @@ async function init(): Promise<DutchExchange> {

const allEvents: DutchExchange['allEvents'] = dx.allEvents.bind(dx)

console.warn(`
API/DUTCHX SETUP FINISHED
`)

return {
get address() {
return dx.address
Expand Down
Loading