Appearance
Read the current auction
The contract derives auction IDs from represented Tokyo days. The daily cutoff is midnight in Japan, which is 15:00 UTC.
Read the current auction before preparing a submission or increase. At minimum, determine:
- the current auction ID;
- its start and end timestamps;
- whether it has ended;
- whether it has already been finalized;
- the current leader and leading bid, if any;
- the current protocol minimum; and
- whether the calling address has already submitted for that auction.
A valid new bid must meet the protocol minimum and strictly exceed the current leader. An equal bid does not take the lead. Read the protocol minimum and leading bid from the same current block before calculating the required total.
Example: read the auction and derive the required total
ts
const account = await getActiveAccount();
const quote = await readCurrentAuction(account);ts
import { getAddress, type Address, type Hash } from "viem";
import { tabletsAbi } from "@tablets/abi";
import {
MAX_UINT256,
TABLETS_ADDRESS,
assertPin,
invariant,
pinLatestBlock,
publicClient,
} from "./tablets-client.js";
export type CurrentAuctionQuote = {
readonly block: {
readonly number: bigint;
readonly hash: Hash;
readonly timestamp: bigint;
};
readonly auctionId: bigint;
readonly cutoff: bigint;
readonly minimumBid: bigint;
readonly leaderSubmissionId: bigint;
readonly leaderBid: bigint;
readonly accountSubmissionId: bigint;
readonly accountBid: bigint;
readonly requiredSubmitTotal: bigint;
readonly requiredIncreaseDelta: bigint | null;
readonly canSubmit: boolean;
};
export async function readCurrentAuction(
account: Address,
): Promise<CurrentAuctionQuote> {
const pin = await pinLatestBlock();
const auctionId = await publicClient.readContract({
address: TABLETS_ADDRESS,
abi: tabletsAbi,
functionName: "currentAuctionId",
blockNumber: pin.number,
});
const [auction, cutoff, minimumBid, accountSubmissionId] = await Promise.all([
publicClient.readContract({
address: TABLETS_ADDRESS,
abi: tabletsAbi,
functionName: "getAuction",
args: [auctionId],
blockNumber: pin.number,
}),
publicClient.readContract({
address: TABLETS_ADDRESS,
abi: tabletsAbi,
functionName: "auctionEndTimestamp",
args: [auctionId],
blockNumber: pin.number,
}),
publicClient.readContract({
address: TABLETS_ADDRESS,
abi: tabletsAbi,
functionName: "minimumBid",
blockNumber: pin.number,
}),
publicClient.readContract({
address: TABLETS_ADDRESS,
abi: tabletsAbi,
functionName: "submissionOf",
args: [auctionId, account],
blockNumber: pin.number,
}),
]);
invariant(!auction.finalized, "Current auction is unexpectedly finalized");
invariant(pin.timestamp < cutoff, "The auction cutoff has passed");
invariant(
auction.leaderSubmissionId === 0n || auction.leaderBid < MAX_UINT256,
"The current leader cannot be exceeded within uint256",
);
const requiredSubmitTotal =
auction.leaderSubmissionId === 0n
? minimumBid
: minimumBid > auction.leaderBid + 1n
? minimumBid
: auction.leaderBid + 1n;
let accountBid = 0n;
let requiredIncreaseDelta: bigint | null = null;
if (accountSubmissionId !== 0n) {
const submission = await publicClient.readContract({
address: TABLETS_ADDRESS,
abi: tabletsAbi,
functionName: "getSubmission",
args: [accountSubmissionId],
blockNumber: pin.number,
});
invariant(
submission.auctionId === auctionId &&
getAddress(submission.submitter) === getAddress(account),
"submissionOf and getSubmission disagree",
);
invariant(
submission.bidAmount <= auction.leaderBid,
"Account bid exceeds the leader snapshot",
);
accountBid = submission.bidAmount;
const strictDelta = auction.leaderBid - accountBid + 1n;
requiredIncreaseDelta = minimumBid > strictDelta ? minimumBid : strictDelta;
}
await assertPin(pin);
return {
block: pin,
auctionId,
cutoff,
minimumBid,
leaderSubmissionId: auction.leaderSubmissionId,
leaderBid: auction.leaderBid,
accountSubmissionId,
accountBid,
requiredSubmitTotal,
requiredIncreaseDelta,
canSubmit: accountSubmissionId === 0n,
};
}