Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 86 additions & 33 deletions apps/dapp/src/modules/auction/hooks/use-decrypt-auction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
useQueryClient,
} from "@tanstack/react-query";
import type { Auction, AuctionId, BatchAuction } from "@axis-finance/types";
import { useEffect, useRef } from "react";
import { useEffect } from "react";
import {
useSimulateContract,
useWaitForTransactionReceipt,
Expand All @@ -19,6 +19,9 @@ import {
optimisticUpdate,
} from "modules/auction/utils/optimistic";
import { cloakClient } from "utils/cloak-client";
import { useHasPrivateKey } from "./use-has-private-key";

const DECRYPT_NUM = 100; // TODO determine limit on amount per chain

/** Used to manage decrypting the next set of bids */
export const useDecryptBids = (auction: BatchAuction) => {
Expand All @@ -29,6 +32,15 @@ export const useDecryptBids = (auction: BatchAuction) => {
const queryKey = getAuctionQueryKey(auction.id as AuctionId);

const params = deriveParamsFromAuction(auction);

const { data, ...hasPKQuery } = useHasPrivateKey({
lotId: auction.lotId,
chainId: auction.chainId,
address: emp.address,
});

const isPKSubmitted = hasPKQuery.isSuccess && data;

const privateKeyQuery = useQuery({
queryKey: ["get_private_key", auction.id, auctionHouse.address, params],
queryFn: () =>
Expand All @@ -38,13 +50,12 @@ export const useDecryptBids = (auction: BatchAuction) => {
}),
placeholderData: keepPreviousData,
enabled:
auction.bids.length === 0 ||
auction.bids.length - auction.bidsRefunded.length >
auction.bidsDecrypted.length,
(auction.bids.length === 0 ||
auction.bids.length - auction.bidsRefunded.length >
auction.bidsDecrypted.length) &&
!isPKSubmitted,
});

const DECRYPT_NUM = 100; // TODO determine limit on amount per chain

const hintsQuery = useQuery({
queryKey: ["hints", auction.id, auctionHouse.address, params, DECRYPT_NUM],
queryFn: () =>
Expand All @@ -57,70 +68,112 @@ export const useDecryptBids = (auction: BatchAuction) => {

const hints = hintsQuery.data as Hex[];

//Send bids to the contract for decryption
const { data: decryptCall, ...decryptCallQuery } = useSimulateContract({
//Submit private key and some bids to be decrypted
const { data: submitPKCall, ...submitPKCallQuery } = useSimulateContract({
address: emp.address,
abi: emp.abi,
functionName: "submitPrivateKey",
chainId: auction.chainId,
args: [
BigInt(auction.lotId),
BigInt(privateKeyQuery.data ?? 0),
BigInt(privateKeyQuery.data ?? 0n),
BigInt(hints?.length ?? 0),
hints,
],
query: { enabled: privateKeyQuery.isSuccess },
query: { enabled: !isPKSubmitted && privateKeyQuery.isSuccess },
});

const submitPk = useWriteContract();
const submitPkReceipt = useWaitForTransactionReceipt({ hash: submitPk.data });

//Send bids to the contract for decryption
const { data: decryptCall, ...decryptCallQuery } = useSimulateContract({
address: emp.address,
abi: emp.abi,
functionName: "decryptAndSortBids",
chainId: auction.chainId,
args: [BigInt(auction.lotId), BigInt(hints?.length ?? 0), hints],
query: { enabled: isPKSubmitted && privateKeyQuery.isSuccess },
});

const decrypt = useWriteContract();
const decryptReceipt = useWaitForTransactionReceipt({ hash: decrypt.data });

const handleDecryption = () => decrypt.writeContract(decryptCall!.request);
const handleDecryption = () => {
const onSuccess = () => hintsQuery.refetch();
isPKSubmitted
? decrypt.writeContract(decryptCall!.request, { onSuccess })
: submitPk.writeContract(submitPKCall!.request, { onSuccess });
};

const queryClient = useQueryClient();
const decryptTxnSucceeded = useRef(false);

useEffect(() => {
if (decryptTxnSucceeded.current || !decryptReceipt.isSuccess) {
return;
if (
!isPKSubmitted &&
submitPkReceipt.isSuccess &&
!hasPKQuery.isRefetching
) {
hasPKQuery.refetch();
}
}, [isPKSubmitted, submitPkReceipt.isSuccess]);

decryptTxnSucceeded.current = true;

if (!hintsQuery.isRefetching) {
hintsQuery.refetch();
useEffect(() => {
const totalBidsRemaining =
(auction.formatted?.totalBids ?? 0) -
(auction.formatted?.totalBidsClaimed ?? 0);

if (decryptReceipt.isSuccess || submitPkReceipt.isSuccess) {
/** Update bids to decrypted to show the correct progress*/
if ((auction.formatted?.totalBidsDecrypted ?? 0) < totalBidsRemaining) {
optimisticUpdate(
queryClient,
queryKey,
(cachedAuction: GetBatchAuctionLotQuery) =>
auctionCache.updateDecryptedBids(cachedAuction, DECRYPT_NUM),
);

return;
}
/** Optimistically update the auction status to "decrypted" */
optimisticUpdate(
queryClient,
queryKey,
(cachedAuction: GetBatchAuctionLotQuery) =>
auctionCache.updateStatus(cachedAuction, "decrypted"),
);
}

/** Optimistically update the auction status to "decrypted" */
optimisticUpdate(
queryClient,
queryKey,
(cachedAuction: GetBatchAuctionLotQuery) =>
auctionCache.updateStatus(cachedAuction, "decrypted"),
);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [
submitPkReceipt.isSuccess,
submitPkReceipt.isRefetching,
decryptReceipt.isSuccess,
hintsQuery.isRefetching,
hintsQuery.refetch,
queryClient,
queryKey,
decryptReceipt.isRefetching,
]);

const error = [
privateKeyQuery,
decrypt,
decryptCallQuery,
decryptReceipt,
submitPKCallQuery,
submitPk,
submitPkReceipt,
].find((tx) => tx.isError)?.error;

const isWaiting =
submitPk.isPending ||
submitPkReceipt.isLoading ||
decrypt.isPending ||
decryptReceipt.isLoading;

return {
nextBids: privateKeyQuery,
decryptTx: decrypt,
decryptReceipt,
decryptTx: isPKSubmitted ? decrypt : submitPk,
decryptReceipt: isPKSubmitted ? decryptReceipt : submitPkReceipt,
handleDecryption,
error,
isWaiting: decrypt.isPending || decryptReceipt.isLoading,
isWaiting,
};
};

Expand Down
33 changes: 33 additions & 0 deletions apps/dapp/src/modules/auction/hooks/use-has-private-key.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { abis } from "@axis-finance/abis";
import { Address } from "viem";
import { useReadContract } from "wagmi";

type UseHasPrivateKeyParameters = {
address: Address;
lotId: string;
chainId: number;
enabled?: boolean;
};

export function useHasPrivateKey({
lotId,
address,
chainId,
enabled,
}: UseHasPrivateKeyParameters) {
const { data, ...query } = useReadContract({
address,
chainId,
abi: abis.encryptedMarginalPrice,
functionName: "auctionData",
args: [BigInt(lotId)],
query: { enabled },
});

const privateKey = data?.[9] !== 0n;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add a comment here that states that when a private key is not yet submitted the smart contract stores 0n in this data field?


return {
data: query.isSuccess && !!privateKey,
...query,
};
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from "./insert-bid";
export * from "./update-status";
export * from "./update-bids-decrypted";
export * from "./create";
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import type { GetBatchAuctionLotQuery } from "@axis-finance/subgraph-client";

const updateDecryptedBids = (
cachedAuction: GetBatchAuctionLotQuery,
numOfBids: number,
): GetBatchAuctionLotQuery => {
const bids = Array.from(cachedAuction.batchAuctionLot?.bids ?? []);
let updateCount = 0;

for (let i = 0; i < bids.length && updateCount < numOfBids; i++) {
if (bids[i].status === "decrypted") {
continue;
}
bids[i].status = "decrypted";
updateCount++;
}

return {
...cachedAuction,
batchAuctionLot: {
...cachedAuction.batchAuctionLot!,
bids,
},
} satisfies GetBatchAuctionLotQuery;
};

export { updateDecryptedBids };
Loading