submit flow

This commit is contained in:
Kamen Stoykov 2019-05-21 10:16:25 +03:00
parent df750b6dbb
commit b2dd152fae
10 changed files with 482 additions and 141 deletions

View File

@ -1,5 +1,6 @@
const submit = { const submit = {
visible: false, visible_submit: false,
visible_rating: false,
id: '', id: '',
name: '', name: '',
desc: '', desc: '',
@ -11,6 +12,7 @@ const submit = {
imgControlMove: false, imgControlMove: false,
imgControlX: 0, imgControlX: 0,
imgControlY: 0, imgControlY: 0,
sntValue: '0',
} }
export default submit export default submit

View File

@ -2,6 +2,7 @@ import hardcodedDapps from '../../common/data/dapps'
import * as Categories from '../../common/data/categories' import * as Categories from '../../common/data/categories'
import reducerUtil from '../../common/utils/reducer' import reducerUtil from '../../common/utils/reducer'
import { showAlertAction } from '../Alert/Alert.reducer' import { showAlertAction } from '../Alert/Alert.reducer'
import { TYPE_SUBMIT } from '../TransactionStatus/TransactionStatus.utilities'
//import BlockchainTool from '../../common/blockchain' //import BlockchainTool from '../../common/blockchain'
const ON_FINISH_FETCH_ALL_DAPPS_ACTION = const ON_FINISH_FETCH_ALL_DAPPS_ACTION =
@ -100,7 +101,9 @@ export const onFinishFetchByCategoryAction = (category, dapps) => ({
}) })
const fetchAllDappsInState = async (dispatch, getState) => { const fetchAllDappsInState = async (dispatch, getState) => {
const stateDapps = getState().dapps const state = getState()
const { transactionStatus } = state
const stateDapps = state.dapps
if (stateDapps.dapps === null) { if (stateDapps.dapps === null) {
try { try {
let dapps = await BlockchainSDK.DiscoverService.getDApps() let dapps = await BlockchainSDK.DiscoverService.getDApps()
@ -112,6 +115,14 @@ const fetchAllDappsInState = async (dispatch, getState) => {
dapps.sort((a, b) => { dapps.sort((a, b) => {
return b.sntValue - a.sntValue return b.sntValue - a.sntValue
}) })
if (transactionStatus.type === TYPE_SUBMIT) {
for (let i = 0; i < dapps.length; i += 1) {
if (dapps[i].id === transactionStatus.dappId) {
dapps.splice(i, 1)
break
}
}
}
dispatch(onFinishFetchAllDappsAction(dapps)) dispatch(onFinishFetchAllDappsAction(dapps))
return dapps return dapps

View File

@ -15,9 +15,12 @@ import {
onImgDoneAction, onImgDoneAction,
onImgCancelAction, onImgCancelAction,
submitAction, submitAction,
switchToRatingAction,
onInputSntValueAction,
} from './Submit.reducer' } from './Submit.reducer'
const mapStateToProps = state => state.submit const mapStateToProps = state =>
Object.assign(state.submit, { dapps: state.dapps.dapps })
const mapDispatchToProps = dispatch => ({ const mapDispatchToProps = dispatch => ({
onClickClose: () => dispatch(closeSubmitAction()), onClickClose: () => dispatch(closeSubmitAction()),
onInputName: name => dispatch(onInputNameAction(name)), onInputName: name => dispatch(onInputNameAction(name)),
@ -31,6 +34,8 @@ const mapDispatchToProps = dispatch => ({
onImgDone: imgBase64 => dispatch(onImgDoneAction(imgBase64)), onImgDone: imgBase64 => dispatch(onImgDoneAction(imgBase64)),
onSubmit: dapp => dispatch(submitAction(dapp)), onSubmit: dapp => dispatch(submitAction(dapp)),
onClickTerms: () => dispatch(push('/terms')), onClickTerms: () => dispatch(push('/terms')),
switchToRating: () => dispatch(switchToRatingAction()),
onInputSntValue: sntValue => dispatch(onInputSntValueAction(sntValue)),
}) })
export default withRouter( export default withRouter(

View File

@ -1,12 +1,20 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import ReactImageFallback from 'react-image-fallback'
import styles from './Submit.module.scss' import styles from './Submit.module.scss'
import Modal from '../../common/components/Modal' import Modal from '../../common/components/Modal'
import CategorySelector from '../CategorySelector/CategorySelector.picker' import CategorySelector from '../CategorySelector/CategorySelector.picker'
import Slider from '../../common/components/Slider/Slider' import Slider from '../../common/components/Slider/Slider'
import CategoriesUtils from '../Categories/Categories.utils'
import Categories from '../../common/utils/categories'
import icon from '../../common/assets/images/icon.svg'
import sntIcon from '../../common/assets/images/SNT.svg'
import 'rc-slider/assets/index.css' import 'rc-slider/assets/index.css'
import 'rc-tooltip/assets/bootstrap.css' import 'rc-tooltip/assets/bootstrap.css'
const getCategoryName = category =>
Categories.find(x => x.key === category).value
class Submit extends React.Component { class Submit extends React.Component {
constructor(props) { constructor(props) {
super(props) super(props)
@ -24,6 +32,7 @@ class Submit extends React.Component {
this.onEndMove = this.onEndMove.bind(this) this.onEndMove = this.onEndMove.bind(this)
this.onImgDone = this.onImgDone.bind(this) this.onImgDone = this.onImgDone.bind(this)
this.onSubmit = this.onSubmit.bind(this) this.onSubmit = this.onSubmit.bind(this)
this.handleSNTChange = this.handleSNTChange.bind(this)
} }
componentDidUpdate() { componentDidUpdate() {
@ -153,9 +162,29 @@ class Submit extends React.Component {
onSubmit(dapp) onSubmit(dapp)
} }
handleSNTChange(e) {
const { value } = e.target
if (value !== '' && /^[1-9][0-9]*$/.test(value) === false) return
const intValue = value === '' ? 0 : parseInt(value, 10)
if (intValue > 1571296) return
const { dapp, onInputSntValue, fetchVoteRating } = this.props
onInputSntValue(value)
}
title() {
const { visible_submit, visible_rating, imgControl } = this.props
if (visible_submit)
return imgControl ? 'Position and size your image' : 'Submit a Ðapp'
return 'Ðapp rating'
}
render() { render() {
const { const {
visible, dapps,
visible_submit,
visible_rating,
onClickClose, onClickClose,
name, name,
desc, desc,
@ -166,21 +195,47 @@ class Submit extends React.Component {
imgControlZoom, imgControlZoom,
onImgCancel, onImgCancel,
onClickTerms, onClickTerms,
switchToRating,
sntValue,
} = this.props } = this.props
const canSubmit = const canSubmit =
name !== '' && desc !== '' && url !== '' && img !== '' && category !== '' name !== '' && desc !== '' && url !== '' && img !== '' && category !== ''
const visible = visible_submit || visible_rating
/* rating */
let currentSNTamount = 0
let dappsByCategory = []
let catPosition = 0
let afterVoteRating = null
let afterVoteCategoryPosition = null
if (visible_rating) {
dappsByCategory = dapps.filter(dapp_ => dapp_.category === category)
catPosition = dappsByCategory.length + 1
if (sntValue !== '') {
afterVoteRating = parseInt(sntValue, 10)
afterVoteCategoryPosition = 1
for (let i = 0; i < dappsByCategory.length; ++i) {
if (dappsByCategory[i].sntValue < afterVoteRating) break
afterVoteCategoryPosition++
}
}
}
return ( return (
<Modal <Modal
visible={visible && window.location.hash === '#submit'} visible={visible && window.location.hash === '#submit'}
onClickClose={onClickClose} onClickClose={onClickClose}
windowClassName={styles.modalWindow} windowClassName={styles.modalWindow}
contentClassName={imgControl ? styles.modalContentImgControl : ''} contentClassName={
imgControl || visible_rating ? styles.modalContentFullScreen : ''
}
> >
<div className={styles.title}> <div className={styles.title}>{this.title()}</div>
{imgControl ? 'Position and size your image' : 'Submit a Ðapp'} {visible_submit && (
</div>
<div className={imgControl ? styles.cntWithImgControl : ''}> <div className={imgControl ? styles.cntWithImgControl : ''}>
<div className={imgControl ? styles.withImgControl : ''}> <div className={imgControl ? styles.withImgControl : ''}>
<div className={styles.block}> <div className={styles.block}>
@ -235,8 +290,9 @@ class Submit extends React.Component {
/> />
</div> </div>
<div className={styles.imgInfo}> <div className={styles.imgInfo}>
The image should be a square 1:1 ratio JPG or PNG file, minimum The image should be a square 1:1 ratio JPG or PNG file,
size is 160 × 160 pixels. The image will be placed in a circle minimum size is 160 × 160 pixels. The image will be placed in
a circle
</div> </div>
</div> </div>
<div className={styles.block}> <div className={styles.block}>
@ -259,7 +315,7 @@ class Submit extends React.Component {
className={styles.submitButton} className={styles.submitButton}
type="submit" type="submit"
disabled={!canSubmit} disabled={!canSubmit}
onClick={this.onSubmit} onClick={switchToRating}
> >
Continue Continue
</button> </button>
@ -314,13 +370,81 @@ class Submit extends React.Component {
</div> </div>
)} )}
</div> </div>
)}
{visible_rating && (
<>
<div className={styles.dapp}>
<ReactImageFallback
className={styles.image}
src={img}
fallbackImage={icon}
alt="App icon"
width={24}
height={24}
/>
{name}
</div>
<div className={styles.items}>
<div className={styles.itemRow}>
<span className={styles.item}>
<img src={sntIcon} alt="SNT" width="24" height="24" />
{currentSNTamount.toLocaleString()}
</span>
{afterVoteRating !== null &&
afterVoteRating !== currentSNTamount && (
<span className={styles.greenBadge}>
{`${afterVoteRating.toLocaleString()}`}
</span>
)}
</div>
<div className={styles.itemRow}>
<span className={styles.item}>
<img
src={CategoriesUtils(category)}
alt={getCategoryName(category)}
width="24"
height="24"
/>
{`${getCategoryName(category)}${catPosition}`}
</span>
{afterVoteCategoryPosition !== null &&
afterVoteCategoryPosition !== catPosition && (
<span className={styles.greenBadge}>
{`${afterVoteCategoryPosition}`}
</span>
)}
</div>
</div>
<div className={`${styles.inputArea} ${styles.inputAreaBorder}`}>
<input
type="text"
value={sntValue}
onChange={this.handleSNTChange}
style={{ width: `${21 * Math.max(1, sntValue.length)}px` }}
/>
</div>
<div className={styles.footer}>
<p className={styles.disclaimer}>
SNT you spend to rank your DApp is locked in the store. You can
earn back through votes, or withdraw, the majority of this SNT
at any time.
</p>
<button type="submit" onClick={this.onSubmit}>
{!sntValue || sntValue === '0'
? 'Publish'
: 'Stake and Publish'}
</button>
</div>
</>
)}
</Modal> </Modal>
) )
} }
} }
Submit.propTypes = { Submit.propTypes = {
visible: PropTypes.bool.isRequired, visible_submit: PropTypes.bool.isRequired,
visible_rating: PropTypes.bool.isRequired,
name: PropTypes.string.isRequired, name: PropTypes.string.isRequired,
desc: PropTypes.string.isRequired, desc: PropTypes.string.isRequired,
url: PropTypes.string.isRequired, url: PropTypes.string.isRequired,
@ -331,6 +455,7 @@ Submit.propTypes = {
imgControlMove: PropTypes.bool.isRequired, imgControlMove: PropTypes.bool.isRequired,
imgControlX: PropTypes.number.isRequired, imgControlX: PropTypes.number.isRequired,
imgControlY: PropTypes.number.isRequired, imgControlY: PropTypes.number.isRequired,
sntValue: PropTypes.string.isRequired,
onClickClose: PropTypes.func.isRequired, onClickClose: PropTypes.func.isRequired,
onInputName: PropTypes.func.isRequired, onInputName: PropTypes.func.isRequired,
onInputDesc: PropTypes.func.isRequired, onInputDesc: PropTypes.func.isRequired,
@ -342,7 +467,9 @@ Submit.propTypes = {
onImgCancel: PropTypes.func.isRequired, onImgCancel: PropTypes.func.isRequired,
onImgDone: PropTypes.func.isRequired, onImgDone: PropTypes.func.isRequired,
onSubmit: PropTypes.func.isRequired, onSubmit: PropTypes.func.isRequired,
onInputSntValue: PropTypes.func.isRequired,
onClickTerms: PropTypes.func.isRequired, onClickTerms: PropTypes.func.isRequired,
switchToRating: PropTypes.func.isRequired,
} }
export default Submit export default Submit

View File

@ -13,14 +13,14 @@
} }
} }
.modalContentImgControl { .modalContentFullScreen {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
flex: 1 1 auto; flex: 1 1 auto;
} }
@media (min-width: $desktop) { @media (min-width: $desktop) {
.modalContentImgControl { .modalContentFullScreen {
height: 512px; height: 512px;
} }
} }
@ -271,3 +271,142 @@
} }
} }
} }
/* rating */
.dapp {
height: 48px;
display: flex;
align-items: center;
font-family: $font;
font-weight: 500;
padding: 0 calculateRem(12);
}
.dapp .image {
max-width: 24px;
max-height: 24px;
border-radius: 50%;
margin-right: calculateRem(12);
}
.items {
display: flex;
flex-direction: column;
font-family: $font;
}
.items .itemRow {
height: 32px;
display: flex;
align-items: center;
padding: 0 calculateRem(12);
}
.items .item {
display: flex;
align-items: center;
}
.items .item img {
margin-right: calculateRem(12);
}
.badge {
border-radius: 24px;
color: #ffffff;
font-family: $font;
font-size: calculateRem(15);
margin-right: calculateRem(16);
margin-left: auto;
padding: calculateRem(3) calculateRem(10);
}
.greenBadge {
@extend .badge;
background: #44d058;
}
.redBadge {
@extend .badge;
background: #f00;
}
.inputArea {
width: calc(100% - 2 * 16px);
height: 64px;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
margin: auto;
}
.inputArea.inputAreaBorder {
border-bottom: 1px solid #eef2f5;
}
.inputArea input {
width: 19px;
border: none;
text-align: center;
font-size: calculateRem(32);
line-height: calculateRem(28);
font-family: $font;
margin-right: calculateRem(6);
}
.inputArea input:focus {
outline: none;
}
.inputArea::after {
transition: all 0.05s ease-in-out;
content: 'SNT';
color: #939ba1;
font-size: calculateRem(32);
line-height: calculateRem(28);
font-family: $font;
}
.inputArea span {
font-size: calculateRem(32);
line-height: calculateRem(28);
font-family: $font;
margin-right: calculateRem(6);
}
.footer {
text-align: center;
}
.footer button {
background: $link-color;
border-radius: 8px;
color: #fff;
margin: calculateRem(10) auto;
border: none;
font-family: $font;
padding: calculateRem(11) calculateRem(38);
font-size: calculateRem(15);
cursor: pointer;
}
.footer button:disabled,
.footer button[disabled] {
background: $text-color;
}
.footer .disclaimer {
font-size: calculateRem(15);
color: $text-color;
line-height: 22px;
font-family: $font;
padding: calculateRem(16);
border-bottom: 1px solid #eef2f5;
margin: 0;
}
.footer .disclaimer a {
text-decoration: none;
color: $link-color;
}

View File

@ -6,6 +6,7 @@ import {
onStartProgressAction, onStartProgressAction,
hideAction, hideAction,
} from '../TransactionStatus/TransactionStatus.recuder' } from '../TransactionStatus/TransactionStatus.recuder'
import { TYPE_SUBMIT } from '../TransactionStatus/TransactionStatus.utilities'
import { showAlertAction } from '../Alert/Alert.reducer' import { showAlertAction } from '../Alert/Alert.reducer'
// import BlockchainTool from '../../common/blockchain' // import BlockchainTool from '../../common/blockchain'
@ -36,6 +37,9 @@ const ON_IMG_MOVE = 'SUBMIT_ON_IMG_MOVE'
const ON_IMG_CANCEL = 'SUBMIT_ON_IMG_CANCEL' const ON_IMG_CANCEL = 'SUBMIT_ON_IMG_CANCEL'
const ON_IMG_DONE = 'SUBMIT_ON_IMG_DONE' const ON_IMG_DONE = 'SUBMIT_ON_IMG_DONE'
const SWITCH_TO_RATING = 'SUBMIT_SWITCH_TO_RATING'
const ON_INPUT_SNT_VALUE = 'SUBMIT_ON_INPUT_SNT_VALUE'
export const showSubmitActionAfterCheck = () => { export const showSubmitActionAfterCheck = () => {
window.location.hash = 'submit' window.location.hash = 'submit'
return { return {
@ -123,6 +127,7 @@ export const submitAction = dapp => {
dapp.name, dapp.name,
dapp.img, dapp.img,
'Status is an open source mobile DApp browser and messenger build for #Etherium', 'Status is an open source mobile DApp browser and messenger build for #Etherium',
TYPE_SUBMIT,
), ),
) )
try { try {
@ -142,9 +147,20 @@ export const submitAction = dapp => {
} }
} }
export const switchToRatingAction = () => ({
type: SWITCH_TO_RATING,
paylaod: null,
})
export const onInputSntValueAction = sntValue => ({
type: ON_INPUT_SNT_VALUE,
payload: sntValue,
})
const showSubmitAfterCheck = state => { const showSubmitAfterCheck = state => {
return Object.assign({}, state, { return Object.assign({}, state, {
visible: true, visible_submit: true,
visible_rating: false,
id: '', id: '',
name: '', name: '',
desc: '', desc: '',
@ -156,6 +172,7 @@ const showSubmitAfterCheck = state => {
imgControlMove: false, imgControlMove: false,
imgControlX: 0, imgControlX: 0,
imgControlY: 0, imgControlY: 0,
sntValue: '0',
}) })
} }
@ -233,6 +250,19 @@ const onImgDone = (state, imgBase64) => {
}) })
} }
const switchToRating = state => {
return Object.assign({}, state, {
visible_submit: false,
visible_rating: true,
})
}
const onInputSntValue = (state, sntValue) => {
return Object.assign({}, state, {
sntValue,
})
}
const map = { const map = {
[SHOW_SUBMIT_AFTER_CHECK]: showSubmitAfterCheck, [SHOW_SUBMIT_AFTER_CHECK]: showSubmitAfterCheck,
[CLOSE_SUBMIT]: closeSubmit, [CLOSE_SUBMIT]: closeSubmit,
@ -246,6 +276,8 @@ const map = {
[ON_IMG_MOVE]: onImgMove, [ON_IMG_MOVE]: onImgMove,
[ON_IMG_CANCEL]: onImgCancel, [ON_IMG_CANCEL]: onImgCancel,
[ON_IMG_DONE]: onImgDone, [ON_IMG_DONE]: onImgDone,
[SWITCH_TO_RATING]: switchToRating,
[ON_INPUT_SNT_VALUE]: onInputSntValue,
} }
export default reducerUtil(map, submitInitialState) export default reducerUtil(map, submitInitialState)

View File

@ -3,6 +3,7 @@ import reducerUtil from '../../common/utils/reducer'
import { import {
transactionStatusFetchedInstance, transactionStatusFetchedInstance,
transactionStatusInitInstance, transactionStatusInitInstance,
TYPE_NONE,
} from './TransactionStatus.utilities' } from './TransactionStatus.utilities'
import { onUpdateDappDataAction } from '../Dapps/Dapps.reducer' import { onUpdateDappDataAction } from '../Dapps/Dapps.reducer'
import { showAlertAction } from '../Alert/Alert.reducer' import { showAlertAction } from '../Alert/Alert.reducer'
@ -46,9 +47,9 @@ export const hideAction = () => ({
payload: null, payload: null,
}) })
export const onStartProgressAction = (dappName, dappImg, desc) => ({ export const onStartProgressAction = (dappName, dappImg, desc, type) => ({
type: ON_START_PROGRESS, type: ON_START_PROGRESS,
payload: { dappName, dappImg, desc }, payload: { dappName, dappImg, desc, type },
}) })
export const onReceiveTransactionInfoAction = (id, tx) => ({ export const onReceiveTransactionInfoAction = (id, tx) => ({
@ -114,15 +115,17 @@ const hide = state => {
const transacationStatus = transactionStatusFetchedInstance() const transacationStatus = transactionStatusFetchedInstance()
transacationStatus.setDappName('') transacationStatus.setDappName('')
transacationStatus.setProgress(false) transacationStatus.setProgress(false)
transacationStatus.setType(TYPE_NONE)
return Object.assign({}, state, transacationStatus) return Object.assign({}, state, transacationStatus)
} }
const onStartProgress = (state, payload) => { const onStartProgress = (state, payload) => {
const { dappName, dappImg, desc } = payload const { dappName, dappImg, desc, type } = payload
const transacationStatus = transactionStatusInitInstance( const transacationStatus = transactionStatusInitInstance(
dappName, dappName,
dappImg, dappImg,
desc, desc,
type,
) )
transacationStatus.persistTransactionData() transacationStatus.persistTransactionData()
return Object.assign({}, state, transacationStatus) return Object.assign({}, state, transacationStatus)

View File

@ -1,5 +1,10 @@
const COOKIE_NAME = 'TRANSACTION_STATUS_COOKIE' const COOKIE_NAME = 'TRANSACTION_STATUS_COOKIE'
export const TYPE_NONE = 0
export const TYPE_SUBMIT = 1
export const TYPE_UPVOTE = 2
export const TYPE_DOWNVOTE = 3
class TransactionStatus { class TransactionStatus {
constructor() { constructor() {
this.dappId = '' this.dappId = ''
@ -7,6 +12,7 @@ class TransactionStatus {
this.txDesc = '' this.txDesc = ''
this.dappName = '' this.dappName = ''
this.dappImg = '' this.dappImg = ''
this.type = TYPE_NONE
this.progress = false this.progress = false
this.published = false this.published = false
this.failed = false this.failed = false
@ -49,18 +55,24 @@ class TransactionStatus {
this.failed = failed this.failed = failed
this.persistTransactionData() this.persistTransactionData()
} }
setType(type) {
this.type = type
this.persistTransactionData()
}
} }
const getTransactionData = () => { const getTransactionData = () => {
return localStorage.getItem(COOKIE_NAME) return localStorage.getItem(COOKIE_NAME)
} }
export const transactionStatusInitInstance = (name, img, desc) => { export const transactionStatusInitInstance = (name, img, desc, type) => {
const model = new TransactionStatus() const model = new TransactionStatus()
model.dappName = name model.dappName = name
model.dappImg = img model.dappImg = img
model.progress = true model.progress = true
model.txDesc = desc model.txDesc = desc
model.type = type
return model return model
} }

View File

@ -174,7 +174,7 @@ class Vote extends Component {
</div> </div>
</div> </div>
{!isUpvote && ( {!isUpvote && (
<div className={styles.inputArea}> <div className={styles.inputArea} style={{ opacity: 0 }}>
<span>{downvoteSNTcost}</span> <span>{downvoteSNTcost}</span>
</div> </div>
)} )}

View File

@ -6,6 +6,10 @@ import {
onReceiveTransactionInfoAction, onReceiveTransactionInfoAction,
checkTransactionStatusAction, checkTransactionStatusAction,
} from '../TransactionStatus/TransactionStatus.recuder' } from '../TransactionStatus/TransactionStatus.recuder'
import {
TYPE_UPVOTE,
TYPE_DOWNVOTE,
} from '../TransactionStatus/TransactionStatus.utilities'
const SHOW_UP_VOTE_AFTER_CHECK = 'VOTE_SHOW_UP_VOTE_AFTER_CHECK' const SHOW_UP_VOTE_AFTER_CHECK = 'VOTE_SHOW_UP_VOTE_AFTER_CHECK'
const SHOW_DOWN_VOTE_AFTER_CHEECK = 'VOTE_SHOW_DOWN_VOTE_AFTER_CHEECK' const SHOW_DOWN_VOTE_AFTER_CHEECK = 'VOTE_SHOW_DOWN_VOTE_AFTER_CHEECK'
@ -138,7 +142,12 @@ export const upVoteAction = (dapp, amount) => {
return async dispatch => { return async dispatch => {
dispatch(closeVoteAction()) dispatch(closeVoteAction())
dispatch( dispatch(
onStartProgressAction(dapp.name, dapp.image, `↑ Upvote by ${amount} SNT`), onStartProgressAction(
dapp.name,
dapp.image,
`↑ Upvote by ${amount} SNT`,
TYPE_UPVOTE,
),
) )
try { try {
const tx = await BlockchainSDK.DiscoverService.upVote(dapp.id, amount) const tx = await BlockchainSDK.DiscoverService.upVote(dapp.id, amount)
@ -158,6 +167,7 @@ export const downVoteAction = (dapp, amount) => {
dapp.name, dapp.name,
dapp.image, dapp.image,
`↓ Downvote by ${amount} SNT`, `↓ Downvote by ${amount} SNT`,
TYPE_DOWNVOTE,
), ),
) )
try { try {