feat: add UI to blacklist sellers

This commit is contained in:
Jonathan Rainville 2019-07-22 16:40:53 -04:00
parent 63677fa6b4
commit 75c134e482
No known key found for this signature in database
GPG Key ID: 5F4630B759727D9C
8 changed files with 183 additions and 19 deletions

View File

@ -1,4 +1,26 @@
import {ARBITRATION_UNSOLVED, GET_DISPUTED_ESCROWS, RESOLVE_DISPUTE, RESOLVE_DISPUTE_FAILED, BUY_LICENSE,CANCEL_ARBITRATOR_SELECTION_ACTIONS, CHECK_LICENSE_OWNER, LOAD_PRICE, LOAD_ARBITRATION, GET_ARBITRATORS, OPEN_DISPUTE, CANCEL_DISPUTE, REQUEST_ARBITRATOR, CANCEL_ARBITRATOR_REQUEST, CHANGE_ACCEPT_EVERYONE, GET_ARBITRATION_REQUESTS, ACCEPT_ARBITRATOR_REQUEST, REJECT_ARBITRATOR_REQUEST} from './constants';
import {
ARBITRATION_UNSOLVED,
GET_DISPUTED_ESCROWS,
RESOLVE_DISPUTE,
RESOLVE_DISPUTE_FAILED,
BUY_LICENSE,
CANCEL_ARBITRATOR_SELECTION_ACTIONS,
CHECK_LICENSE_OWNER,
LOAD_PRICE,
LOAD_ARBITRATION,
GET_ARBITRATORS,
OPEN_DISPUTE,
CANCEL_DISPUTE,
REQUEST_ARBITRATOR,
CANCEL_ARBITRATOR_REQUEST,
CHANGE_ACCEPT_EVERYONE,
GET_ARBITRATION_REQUESTS,
ACCEPT_ARBITRATOR_REQUEST,
REJECT_ARBITRATOR_REQUEST,
BLACKLIST_SELLER,
UNBLACKLIST_SELLER,
GET_BLACKLISTED_SELLERS
} from './constants';
import Escrow from '../../../embarkArtifacts/contracts/Escrow';
import ArbitrationLicense from '../../../embarkArtifacts/contracts/ArbitrationLicense';
import ArbitrationLicenseProxy from '../../../embarkArtifacts/contracts/ArbitrationLicenseProxy';
@ -48,8 +70,14 @@ export const cancelArbitratorActions = () => ({type: CANCEL_ARBITRATOR_SELECTION
export const changeAcceptEveryone = (acceptAny) => ({type: CHANGE_ACCEPT_EVERYONE, acceptAny, toSend: ArbitrationLicense.methods.changeAcceptAny(acceptAny)});
export const getArbitratorRequests = () => ({type: GET_ARBITRATION_REQUESTS});
export const getArbitratorRequests = () => ({type: GET_ARBITRATION_REQUESTS});
export const acceptRequest = (id) => ({type: ACCEPT_ARBITRATOR_REQUEST, id, toSend: ArbitrationLicense.methods.acceptRequest(id)});
export const rejectRequest = (id) => ({type: REJECT_ARBITRATOR_REQUEST, id, toSend: ArbitrationLicense.methods.rejectRequest(id)});
export const getBlacklistedSellers = () => ({type: GET_BLACKLISTED_SELLERS});
export const blacklistSeller = (sellerAddress) => ({type: BLACKLIST_SELLER, sellerAddress, toSend: ArbitrationLicense.methods.blacklistSeller(sellerAddress)});
export const unBlacklistSeller = (sellerAddress) => ({type: UNBLACKLIST_SELLER, sellerAddress, toSend: ArbitrationLicense.methods.unBlacklistSeller(sellerAddress)});

View File

@ -64,6 +64,20 @@ export const GET_ARBITRATION_REQUESTS = 'GET_ARBITRATION_REQUESTS';
export const GET_ARBITRATION_REQUESTS_SUCCEEDED = 'GET_ARBITRATION_REQUESTS_SUCCEEDED';
export const GET_ARBITRATION_REQUESTS_FAILED = 'GET_ARBITRATION_REQUESTS_FAILED';
export const BLACKLIST_SELLER = 'BLACKLIST_SELLER';
export const BLACKLIST_SELLER_PRE_SUCCESS = 'BLACKLIST_SELLER_PRE_SUCCESS';
export const BLACKLIST_SELLER_SUCCEEDED = 'BLACKLIST_SELLER_SUCCEEDED';
export const BLACKLIST_SELLER_FAILED = 'BLACKLIST_SELLER_FAILED';
export const UNBLACKLIST_SELLER = 'UNBLACKLIST_SELLER';
export const UNBLACKLIST_SELLER_PRE_SUCCESS = 'UNBLACKLIST_SELLER_PRE_SUCCESS';
export const UNBLACKLIST_SELLER_SUCCEEDED = 'UNBLACKLIST_SELLER_SUCCEEDED';
export const UNBLACKLIST_SELLER_FAILED = 'UNBLACKLIST_SELLER_FAILED';
export const GET_BLACKLISTED_SELLERS = 'GET_BLACKLISTED_SELLERS';
export const GET_BLACKLISTED_SELLERS_SUCCEEDED = 'GET_BLACKLISTED_SELLERS_SUCCEEDED';
export const GET_BLACKLISTED_SELLERS_FAILED = 'GET_BLACKLISTED_SELLERS_FAILED';
export const NONE = '0';
export const AWAIT = '1';
export const ACCEPTED = '2';

View File

@ -53,7 +53,9 @@ import {
REJECT_ARBITRATOR_REQUEST,
REJECT_ARBITRATOR_REQUEST_SUCCEEDED,
REJECTED,
ACCEPTED
ACCEPTED,
GET_BLACKLISTED_SELLERS_SUCCEEDED, GET_BLACKLISTED_SELLERS_FAILED,
BLACKLIST_SELLER_SUCCEEDED, UNBLACKLIST_SELLER_SUCCEEDED
} from './constants';
import { fromTokenDecimals } from '../../utils/numbers';
import {RESET_STATE, PURGE_STATE} from "../network/constants";
@ -65,7 +67,8 @@ const DEFAULT_STATE = {
price: Number.MAX_SAFE_INTEGER,
loading: false,
error: '',
arbitratorRequests: []
arbitratorRequests: [],
blacklistedSellers: []
};
function reducer(state = DEFAULT_STATE, action) {
@ -130,6 +133,7 @@ function reducer(state = DEFAULT_STATE, action) {
case GET_ARBITRATION_REQUESTS_FAILED:
case ACCEPT_ARBITRATOR_REQUEST_FAILED:
case REJECT_ARBITRATOR_REQUEST_FAILED:
case GET_BLACKLISTED_SELLERS_FAILED:
return {
...state, ...{
errorGet: action.error,
@ -203,7 +207,7 @@ function reducer(state = DEFAULT_STATE, action) {
errorGet: '',
acceptAny: action.acceptAny
};
case REQUEST_ARBITRATOR_SUCCEEDED:
case REQUEST_ARBITRATOR_SUCCEEDED:
{
const arbitrators = {...state.arbitrators};
arbitrators[action.arbitrator].request.status = AWAIT;
@ -214,7 +218,7 @@ function reducer(state = DEFAULT_STATE, action) {
error: ''
};
}
case CANCEL_ARBITRATOR_REQUEST_SUCCEEDED:
case CANCEL_ARBITRATOR_REQUEST_SUCCEEDED:
{
const arbitrators = {...state.arbitrators};
arbitrators[action.arbitrator].request.status = CLOSED;
@ -240,7 +244,7 @@ function reducer(state = DEFAULT_STATE, action) {
};
case CHECK_LICENSE_OWNER_SUCCEEDED:
return {
...state,
...state,
licenseOwner: action.isLicenseOwner,
acceptAny: action.acceptAny
};
@ -251,12 +255,37 @@ function reducer(state = DEFAULT_STATE, action) {
error: action.error,
loading: false
};
case GET_ARBITRATION_REQUESTS_SUCCEEDED:
case GET_ARBITRATION_REQUESTS_SUCCEEDED:
return {
...state,
arbitratorRequests: action.requests
};
case REJECT_ARBITRATOR_REQUEST_SUCCEEDED:
case GET_BLACKLISTED_SELLERS_SUCCEEDED:
return {
...state,
blacklistedSellers: action.sellers
};
case BLACKLIST_SELLER_SUCCEEDED:
return {
...state,
blacklistedSellers: [
...state.blacklistedSellers,
action.sellerAddress
]
};
case UNBLACKLIST_SELLER_SUCCEEDED: {
const blacklistedSellers = [...state.blacklistedSellers];
const index = blacklistedSellers.indexOf(action.sellerAddress);
if (index === -1) {
return state;
}
blacklistedSellers.splice(index, 1);
return {
...state,
blacklistedSellers: blacklistedSellers
};
}
case REJECT_ARBITRATOR_REQUEST_SUCCEEDED:
{
const arbitratorRequests = [...state.arbitratorRequests];
arbitratorRequests.find(x => x.id === action.id).status = REJECTED;

View File

@ -15,7 +15,17 @@ import {
RESOLVE_DISPUTE_PRE_SUCCESS, LOAD_ARBITRATION, LOAD_ARBITRATION_FAILED, LOAD_ARBITRATION_SUCCEEDED, GET_ARBITRATORS,
GET_ARBITRATORS_SUCCEEDED, GET_ARBITRATORS_FAILED, BUY_LICENSE, BUY_LICENSE_FAILED, BUY_LICENSE_PRE_SUCCESS, BUY_LICENSE_SUCCEEDED,
LOAD_PRICE, LOAD_PRICE_FAILED, LOAD_PRICE_SUCCEEDED, CHECK_LICENSE_OWNER, CHECK_LICENSE_OWNER_FAILED, CHECK_LICENSE_OWNER_SUCCEEDED,
OPEN_DISPUTE, OPEN_DISPUTE_SUCCEEDED, OPEN_DISPUTE_FAILED, OPEN_DISPUTE_PRE_SUCCESS, CANCEL_DISPUTE, CANCEL_DISPUTE_PRE_SUCCESS, CANCEL_DISPUTE_SUCCEEDED, CANCEL_DISPUTE_FAILED, REQUEST_ARBITRATOR, REQUEST_ARBITRATOR_PRE_SUCCESS, REQUEST_ARBITRATOR_SUCCEEDED, REQUEST_ARBITRATOR_FAILED, CANCEL_ARBITRATOR_REQUEST, CANCEL_ARBITRATOR_REQUEST_SUCCEEDED, CANCEL_ARBITRATOR_REQUEST_FAILED, CANCEL_ARBITRATOR_REQUEST_PRE_SUCCESS, CHANGE_ACCEPT_EVERYONE, CHANGE_ACCEPT_EVERYONE_PRE_SUCCESS, CHANGE_ACCEPT_EVERYONE_FAILED, CHANGE_ACCEPT_EVERYONE_SUCCEEDED, GET_ARBITRATION_REQUESTS, GET_ARBITRATION_REQUESTS_FAILED, GET_ARBITRATION_REQUESTS_SUCCEEDED, ACCEPT_ARBITRATOR_REQUEST, ACCEPT_ARBITRATOR_REQUEST_PRE_SUCCESS, ACCEPT_ARBITRATOR_REQUEST_SUCCEEDED, ACCEPT_ARBITRATOR_REQUEST_FAILED, REJECT_ARBITRATOR_REQUEST, REJECT_ARBITRATOR_REQUEST_PRE_SUCCESS, REJECT_ARBITRATOR_REQUEST_SUCCEEDED, REJECT_ARBITRATOR_REQUEST_FAILED
OPEN_DISPUTE, OPEN_DISPUTE_SUCCEEDED, OPEN_DISPUTE_FAILED, OPEN_DISPUTE_PRE_SUCCESS,
CANCEL_DISPUTE, CANCEL_DISPUTE_PRE_SUCCESS, CANCEL_DISPUTE_SUCCEEDED, CANCEL_DISPUTE_FAILED,
REQUEST_ARBITRATOR, REQUEST_ARBITRATOR_PRE_SUCCESS, REQUEST_ARBITRATOR_SUCCEEDED, REQUEST_ARBITRATOR_FAILED,
CANCEL_ARBITRATOR_REQUEST, CANCEL_ARBITRATOR_REQUEST_SUCCEEDED, CANCEL_ARBITRATOR_REQUEST_FAILED, CANCEL_ARBITRATOR_REQUEST_PRE_SUCCESS,
CHANGE_ACCEPT_EVERYONE, CHANGE_ACCEPT_EVERYONE_PRE_SUCCESS, CHANGE_ACCEPT_EVERYONE_FAILED, CHANGE_ACCEPT_EVERYONE_SUCCEEDED,
GET_ARBITRATION_REQUESTS, GET_ARBITRATION_REQUESTS_FAILED, GET_ARBITRATION_REQUESTS_SUCCEEDED,
ACCEPT_ARBITRATOR_REQUEST, ACCEPT_ARBITRATOR_REQUEST_PRE_SUCCESS, ACCEPT_ARBITRATOR_REQUEST_SUCCEEDED, ACCEPT_ARBITRATOR_REQUEST_FAILED,
REJECT_ARBITRATOR_REQUEST, REJECT_ARBITRATOR_REQUEST_PRE_SUCCESS, REJECT_ARBITRATOR_REQUEST_SUCCEEDED, REJECT_ARBITRATOR_REQUEST_FAILED,
BLACKLIST_SELLER, BLACKLIST_SELLER_PRE_SUCCESS, BLACKLIST_SELLER_FAILED, BLACKLIST_SELLER_SUCCEEDED,
UNBLACKLIST_SELLER, UNBLACKLIST_SELLER_FAILED, UNBLACKLIST_SELLER_PRE_SUCCESS, UNBLACKLIST_SELLER_SUCCEEDED,
GET_BLACKLISTED_SELLERS, GET_BLACKLISTED_SELLERS_FAILED, GET_BLACKLISTED_SELLERS_SUCCEEDED
} from './constants';
import ArbitrationLicenseProxy from '../../../embarkArtifacts/contracts/ArbitrationLicenseProxy';
import EscrowProxy from '../../../embarkArtifacts/contracts/EscrowProxy';
@ -148,7 +158,30 @@ export function *doGetArbitratorApprovalRequests() {
console.error(error);
yield put({type: GET_ARBITRATION_REQUESTS_FAILED, error: error.message});
}
}
export function *onGetArbitratorBlacklist() {
yield takeEvery(GET_BLACKLISTED_SELLERS, doGetArbitratorBlacklist);
}
export function *doGetArbitratorBlacklist() {
try {
const events = yield ArbitrationLicense.getPastEvents('BlacklistSeller', {fromBlock: 1, filter: {arbitrator: web3.eth.defaultAccount} });
const sellers = yield all(events.map(function *(event) {
const isBlacklisted = yield ArbitrationLicense.methods.blacklist(event.returnValues.seller).call();
if (!isBlacklisted) {
return null;
}
return event.returnValues.seller;
}));
yield put({type: GET_BLACKLISTED_SELLERS_SUCCEEDED, sellers: sellers.filter(x => x !== null)});
} catch (error) {
console.error(error);
yield put({type: GET_BLACKLISTED_SELLERS_FAILED, error: error.message});
}
}
export function *doBuyLicense() {
@ -239,6 +272,14 @@ export function *onRejectRequest() {
yield takeEvery(REJECT_ARBITRATOR_REQUEST, doTransaction.bind(null, REJECT_ARBITRATOR_REQUEST_PRE_SUCCESS, REJECT_ARBITRATOR_REQUEST_SUCCEEDED, REJECT_ARBITRATOR_REQUEST_FAILED));
}
export function *onBlacklistSeller() {
yield takeEvery(BLACKLIST_SELLER, doTransaction.bind(null, BLACKLIST_SELLER_PRE_SUCCESS, BLACKLIST_SELLER_SUCCEEDED, BLACKLIST_SELLER_FAILED));
}
export function *onUnBlacklistSeller() {
yield takeEvery(UNBLACKLIST_SELLER, doTransaction.bind(null, UNBLACKLIST_SELLER_PRE_SUCCESS, UNBLACKLIST_SELLER_SUCCEEDED, UNBLACKLIST_SELLER_FAILED));
}
export default [
fork(onGetEscrows),
fork(onResolveDispute),
@ -254,5 +295,7 @@ export default [
fork(onChangeAcceptAll),
fork(onGetArbitratorApprovalRequests),
fork(onAcceptRequest),
fork(onBlacklistSeller),
fork(onUnBlacklistSeller),
fork(onRejectRequest)
];

View File

@ -29,3 +29,5 @@ export const isLoading = state => state.arbitration.loading;
export const getLicensePrice = state => parseInt(state.arbitration.price, 10);
export const getArbitratorRequests = state => state.arbitration.arbitratorRequests;
export const getBlacklistedSellers = state => state.arbitration.blacklistedSellers;

View File

@ -78,7 +78,6 @@ export function *onCheckLicenseOwner() {
export function *doGetLicenseOwners() {
try {
// TODO get more information like position and rate
const events = yield SellerLicense.getPastEvents('Bought', {fromBlock: 1});
const licenseOwners = events.map(event => {
return {address: event.returnValues.buyer};

View File

@ -3,6 +3,7 @@ import { connect } from 'react-redux';
import {withRouter, Link} from "react-router-dom";
import network from '../../features/network';
import arbitration from '../../features/arbitration';
import license from '../../features/license';
import metadata from '../../features/metadata';
import Loading from '../../components/Loading';
import ErrorInformation from '../../components/ErrorInformation';
@ -27,13 +28,16 @@ class SellerApproval extends Component {
props.checkLicenseOwner();
props.getArbitratorRequests();
this.loadedUsers = [];
if (props.acceptsEveryone) {
this.props.getLicenseOwners();
this.props.getBlacklistedSellers();
}
}
onToggleCheckbox = (checked) => {
this.props.changeAcceptEveryone(checked);
};
componentDidUpdate(prevProps) {
if ((!prevProps.requests && this.props.requests) || prevProps.requests.length !== this.props.requests) {
this.props.requests.map(x => x.seller).forEach(seller => {
@ -43,6 +47,11 @@ class SellerApproval extends Component {
}
});
}
if (!prevProps.acceptsEveryone && this.props.acceptsEveryone) {
this.props.getLicenseOwners();
this.props.getBlacklistedSellers();
}
}
acceptRequest = id => () => {
@ -53,8 +62,18 @@ class SellerApproval extends Component {
this.props.rejectRequest(id);
};
blacklist(e, sellerAddr) {
e.preventDefault();
this.props.blacklistSeller(sellerAddr);
}
unBlacklist(e, sellerAddr) {
e.preventDefault();
this.props.unBlacklistSeller(sellerAddr);
}
render(){
const {loading, error, txHash, cancelArbitratorsActions, profile, acceptsEveryone, requests, users} = this.props;
const {loading, error, txHash, cancelArbitratorsActions, profile, acceptsEveryone, requests, users, sellers, blacklistedSellers} = this.props;
if(error) {
return <ErrorInformation transaction message={error} cancel={cancelArbitratorsActions}/>;
}
@ -72,7 +91,7 @@ class SellerApproval extends Component {
<div>Off <Switch onChange={this.onToggleCheckbox} checked={acceptsEveryone} className="accept-all-switch"
onColor="#44D058"/> On
</div>
<p className="mt-2">Setting this switch to &quot;On&quot; will make it so that all sellers can choose you as an arbitrator</p>
<p className="mt-2 text-muted">Setting this switch to &quot;On&quot; will make it so that all sellers can choose you as an arbitrator</p>
{!acceptsEveryone && <Fragment>
<h3 className="mb-2 mt-5">Requests for arbitrator</h3>
@ -109,6 +128,25 @@ class SellerApproval extends Component {
</Fragment>
}
{acceptsEveryone &&
<Fragment>
<h3 className="mb-2 mt-5">Blacklist sellers</h3>
<p className="text-muted">Even though you accept every seller, you can blacklist some sellers if you suspect
them to be malicious</p>
<ListGroup>
{sellers.map((seller, i) => {
const isBlacklisted = blacklistedSellers.includes(seller.address);
return (<ListGroupItem key={i}>
<span
className="mr-2">{users[seller.address] && formatArbitratorName(users[seller.address], seller.address, 'No username', i)}{!users[seller.address] && seller.address}</span>
{isBlacklisted &&
<Button color="success" className="float-right" onClick={(e) => this.unBlacklist(e, seller.address)}>Un-Blacklist</Button>}
{!isBlacklisted &&
<Button color="danger" className="float-right" onClick={(e) => this.blacklist(e, seller.address)}>Blacklist</Button>}
</ListGroupItem>);
})}
</ListGroup>
</Fragment>}
</Fragment>
);
}
@ -126,10 +164,16 @@ SellerApproval.propTypes = {
acceptsEveryone: PropTypes.bool,
profile: PropTypes.object,
requests: PropTypes.array,
sellers: PropTypes.array,
blacklistedSellers: PropTypes.array,
getArbitratorRequests: PropTypes.func,
getUser: PropTypes.func,
blacklistSeller: PropTypes.func,
unBlacklistSeller: PropTypes.func,
users: PropTypes.object,
acceptRequest: PropTypes.func,
getLicenseOwners: PropTypes.func,
getBlacklistedSellers: PropTypes.func,
rejectRequest: PropTypes.func
};
@ -141,11 +185,13 @@ const mapStateToProps = state => {
loading: arbitration.selectors.isLoading(state),
error: arbitration.selectors.errorGet(state),
txHash: arbitration.selectors.txHash(state),
profile: metadata.selectors.getProfile(state, address) ,
profile: metadata.selectors.getProfile(state, address),
acceptsEveryone: arbitration.selectors.acceptsEveryone(state),
requests: arbitration.selectors.getArbitratorRequests(state),
users: metadata.selectors.getAllUsers(state)
};
users: metadata.selectors.getAllUsers(state),
sellers: license.selectors.licenseOwners(state),
blacklistedSellers: arbitration.selectors.getBlacklistedSellers(state)
};
};
export default connect(
@ -157,5 +203,9 @@ export default connect(
getArbitratorRequests: arbitration.actions.getArbitratorRequests,
getUser: metadata.actions.loadUserOnly,
acceptRequest: arbitration.actions.acceptRequest,
rejectRequest: arbitration.actions.rejectRequest
rejectRequest: arbitration.actions.rejectRequest,
getLicenseOwners: license.actions.getLicenseOwners,
blacklistSeller: arbitration.actions.blacklistSeller,
unBlacklistSeller: arbitration.actions.unBlacklistSeller,
getBlacklistedSellers: arbitration.actions.getBlacklistedSellers
})(withRouter(SellerApproval));

View File

@ -7,7 +7,6 @@ import {compactAddress} from '../../../../utils/address';
import {Link} from "react-router-dom";
import {formatArbitratorName} from '../../../../utils/strings';
class ArbitratorSelectorForm extends Component {
onChange = (items) => {
if(items.length){