diff --git a/package.json b/package.json
index 2605c3f..db37831 100644
--- a/package.json
+++ b/package.json
@@ -6,6 +6,7 @@
"dependencies": {
"@ledgerhq/hw-app-eth": "^4.7.3",
"@ledgerhq/hw-transport-u2f": "^4.7.3",
+ "abi-decoder": "^1.2.0",
"autoprefixer": "7.1.2",
"babel-core": "6.25.0",
"babel-eslint": "7.2.3",
diff --git a/src/components/Routes.jsx b/src/components/Routes.jsx
index 1af260f..b860545 100644
--- a/src/components/Routes.jsx
+++ b/src/components/Routes.jsx
@@ -3,8 +3,6 @@ import React from "react";
import {withRouter, Route, Switch} from "react-router-dom";
// Components
-import FAQ from "./FAQ";
-import Main from "./Main";
import Widget from "./Widget";
@withRouter
@@ -18,9 +16,7 @@ class Routes extends React.Component {
render() {
return (
- } />
- } />
- } />} />
+ } />
{/* */}
);
diff --git a/src/components/TaxWidget.jsx b/src/components/TaxWidget.jsx
new file mode 100644
index 0000000..0194bd0
--- /dev/null
+++ b/src/components/TaxWidget.jsx
@@ -0,0 +1,514 @@
+import React, { Component } from 'react';
+import abiDecoder from 'abi-decoder';
+import config from '../exporter-config';
+import web3 from '../utils/web3';
+import * as Blockchain from '../utils/blockchain';
+import { fromWei, isAddress } from '../utils/helpers';
+import { vulcan0x } from '../utils/vulcan0x';
+import Spinner from '../components-ui/Spinner';
+
+
+const schema = {};
+
+schema.dstoken = require('../abi/dstoken');
+schema.dsethtoken = require('../abi/dsethtoken');
+schema.proxyregistry = require('../abi/proxyregistry');
+schema.legacyproxyregistry = require('../abi/legacyproxyregistry');
+schema.dsproxy = require('../abi/dsproxy');
+schema.matchingmarket = require('../abi/matchingmarket');
+schema.proxycreateandexecute = require('../abi/proxycreateandexecute');
+
+class TaxWidget extends Component {
+ constructor(props) {
+ super();
+ this.props = props;
+ this.state = {
+ isLoading: false,
+ accounts: [
+ this.props.account,
+ ],
+ exchanges: [
+ 'oasis'
+ ],
+ newAddress: "",
+ csvData: []
+ }
+ }
+
+ removeAccount = id => {
+ // making copy of the accounts
+ const accounts = [...this.state.accounts];
+
+ // Splice removes the selected element and modifies the array beneath
+ // We discard the returned value because we care only in the modified version
+ accounts.splice(id, 1);
+
+ // Set the new array with the removed account
+ this.setState({accounts});
+ }
+
+ addAccount = event => {
+ event.preventDefault();
+ const address = (this.state.newAddress || "").trim();
+
+ if (isAddress(address)) {
+ const accounts = [...this.state.accounts];
+
+ if (!accounts.includes(address)) {
+ accounts.push(address);
+ this.setState({accounts, newAddress: ''});
+ } else {
+ alert("This address is already in the list");
+ }
+ } else {
+ alert("This is not a valid address");
+ }
+ }
+
+ getLegacyProxies = (registry, address) => {
+ return new Promise((resolve, reject) => {
+ const proxies = [];
+ const registryObj = Blockchain.loadObject('legacyproxyregistry', registry);
+ registryObj.proxiesCount(address, async (e, count) => {
+ if (!e) {
+ if (count.gt(0)) {
+ for (let i = count.toNumber() - 1; i >= 0; i--) {
+ proxies.push(await Blockchain.legacy_getProxy(registryObj, address, i));
+ }
+ }
+ resolve(proxies);
+ } else {
+ reject(e);
+ }
+ });
+ });
+ }
+
+ getPossibleProxies = address => {
+ return new Promise((resolve, reject) => {
+ const promises = [];
+ config.taxProxyRegistries[this.props.network].legacy.forEach(registry => {
+ promises.push(this.getLegacyProxies(registry, address));
+ });
+ promises.push(Blockchain.getProxy(address));
+ let proxies = [];
+ Promise.all(promises).then(r => {
+ for (let i = 0; i < r.length; i++) {
+ if (typeof r[i] === 'object') {
+ proxies = proxies.concat(r[i]);
+ } else {
+ proxies.push(r[i]);
+ }
+ }
+ resolve(proxies);
+ }, e => reject(e));
+ });
+ }
+
+ fetchOasisTradesFromAccount = (contract, filter) => {
+ return new Promise((resolve, reject) => {
+ Blockchain.loadObject('matchingmarket', contract.address).LogTake(filter, {
+ fromBlock: contract.block_start,
+ toBlock: contract.block_end
+ }).get((error, logs) => {
+ if (!error) {
+ resolve(logs);
+ } else {
+ reject(error);
+ }
+ });
+ });
+ }
+
+ getOwnerTransaction = tx => {
+ return new Promise((resolve, reject) => {
+ Blockchain.getTransactionReceipt(tx).then(r => resolve(r.from), e => reject(e));
+ });
+ }
+
+ fetchOasisMakeTrades = (contract, address) => {
+ return new Promise((resolve, reject) => {
+
+ this.fetchOasisTradesFromAccount(contract, {maker: address}).then(logs => {
+ const promises = [];
+ logs.forEach(log => {
+ promises.push(this.addOasisTradeFor(address, 'maker', log.args));
+ });
+ Promise.all(promises).then(() => resolve(true));
+ }, () => {
+ reject();
+ })
+ });
+ }
+
+ fetchOasisMakeTradesCached = (address) => {
+ return new Promise(async (resolve, reject) => {
+ try {
+ const promises = [];
+
+ address = web3.toChecksumAddress(address);
+
+ const take_trades = await this.getTradesFromCache([address], 'maker');
+
+ for (let i = 0; i < take_trades.length; i++) {
+ promises.push(this.addOasisTradeForCached(address, 'maker', take_trades[i]));
+ }
+ Promise.all(promises).then(() => resolve(true));
+ }catch (e) {
+ reject(e);
+ }
+ });
+ }
+
+ fetchOasisTakeTrades = (contract, address) => {
+ return new Promise(async (resolve, reject) => {
+ try {
+ const promises = [];
+ const proxiesAddr = await this.getPossibleProxies(address);
+
+ promises.push(this.fetchOasisTradesFromAccount(contract, {taker: address}));
+ proxiesAddr.forEach(proxyAddr => {
+ promises.push(this.fetchOasisTradesFromAccount(contract, {taker: proxyAddr}));
+ });
+ config.supportContracts[this.props.network].forEach(supportContract => {
+ promises.push(this.fetchOasisTradesFromAccount(contract, {taker: supportContract.address}));
+ });
+ Promise.all(promises).then(async r => {
+ const promises2 = [];
+
+ for (let i = 0; i < r.length; i++) {
+ for (let j = 0; j < r[i].length; j++) {
+
+ const owner = await this.getOwnerTransaction(r[i][j].transactionHash);
+ if (i === 0 || owner === address) {
+ // For the cases of proxy trades we need to verify if they were done by the address requested or the proxy might have been transferred before
+ promises2.push(this.addOasisTradeFor(address, 'taker', r[i][j].args));
+ }
+ }
+ }
+ Promise.all(promises2).then(() => resolve(true));
+ }, e => {
+ reject(e);
+ })
+ } catch (e) {
+ reject(e);
+ }
+ });
+ }
+
+ getTradesFromCache = (addresses, side) => {
+ return new Promise((resolve, reject) => {
+ try {
+ const vulcanquery = vulcan0x(addresses, side);
+ vulcanquery.then((res) => {
+ const trades = [];
+ const nodes = res.data['allOasisTrades']['nodes'];
+ for (let i = 0; i < nodes.length; i++) {
+ trades.push(nodes[i]);
+ }
+ resolve(trades);
+ });
+ }catch (e) {
+ reject(e);
+ }
+ });
+ }
+
+ getTransactionInfo = (tx) => {
+ return new Promise((resolve, reject) => {
+ Blockchain.getTransaction(tx).then(r => {
+
+ abiDecoder.addABI(schema.proxyregistry.abi);
+ abiDecoder.addABI(schema.dstoken.abi);
+ abiDecoder.addABI(schema.dsethtoken.abi);
+ abiDecoder.addABI(schema.legacyproxyregistry.abi);
+ abiDecoder.addABI(schema.dsproxy.abi);
+ abiDecoder.addABI(schema.matchingmarket.abi);
+ abiDecoder.addABI(schema.proxycreateandexecute.abi);
+
+ const transactionData = abiDecoder.decodeMethod(r.input);
+
+ resolve(transactionData);
+
+ });
+
+ });
+
+ };
+
+ fetchOasisTakeTradesCached = (address) => {
+ return new Promise(async (resolve, reject) => {
+ try {
+ const promises = [];
+ const proxiesAddr = await this.getPossibleProxies(address);
+
+ const supportContracts = [];
+ config.supportContracts[this.props.network].forEach(supportContract => {
+ supportContracts.push(supportContract.address);
+ });
+
+ const addresses = [address, ...proxiesAddr, ...supportContracts].filter(address => address).map(address => web3.toChecksumAddress(address));
+ const take_trades = await this.getTradesFromCache(addresses, 'taker');
+
+ for (let i = 0; i < take_trades.length; i++) {
+ promises.push(this.addOasisTradeForCached(address, 'taker', take_trades[i]));
+ }
+
+ Promise.all(promises).then(() => resolve(true));
+
+ } catch (e) {
+ reject(e);
+ }
+ });
+ }
+
+ setLoading = value => {
+ this.setState(() => {
+ return {isLoading: value};
+ });
+ }
+
+ fetchData = e => {
+ e.preventDefault();
+ this.setLoading(true);
+ let accounts = [...this.state.accounts];
+ let oasisPromises = [];
+ this.setState({csvData: []}, () => {
+ accounts.forEach(account => {
+
+ // New methods to fetch make/take trades from vulcan0x cache instead of web3 instance.
+ // Old fetch methods left below for testing purposes.
+
+ oasisPromises.push(this.fetchOasisMakeTradesCached(account));
+ oasisPromises.push(this.fetchOasisTakeTradesCached(account));
+
+ // config.oasis.contract[this.props.network].forEach(contract => {
+ // oasisPromises.push(this.fetchOasisMakeTrades(contract, account));
+ // oasisPromises.push(this.fetchOasisTakeTrades(contract, account));
+ // });
+
+
+ if (this.props.network === 'main') {
+ oasisPromises.push(this.fetchLegacyTrades(account));
+ }
+ });
+
+ Promise.all(oasisPromises).then(() => {
+ this.downloadCSV();
+ this.setLoading(false);
+ });
+ });
+ }
+
+ fetchLegacyFile = (fileIndex, address) => {
+ return new Promise((resolve, reject) => {
+ const xhr = new XMLHttpRequest();
+ xhr.open('GET', `https://oasisdex.github.io/oasis-dex-script/maker-otc-${fileIndex < 10 ? "0" : ""}${fileIndex}.trades.json`, true);
+ xhr.onreadystatechange = () => {
+ if (xhr.readyState === 4 && xhr.status === 200) {
+ const promises = [];
+ const data = JSON.parse(xhr.responseText);
+ for (let i = 0; i < data.length; i++) {
+ const taker = `0x${data[i].taker}`;
+ const maker = `0x${data[i].maker}`;
+ if (taker === address || maker === address) {
+ promises.push(this.addOasisLegacyTradeFor(address, maker === address ? 'maker' : 'taker', data[i]));
+ }
+ }
+ Promise.all(promises).then(() => resolve(true));
+ } else if (xhr.readyState === 4 && xhr.status !== 200) {
+ reject(xhr.status);
+ }
+ }
+ xhr.send();
+ });
+ }
+
+ fetchLegacyTrades = address => {
+ return new Promise((resolve, reject) => {
+ const promises = [];
+ for (let i = 2; i <= 19; i++) {
+ promises.push(this.fetchLegacyFile(i, address));
+ }
+ Promise.all(promises).then(() => resolve(true));
+ });
+ }
+
+ addOasisTradeFor = (address, side, log) => {
+ return new Promise((resolve, reject) => {
+ const sellAmount = fromWei(side === 'maker' ? log.take_amt : log.give_amt).toString(10);
+ const buyAmount = fromWei(side === 'maker' ? log.give_amt : log.take_amt).toString(10);
+ const sellTokenAddress = side === 'maker' ? log.pay_gem : log.buy_gem;
+ const buyTokenAddress = side === 'maker' ? log.buy_gem : log.pay_gem;
+ const sellToken = config.tokens[this.props.network][sellTokenAddress];
+ const buyToken = config.tokens[this.props.network][buyTokenAddress];
+
+ const trade = {
+ type: 'Trade',
+ buyAmount,
+ buyToken,
+ sellAmount,
+ sellToken: sellToken,
+ fee: '',
+ feeToken: '',
+ exchange: 'Oasisdex.com',
+ group: '',
+ address,
+ timestamp: log.timestamp,
+ };
+
+ //add trade to CSV
+ this.addTradeToCSV(trade).then(() => resolve(true));
+ });
+ }
+
+ addOasisTradeForCached = (address, side, log) => {
+
+ return new Promise((resolve, reject) => {
+ const sellAmount = side === 'maker' ? log['lotAmt'] : log['bidAmt'];
+ const buyAmount = side === 'maker' ? log['bidAmt'] : log['lotAmt'];
+ const sellToken = side === 'maker' ? log.lotTkn : log.bidTkn;
+ const buyToken = side === 'maker' ? log.bidTkn : log.lotTkn;
+
+ const trade = {
+ type: 'Trade',
+ side,
+ buyAmount: buyAmount,
+ buyToken: buyToken,
+ sellAmount: sellAmount,
+ sellToken: sellToken,
+ exchange: 'Oasisdex.com',
+ tx: log['tx'],
+ address,
+ timestamp: Date.parse(log['time'])/1000,
+ };
+
+ //add trade to CSV
+ this.addTradeToCSV(trade).then(() => resolve(true));
+ });
+ }
+
+ addOasisLegacyTradeFor = (address, side, log) => {
+ return new Promise((resolve, reject) => {
+ const sellAmount = fromWei(`0x${side === 'maker' ? log.takeAmount : log.giveAmount}`).toString(10);
+ const buyAmount = fromWei(`0x${side === 'maker' ? log.giveAmount : log.takeAmount}`).toString(10);
+ const sellTokenAddress = `0x${side === 'maker' ? log.haveToken : log.wantToken}`;
+ const buyTokenAddress = `0x${side === 'maker' ? log.wantToken : log.haveToken}`;
+ const sellToken = config.tokens[this.props.network][sellTokenAddress];
+ const buyToken = config.tokens[this.props.network][buyTokenAddress];
+
+ const trade = {
+ type: 'Trade',
+ buyAmount,
+ buyToken,
+ sellAmount,
+ sellToken: sellToken,
+ fee: '',
+ feeToken: '',
+ exchange: 'Oasisdex.com',
+ group: '',
+ address,
+ timestamp: log.timestamp,
+ };
+
+ //add trade to CSV
+ this.addTradeToCSV(trade).then(() => resolve(true), e => reject(e));
+ });
+ }
+
+ addTradeToCSV = trade => {
+ return new Promise((resolve, reject) => {
+ //add a line break after each row
+ this.setState(prevState => {
+ const csvData = [...prevState.csvData];
+ csvData.push(trade);
+ return {csvData};
+ }, () => resolve(true));
+ });
+ }
+
+ downloadCSV = () => {
+ const currentDate = new Date();
+ const fileName = `trades-report-${currentDate.getFullYear()}-${ (currentDate.getMonth()+1) <= 9 ? '0'+(currentDate.getMonth()+1) : (currentDate.getMonth()+1) }-${currentDate.getDate()}`;
+ let csvData = [...this.state.csvData];
+ csvData = csvData.sort((a, b) => a.timestamp > b.timestamp);
+ csvData.map(trade => {
+ trade.date = new Date(trade.timestamp * 1000).toLocaleString().replace(',', '');
+ // delete trade.timestamp;
+ return trade;
+ })
+ var uri = 'data:text/csv;charset=utf-8,'
+ +
+ encodeURIComponent(`"Type";"Side";"Buy";"Cur.";"Sell";"Cur.";"Exchange";"Tx";"Address";"TS";"Date"\r\n${csvData.map(trade => `"${Object.keys(trade).map(key => trade[key]).join('";"')}"\r\n`).join('')}`);
+ const link = document.createElement("a");
+ link.href = uri;
+
+ link.style = 'visibility:hidden';
+ link.download = fileName + ".csv";
+
+ //this part will append the anchor tag and remove it after automatic click
+ document.body.appendChild(link);
+ link.click();
+ document.body.removeChild(link);
+ }
+
+ toggleExchange = (thisOne) => {
+ if(!thisOne) return;
+
+ this.setState(prevState => {
+ const currentExchanges = [...prevState.exchanges];
+
+ if (currentExchanges.includes(thisOne) && currentExchanges.length > 1) {
+ const position = currentExchanges.indexOf(thisOne);
+ currentExchanges.splice(position, 1);
+ } else if (!currentExchanges.includes(thisOne)) {
+ currentExchanges.push(thisOne);
+ }
+
+ return { exchanges: currentExchanges };
+ });
+ }
+
+ render() {
+ return (
+
+
+
Enter Addresses
+
+
+
+
+ {
+ this.state.accounts.map((account, index) => {
+
+ return (
+ -
+
+ {account.toLowerCase()}
+
+
+ )
+ })
+ }
+
+
+
+ this.setState({newAddress: event.target.value})}/>
+
+
+
+
+
+ )
+ }
+}
+
+export default TaxWidget;
diff --git a/src/components/Widget.jsx b/src/components/Widget.jsx
index 50f018e..4a16622 100644
--- a/src/components/Widget.jsx
+++ b/src/components/Widget.jsx
@@ -5,7 +5,7 @@ import {inject, observer} from "mobx-react";
// Components
import HardWallet from "./HardWallet";
import LockedAccount from "./LockedAccount";
-import TradeWidget from "./TradeWidget";
+import TaxWidget from './TaxWidget';
import Wallets from "./Wallets";
// Utils
@@ -15,6 +15,7 @@ import {isAddress} from "../utils/helpers";
@observer
class Widget extends React.Component {
render() {
+
return (
{
@@ -28,7 +29,10 @@ class Widget extends React.Component {
:
this.props.network.defaultAccount && isAddress(this.props.network.defaultAccount)
?
-
+
:
}
diff --git a/src/exporter-config.json b/src/exporter-config.json
new file mode 100644
index 0000000..0d4281d
--- /dev/null
+++ b/src/exporter-config.json
@@ -0,0 +1,157 @@
+{
+ "volcan0x": {
+ "url": "https://kovan-oasisvulcan0x.makerfoundation.com/v1"
+ },
+ "csv": {
+ "title": "TaxReport",
+ "header": [
+ "Type",
+ "Buy",
+ "Cur.",
+ "Sell",
+ "Cur.",
+ "Fee",
+ "Cur.",
+ "Exchange",
+ "Comment",
+ "Date"
+ ]
+ },
+ "tokens": {
+ "kovan": {
+ "0x53eccc9246c1e537d79199d0c7231e425a40f896": "ETH",
+ "0x4bb514a7f83fbb13c2b41448208e89fabbcfe2fb": "MKR",
+ "0xbb7697d091a2b9428053e2d42d088fcd2a6a0aaf": "DGD",
+ "0xece9fa304cc965b00afc186f5d0281a00d3dbbfd": "GNT",
+ "0xbd1ceb35769eb44b641c8e257005817183fc2817": "W-GNT",
+ "0x99e846cfe0321260e51963a2114bc4008d092e24": "REP",
+ "0x8a55df5de91eceb816bd9263d2e5f35fd516d4d0": "ICN",
+ "0x846f258ac72f8a60920d9b613ce9e91f8a7a7b54": "1ST",
+ "0xf7d57c676ac2bc4997ca5d4d34adc0d072213d29": "SNGLS",
+ "0x2e65483308968f5210167a23bdb46ec94752fe39": "VSL",
+ "0x00a0fcaa32b47c4ab4a8fdda6d108e5c1ffd8e4f": "PLU",
+ "0xc3ce96164012ed51c9b1e34a9323fdc38c96ad8a": "MLN",
+ "0x7352c20e00d3c89037a8959699741c341771ed59": "RHOC",
+ "0xd944954588061c969fbd828d1f00c297c3511dbd": "TIME",
+ "0xa786d73316e43c3361145241755566e72424274c": "GUP",
+ "0xd0a1e359811322d97991e03f863a0c30c2cf029c": "WETH",
+ "0xc4375b7de8af5a38a93548eb8453a498222c4ff2": "DAI",
+ "0xaaf64bfcc32d0f15873a02163e7e500671a4ffcd": "MKR"
+ },
+ "main": {
+ "0xecf8f87f810ecf450940c9f60066b4a7a501d6a7": "WETH",
+ "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2": "WETH",
+ "0xc66ea802717bfb9833400264dd12c2bceaa34a6d": "MKR",
+ "0x9f8f72aa9304c8b593d555f12ef6589cc3a579a2": "MKR",
+ "0x89d24a6b4ccb1b6faa2625fe562bdd9a23260359": "DAI",
+ "0x59adcf176ed2f6788a41b8ea4c4904518e62b6a4": "SAI",
+ "0x0000000000000000000000000000000000000000": "ETH",
+ "0xd8912c10681d8b21fd3742244f44658dba12264e": "PLU",
+ "0xaf30d2a7e90d7dc361c8c4585e9bb7d2f6f15bc7": "1ST",
+ "0x936f78b9852d12f5cb93177c1f84fb8513d06263": "GNT",
+ "0x01afc37f4f85babc47c0e2d0eababc7fb49793c8": "GNT",
+ "0xa74476443119a942de498590fe1f2454d7d4ac0d": "GNT",
+ "0x5c543e7ae0a1104f78406c340e9c64fd9fce5170": "VSL",
+ "0xac709fcb44a43c35f0da4e3163b117a17f3770f5": "ARC",
+ "0x14f37b574242d366558db61f3335289a5035c506": "HKG",
+ "0x888666ca69e0f178ded6d75b5726cee99a87d698": "ICN",
+ "0x48c80f1f4d53d5951e5d5438b54cba84f29f32a5": "REP",
+ "0xaec2e87e0a235266d9c5adc9deb4b2e29b54d009": "SNGLS",
+ "0x4df812f6064def1e5e029f1ca858777cc98d2d81": "XAUR",
+ "0xe0b7927c4af23765cb51314a0e0521a9645f0e2a": "DGD",
+ "0xce3d9c3f3d302436d12f18eca97a3b00e97be7cd": "EPOSY",
+ "0x289fe11c6f46e28f9f1cfc72119aee92c1da50d0": "EPOSN",
+ "0xbb9bc244d798123fde783fcc1c72d3bb8c189413": "DAO",
+ "0x55e7c4a77821d5c50b4570b08f9f92896a25e012": "P+",
+ "0x45e42d659d9f9466cd5df622506033145a9b89bc": "NXC",
+ "0x08d32b0da63e2C3bcF8019c9c5d849d7a9d791e6": "DCN",
+ "0x01a7018e6d1fde8a68d12f59b6532fb523b6259d": "USD.DC",
+ "0xffad42d96e43df36652c8eaf61a7e6dba2ad0e41": "BTC.DC",
+ "0x949bed886c739f1a3273629b3320db0c5024c719": "AMIS",
+ "0xb9e7f8568e08d5659f5d29c4997173d84cdf2607": "SWT",
+ "0xf77089f2f00fca83501705b711cbb10a0de77628": "BME",
+ "0xb802b24e0637c2b87d2e8b7784c055bbe921011a": "EMV",
+ "0x6531f133e6deebe7f2dce5a0441aa7ef330b4e53": "TIME",
+ "0x059d4329078dcA62c521779c0Ce98EB9329349e6": "TIG",
+ "0xbeb9ef514a379b997e0798fdcc901ee474b6d9a1": "MLN",
+ "0x168296bb09e24a88805cb9c33356536b980d3fc5": "RHOC",
+ "0x08711d3b02c8758f2fb3ab4e80228418a7f8e39c": "EDG",
+ "0xf7b098298f7c69fc14610bf71d5e02c60792894c": "GUP",
+ "0xc2921ea1c150405ef952f73952f37fa2746168d8": "ETB",
+ "0x607f4c5bb672230e8672085532f7e901544a7375": "RLC",
+ "0xcb94be6f13a1182e4a4b6140cb7bf2025d28e41b": "TRST",
+ "0x2e071d2966aa7d8decb1005885ba1977d6038a65": "DICE",
+ "0xe7775a6e9bcf904eb39da2b68c5efb4f9360e08c": "TAAS",
+ "0x6810e776880c02933d47db1b9fc05908e5386b96": "GNO",
+ "0x667088b212ce3d06a1b553a7221e1fd19000d9af": "WINGS",
+ "0xfa05a73ffe78ef8f1a739473e462c54bae6567d9": "LUN",
+ "0xaaaf91d9b90df800df4f55c205fd6989c977e73a": "TKN",
+ "0xcbcc0f036ed4788f63fc0fee32873d6a7487b908": "HMQ"
+ }
+ },
+ "oasis": {
+ "contract": {
+ "kovan": [
+ {
+ "address": "0x45ab8d410049116c7a01f6edfc08d564475c08ed",
+ "block_start": 685569,
+ "block_end": 5216718
+ },
+ {
+ "address": "0x8cf1cab422a0b6b554077a361f8419cdf122a9f9",
+ "block_start": 5216718,
+ "block_end": "latest"
+ }
+ ],
+ "main": [
+ {
+ "address": "0x83ce340889c15a3b4d38cfcd1fc93e5d8497691f",
+ "block_start": 3435757,
+ "block_end": 4262880
+ },
+ {
+ "address": "0x3aa927a97594c3ab7d7bf0d47c71c3877d1de4a1",
+ "block_start": 4262057,
+ "block_end": 4761589
+ },
+ {
+ "address": "0x91dfe531ff8ba876a505c8f1c98bafede6c7effc",
+ "block_start": 4732388,
+ "block_end": 4732986
+ },
+ {
+ "address": "0x14fbca95be7e99c15cc2996c6c9d841e54b79425",
+ "block_start": 4751582,
+ "block_end": "latest"
+ }
+ ]
+ }
+ },
+ "taxProxyRegistries": {
+ "kovan": {
+ "legacy": [
+ "0x383a7fc29edde64aec7f776e2517ec8819e147f1"
+ ]
+ },
+ "main": {
+ "legacy": [
+ "0xaa63c8683647ef91b3fdab4b4989ee9588da297b"
+ ]
+ }
+ },
+ "supportContracts": {
+ "kovan": [],
+ "main": [
+ {
+ "address": "0xb0a00896f34655edff6c8d915fb342194c4a6d48",
+ "block_start": 5120103,
+ "block_end": 5267186
+ },
+ {
+ "address": "0x793ebbe21607e4f04788f89c7a9b97320773ec59",
+ "block_start": 5267186,
+ "block_end": "latest"
+ }
+ ]
+ }
+}
diff --git a/src/styles/App.css b/src/styles/App.css
index 3762425..14b96df 100644
--- a/src/styles/App.css
+++ b/src/styles/App.css
@@ -199,6 +199,10 @@
height: 18px;
}
+.frame {
+ margin: 40px auto 0;
+}
+
.label {
font-family: Montserrat, sans-serif;
font-size: 12px;
@@ -1037,8 +1041,7 @@ button[disabled] {
.frame button.close {
position: absolute;
- top: 18px;
- right: 22px;
+ right: 30px;
}
.swap-tokens {
diff --git a/src/utils/vulcan0x.js b/src/utils/vulcan0x.js
new file mode 100644
index 0000000..d03d85f
--- /dev/null
+++ b/src/utils/vulcan0x.js
@@ -0,0 +1,46 @@
+import config from '../exporter-config';
+
+export const vulcan0x = async (accounts, type) => {
+
+ const res = await fetch(config.volcan0x.url,
+ {
+ headers: {"Content-Type": "application/json; charset=utf-8"},
+ method: 'POST',
+ body: JSON.stringify({
+ query: `query tradesForAddresses($filter: OasisTradeFilter) {
+ allOasisTrades(filter: $filter) {
+ nodes {
+ offerId
+ act
+ maker
+ taker
+ bidAmt
+ bidTkn
+ bidGem
+ lotAmt
+ lotTkn
+ lotGem
+ price
+ time
+ tx
+ }
+ }
+ }`,
+ variables: {
+ "devMode": "2232759874",
+ "filter": {
+ [type]: {
+ "in": accounts
+ },
+ // "time": {
+ // "lessThan": "2018-08-05T19:15:19.062Z",
+ // "greaterThan": "2018-06-05T19:15:19.062Z"
+ // },
+ }
+ }
+ })
+ }
+ );
+
+ return res.json();
+};
diff --git a/yarn.lock b/yarn.lock
index 298a51a..254b058 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -113,6 +113,13 @@ abbrev@1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
+abi-decoder@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/abi-decoder/-/abi-decoder-1.2.0.tgz#c42882dbb91b444805f0cd203a87a5cc3c22f4a8"
+ integrity sha512-y2OKSEW4gf2838Eavc56vQY9V46zaXkf3Jl1WpTfUBbzAVrXSr4JRZAAWv55Tv9s5WNz1rVgBgz5d2aJIL1QCg==
+ dependencies:
+ web3 "^0.18.4"
+
abstract-leveldown@~2.6.0:
version "2.6.3"
resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz#1c5e8c6a5ef965ae8c35dfb3a8770c476b82c4b8"
@@ -1356,6 +1363,10 @@ bignumber.js@^7.2.1:
version "7.2.1"
resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-7.2.1.tgz#80c048759d826800807c4bfd521e50edbba57a5f"
+"bignumber.js@git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2":
+ version "2.0.7"
+ resolved "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2"
+
"bignumber.js@git+https://github.com/frozeman/bignumber.js-nolookahead.git":
version "2.0.7"
resolved "git+https://github.com/frozeman/bignumber.js-nolookahead.git#57692b3ecfc98bbdd6b3a516cb2353652ea49934"
@@ -9889,6 +9900,17 @@ web3-utils@1.0.0-beta.36:
underscore "1.8.3"
utf8 "2.1.1"
+web3@^0.18.4:
+ version "0.18.4"
+ resolved "https://registry.yarnpkg.com/web3/-/web3-0.18.4.tgz#81ec1784145491f2eaa8955b31c06049e07c5e7d"
+ integrity sha1-gewXhBRUkfLqqJVbMcBgSeB8Xn0=
+ dependencies:
+ bignumber.js "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2"
+ crypto-js "^3.1.4"
+ utf8 "^2.1.1"
+ xhr2 "*"
+ xmlhttprequest "*"
+
web3@^0.20.6:
version "0.20.7"
resolved "https://registry.yarnpkg.com/web3/-/web3-0.20.7.tgz#1605e6d81399ed6f85a471a4f3da0c8be57df2f7"
@@ -10175,6 +10197,11 @@ xhr2-cookies@1.1.0, xhr2-cookies@^1.1.0:
dependencies:
cookiejar "^2.1.1"
+xhr2@*:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/xhr2/-/xhr2-0.1.4.tgz#7f87658847716db5026323812f818cadab387a5f"
+ integrity sha1-f4dliEdxbbUCYyOBL4GMras4el8=
+
xhr@^2.0.4, xhr@^2.2.0, xhr@^2.3.3:
version "2.5.0"
resolved "https://registry.yarnpkg.com/xhr/-/xhr-2.5.0.tgz#bed8d1676d5ca36108667692b74b316c496e49dd"