Skip to content

Commit

Permalink
feat(app): add staking gate creation flow
Browse files Browse the repository at this point in the history
  • Loading branch information
tracychen committed Apr 15, 2023
1 parent 4323ba5 commit 9206003
Show file tree
Hide file tree
Showing 3 changed files with 230 additions and 13 deletions.
233 changes: 223 additions & 10 deletions app/src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import WalletConnectButton from "@/components/wallet/WalletConnectButton";
import { useWalletState } from "@/components/wallet/useWalletState";
import { periods } from "@/types/gate";
import { GateType, Operator, Period, operators, periods } from "@/types/gate";
import { Button } from "@/ui/Button";
import { Dropdown } from "@/ui/Dropdown";
import { Heading } from "@/ui/Heading";
Expand Down Expand Up @@ -31,19 +31,15 @@ This request will not trigger a blockchain transaction or cost any gas fees.
Your address: <WALLET_ADDRESS>
`.replace("<WALLET_ADDRESS>", address);
};
export enum GATE_TYPE {
INTERACTION = "EVENTS_EMITTED",
STAKING = "READ_CONTRACT_INFO",
}

const INTERACTIONS_ARRAY = [
{
type: GATE_TYPE.INTERACTION,
type: GateType.EVENTS_EMITTED,
label: `Check for wallet contract interaction`,
icon: ``,
},
{
type: GATE_TYPE.STAKING,
type: GateType.READ_CONTRACT_INFO,
label: `Check for wallet staking activity`,
icon: ``,
},
Expand Down Expand Up @@ -114,7 +110,10 @@ const Home = () => {
const [signatureValue, setSignatureValue] = useState();
const [selectedGate, setSelectedGate] = useState(INTERACTIONS_ARRAY[0]);
const [selectedChain, setSelectedChain] = useState(NETWORK_ARRAY[0]);
const [selectedPeriod, setSelectedPeriod] = useState("day");
const [selectedPeriod, setSelectedPeriod] = useState<Period>("day");
const [selectedOperator, setSelectedOperator] = useState<Operator>(">=");
const [returnKey, setReturnKey] = useState("");
const [threshold, setThreshold] = useState(100);
const [evaluationPeriod, setEvaluationPeriod] = useState(1);
const [requiredCount, setRequiredCount] = useState(1);
const [contractAddress, setContractAddress] = useState("");
Expand Down Expand Up @@ -174,7 +173,7 @@ const Home = () => {
<div className="flex-grow border-t border-gray-400"></div>
</div>

{selectedGate.type === GATE_TYPE.INTERACTION && (
{selectedGate.type === GateType.EVENTS_EMITTED && (
<>
<div>
<Text variant={"regular"} weight={"bold"}>
Expand Down Expand Up @@ -368,7 +367,7 @@ const Home = () => {
: "undefined",
indexed: selectedEvent
? selectedEvent.index
: "undefined",
: undefined,
},
requiredCount: requiredCount,
},
Expand All @@ -386,6 +385,220 @@ const Home = () => {
</div>
</>
)}
{selectedGate.type === GateType.READ_CONTRACT_INFO && (
<>
<div>
<Text variant={"regular"} weight={"bold"}>
Staking activity configuration
</Text>
<div className="mt-[10px]">
<Text variant={"small"} color={"tertiary"}>
Please specify details of the required staking activity.
</Text>
</div>
<div className="pt-[10px] pb-[10px]">
<Text variant={"small"}>Contract chain</Text>
<Dropdown
items={NETWORK_ARRAY.map((i) => {
return {
label: i.label,
icon: i.icon,
onClick: () => {
setSelectedChain(i);
},
};
})}
>
<div className="mt-[5px]">
<PopoverButton
selectedItem={{
label: selectedChain.label,
icon: selectedChain.icon,
}}
height={"64px"}
/>
</div>
</Dropdown>
</div>
</div>
<div className="pt-[10px] pb-[10px]">
<Text variant={"small"}>Contract address</Text>
<Input
className={
"h-16 rounded-lg border border-tertiary/20 px-5 text-small placeholder:text-placeholder focus:border-primary focus:outline-none w-full mt-[5px]"
}
placeholder={"Paste contract address"}
type={"text"}
onChange={(e) => setContractAddress(e.target.value)}
value={contractAddress}
/>
</div>
<div className="pt-[10px] pb-[10px]">
<div className="pt-[10px]">
<Text variant={"small"}>
Upload Application Binary Interface (ABI)
</Text>
</div>
<div className="pt-[10px] pb-[10px]">
<Text variant={"small"} color={"tertiary"}>
To check for custom functions and events
</Text>
</div>
<Input
className={
"h-16 rounded-lg border border-tertiary/20 px-5 text-small placeholder:text-placeholder focus:border-primary focus:outline-none w-full mt-[5px]"
}
placeholder={"Paste contract ABI"}
type={"text"}
onChange={(e) => {
setContractABI(e.target.value);
console.log("ABI: ", e.target.value);
const parsed = parseEvents(e.target.value);
console.log(parsed);
setEventOptions(parsed);
}}
value={contractABI}
/>
</div>
<div className="pt-[10px] pb-[10px]">
<Text variant={"small"}>Select staking function</Text>
<Dropdown
items={eventOptions.map((eventOption) => {
return {
label: `${eventOption.type}: ${eventOption.name} -> ${eventOption.field} (topic index: ${eventOption.index})`,
icon: eventOption.icon,
onClick: () => {
setSelectedEvent(eventOption);
},
};
})}
>
<div className="mt-[5px]">
<PopoverButton
selectedItem={{
label: selectedEvent
? selectedEvent!.name + " " + selectedEvent!.field
: "Select Event Option",
}}
height={"64px"}
/>
</div>
</Dropdown>
</div>
<div className="pt-[10px] pb-[10px]">
<div className="pt-[10px]">
<Text variant={"small"}>
(optional) Response field to check against
</Text>
</div>
<div className="pt-[10px] pb-[10px]">
<Text variant={"small"} color={"tertiary"}>
This is only necessary if the function to check staking
amounts for returns a multiple fields
</Text>
</div>
<Input
className={
"h-16 rounded-lg border border-tertiary/20 px-5 text-small placeholder:text-placeholder focus:border-primary focus:outline-none w-full mt-[5px]"
}
placeholder={"deposit"}
type={"text"}
onChange={(e) => {
setReturnKey(e.target.value);
}}
value={returnKey}
/>
</div>
<div className="flex items-center">
<div className="pr-2">
<Text variant={"small"}>Require staked amount</Text>
</div>
<Dropdown
items={operators.map((operator) => {
return {
label: operator,
onClick: () => {
setSelectedOperator(operator);
},
};
})}
>
<div className="mt-[5px]">
<PopoverButton
selectedItem={{
label: selectedOperator,
}}
height={"40px"}
/>
</div>
</Dropdown>
<div className="pl-2">
<Input
min={0}
type={"number"}
placeholder="100"
defaultValue={threshold}
onChange={(e) => setThreshold(parseInt(e.target.value))}
/>
</div>
</div>
<div className="relative flex py-5 items-center">
<div className="flex-grow border-t border-gray-400"></div>
</div>
<div className="pt-[10px] pb-[10px]">
<Text variant={"regular"} weight={"bold"}>
Name your Gate
</Text>
<div className="mt-[10px]">
<Text variant={"small"} color={"tertiary"}>
Gate name
</Text>
</div>
<Input
className={
"h-16 rounded-lg border border-tertiary/20 px-5 text-small placeholder:text-placeholder focus:border-primary focus:outline-none w-full mt-[5px]"
}
placeholder={"e.g. ApeCoin Staker"}
type={"text"}
onChange={(e) => setGateName(e.target.value)}
value={gateName}
/>
</div>
<div className="flex justify-end mt-[12px] mb-[12px]">
<Button
isLoading={isCreatingGate}
onClick={async () => {
setIsCreatingGate(true);
console.log("hi");
const gateId = await createGate(
{
gate: {
gateName: gateName,
gateType: selectedGate.type,
contractAddress: contractAddress,
chainId: selectedChain.chainId,
gateConfiguration: {
method: selectedEvent!.name,
comparison: {
operator: selectedOperator,
value: threshold,
},
resultKey: returnKey,
},
},
abi: contractABI,
},
setIsCreatingGate
);
setCreatedGateId(gateId);
setShowCreatedGate(true);
}}
>
Confirm
</Button>
</div>
</>
)}
</div>
</>
);
Expand Down
4 changes: 3 additions & 1 deletion app/src/types/gate.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
export type Operator = "==" | "!=" | ">" | ">=" | "<" | "<=";
export const operators = ["==", "!=", ">", ">=", "<", "<="] as const;

export type Operator = (typeof operators)[number];

export const periods = ["hour", "day", "week", "month", "year"] as const;

Expand Down
6 changes: 4 additions & 2 deletions app/src/utils/gate/create.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { Gate } from "@/types/gate";

export interface CreateGateInputs {
gate: any;
abi: any;
gate: Gate;
abi: string;
}

export const createGate = async (
Expand Down

0 comments on commit 9206003

Please sign in to comment.