+
+
+ * Some data provided by Nomics.com
+
+
+ Cryptocurrency Market Data API
+
+
+
+ );
+ }
+
+ if (tokenName) {
+ return (
+
+ {tokenName} (NFT-ERC721) with id: {collectibleId}
+
+ );
+ }
+
+ return
NFT-ERC721 with id: {collectibleId} ;
+ }
+}
+
+CollectibleDisplay.propTypes = {
+ collectibleId: PropTypes.any,
+ onlyText: PropTypes.any,
+ tokenAddress: PropTypes.any,
+ tokenHelper: PropTypes.any,
+ tokenName: PropTypes.any
+};
+
+export default CollectibleDisplay;
diff --git a/app/components/Header/Header.js b/app/components/Header/Header.js
index b6b93904..e8cf2492 100644
--- a/app/components/Header/Header.js
+++ b/app/components/Header/Header.js
@@ -99,17 +99,14 @@ class Header extends Component {
Transferred:
-
+
{eacStore.totalEthTransferred !== null ? (
`${eacStore.totalEthTransferred} ETH`
) : (
)}
{eacStore.totalUsdTransferred !== null &&
- ` (${eacStore.getFormattedUSDTranferred()})`}
+ ` (${eacStore.getFormattedUSDTranferred()}*)`}
diff --git a/app/components/ScheduleWizard/ConfirmSettings.js b/app/components/ScheduleWizard/ConfirmSettings.js
index 59eb6525..f9635606 100644
--- a/app/components/ScheduleWizard/ConfirmSettings.js
+++ b/app/components/ScheduleWizard/ConfirmSettings.js
@@ -3,7 +3,11 @@ import PropTypes from 'prop-types';
import { action } from 'mobx';
import { inject, observer } from 'mobx-react';
import Alert from '../Common/Alert';
+import CollectibleDisplay from '../Common/CollectibleDisplay';
+const EMPTY_FIELD_SIGN = '-';
+
+@inject('tokenHelper')
@inject('scheduleStore')
@inject('eacService')
@inject('web3Service')
@@ -100,6 +104,45 @@ class ConfirmSettings extends Component {
this._mounted = false;
}
+ isCollectibleTransfer() {
+ const { scheduleStore, tokenHelper } = this.props;
+
+ return scheduleStore && tokenHelper.isCollectible(scheduleStore.toAddress);
+ }
+
+ getAmountToSendDisplay() {
+ const { scheduleStore } = this.props;
+
+ if (scheduleStore.isTokenTransfer) {
+ if (this.isCollectibleTransfer() && scheduleStore.collectibleIdToTransfer) {
+ return (
+
+
+
+ );
+ }
+
+ return (
+
+ {scheduleStore.tokenToSend
+ ? scheduleStore.tokenToSend + ' ' + scheduleStore.tokenSymbol
+ : EMPTY_FIELD_SIGN}
+
+ );
+ }
+
+ return (
+
+ {scheduleStore.amountToSend ? scheduleStore.amountToSend + ' ETH' : EMPTY_FIELD_SIGN}
+
+ );
+ }
+
render() {
const Tabs = {
info: ' INFORMATION',
@@ -108,7 +151,6 @@ class ConfirmSettings extends Component {
block: ' DATE & TIME'
};
const { scheduleStore } = this.props;
- const emptyFieldSign = '-';
let errMsg = [];
Object.keys(this.state.errors).map(section => {
this.state.errors[section] ? errMsg.push(section) : null;
@@ -164,7 +206,7 @@ class ConfirmSettings extends Component {
{scheduleStore.toAddress}
) : (
- emptyFieldSign
+ EMPTY_FIELD_SIGN
)}
@@ -190,20 +232,7 @@ class ConfirmSettings extends Component {
Amount to Send
- {!scheduleStore.isTokenTransfer && (
-
- {scheduleStore.amountToSend
- ? scheduleStore.amountToSend + ' ETH'
- : emptyFieldSign}
-
- )}
- {scheduleStore.isTokenTransfer && (
-
- {scheduleStore.tokenToSend
- ? scheduleStore.tokenToSend + ' ' + scheduleStore.tokenSymbol
- : emptyFieldSign}
-
- )}
+ {this.getAmountToSendDisplay()}
Data
@@ -212,7 +241,7 @@ class ConfirmSettings extends Component {
className="d-inline-block col-6 col-lg-8 data-field"
title={scheduleStore.tokenData}
>
- {scheduleStore.yourData ? scheduleStore.yourData : emptyFieldSign}
+ {scheduleStore.yourData ? scheduleStore.yourData : EMPTY_FIELD_SIGN}
)}
{scheduleStore.isTokenTransfer && (
@@ -230,7 +259,7 @@ class ConfirmSettings extends Component {
Window Size
- {this.executionWindow || emptyFieldSign}
+ {this.executionWindow || EMPTY_FIELD_SIGN}
@@ -248,31 +277,33 @@ class ConfirmSettings extends Component {
Gas Amount
- {scheduleStore.gasAmount ? scheduleStore.gasAmount : emptyFieldSign}
+ {scheduleStore.gasAmount ? scheduleStore.gasAmount : EMPTY_FIELD_SIGN}
Gas Price
- {scheduleStore.gasPrice ? scheduleStore.gasPrice + ' Gwei' : emptyFieldSign}
+ {scheduleStore.gasPrice ? scheduleStore.gasPrice + ' Gwei' : EMPTY_FIELD_SIGN}
Fee
- {scheduleStore.fee ? scheduleStore.fee : emptyFieldSign}
+ {scheduleStore.fee ? scheduleStore.fee : EMPTY_FIELD_SIGN}
Time Bounty
- {scheduleStore.timeBounty ? scheduleStore.timeBounty + ' ETH' : emptyFieldSign}
+ {scheduleStore.timeBounty
+ ? scheduleStore.timeBounty + ' ETH'
+ : EMPTY_FIELD_SIGN}
Deposit
- {scheduleStore.deposit ? scheduleStore.deposit + ' ETH' : emptyFieldSign}
+ {scheduleStore.deposit ? scheduleStore.deposit + ' ETH' : EMPTY_FIELD_SIGN}
@@ -289,6 +320,7 @@ class ConfirmSettings extends Component {
ConfirmSettings.propTypes = {
scheduleStore: PropTypes.any,
+ tokenHelper: PropTypes.any,
web3Service: PropTypes.any,
eacService: PropTypes.any,
isWeb3Usable: PropTypes.any,
diff --git a/app/components/ScheduleWizard/InfoSettings.js b/app/components/ScheduleWizard/InfoSettings.js
index 52b5d005..fefed248 100644
--- a/app/components/ScheduleWizard/InfoSettings.js
+++ b/app/components/ScheduleWizard/InfoSettings.js
@@ -4,8 +4,9 @@ import Bb from 'bluebird';
import Switch from 'react-switch';
import AbstractSetting from './AbstractSetting';
import Alert from '../Common/Alert';
-import { TOKEN_ADDRESSES, PREDEFINED_TOKENS_FOR_NETWORK } from '../../config/web3Config';
+import { TOKEN_ADDRESSES } from '../../config/web3Config';
import Select from '../Common/Select';
+import CollectibleDisplay from '../Common/CollectibleDisplay';
@inject('tokenHelper')
@inject('scheduleStore')
@@ -18,7 +19,8 @@ class InfoSettings extends AbstractSetting {
this.state = {
account: '',
minGas: 21000,
- token: {}
+ token: {},
+ tokensOfOwner: []
};
const { _validations, _validationsErrors } = this.props;
this._validations = _validations.InfoSettings;
@@ -95,7 +97,7 @@ class InfoSettings extends AbstractSetting {
return estimate;
}
- async calculateTokenTransferMinimumGasandData() {
+ async calculateTokenTransferMinimumGasAndData() {
const {
web3Service: { web3 },
scheduleStore,
@@ -110,18 +112,37 @@ class InfoSettings extends AbstractSetting {
isAddress(scheduleStore.receiverAddress, web3) == 0
) {
try {
- estimate = await tokenHelper.estimateTokenTransfer(
- scheduleStore.toAddress,
- scheduleStore.receiverAddress,
- scheduleStore.tokenToSend * 10 ** this.state.token.decimals
- );
- estimate = estimate + 20000;
- scheduleStore.tokenData = await tokenHelper.getTokenTransferData(
- scheduleStore.toAddress,
- scheduleStore.receiverAddress,
- scheduleStore.tokenToSend * 10 ** this.state.token.decimals
- );
+ const isCollectibleTransfer = this.isCollectibleTransfer();
+
+ if (isCollectibleTransfer) {
+ estimate = await tokenHelper.estimateERC721Transfer(
+ scheduleStore.toAddress,
+ null,
+ scheduleStore.receiverAddress,
+ scheduleStore.collectibleIdToTransfer
+ );
+ estimate = estimate + 20000;
+ scheduleStore.tokenData = await tokenHelper.getERC721TransferData(
+ scheduleStore.toAddress,
+ null,
+ scheduleStore.receiverAddress,
+ scheduleStore.collectibleIdToTransfer
+ );
+ } else {
+ estimate = await tokenHelper.estimateTokenTransfer(
+ scheduleStore.toAddress,
+ scheduleStore.receiverAddress,
+ scheduleStore.tokenToSend * 10 ** this.state.token.decimals
+ );
+ estimate = estimate + 20000;
+ scheduleStore.tokenData = await tokenHelper.getTokenTransferData(
+ scheduleStore.toAddress,
+ scheduleStore.receiverAddress,
+ scheduleStore.tokenToSend * 10 ** this.state.token.decimals
+ );
+ }
} catch (e) {
+ console.error('Error in function calculateTokenTransferMinimumGasAndData', e);
scheduleStore.tokenData = '';
return;
}
@@ -136,6 +157,7 @@ class InfoSettings extends AbstractSetting {
if (!this._mounted) {
return;
}
+
const {
web3Service,
web3Service: { web3 },
@@ -149,10 +171,12 @@ class InfoSettings extends AbstractSetting {
) {
return;
}
+
this.setState({ account: web3Service.accounts[0] });
+
if (scheduleStore.isTokenTransfer && isAddress(scheduleStore.toAddress, web3) === 0) {
await this.getTokenDetails(true);
- await this.calculateTokenTransferMinimumGasandData();
+ await this.calculateTokenTransferMinimumGasAndData();
}
}
@@ -162,6 +186,7 @@ class InfoSettings extends AbstractSetting {
const tokenDetails = await tokenHelper.fetchTokenDetails(scheduleStore.toAddress);
this.setState({ token: tokenDetails });
scheduleStore.tokenSymbol = tokenDetails.symbol;
+ scheduleStore.tokenName = tokenDetails.name;
}
let _balance = await tokenHelper.fetchTokenBalance(scheduleStore.toAddress);
_balance = _balance == '-' ? _balance : Number(_balance / 10 ** this.state.token.decimals);
@@ -171,6 +196,13 @@ class InfoSettings extends AbstractSetting {
1 / 10 ** this.state.token.decimals,
balance
);
+
+ const tokensOfOwner = await tokenHelper.getTokensOfOwner(scheduleStore.toAddress);
+
+ this.setState({
+ tokensOfOwner
+ });
+
this.checkAmountValidation();
this.forceUpdate();
}
@@ -205,19 +237,27 @@ class InfoSettings extends AbstractSetting {
this.validators.tokenToSend = this.decimalValidator();
return;
}
+
if (property === 'toAddress') {
await this.getTokenDetails();
}
- await this.calculateTokenTransferMinimumGasandData();
+
+ await this.calculateTokenTransferMinimumGasAndData();
this.forceUpdate();
}
+ async chooseCollectible(tokenId) {
+ this.props.scheduleStore.collectibleIdToTransfer = tokenId;
+
+ await this.calculateTokenTransferMinimumGasAndData();
+ }
+
onChangeCheck = property => async event => {
let {
target: { value }
} = event;
const { scheduleStore } = this.props;
- this.onChange(property)({ target: { value: value } });
+ this.onChange(property)({ target: { value } });
if (scheduleStore.isTokenTransfer) {
await this.tokenChangeCheck(property);
@@ -229,11 +269,18 @@ class InfoSettings extends AbstractSetting {
};
async useToken(tokenSymbol) {
+ const { scheduleStore, web3Service } = this.props;
+
if (tokenSymbol && tokenSymbol !== 'PLACEHOLDER') {
- this.props.scheduleStore.toAddress =
- TOKEN_ADDRESSES[tokenSymbol][this.props.web3Service.network.id];
+ const tokenInfo = TOKEN_ADDRESSES[tokenSymbol][web3Service.network.id];
+ scheduleStore.toAddress = tokenInfo.address;
+
+ if (tokenInfo.type === 'erc721') {
+ scheduleStore.tokenToSend = 1;
+ }
} else {
- this.props.scheduleStore.toAddress = '';
+ scheduleStore.toAddress = '';
+ scheduleStore.tokenToSend = null;
}
await this.revalidateToAddress();
@@ -265,13 +312,24 @@ class InfoSettings extends AbstractSetting {
this._mounted = false;
}
+ isCollectibleTransfer() {
+ const { tokenHelper } = this.props;
+ const { token } = this.state;
+
+ return token && tokenHelper.isCollectible(token.address);
+ }
+
render() {
- const { scheduleStore, web3Service } = this.props;
+ const { scheduleStore, tokenHelper } = this.props;
const { _validations, _validationsErrors } = this;
- this.validators.gasAmount = this.integerValidator(this.state.minGas);
+ const { minGas, token, tokensOfOwner } = this.state;
+ const { collectibleIdToTransfer } = scheduleStore;
+
+ this.validators.gasAmount = this.integerValidator(minGas);
+
+ const predefinedTokensSymbols = tokenHelper.getPredefinedTokenSymbols();
- const predefinedTokens =
- web3Service.network && PREDEFINED_TOKENS_FOR_NETWORK[web3Service.network.id];
+ const isCollectibleTransfer = this.isCollectibleTransfer();
return (
@@ -310,9 +368,9 @@ class InfoSettings extends AbstractSetting {
Name:
{scheduleStore.isTokenTransfer &&
- predefinedTokens &&
+ predefinedTokensSymbols &&
(!scheduleStore.toAddress ||
- predefinedTokens.includes(this.state.token.symbol)) ? (
+ predefinedTokensSymbols.includes(token.symbol)) ? (
this.useToken(event.target.value)}
- value={this.state.token.symbol}
+ value={token.symbol}
>
Predefined Tokens
- {predefinedTokens.map(token => (
+ {predefinedTokensSymbols.map(token => (
{token}
@@ -335,17 +393,19 @@ class InfoSettings extends AbstractSetting {
) : (
- this.state.token.name
+ token.name
)}
-
- Decimals:
- {this.state.token.decimals}
-
+ {!isCollectibleTransfer && (
+
+ Decimals:
+ {token.decimals}
+
+ )}
Balance:
- {this.state.token.balance}
+ {token.balance}
@@ -399,7 +459,7 @@ class InfoSettings extends AbstractSetting {