From 084d42ee7df53c11696b08b5c3ef9e9578d30e11 Mon Sep 17 00:00:00 2001 From: aphex Date: Wed, 9 Apr 2025 23:56:44 +0100 Subject: [PATCH 1/3] add hook to check EMP private key status --- .../auction/hooks/use-has-private-key.ts | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 apps/dapp/src/modules/auction/hooks/use-has-private-key.ts diff --git a/apps/dapp/src/modules/auction/hooks/use-has-private-key.ts b/apps/dapp/src/modules/auction/hooks/use-has-private-key.ts new file mode 100644 index 00000000..776df07e --- /dev/null +++ b/apps/dapp/src/modules/auction/hooks/use-has-private-key.ts @@ -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]; + + return { + data: query.isSuccess && !!privateKey, + ...query, + }; +} From 8bb9ccf41f51a732048506c3cd4664e581968864 Mon Sep 17 00:00:00 2001 From: aphex Date: Thu, 10 Apr 2025 23:41:28 +0100 Subject: [PATCH 2/3] update decrypt hook to call decrypt bids after submitting private key --- .../auction/hooks/use-decrypt-auction.ts | 68 ++++++++++++++++--- 1 file changed, 58 insertions(+), 10 deletions(-) diff --git a/apps/dapp/src/modules/auction/hooks/use-decrypt-auction.ts b/apps/dapp/src/modules/auction/hooks/use-decrypt-auction.ts index 12050150..0a3afd06 100644 --- a/apps/dapp/src/modules/auction/hooks/use-decrypt-auction.ts +++ b/apps/dapp/src/modules/auction/hooks/use-decrypt-auction.ts @@ -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) => { @@ -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: () => @@ -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: () => @@ -58,7 +69,7 @@ export const useDecryptBids = (auction: BatchAuction) => { const hints = hintsQuery.data as Hex[]; //Send bids to the contract for decryption - const { data: decryptCall, ...decryptCallQuery } = useSimulateContract({ + const { data: submitPKCall, ...submitPKCallQuery } = useSimulateContract({ address: emp.address, abi: emp.abi, functionName: "submitPrivateKey", @@ -69,17 +80,45 @@ export const useDecryptBids = (auction: BatchAuction) => { BigInt(hints?.length ?? 0), hints, ], + 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: 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 ( + !isPKSubmitted && + submitPkReceipt.isSuccess && + !hasPKQuery.isRefetching + ) { + hasPKQuery.refetch(); + } + }, [isPKSubmitted, submitPkReceipt.isSuccess]); + useEffect(() => { if (decryptTxnSucceeded.current || !decryptReceipt.isSuccess) { return; @@ -112,15 +151,24 @@ export const useDecryptBids = (auction: BatchAuction) => { 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 : submitPk, handleDecryption, error, - isWaiting: decrypt.isPending || decryptReceipt.isLoading, + isWaiting, }; }; From 1d0532056f4a5b3cd61b025c9e73f291b9b76069 Mon Sep 17 00:00:00 2001 From: aphex Date: Mon, 14 Apr 2025 08:59:38 +0100 Subject: [PATCH 3/3] add optmistic update for bid decryption --- .../auction/hooks/use-decrypt-auction.ts | 57 ++++++++++--------- .../auction/hooks/use-has-private-key.ts | 2 +- .../auction/utils/optimistic/auction/index.ts | 1 + .../auction/update-bids-decrypted.ts | 27 +++++++++ 4 files changed, 60 insertions(+), 27 deletions(-) create mode 100644 apps/dapp/src/modules/auction/utils/optimistic/auction/update-bids-decrypted.ts diff --git a/apps/dapp/src/modules/auction/hooks/use-decrypt-auction.ts b/apps/dapp/src/modules/auction/hooks/use-decrypt-auction.ts index 0a3afd06..2a573325 100644 --- a/apps/dapp/src/modules/auction/hooks/use-decrypt-auction.ts +++ b/apps/dapp/src/modules/auction/hooks/use-decrypt-auction.ts @@ -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, @@ -68,7 +68,7 @@ export const useDecryptBids = (auction: BatchAuction) => { const hints = hintsQuery.data as Hex[]; - //Send bids to the contract for decryption + //Submit private key and some bids to be decrypted const { data: submitPKCall, ...submitPKCallQuery } = useSimulateContract({ address: emp.address, abi: emp.abi, @@ -76,7 +76,7 @@ export const useDecryptBids = (auction: BatchAuction) => { chainId: auction.chainId, args: [ BigInt(auction.lotId), - BigInt(privateKeyQuery.data ?? 0), + BigInt(privateKeyQuery.data ?? 0n), BigInt(hints?.length ?? 0), hints, ], @@ -93,7 +93,7 @@ export const useDecryptBids = (auction: BatchAuction) => { functionName: "decryptAndSortBids", chainId: auction.chainId, args: [BigInt(auction.lotId), BigInt(hints?.length ?? 0), hints], - query: { enabled: privateKeyQuery.isSuccess }, + query: { enabled: isPKSubmitted && privateKeyQuery.isSuccess }, }); const decrypt = useWriteContract(); @@ -107,7 +107,6 @@ export const useDecryptBids = (auction: BatchAuction) => { }; const queryClient = useQueryClient(); - const decryptTxnSucceeded = useRef(false); useEffect(() => { if ( @@ -120,30 +119,36 @@ export const useDecryptBids = (auction: BatchAuction) => { }, [isPKSubmitted, submitPkReceipt.isSuccess]); useEffect(() => { - if (decryptTxnSucceeded.current || !decryptReceipt.isSuccess) { - return; + 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"), + ); } - - decryptTxnSucceeded.current = true; - - if (!hintsQuery.isRefetching) { - hintsQuery.refetch(); - } - - /** 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 = [ @@ -165,7 +170,7 @@ export const useDecryptBids = (auction: BatchAuction) => { return { nextBids: privateKeyQuery, decryptTx: isPKSubmitted ? decrypt : submitPk, - decryptReceipt: isPKSubmitted ? decryptReceipt : submitPk, + decryptReceipt: isPKSubmitted ? decryptReceipt : submitPkReceipt, handleDecryption, error, isWaiting, diff --git a/apps/dapp/src/modules/auction/hooks/use-has-private-key.ts b/apps/dapp/src/modules/auction/hooks/use-has-private-key.ts index 776df07e..0ad55b36 100644 --- a/apps/dapp/src/modules/auction/hooks/use-has-private-key.ts +++ b/apps/dapp/src/modules/auction/hooks/use-has-private-key.ts @@ -24,7 +24,7 @@ export function useHasPrivateKey({ query: { enabled }, }); - const privateKey = data?.[9]; + const privateKey = data?.[9] !== 0n; return { data: query.isSuccess && !!privateKey, diff --git a/apps/dapp/src/modules/auction/utils/optimistic/auction/index.ts b/apps/dapp/src/modules/auction/utils/optimistic/auction/index.ts index 56dd3af7..dd857e9b 100644 --- a/apps/dapp/src/modules/auction/utils/optimistic/auction/index.ts +++ b/apps/dapp/src/modules/auction/utils/optimistic/auction/index.ts @@ -1,3 +1,4 @@ export * from "./insert-bid"; export * from "./update-status"; +export * from "./update-bids-decrypted"; export * from "./create"; diff --git a/apps/dapp/src/modules/auction/utils/optimistic/auction/update-bids-decrypted.ts b/apps/dapp/src/modules/auction/utils/optimistic/auction/update-bids-decrypted.ts new file mode 100644 index 00000000..af4bc383 --- /dev/null +++ b/apps/dapp/src/modules/auction/utils/optimistic/auction/update-bids-decrypted.ts @@ -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 };