Commit c465d2d0 authored by Chi Kei Chan's avatar Chi Kei Chan Committed by GitHub

Add all smart trade methods to swap (#45)

* wip

* ETH to ERC20 swap input

* ERC20 to ETH swap input

* Add ERC20 to ETH swapInput

* Add ETH to ERC20 swapOutput

* Add ERC20 to ETH swapOutput

* Add ERC20 to ERC20 swapInput

* Add ERC20 to ERC20 swapOutput

* Remove console.log
parent b6ad0dbb
[{"name": "TokenPurchase", "inputs": [{"type": "address", "name": "buyer", "indexed": true}, {"type": "uint256", "name": "eth_sold", "indexed": true}, {"type": "uint256", "name": "tokens_bought", "indexed": true}], "anonymous": false, "type": "event"}, {"name": "EthPurchase", "inputs": [{"type": "address", "name": "buyer", "indexed": true}, {"type": "uint256", "name": "tokens_sold", "indexed": true}, {"type": "uint256", "name": "eth_bought", "indexed": true}], "anonymous": false, "type": "event"}, {"name": "AddLiquidity", "inputs": [{"type": "address", "name": "provider", "indexed": true}, {"type": "uint256", "name": "eth_amount", "indexed": true}, {"type": "uint256", "name": "token_amount", "indexed": true}], "anonymous": false, "type": "event"}, {"name": "RemoveLiquidity", "inputs": [{"type": "address", "name": "provider", "indexed": true}, {"type": "uint256", "name": "eth_amount", "indexed": true}, {"type": "uint256", "name": "token_amount", "indexed": true}], "anonymous": false, "type": "event"}, {"name": "Transfer", "inputs": [{"type": "address", "name": "_from", "indexed": true}, {"type": "address", "name": "_to", "indexed": true}, {"type": "uint256", "name": "_value", "indexed": false}], "anonymous": false, "type": "event"}, {"name": "Approval", "inputs": [{"type": "address", "name": "_owner", "indexed": true}, {"type": "address", "name": "_spender", "indexed": true}, {"type": "uint256", "name": "_value", "indexed": false}], "anonymous": false, "type": "event"}, {"name": "setup", "outputs": [], "inputs": [{"type": "address", "name": "token_addr"}], "constant": false, "payable": false, "type": "function", "gas": 175875}, {"name": "addLiquidity", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "min_liquidity"}, {"type": "uint256", "name": "max_tokens"}, {"type": "uint256", "name": "deadline"}], "constant": false, "payable": true, "type": "function", "gas": 82605}, {"name": "removeLiquidity", "outputs": [{"type": "uint256", "name": "out"}, {"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "amount"}, {"type": "uint256", "name": "min_eth"}, {"type": "uint256", "name": "min_tokens"}, {"type": "uint256", "name": "deadline"}], "constant": false, "payable": false, "type": "function", "gas": 116814}, {"name": "__default__", "outputs": [], "inputs": [], "constant": false, "payable": true, "type": "function"}, {"name": "ethToTokenSwapInput", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "min_tokens"}, {"type": "uint256", "name": "deadline"}], "constant": false, "payable": true, "type": "function", "gas": 12757}, {"name": "ethToTokenTransferInput", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "min_tokens"}, {"type": "uint256", "name": "deadline"}, {"type": "address", "name": "recipient"}], "constant": false, "payable": true, "type": "function", "gas": 12965}, {"name": "ethToTokenSwapOutput", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "tokens_bought"}, {"type": "uint256", "name": "deadline"}], "constant": false, "payable": true, "type": "function", "gas": 50463}, {"name": "ethToTokenTransferOutput", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "tokens_bought"}, {"type": "uint256", "name": "deadline"}, {"type": "address", "name": "recipient"}], "constant": false, "payable": true, "type": "function", "gas": 50671}, {"name": "tokenToEthSwapInput", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "tokens_sold"}, {"type": "uint256", "name": "min_eth"}, {"type": "uint256", "name": "deadline"}], "constant": false, "payable": false, "type": "function", "gas": 47503}, {"name": "tokenToEthTransferInput", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "tokens_sold"}, {"type": "uint256", "name": "min_eth"}, {"type": "uint256", "name": "deadline"}, {"type": "address", "name": "recipient"}], "constant": false, "payable": false, "type": "function", "gas": 47712}, {"name": "tokenToEthSwapOutput", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "eth_bought"}, {"type": "uint256", "name": "max_tokens"}, {"type": "uint256", "name": "deadline"}], "constant": false, "payable": false, "type": "function", "gas": 50175}, {"name": "tokenToEthTransferOutput", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "eth_bought"}, {"type": "uint256", "name": "max_tokens"}, {"type": "uint256", "name": "deadline"}, {"type": "address", "name": "recipient"}], "constant": false, "payable": false, "type": "function", "gas": 50384}, {"name": "tokenToTokenSwapInput", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "tokens_sold"}, {"type": "uint256", "name": "min_tokens_bought"}, {"type": "uint256", "name": "min_eth_bought"}, {"type": "uint256", "name": "deadline"}, {"type": "address", "name": "token_addr"}], "constant": false, "payable": false, "type": "function", "gas": 51007}, {"name": "tokenToTokenTransferInput", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "tokens_sold"}, {"type": "uint256", "name": "min_tokens_bought"}, {"type": "uint256", "name": "min_eth_bought"}, {"type": "uint256", "name": "deadline"}, {"type": "address", "name": "recipient"}, {"type": "address", "name": "token_addr"}], "constant": false, "payable": false, "type": "function", "gas": 51098}, {"name": "tokenToTokenSwapOutput", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "tokens_bought"}, {"type": "uint256", "name": "max_tokens_sold"}, {"type": "uint256", "name": "max_eth_sold"}, {"type": "uint256", "name": "deadline"}, {"type": "address", "name": "token_addr"}], "constant": false, "payable": false, "type": "function", "gas": 54928}, {"name": "tokenToTokenTransferOutput", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "tokens_bought"}, {"type": "uint256", "name": "max_tokens_sold"}, {"type": "uint256", "name": "max_eth_sold"}, {"type": "uint256", "name": "deadline"}, {"type": "address", "name": "recipient"}, {"type": "address", "name": "token_addr"}], "constant": false, "payable": false, "type": "function", "gas": 55019}, {"name": "tokenToExchangeSwapInput", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "tokens_sold"}, {"type": "uint256", "name": "min_tokens_bought"}, {"type": "uint256", "name": "min_eth_bought"}, {"type": "uint256", "name": "deadline"}, {"type": "address", "name": "exchange_addr"}], "constant": false, "payable": false, "type": "function", "gas": 49342}, {"name": "tokenToExchangeTransferInput", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "tokens_sold"}, {"type": "uint256", "name": "min_tokens_bought"}, {"type": "uint256", "name": "min_eth_bought"}, {"type": "uint256", "name": "deadline"}, {"type": "address", "name": "recipient"}, {"type": "address", "name": "exchange_addr"}], "constant": false, "payable": false, "type": "function", "gas": 49532}, {"name": "tokenToExchangeSwapOutput", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "tokens_bought"}, {"type": "uint256", "name": "max_tokens_sold"}, {"type": "uint256", "name": "max_eth_sold"}, {"type": "uint256", "name": "deadline"}, {"type": "address", "name": "exchange_addr"}], "constant": false, "payable": false, "type": "function", "gas": 53233}, {"name": "tokenToExchangeTransferOutput", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "tokens_bought"}, {"type": "uint256", "name": "max_tokens_sold"}, {"type": "uint256", "name": "max_eth_sold"}, {"type": "uint256", "name": "deadline"}, {"type": "address", "name": "recipient"}, {"type": "address", "name": "exchange_addr"}], "constant": false, "payable": false, "type": "function", "gas": 53423}, {"name": "getEthToTokenInputPrice", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "eth_sold"}], "constant": true, "payable": false, "type": "function", "gas": 5542}, {"name": "getEthToTokenOutputPrice", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "tokens_bought"}], "constant": true, "payable": false, "type": "function", "gas": 6872}, {"name": "getTokenToEthInputPrice", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "tokens_sold"}], "constant": true, "payable": false, "type": "function", "gas": 5637}, {"name": "getTokenToEthOutputPrice", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "eth_bought"}], "constant": true, "payable": false, "type": "function", "gas": 6897}, {"name": "tokenAddress", "outputs": [{"type": "address", "name": "out"}], "inputs": [], "constant": true, "payable": false, "type": "function", "gas": 1413}, {"name": "factoryAddress", "outputs": [{"type": "address", "name": "out"}], "inputs": [], "constant": true, "payable": false, "type": "function", "gas": 1443}, {"name": "balanceOf", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "address", "name": "_owner"}], "constant": true, "payable": false, "type": "function", "gas": 1645}, {"name": "transfer", "outputs": [{"type": "bool", "name": "out"}], "inputs": [{"type": "address", "name": "_to"}, {"type": "uint256", "name": "_value"}], "constant": false, "payable": false, "type": "function", "gas": 75034}, {"name": "transferFrom", "outputs": [{"type": "bool", "name": "out"}], "inputs": [{"type": "address", "name": "_from"}, {"type": "address", "name": "_to"}, {"type": "uint256", "name": "_value"}], "constant": false, "payable": false, "type": "function", "gas": 110907}, {"name": "approve", "outputs": [{"type": "bool", "name": "out"}], "inputs": [{"type": "address", "name": "_spender"}, {"type": "uint256", "name": "_value"}], "constant": false, "payable": false, "type": "function", "gas": 38769}, {"name": "allowance", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "address", "name": "_owner"}, {"type": "address", "name": "_spender"}], "constant": true, "payable": false, "type": "function", "gas": 1925}, {"name": "name", "outputs": [{"type": "bytes32", "name": "out"}], "inputs": [], "constant": true, "payable": false, "type": "function", "gas": 1623}, {"name": "symbol", "outputs": [{"type": "bytes32", "name": "out"}], "inputs": [], "constant": true, "payable": false, "type": "function", "gas": 1653}, {"name": "decimals", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [], "constant": true, "payable": false, "type": "function", "gas": 1683}, {"name": "totalSupply", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [], "constant": true, "payable": false, "type": "function", "gas": 1713}] [{"name": "TokenPurchase", "inputs": [{"type": "address", "name": "buyer", "indexed": true}, {"type": "uint256", "name": "eth_sold", "indexed": true}, {"type": "uint256", "name": "tokens_bought", "indexed": true}], "anonymous": false, "type": "event"}, {"name": "EthPurchase", "inputs": [{"type": "address", "name": "buyer", "indexed": true}, {"type": "uint256", "name": "tokens_sold", "indexed": true}, {"type": "uint256", "name": "eth_bought", "indexed": true}], "anonymous": false, "type": "event"}, {"name": "AddLiquidity", "inputs": [{"type": "address", "name": "provider", "indexed": true}, {"type": "uint256", "name": "eth_amount", "indexed": true}, {"type": "uint256", "name": "token_amount", "indexed": true}], "anonymous": false, "type": "event"}, {"name": "RemoveLiquidity", "inputs": [{"type": "address", "name": "provider", "indexed": true}, {"type": "uint256", "name": "eth_amount", "indexed": true}, {"type": "uint256", "name": "token_amount", "indexed": true}], "anonymous": false, "type": "event"}, {"name": "Transfer", "inputs": [{"type": "address", "name": "_from", "indexed": true}, {"type": "address", "name": "_to", "indexed": true}, {"type": "uint256", "name": "_value", "indexed": false}], "anonymous": false, "type": "event"}, {"name": "Approval", "inputs": [{"type": "address", "name": "_owner", "indexed": true}, {"type": "address", "name": "_spender", "indexed": true}, {"type": "uint256", "name": "_value", "indexed": false}], "anonymous": false, "type": "event"}, {"name": "setup", "outputs": [], "inputs": [{"type": "address", "name": "token_addr"}], "constant": false, "payable": false, "type": "function", "gas": 175875}, {"name": "addLiquidity", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "min_liquidity"}, {"type": "uint256", "name": "max_tokens"}, {"type": "uint256", "name": "deadline"}], "constant": false, "payable": true, "type": "function", "gas": 82605}, {"name": "removeLiquidity", "outputs": [{"type": "uint256", "name": "out"}, {"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "amount"}, {"type": "uint256", "name": "min_eth"}, {"type": "uint256", "name": "min_tokens"}, {"type": "uint256", "name": "deadline"}], "constant": false, "payable": false, "type": "function", "gas": 116814}, {"name": "__default__", "outputs": [], "inputs": [], "constant": false, "payable": true, "type": "function"}, {"name": "ethToTokenSwapInput", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "min_tokens"}, {"type": "uint256", "name": "deadline"}], "constant": false, "payable": true, "type": "function", "gas": 12757}, {"name": "ethToTokenTransferInput", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "min_tokens"}, {"type": "uint256", "name": "deadline"}, {"type": "address", "name": "recipient"}], "constant": false, "payable": true, "type": "function", "gas": 12965}, {"name": "ethToTokenSwapOutput", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "tokens_bought"}, {"type": "uint256", "name": "deadline"}], "constant": false, "payable": true, "type": "function", "gas": 50463}, {"name": "ethToTokenTransferOutput", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "tokens_bought"}, {"type": "uint256", "name": "deadline"}, {"type": "address", "name": "recipient"}], "constant": false, "payable": true, "type": "function", "gas": 50671}, {"name": "tokenToEthSwapInput", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "tokens_sold"}, {"type": "uint256", "name": "min_eth"}, {"type": "uint256", "name": "deadline"}], "constant": false, "payable": false, "type": "function", "gas": 47503}, {"name": "tokenToEthTransferInput", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "tokens_sold"}, {"type": "uint256", "name": "min_eth"}, {"type": "uint256", "name": "deadline"}, {"type": "address", "name": "recipient"}], "constant": false, "payable": false, "type": "function", "gas": 47712}, {"name": "tokenToEthSwapOutput", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "eth_bought"}, {"type": "uint256", "name": "max_tokens"}, {"type": "uint256", "name": "deadline"}], "constant": false, "payable": false, "type": "function", "gas": 50175}, {"name": "tokenToEthTransferOutput", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "eth_bought"}, {"type": "uint256", "name": "max_tokens"}, {"type": "uint256", "name": "deadline"}, {"type": "address", "name": "recipient"}], "constant": false, "payable": false, "type": "function", "gas": 50384}, {"name": "tokenToTokenSwapInput", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "tokens_sold"}, {"type": "uint256", "name": "min_tokens_bought"}, {"type": "uint256", "name": "min_eth_bought"}, {"type": "uint256", "name": "deadline"}, {"type": "address", "name": "token_addr"}], "constant": false, "payable": false, "type": "function", "gas": 51007}, {"name": "tokenToTokenTransferInput", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "tokens_sold"}, {"type": "uint256", "name": "min_tokens_bought"}, {"type": "uint256", "name": "min_eth_bought"}, {"type": "uint256", "name": "deadline"}, {"type": "address", "name": "recipient"}, {"type": "address", "name": "token_addr"}], "constant": false, "payable": false, "type": "function", "gas": 51098}, {"name": "tokenToTokenSwapOutput", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "tokens_bought"}, {"type": "uint256", "name": "max_tokens_sold"}, {"type": "uint256", "name": "max_eth_sold"}, {"type": "uint256", "name": "deadline"}, {"type": "address", "name": "token_addr"}], "constant": false, "payable": false, "type": "function", "gas": 54928}, {"name": "tokenToTokenTransferOutput", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "tokens_bought"}, {"type": "uint256", "name": "max_tokens_sold"}, {"type": "uint256", "name": "max_eth_sold"}, {"type": "uint256", "name": "deadline"}, {"type": "address", "name": "recipient"}, {"type": "address", "name": "token_addr"}], "constant": false, "payable": false, "type": "function", "gas": 55019}, {"name": "tokenToExchangeSwapInput", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "tokens_sold"}, {"type": "uint256", "name": "min_tokens_bought"}, {"type": "uint256", "name": "min_eth_bought"}, {"type": "uint256", "name": "deadline"}, {"type": "address", "name": "exchange_addr"}], "constant": false, "payable": false, "type": "function", "gas": 49342}, {"name": "tokenToExchangeTransferInput", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "tokens_sold"}, {"type": "uint256", "name": "min_tokens_bought"}, {"type": "uint256", "name": "min_eth_bought"}, {"type": "uint256", "name": "deadline"}, {"type": "address", "name": "recipient"}, {"type": "address", "name": "exchange_addr"}], "constant": false, "payable": false, "type": "function", "gas": 49532}, {"name": "tokenToExchangeSwapOutput", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "tokens_bought"}, {"type": "uint256", "name": "max_tokens_sold"}, {"type": "uint256", "name": "max_eth_sold"}, {"type": "uint256", "name": "deadline"}, {"type": "address", "name": "exchange_addr"}], "constant": false, "payable": false, "type": "function", "gas": 53233}, {"name": "tokenToExchangeTransferOutput", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "tokens_bought"}, {"type": "uint256", "name": "max_tokens_sold"}, {"type": "uint256", "name": "max_eth_sold"}, {"type": "uint256", "name": "deadline"}, {"type": "address", "name": "recipient"}, {"type": "address", "name": "exchange_addr"}], "constant": false, "payable": false, "type": "function", "gas": 53423}, {"name": "getEthToTokenInputPrice", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "eth_sold"}], "constant": true, "payable": false, "type": "function", "gas": 5542}, {"name": "getEthToTokenOutputPrice", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "tokens_bought"}], "constant": true, "payable": false, "type": "function", "gas": 6872}, {"name": "getTokenToEthInputPrice", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "tokens_sold"}], "constant": true, "payable": false, "type": "function", "gas": 5637}, {"name": "getTokenToEthOutputPrice", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "uint256", "name": "eth_bought"}], "constant": true, "payable": false, "type": "function", "gas": 6897}, {"name": "tokenAddress", "outputs": [{"type": "address", "name": "out"}], "inputs": [], "constant": true, "payable": false, "type": "function", "gas": 1413}, {"name": "factoryAddress", "outputs": [{"type": "address", "name": "out"}], "inputs": [], "constant": true, "payable": false, "type": "function", "gas": 1443}, {"name": "balanceOf", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "address", "name": "_owner"}], "constant": true, "payable": false, "type": "function", "gas": 1645}, {"name": "transfer", "outputs": [{"type": "bool", "name": "out"}], "inputs": [{"type": "address", "name": "_to"}, {"type": "uint256", "name": "_value"}], "constant": false, "payable": false, "type": "function", "gas": 75034}, {"name": "transferFrom", "outputs": [{"type": "bool", "name": "out"}], "inputs": [{"type": "address", "name": "_from"}, {"type": "address", "name": "_to"}, {"type": "uint256", "name": "_value"}], "constant": false, "payable": false, "type": "function", "gas": 110907}, {"name": "approve", "outputs": [{"type": "bool", "name": "out"}], "inputs": [{"type": "address", "name": "_spender"}, {"type": "uint256", "name": "_value"}], "constant": false, "payable": false, "type": "function", "gas": 38769}, {"name": "allowance", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [{"type": "address", "name": "_owner"}, {"type": "address", "name": "_spender"}], "constant": true, "payable": false, "type": "function", "gas": 1925}, {"name": "name", "outputs": [{"type": "bytes32", "name": "out"}], "inputs": [], "constant": true, "payable": false, "type": "function", "gas": 1623}, {"name": "symbol", "outputs": [{"type": "bytes32", "name": "out"}], "inputs": [], "constant": true, "payable": false, "type": "function", "gas": 1653}, {"name": "decimals", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [], "constant": true, "payable": false, "type": "function", "gas": 1683}, {"name": "totalSupply", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [], "constant": true, "payable": false, "type": "function", "gas": 1713}]
...@@ -103,7 +103,7 @@ class CurrencyInputPanel extends Component { ...@@ -103,7 +103,7 @@ class CurrencyInputPanel extends Component {
} }
if (selectedTokenAddress === 'ETH') { if (selectedTokenAddress === 'ETH') {
return `Balance: ${web3.utils.fromWei(balance, 'ether')}`; return `Balance: ${BN(web3.utils.fromWei(balance, 'ether')).toFixed(2)}`;
} }
const tokenData = this.getTokenData(selectedTokenAddress); const tokenData = this.getTokenData(selectedTokenAddress);
...@@ -145,32 +145,36 @@ class CurrencyInputPanel extends Component { ...@@ -145,32 +145,36 @@ class CurrencyInputPanel extends Component {
this.props.onCurrencySelected(address); this.props.onCurrencySelected(address);
if (address && address !== 'ETH') { if (address && address !== 'ETH') {
// Add Token Contract
const { drizzle } = this.context; const { drizzle } = this.context;
const { fromToken } = this.props.exchangeAddresses; const { fromToken } = this.props.exchangeAddresses;
const { web3 } = drizzle; const { web3 } = drizzle;
const tokenConfig = {
contractName: address,
web3Contract: new web3.eth.Contract(ERC20_ABI, address),
};
const tokenEvents = ['Approval', 'Transfer'];
this.context.drizzle.addContract(tokenConfig, tokenEvents, { from: this.props.account }); // Add Token Contract
if (!this.props.contracts[address]) {
// console.log(`Adding Token Contract - ${address}`);
const tokenConfig = {
contractName: address,
web3Contract: new web3.eth.Contract(ERC20_ABI, address),
};
const tokenEvents = ['Approval', 'Transfer'];
this.context.drizzle.addContract(tokenConfig, tokenEvents, { from: this.props.account });
}
// Add Exchange Contract // Add Exchange Contract
const exchangeAddress = fromToken[address]; const exchangeAddress = fromToken[address];
if (!exchangeAddress) { if (!exchangeAddress) {
return; return;
} }
const exchangeConfig = { if (!this.props.contracts[exchangeAddress]) {
contractName: exchangeAddress, // console.log(`Adding Exchange Contract - ${exchangeAddress}`);
web3Contract: new web3.eth.Contract(EXCHANGE_ABI, exchangeAddress), const exchangeConfig = {
}; contractName: exchangeAddress,
const exchangeEvents = ['Approval', 'Transfer', 'TokenPurchase', 'EthPurchase', 'AddLiquidity', 'RemoveLiquidity']; web3Contract: new web3.eth.Contract(EXCHANGE_ABI, exchangeAddress),
};
this.context.drizzle.addContract(exchangeConfig, exchangeEvents , { from: this.props.account }); const exchangeEvents = ['Approval', 'Transfer', 'TokenPurchase', 'EthPurchase', 'AddLiquidity', 'RemoveLiquidity'];
this.context.drizzle.addContract(exchangeConfig, exchangeEvents , { from: this.props.account });
}
} }
}; };
......
import {BigNumber as BN} from "bignumber.js"; import {BigNumber as BN} from "bignumber.js";
import promisify from "./web3-promisfy";
export const calculateExchangeRateFromInput = async opts => { export const calculateExchangeRateFromInput = async opts => {
const { inputCurrency, outputCurrency } = opts; const { inputCurrency, outputCurrency } = opts;
...@@ -47,6 +48,53 @@ export const calculateExchangeRateFromOutput = async opts => { ...@@ -47,6 +48,53 @@ export const calculateExchangeRateFromOutput = async opts => {
return ERC20_TO_ERC20.calculateInput(opts); return ERC20_TO_ERC20.calculateInput(opts);
}; };
export const swapInput = async opts => {
const { inputCurrency, outputCurrency } = opts;
if (!inputCurrency || !outputCurrency) {
return;
}
if (inputCurrency === outputCurrency) {
console.error(`Input and Output currency cannot be the same`);
return;
}
if (inputCurrency === 'ETH' && outputCurrency !== 'ETH') {
return ETH_TO_ERC20.swapInput(opts);
}
if (outputCurrency === 'ETH' && inputCurrency !== 'ETH') {
return ERC20_TO_ETH.swapInput(opts);
}
return ERC20_TO_ERC20.swapInput(opts);
};
export const swapOutput = async opts => {
const { inputCurrency, outputCurrency } = opts;
if (!inputCurrency || !outputCurrency) {
return;
}
if (inputCurrency === outputCurrency) {
console.error(`Input and Output currency cannot be the same`);
return;
}
if (inputCurrency === 'ETH' && outputCurrency !== 'ETH') {
return ETH_TO_ERC20.swapOutput(opts);
}
if (outputCurrency === 'ETH' && inputCurrency !== 'ETH') {
return ERC20_TO_ETH.swapOutput(opts);
}
return ERC20_TO_ERC20.swapOutput(opts);
};
const ETH_TO_ERC20 = { const ETH_TO_ERC20 = {
calculateOutput: async ({drizzleCtx, contractStore, input, inputCurrency, outputCurrency, exchangeAddresses }) => { calculateOutput: async ({drizzleCtx, contractStore, input, inputCurrency, outputCurrency, exchangeAddresses }) => {
if (inputCurrency !== 'ETH') { if (inputCurrency !== 'ETH') {
...@@ -137,6 +185,73 @@ const ETH_TO_ERC20 = { ...@@ -137,6 +185,73 @@ const ETH_TO_ERC20 = {
return exchangeRate; return exchangeRate;
}, },
swapInput: async ({drizzleCtx, contractStore, input, output, account, inputCurrency, outputCurrency, exchangeAddresses }) => {
if (inputCurrency !== 'ETH') {
console.error('Input Currency should be ETH');
return;
}
if (!outputCurrency || outputCurrency === 'ETH') {
console.error('Output Currency should be ERC20');
return;
}
const exchangeAddress = exchangeAddresses.fromToken[outputCurrency];
const exchange = drizzleCtx.contracts[exchangeAddress];
if (!exchangeAddress || !exchange) {
console.error(`Cannot find Exchange Address for ${outputCurrency}`);
return;
}
const { web3 } = drizzleCtx;
const blockNumber = await promisify(web3, 'getBlockNumber');
const block = await promisify(web3, 'getBlock', blockNumber);
const deadline = block.timestamp + 300;
const ALLOWED_SLIPPAGE = BN(0.025);
const outputDecimals = await getDecimals({ address: outputCurrency, contractStore, drizzleCtx });
const minOutput = BN(output).multipliedBy(10 ** outputDecimals).multipliedBy(BN(1).minus(ALLOWED_SLIPPAGE));
exchange.methods.ethToTokenSwapInput.cacheSend(minOutput.toFixed(0), deadline, {
from: account,
value: BN(input).multipliedBy(10 ** 18).toFixed(0),
});
},
swapOutput: async ({drizzleCtx, contractStore, input, output, account, inputCurrency, outputCurrency, exchangeAddresses }) => {
if (inputCurrency !== 'ETH') {
console.error('Input Currency should be ETH');
return;
}
if (!outputCurrency || outputCurrency === 'ETH') {
console.error('Output Currency should be ERC20');
return;
}
const exchangeAddress = exchangeAddresses.fromToken[outputCurrency];
const exchange = drizzleCtx.contracts[exchangeAddress];
if (!exchangeAddress || !exchange) {
console.error(`Cannot find Exchange Address for ${outputCurrency}`);
return;
}
const { web3 } = drizzleCtx;
const blockNumber = await promisify(web3, 'getBlockNumber');
const block = await promisify(web3, 'getBlock', blockNumber);
const deadline = block.timestamp + 300;
const ALLOWED_SLIPPAGE = BN(0.025);
const outputDecimals = await getDecimals({ address: outputCurrency, contractStore, drizzleCtx });
const outputAmount = BN(output).multipliedBy(BN(10 ** outputDecimals));
const maxInput = BN(input).multipliedBy(10 ** 18).multipliedBy(BN(1).plus(ALLOWED_SLIPPAGE));
exchange.methods.ethToTokenSwapOutput.cacheSend(outputAmount.toFixed(0), deadline, {
from: account,
value: maxInput.toFixed(0),
});
},
}; };
const ERC20_TO_ETH = { const ERC20_TO_ETH = {
...@@ -192,7 +307,7 @@ const ERC20_TO_ETH = { ...@@ -192,7 +307,7 @@ const ERC20_TO_ETH = {
} }
if (!inputCurrency || inputCurrency === 'ETH') { if (!inputCurrency || inputCurrency === 'ETH') {
console.error('Output Currency should be ERC20'); console.error('Input Currency should be ERC20');
return; return;
} }
...@@ -229,6 +344,78 @@ const ERC20_TO_ETH = { ...@@ -229,6 +344,78 @@ const ERC20_TO_ETH = {
return exchangeRate; return exchangeRate;
}, },
swapInput: async ({drizzleCtx, contractStore, input, output, account, inputCurrency, outputCurrency, exchangeAddresses }) => {
if (outputCurrency !== 'ETH') {
console.error('Output Currency should be ETH');
return;
}
if (!inputCurrency || inputCurrency === 'ETH') {
console.error('Input Currency should be ERC20');
return;
}
const exchangeAddress = exchangeAddresses.fromToken[inputCurrency];
const exchange = drizzleCtx.contracts[exchangeAddress];
if (!exchangeAddress || !exchange) {
console.error(`Cannot find Exchange Address for ${inputCurrency}`);
return;
}
const { web3 } = drizzleCtx;
const blockNumber = await promisify(web3, 'getBlockNumber');
const block = await promisify(web3, 'getBlock', blockNumber);
const deadline = block.timestamp + 300;
const ALLOWED_SLIPPAGE = BN(0.025);
const inputDecimals = await getDecimals({ address: inputCurrency, contractStore, drizzleCtx });
const minOutput = BN(output).multipliedBy(10 ** 18).multipliedBy(BN(1).minus(ALLOWED_SLIPPAGE));
const inputAmount = BN(input).multipliedBy(10 ** inputDecimals);
exchange.methods.tokenToEthSwapInput.cacheSend(
inputAmount.toFixed(0),
minOutput.toFixed(0),
deadline,
{ from: account, value: '0x0' },
);
},
swapOutput: async ({drizzleCtx, contractStore, input, output, account, inputCurrency, outputCurrency, exchangeAddresses }) => {
if (outputCurrency !== 'ETH') {
console.error('Output Currency should be ETH');
return;
}
if (!inputCurrency || inputCurrency === 'ETH') {
console.error('Output Currency should be ERC20');
return;
}
const exchangeAddress = exchangeAddresses.fromToken[inputCurrency];
const exchange = drizzleCtx.contracts[exchangeAddress];
if (!exchangeAddress || !exchange) {
console.error(`Cannot find Exchange Address for ${inputCurrency}`);
return;
}
const { web3 } = drizzleCtx;
const blockNumber = await promisify(web3, 'getBlockNumber');
const block = await promisify(web3, 'getBlock', blockNumber);
const deadline = block.timestamp + 300;
const ALLOWED_SLIPPAGE = BN(0.025);
const inputDecimals = await getDecimals({ address: inputCurrency, contractStore, drizzleCtx });
const maxInput = BN(input).multipliedBy(10 ** inputDecimals).multipliedBy(BN(1).plus(ALLOWED_SLIPPAGE));
const outputAmount = BN(output).multipliedBy(10 ** 18);
exchange.methods.tokenToEthSwapOutput.cacheSend(
outputAmount.toFixed(0),
maxInput.toFixed(0),
deadline,
{ from: account },
);
},
}; };
const ERC20_TO_ERC20 = { const ERC20_TO_ERC20 = {
...@@ -278,9 +465,111 @@ const ERC20_TO_ERC20 = { ...@@ -278,9 +465,111 @@ const ERC20_TO_ERC20 = {
return exchangeRateA.multipliedBy(exchangeRateB); return exchangeRateA.multipliedBy(exchangeRateB);
}, },
}; swapInput: async ({drizzleCtx, contractStore, input, output, account, inputCurrency, outputCurrency, exchangeAddresses }) => {
if (!outputCurrency || outputCurrency === 'ETH') {
console.error('Output Currency should be ERC20');
return;
}
if (!inputCurrency || inputCurrency === 'ETH') {
console.error('Input Currency should be ERC20');
return;
}
const exchangeAddress = exchangeAddresses.fromToken[inputCurrency];
const exchange = drizzleCtx.contracts[exchangeAddress];
if (!exchangeAddress || !exchange) {
console.error(`Cannot find Exchange Address for ${inputCurrency}`);
return;
}
const { web3 } = drizzleCtx;
const blockNumber = await promisify(web3, 'getBlockNumber');
const block = await promisify(web3, 'getBlock', blockNumber);
const deadline = block.timestamp + 300;
const ALLOWED_SLIPPAGE = BN(0.04);
const inputDecimals = await getDecimals({ address: inputCurrency, contractStore, drizzleCtx });
const outputDecimals = await getDecimals({ address: outputCurrency, contractStore, drizzleCtx });
const inputAmount = BN(input).multipliedBy(BN(10 ** inputDecimals));
const outputAmount = BN(input).multipliedBy(BN(10 ** outputDecimals));
const tokenAddress = outputCurrency;
const tokensSold = inputAmount.toFixed(0);
const minTokensBought = outputAmount.multipliedBy(BN(1).plus(ALLOWED_SLIPPAGE)).toFixed(0);
const minEthBought = 1;
exchange.methods.tokenToTokenSwapInput.cacheSend(
tokensSold,
minTokensBought,
minEthBought,
deadline,
tokenAddress,
{ from: account },
);
},
swapOutput: async opts => {
const {
drizzleCtx,
contractStore,
input,
output,
account,
inputCurrency,
outputCurrency,
exchangeAddresses
} = opts;
const exchangeRateA = await ETH_TO_ERC20.calculateInput({ ...opts, inputCurrency: 'ETH' });
if (!exchangeRateA) {
return;
}
if (!outputCurrency || outputCurrency === 'ETH') {
console.error('Output Currency should be ERC20');
return;
}
if (!inputCurrency || inputCurrency === 'ETH') {
console.error('Input Currency should be ERC20');
return;
}
const exchangeAddress = exchangeAddresses.fromToken[inputCurrency];
const exchange = drizzleCtx.contracts[exchangeAddress];
if (!exchangeAddress || !exchange) {
console.error(`Cannot find Exchange Address for ${inputCurrency}`);
return;
}
const { web3 } = drizzleCtx;
const blockNumber = await promisify(web3, 'getBlockNumber');
const block = await promisify(web3, 'getBlock', blockNumber);
const deadline = block.timestamp + 300;
const ALLOWED_SLIPPAGE = BN(0.04);
const inputDecimals = await getDecimals({ address: inputCurrency, contractStore, drizzleCtx });
const outputDecimals = await getDecimals({ address: outputCurrency, contractStore, drizzleCtx });
const inputAmount = BN(input).multipliedBy(BN(10 ** inputDecimals));
const outputAmount = BN(output).multipliedBy(BN(10 ** outputDecimals));
const inputAmountB = BN(output).dividedBy(exchangeRateA).multipliedBy(BN(10 ** 18));
const tokenAddress = outputCurrency;
const tokensBought = outputAmount.toFixed(0);
const maxTokensSold = inputAmount.multipliedBy(BN(1).plus(ALLOWED_SLIPPAGE)).toFixed(0);
const maxEthSold = inputAmountB.multipliedBy(1.2).toFixed(0);
exchange.methods.tokenToTokenSwapOutput.cacheSend(
tokensBought,
maxTokensSold,
maxEthSold,
deadline,
tokenAddress,
{ from: account },
);
},
};
function getDecimals({ address, drizzleCtx, contractStore }) { function getDecimals({ address, drizzleCtx, contractStore }) {
return new Promise(async (resolve, reject) => { return new Promise(async (resolve, reject) => {
...@@ -295,6 +584,8 @@ function getDecimals({ address, drizzleCtx, contractStore }) { ...@@ -295,6 +584,8 @@ function getDecimals({ address, drizzleCtx, contractStore }) {
}); });
} }
const BALANCE_KEY = {};
function getBalance({ currency, address, drizzleCtx, contractStore }) { function getBalance({ currency, address, drizzleCtx, contractStore }) {
return new Promise(async (resolve, reject) => { return new Promise(async (resolve, reject) => {
if (currency === 'ETH') { if (currency === 'ETH') {
...@@ -310,7 +601,14 @@ function getBalance({ currency, address, drizzleCtx, contractStore }) { ...@@ -310,7 +601,14 @@ function getBalance({ currency, address, drizzleCtx, contractStore }) {
if (!token) { if (!token) {
return; return;
} }
const balanceKey = token.methods.balanceOf.cacheCall(address);
let balanceKey = BALANCE_KEY[address];
if (!balanceKey) {
balanceKey = token.methods.balanceOf.cacheCall(address);
BALANCE_KEY[address] = balanceKey;
}
const tokenStore = contractStore[currency]; const tokenStore = contractStore[currency];
if (!tokenStore) { if (!tokenStore) {
......
export default function promisify(web3, methodName, ...args) {
return new Promise((resolve, reject) => {
if (!web3) {
reject(new Error('No Web3 object'));
return;
}
const method = web3.eth[methodName];
if (!method) {
reject(new Error(`Cannot find web3.eth.${methodName}`));
return;
}
method(...args, (error, data) => {
if (error) {
reject(error);
return;
}
resolve(data);
})
});
}
...@@ -6,9 +6,6 @@ import store from './store'; ...@@ -6,9 +6,6 @@ import store from './store';
import './index.scss'; import './index.scss';
import registerServiceWorker from './registerServiceWorker';
window.addEventListener('load', function() { window.addEventListener('load', function() {
ReactDOM.render( ReactDOM.render(
<DrizzleProvider options={{ <DrizzleProvider options={{
...@@ -20,7 +17,5 @@ window.addEventListener('load', function() { ...@@ -20,7 +17,5 @@ window.addEventListener('load', function() {
</DrizzleProvider> </DrizzleProvider>
, document.getElementById('root') , document.getElementById('root')
); );
registerServiceWorker();
}); });
...@@ -9,7 +9,13 @@ import Header from '../../components/Header'; ...@@ -9,7 +9,13 @@ import Header from '../../components/Header';
import CurrencyInputPanel from '../../components/CurrencyInputPanel'; import CurrencyInputPanel from '../../components/CurrencyInputPanel';
import OversizedPanel from '../../components/OversizedPanel'; import OversizedPanel from '../../components/OversizedPanel';
import ArrowDown from '../../assets/images/arrow-down-blue.svg'; import ArrowDown from '../../assets/images/arrow-down-blue.svg';
import { calculateExchangeRateFromInput, calculateExchangeRateFromOutput } from '../../helpers/exchange-utils'; import {
calculateExchangeRateFromInput,
calculateExchangeRateFromOutput,
swapInput,
swapOutput,
} from '../../helpers/exchange-utils';
import promisify from '../../helpers/web3-promisfy';
import "./swap.scss"; import "./swap.scss";
...@@ -36,6 +42,30 @@ class Swap extends Component { ...@@ -36,6 +42,30 @@ class Swap extends Component {
exchangeRate: BN(0), exchangeRate: BN(0),
}; };
componentWillReceiveProps(nextProps) {
this.getExchangeRate(nextProps)
.then(exchangeRate => {
this.setState({ exchangeRate });
if (!exchangeRate) {
return;
}
if (nextProps.lastEditedField === 'input') {
this.props.updateField('output', `${BN(nextProps.input).multipliedBy(exchangeRate).toFixed(7)}`);
} else if (nextProps.lastEditedField === 'output') {
this.props.updateField('input', `${BN(nextProps.output).multipliedBy(BN(1).dividedBy(exchangeRate)).toFixed(7)}`);
}
});
}
componentWillUnmount() {
this.props.updateField('output', '');
this.props.updateField('input', '');
this.props.updateField('outputCurrency', '');
this.props.updateField('inputCurrency', '');
this.props.updateField('lastEditedField', '');
}
getTokenLabel(address) { getTokenLabel(address) {
if (address === 'ETH') { if (address === 'ETH') {
return 'ETH'; return 'ETH';
...@@ -113,41 +143,60 @@ class Swap extends Component { ...@@ -113,41 +143,60 @@ class Swap extends Component {
}) ; }) ;
} }
componentWillReceiveProps(nextProps) { onSwap = async () => {
this.getExchangeRate(nextProps) const {
.then(exchangeRate => { input,
this.setState({ exchangeRate }); output,
if (!exchangeRate) { inputCurrency,
return; outputCurrency,
} exchangeAddresses,
lastEditedField,
account,
contracts,
} = this.props;
if (nextProps.lastEditedField === 'input') { const { drizzle } = this.context;
this.props.updateField('output', `${BN(nextProps.input).multipliedBy(exchangeRate).toFixed(7)}`);
} else if (nextProps.lastEditedField === 'output') {
this.props.updateField('input', `${BN(nextProps.output).multipliedBy(BN(1).dividedBy(exchangeRate)).toFixed(7)}`);
}
});
}
componentWillUnmount() { if (lastEditedField === 'input') {
this.props.updateField('output', ''); swapInput({
this.props.updateField('input', ''); drizzleCtx: drizzle,
this.props.updateField('outputCurrency', ''); contractStore: contracts,
this.props.updateField('inputCurrency', ''); input,
this.props.updateField('lastEditedField', ''); output,
} inputCurrency,
outputCurrency,
exchangeAddresses,
account,
});
}
onCurrencySelected(field, data) { if (lastEditedField === 'output') {
this.props.updateField(field, data); swapOutput({
// this.props drizzleCtx: drizzle,
} contractStore: contracts,
input,
output,
inputCurrency,
outputCurrency,
exchangeAddresses,
account,
});
}
// this.context.drizzle.web3.eth.getBlockNumber((_, d) => this.context.drizzle.web3.eth.getBlock(d, (_,d) => {
// const deadline = d.timestamp + 300;
// const id = exchange.methods.ethToTokenSwapInput.cacheSend(`${output * 10 ** 18}`, deadline, {
// from: "0xCf1dE0b4d1e492080336909f70413a5F4E7eEc62",
// value: `${input * 10 ** 18}`,
// }, );
// }));
};
render() { render() {
const { lastEditedField, inputCurrency, outputCurrency, input, output } = this.props; const { lastEditedField, inputCurrency, outputCurrency, input, output } = this.props;
const { exchangeRate } = this.state; const { exchangeRate } = this.state;
const inputLabel = this.getTokenLabel(inputCurrency); const inputLabel = this.getTokenLabel(inputCurrency);
const outputLabel = this.getTokenLabel(outputCurrency); const outputLabel = this.getTokenLabel(outputCurrency);
const estimatedText = '(estimated)' const estimatedText = '(estimated)';
return ( return (
<div className="swap"> <div className="swap">
...@@ -202,6 +251,7 @@ class Swap extends Component { ...@@ -202,6 +251,7 @@ class Swap extends Component {
className={classnames('swap__cta-btn', { className={classnames('swap__cta-btn', {
'swap--inactive': !this.props.isConnected, 'swap--inactive': !this.props.isConnected,
})} })}
onClick={this.onSwap}
> >
Swap Swap
</button> </button>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment