Skip to content

Commit

Permalink
chore: implement submission funding
Browse files Browse the repository at this point in the history
  • Loading branch information
epiqueras committed Sep 15, 2020
1 parent 9ba7ccf commit 65a5ef2
Show file tree
Hide file tree
Showing 6 changed files with 155 additions and 22 deletions.
2 changes: 1 addition & 1 deletion _pages/profile/[id]/submission-details-card/deadlines.js
Expand Up @@ -39,7 +39,7 @@ export default function Deadlines({ submission, contract, status }) {
return (
<>
<Deadline
label="Submitted"
label="Last Change"
datetime={request[0].lastStatusChange * 1000}
/>
{status === submissionStatusEnum.PendingRegistration ||
Expand Down
97 changes: 97 additions & 0 deletions _pages/profile/[id]/submission-details-card/fund-button.js
@@ -0,0 +1,97 @@
import {
Box,
Button,
Field,
Form,
Popup,
Text,
useContract,
useWeb3,
} from "@kleros/components";
import { useCallback, useMemo } from "react";

export default function FundButton({
totalCost,
totalContribution,
submissionID,
}) {
const [accounts] = useWeb3("eth", "getAccounts");
const amountNeeded = useMemo(() => totalCost.sub(totalContribution), [
totalCost,
totalContribution,
]);
const { web3 } = useWeb3();
const amountNeededString = web3.utils.fromWei(amountNeeded);
const { send } = useContract("proofOfHumanity", "fundSubmission");
return (
<Popup
trigger={
<Button
sx={{
marginBottom: 1,
width: "100%",
}}
disabled={!accounts?.[0]}
>
Fund Submission
</Button>
}
modal
>
<Box sx={{ padding: 2 }}>
<Form
createValidationSchema={useCallback(
({ eth, web3: _web3 }) => ({
contribution: eth()
.test({
test(value) {
if (value.lte(_web3.utils.toBN(0)))
return this.createError({
message: `You need to contribute something.`,
});
return true;
},
})
.test({
test(value) {
if (value.gt(amountNeeded))
return this.createError({
message: `There's no need to contribute this much.`,
});
return true;
},
}),
}),
[amountNeeded]
)}
onSubmit={({ contribution }) =>
send(submissionID, { value: contribution })
}
>
{({ isSubmitting }) => (
<>
<Field
name="contribution"
label={({ field }) => (
<Text>
Contribution
<Text
sx={{ fontWeight: "bold" }}
onClick={() => field[2].setValue(amountNeededString)}
>
(Needed: {amountNeededString})
</Text>
</Text>
)}
type="number"
/>
<Button type="submit" loading={isSubmitting}>
Fund Submission
</Button>
</>
)}
</Form>
</Box>
</Popup>
);
}
55 changes: 40 additions & 15 deletions _pages/profile/[id]/submission-details-card/index.js
Expand Up @@ -13,6 +13,7 @@ import { useMemo } from "react";
import { graphql, useFragment } from "relay-hooks";

import Deadlines from "./deadlines";
import FundButton from "./fund-button";
import VouchButton from "./vouch-button";

import { partyEnum, submissionStatusEnum, useEvidenceFile } from "data";
Expand Down Expand Up @@ -61,8 +62,12 @@ export default function SubmissionDetailsCard({ submission, contract }) {
const request = requests[status.registrationEvidenceFileIndex || 0];

const evidence = useEvidenceFile()(request.evidence[0].URI);
const contributions = request.challenges[0].rounds[0].contributions.map(
(contribution) => partyEnum.parse(contribution)
const contributions = useMemo(
() =>
request.challenges[0].rounds[0].contributions.map((contribution) =>
partyEnum.parse(contribution)
),
[request]
);

const [arbitrationCost] = useContract(
Expand All @@ -85,13 +90,25 @@ export default function SubmissionDetailsCard({ submission, contract }) {
submissionDetailsCardFragments.contract,
contract
));
const totalCost = arbitrationCost
?.add(
const totalCost = useMemo(
() =>
arbitrationCost
.mul(web3.utils.toBN(sharedStakeMultiplier))
.div(web3.utils.toBN(10000))
)
.add(web3.utils.toBN(submissionBaseDeposit));
?.add(
arbitrationCost
.mul(web3.utils.toBN(sharedStakeMultiplier))
.div(web3.utils.toBN(10000))
)
.add(web3.utils.toBN(submissionBaseDeposit)),
[arbitrationCost, web3.utils, sharedStakeMultiplier, submissionBaseDeposit]
);
const totalContribution = useMemo(
() =>
contributions.reduce(
(acc, { values: { Requester } }) => acc.add(web3.utils.toBN(Requester)),
web3.utils.toBN(0)
),
[contributions, web3.utils]
);
return (
<Card
mainSx={{
Expand Down Expand Up @@ -122,7 +139,20 @@ export default function SubmissionDetailsCard({ submission, contract }) {
{evidence?.file?.name}
</Text>
<Text count={2}>{evidence?.file?.bio}</Text>
<VouchButton submissionID={id} />
<Box sx={{ marginY: 2, width: "100%" }}>
{status === submissionStatusEnum.Vouching ? (
<>
{totalCost?.gt(totalContribution) && (
<FundButton
totalCost={totalCost}
totalContribution={totalContribution}
submissionID={id}
/>
)}
<VouchButton submissionID={id} />
</>
) : null}
</Box>
<Flex sx={{ width: "100%" }}>
<Box
sx={{
Expand All @@ -143,12 +173,7 @@ export default function SubmissionDetailsCard({ submission, contract }) {
<Text sx={{ fontWeight: "bold" }}>
{totalCost &&
`${Math.floor(
contributions
.reduce(
(acc, { values: { Requester } }) =>
acc.add(web3.utils.toBN(Requester)),
web3.utils.toBN(0)
)
totalContribution
.mul(web3.utils.toBN(100))
.div(totalCost)
.toNumber()
Expand Down
7 changes: 5 additions & 2 deletions _pages/profile/[id]/submission-details-card/vouch-button.js
Expand Up @@ -23,7 +23,7 @@ export default function VouchButton({ submissionID }) {
"proofOfHumanity",
vouched ? "removeVouch" : "addVouch"
);
const text = status !== "pending" && `${vouched ? "Remove " : ""}Vouch`;
const text = `${vouched ? "Remove " : ""}Vouch`;
return (
<Popup
trigger={
Expand All @@ -32,7 +32,10 @@ export default function VouchButton({ submissionID }) {
marginY: 2,
width: "100%",
}}
disabled={accounts?.[0]?.toLowerCase() === submissionID}
disabled={
status === "pending" ||
accounts?.[0]?.toLowerCase() === submissionID
}
>
{text}
</Button>
Expand Down
13 changes: 10 additions & 3 deletions components/form.js
Expand Up @@ -26,7 +26,9 @@ function ETH(...args) {
? prettyNum(value)
: value
).split(".");
value = `${units}${decimals ? `.${decimals.slice(0, 18)}` : ""}`;
value = `${units[0] === "-" ? 0 : units}${
decimals ? `.${decimals.slice(0, 18)}` : ""
}`;
const bn = Web3.utils.toBN(Web3.utils.toWei(value));
bn.originalString = value;
return bn;
Expand Down Expand Up @@ -63,6 +65,7 @@ File.prototype._typeCheck = (value) => value?.toString() === "[object File]";
const ValidationSchemaContext = createContext();
export default function Form({
createValidationSchema,
onSubmit,
sx,
children,
...rest
Expand Down Expand Up @@ -94,6 +97,9 @@ export default function Form({
<Formik
initialValues={validationSchema.default()}
validationSchema={validationSchema}
onSubmit={(values, formikBag) =>
onSubmit(validationSchema.cast(values), formikBag)
}
{...rest}
>
{(props) => (
Expand All @@ -108,10 +114,11 @@ export default function Form({

export function Field({ label, as = Input, name, ...rest }) {
const validationSchema = useContext(ValidationSchemaContext);
const [{ onChange }] = useField(name);
const field = useField(name);
const [{ onChange }] = field;
return (
<Label>
{label}
{typeof label === "function" ? label({ field }) : label}
<_Field
as={as}
name={name}
Expand Down
3 changes: 2 additions & 1 deletion components/web3-provider.js
Expand Up @@ -151,6 +151,7 @@ export function useContract(
{ address, type, args, options } = {}
) {
const { web3 } = useWeb3();
const contractName = contract;
contract = useMemo(() => {
let _contract = web3.contracts?.[contract];
if (_contract && address && _contract.options.address !== address) {
Expand Down Expand Up @@ -182,7 +183,7 @@ export function useContract(

const [sendState, dispatch] = useStorageReducer(
localStorage,
JSON.stringify({ contract, method, type }),
JSON.stringify({ contract: contractName, method, type }),
sendStateReducer,
{}
);
Expand Down

0 comments on commit 65a5ef2

Please sign in to comment.