Skip to content

Commit

Permalink
✨ Pack dao action verifier (#46)
Browse files Browse the repository at this point in the history
- ✨ Pack verifier for depositing
- ✨ Pack verifier for withdrawing
- ✨ Pack verifier for claiming
- ✨ Reclaim CKB locked by dao verifier cells
- 📝 Add placeholder for docs about packing verifier
  • Loading branch information
doitian authored Feb 18, 2024
2 parents 3dadef2 + 0cf21c0 commit 5d3932c
Show file tree
Hide file tree
Showing 32 changed files with 709 additions and 124 deletions.
11 changes: 11 additions & 0 deletions bin/use-env.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ esac

JOYID_INFO_FILE="$(ls migrations/joyid/*.json | grep -v deployment | head -n 1)"
OMNILOCK_INFO_FILE="$(ls migrations/omnilock/*.json | grep -v deployment | head -n 1)"
DAO_ACTION_VERIFIER_INFO_FILE="$(ls migrations/dao-action-verifier/*.json | grep -v deployment | head -n 1)"

sed -n \
-e 's/,$//' \
Expand All @@ -45,3 +46,13 @@ sed -n \
-e 's/,$//' \
-e 's/^ *"tx_hash": /NEXT_PUBLIC_OMNILOCK_TX_HASH=/p' \
"$OMNILOCK_INFO_FILE" | tail -1

sed -n \
-e 's/,$//' \
-e 's/^ *"type_id": "/NEXT_PUBLIC_DAO_ACTION_VERIFIER_CODE_HASH="/p' \
"$DAO_ACTION_VERIFIER_INFO_FILE" | head -1

sed -n \
-e 's/,$//' \
-e 's/^ *"tx_hash": /NEXT_PUBLIC_DAO_ACTION_VERIFIER_TX_HASH=/p' \
"$DAO_ACTION_VERIFIER_INFO_FILE" | tail -1
1 change: 1 addition & 0 deletions docs/packing-verifier.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Packing Verifier
6 changes: 5 additions & 1 deletion src/actions/claim.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,16 @@ import { claimDao } from "@/lib/cobuild/publishers";
import { getConfig } from "@/lib/config";
import { prepareLockActions } from "@/lib/cobuild/lock-actions";
import { payFee } from "@/lib/cobuild/fee-manager";
import { prepareVerifier } from "@/lib/papps/dao/verifier";

export default async function withdraw(from, cell, config) {
export default async function withdraw(from, cell, shouldPackVerifier, config) {
config = config ?? getConfig();

try {
let buildingPacket = await claimDao(config)({ cell });
if (shouldPackVerifier) {
buildingPacket = await prepareVerifier(buildingPacket, from, config);
}
buildingPacket = await payFee(
buildingPacket,
[{ address: from, feeRate: 1200 }],
Expand Down
6 changes: 5 additions & 1 deletion src/actions/deposit.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
"use server";

import { parseUnit } from "@ckb-lumos/bi";
import { depositDao } from "@/lib/cobuild/publishers";
import { getConfig } from "@/lib/config";
import { prepareLockActions } from "@/lib/cobuild/lock-actions";
import { payFee } from "@/lib/cobuild/fee-manager";
import { prepareVerifier } from "@/lib/papps/dao/verifier";

export default async function deposit(_prevState, formData, config) {
config = config ?? getConfig();

const from = formData.get("from");
const shouldPackVerifier = formData.get("packVerifier") !== undefined;

try {
let buildingPacket = await depositDao(config)(formData);
if (shouldPackVerifier) {
buildingPacket = await prepareVerifier(buildingPacket, from, config);
}
buildingPacket = await payFee(
buildingPacket,
[{ address: from, feeRate: 1200 }],
Expand Down
29 changes: 29 additions & 0 deletions src/actions/get-verifier-cells.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"use server";

import { cache } from "react";
import { getConfig, buildScript } from "@/lib/config";
import { addressToScript } from "@ckb-lumos/helpers";
import { Indexer } from "@ckb-lumos/ckb-indexer";

function buildVerifierScript(ckbChainConfig) {
return buildScript(ckbChainConfig.SCRIPTS.DAO_ACTION_VERIFIER, "0x");
}

export async function getVerifierCellsWithoutCache(lockAddress, config) {
const { ckbRpcUrl, ckbChainConfig } = config ?? getConfig();
const indexer = new Indexer(ckbRpcUrl);

const lock = addressToScript(lockAddress, { config: ckbChainConfig });
const collector = indexer.collector({
lock,
argsLen: (lock.args.length - 2) / 2,
type: buildVerifierScript(ckbChainConfig),
});
const verifierCells = [];
for await (const cell of collector.collect()) {
verifierCells.push(cell);
}
return verifierCells;
}

export const getVerifierCellsWithCache = cache(getVerifierCellsWithoutCache);
29 changes: 29 additions & 0 deletions src/actions/reclaim.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"use server";

import { reclaimDaoVerifiers } from "@/lib/cobuild/publishers";
import { getConfig } from "@/lib/config";
import { prepareLockActions } from "@/lib/cobuild/lock-actions";
import { payFee } from "@/lib/cobuild/fee-manager";

export default async function reclaim(from, config) {
config = config ?? getConfig();

try {
let buildingPacket = await reclaimDaoVerifiers(config)({ from });
buildingPacket = await payFee(
buildingPacket,
[{ address: from, feeRate: 1200 }],
config,
);
buildingPacket = prepareLockActions(buildingPacket, config.ckbChainConfig);

return {
buildingPacket,
};
} catch (err) {
console.error(err.stack);
return {
error: err.toString(),
};
}
}
6 changes: 5 additions & 1 deletion src/actions/withdraw.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,16 @@ import { withdrawDao } from "@/lib/cobuild/publishers";
import { getConfig } from "@/lib/config";
import { prepareLockActions } from "@/lib/cobuild/lock-actions";
import { payFee } from "@/lib/cobuild/fee-manager";
import { prepareVerifier } from "@/lib/papps/dao/verifier";

export default async function withdraw(from, cell, config) {
export default async function withdraw(from, cell, shouldPackVerifier, config) {
config = config ?? getConfig();

try {
let buildingPacket = await withdrawDao(config)({ cell });
if (shouldPackVerifier) {
buildingPacket = await prepareVerifier(buildingPacket, from, config);
}
buildingPacket = await payFee(
buildingPacket,
[{ address: from, feeRate: 1200 }],
Expand Down
56 changes: 51 additions & 5 deletions src/app/u/[wallet]/[connection]/assets.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import Link from "next/link";
import { BI, formatUnit } from "@ckb-lumos/bi";
import { Button } from "flowbite-react";
import Capacity from "@/components/capacity";
import Link from "next/link";

import { fetchAssetsWithCache } from "@/actions/fetch-assets";
import Capacity from "@/components/capacity";
import PackingVerifierHelpText from "@/components/packing-verifier-help-text";
import DaoCells from "./dao-cells";
import Loading from "./loading";

Expand All @@ -25,7 +28,38 @@ export function CkbSection({ wallet, connection, address, ckbBalance }) {
);
}

export function DaoSection({ wallet, connection, address, daoCells }) {
export function VerifierCells({ wallet, connection, verifierCells }) {
let lockedCapacity = BI.from(0);
for (const cell of verifierCells) {
lockedCapacity = lockedCapacity.add(BI.from(cell.cellOutput.capacity));
}
return (
<>
<h3>Verifier Cells</h3>
<PackingVerifierHelpText />
<p>
You have {formatUnit(lockedCapacity, "ckb")} CKB locked in DAO action
verifier cells. You can reclaim them by destroy the verifier cells.
</p>
<Button
as={Link}
href={`/u/${wallet}/${connection}/reclaim`}
color="light"
className="not-prose inline-block"
>
Reclaim
</Button>
</>
);
}

export function DaoSection({
wallet,
connection,
address,
daoCells,
verifierCells,
}) {
return (
<section>
<h2>DAO</h2>
Expand All @@ -44,6 +78,13 @@ export function DaoSection({ wallet, connection, address, daoCells }) {
address={address}
daoCells={daoCells}
/>
{verifierCells.length > 0 ? (
<VerifierCells
wallet={wallet}
connection={connection}
verifierCells={verifierCells}
/>
) : null}
</section>
);
}
Expand All @@ -64,13 +105,18 @@ export function AssetsFallback() {
}

export default async function Assets({ wallet, connection, address }) {
const { ckbBalance, daoCells } = await fetchAssetsWithCache(address);
const { ckbBalance, daoCells, verifierCells } =
await fetchAssetsWithCache(address);
const childProps = { wallet, connection, address };

return (
<>
<CkbSection ckbBalance={ckbBalance} {...childProps} />
<DaoSection daoCells={daoCells} {...childProps} />
<DaoSection
daoCells={daoCells}
verifierCells={verifierCells}
{...childProps}
/>
</>
);
}
58 changes: 48 additions & 10 deletions src/app/u/[wallet]/[connection]/claim/[txHash]/[index]/form.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
"use client";

import { useState } from "react";
import { Alert, Button, Checkbox, Label } from "flowbite-react";
import { useRouter } from "next/navigation";
import { Alert, Button } from "flowbite-react";
import { useState } from "react";

import claim from "@/actions/claim";
import useTipHeader from "@/hooks/use-tip-header";
import PackingVerifierHelpText from "@/components/packing-verifier-help-text";
import useCell from "@/hooks/use-cell";
import useHeader from "@/hooks/use-header";
import useHeaderByNumber from "@/hooks/use-header-by-number";
import useCell from "@/hooks/use-cell";
import useTipHeader from "@/hooks/use-tip-header";

import Capacity from "@/components/capacity";
import * as dao from "@/lib/dao";
import Loading from "./loading";
import SignForm from "../../../sign-form";
import SubmitBuildingPacket from "../../../submit-building-packet";
import Loading from "./loading";

function CellDetailsDisplay({ cell, depositHeader, withdrawHeader }) {
return (
Expand All @@ -31,7 +32,13 @@ function CellDetailsDisplay({ cell, depositHeader, withdrawHeader }) {
);
}

function CellDetails({ cell, pending, onConfirm }) {
function CellDetails({
cell,
pending,
onConfirm,
shouldPackVerifier,
setShouldPackVerifier,
}) {
const tipHeader = useTipHeader();
const depositBlockNumber = dao.getDepositBlockNumberFromWithdrawCell(cell);
const depositHeader = useHeaderByNumber(depositBlockNumber);
Expand Down Expand Up @@ -62,6 +69,18 @@ function CellDetails({ cell, pending, onConfirm }) {
Claim Now
</Button>
)}
<Checkbox
className="mr-2 inline-block"
id="packVerifier"
name="packVerifier"
checked={shouldPackVerifier}
onChange={(e) => {
setShouldPackVerifier(e.target.checked);
}}
/>
<Label htmlFor="packVerifier">
Pack Verifier (<PackingVerifierHelpText />)
</Label>
</p>
<CellDetailsDisplay
{...{ cell, tipHeader, withdrawHeader, depositHeader }}
Expand All @@ -70,9 +89,21 @@ function CellDetails({ cell, pending, onConfirm }) {
);
}

function LoadCell({ outPoint, pending, onConfirm }) {
function LoadCell({
outPoint,
pending,
onConfirm,
shouldPackVerifier,
setShouldPackVerifier,
}) {
const cell = useCell(outPoint);
const childProps = { cell, pending, onConfirm };
const childProps = {
cell,
pending,
onConfirm,
shouldPackVerifier,
setShouldPackVerifier,
};
return cell ? <CellDetails {...childProps} /> : <Loading />;
}

Expand All @@ -86,12 +117,13 @@ export default function ClaimForm({
const router = useRouter();
const [formState, setFormState] = useState({});
const [pending, setPending] = useState(false);
const [shouldPackVerifier, setShouldPackVerifier] = useState(false);
const [signedBuildingPacket, setSignedBuildingPacket] = useState(null);
const back = () => router.back();
const onConfirm = async (cell) => {
setPending(true);
try {
setFormState(await claim(address, cell));
setFormState(await claim(address, cell, shouldPackVerifier));
} catch (err) {
setFormState({ error: err.toString() });
}
Expand All @@ -102,7 +134,13 @@ export default function ClaimForm({
formState.buildingPacket === null ||
formState.buildingPacket === undefined
) {
const childProps = { outPoint, pending, onConfirm };
const childProps = {
outPoint,
pending,
onConfirm,
shouldPackVerifier,
setShouldPackVerifier,
};
return (
<>
{formState.error ? (
Expand Down
15 changes: 11 additions & 4 deletions src/app/u/[wallet]/[connection]/deposit/form.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
"use client";

import { Alert, Checkbox, Label, Popover, TextInput } from "flowbite-react";
import { useRouter } from "next/navigation";
import { useEffect, useState } from "react";
import { useFormState } from "react-dom";
import { useRouter } from "next/navigation";
import { Label, TextInput, Alert } from "flowbite-react";

import deposit from "@/actions/deposit";
import { fetchAssetsWithCache } from "@/actions/fetch-assets";
import Capacity from "@/components/capacity";
import PackingVerifierHelpText from "@/components/packing-verifier-help-text";
import SubmitButton from "@/components/submit-button";
import { fetchAssetsWithCache } from "@/actions/fetch-assets";
import deposit from "@/actions/deposit";
import Loading from "../loading";
import SignForm from "../sign-form";
import SubmitBuildingPacket from "../submit-building-packet";
Expand Down Expand Up @@ -52,6 +53,12 @@ export function TransactionForm({ formAction, formState, address }) {
}
/>
</div>
<div>
<Checkbox className="mr-2" id="packVerifier" name="packVerifier" />
<Label htmlFor="packVerifier">
Pack Verifier (<PackingVerifierHelpText />)
</Label>
</div>
<SubmitButton>Deposit</SubmitButton>
</form>
);
Expand Down
Loading

0 comments on commit 5d3932c

Please sign in to comment.