@fairmint/canton-node-sdk
Version:
Canton Node SDK
151 lines • 6.33 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getCurrentMiningRoundContext = getCurrentMiningRoundContext;
exports.getCurrentMiningRoundDomainId = getCurrentMiningRoundDomainId;
exports.getCurrentRoundNumber = getCurrentRoundNumber;
exports.waitForRoundChange = waitForRoundChange;
/** Sleep utility function */
async function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
/** Extract round number from a mining round object */
function getRoundNumber(miningRound) {
try {
// Try to get round number from various possible locations
return (miningRound.contract.payload.roundNumber ??
miningRound.contract.payload.round_number ??
(miningRound.contract.payload.round?.number ? parseInt(miningRound.contract.payload.round.number, 10) : 0));
}
catch {
return 0;
}
}
/** Find the latest mining round from a list of open mining rounds */
function findLatestMiningRound(openMiningRounds) {
if (openMiningRounds.length === 0)
return null;
// Sort by round number descending and return the first (latest) one
const sorted = openMiningRounds.sort((a, b) => {
const roundA = getRoundNumber(a);
const roundB = getRoundNumber(b);
return roundB - roundA;
});
return sorted[0] ?? null;
}
/**
* Finds the latest mining round that is currently open (`opensAt` is in the past) and returns useful context
* information.
*
* @throws Error if no mining round satisfies the criteria
*/
async function getCurrentMiningRoundContext(validatorClient) {
const miningRoundsResponse = await validatorClient.getOpenAndIssuingMiningRounds();
// Filter for rounds that have opened already (opensAt <= now)
const now = new Date();
const validOpenRounds = miningRoundsResponse.open_mining_rounds.filter((round) => {
try {
const opensAtRaw = round.contract.payload.opensAt;
if (!opensAtRaw)
return false;
const opensAt = new Date(opensAtRaw);
return opensAt <= now;
}
catch {
return false;
}
});
if (validOpenRounds.length === 0) {
throw new Error('No open mining rounds found with opensAt <= now');
}
// Use the *last* round that has opened (the most recent open one)
const lastOpenRound = validOpenRounds[validOpenRounds.length - 1];
if (!lastOpenRound) {
throw new Error('No valid open mining round found');
}
const openMiningRoundContract = {
contractId: lastOpenRound.contract.contract_id,
templateId: lastOpenRound.contract.template_id,
createdEventBlob: lastOpenRound.contract.created_event_blob,
synchronizerId: lastOpenRound.domain_id, // Using domainId as synchronizerId (legacy behaviour)
};
const issuingMiningRounds = miningRoundsResponse.issuing_mining_rounds.map((round) => ({
round: round.round_number,
contractId: round.contract_id ?? round.contract?.contract_id ?? '',
}));
return {
openMiningRound: openMiningRoundContract.contractId,
openMiningRoundContract,
issuingMiningRounds,
};
}
/**
* Gets the domain ID from the current mining round context. This is useful for operations that need to automatically
* determine the domain ID.
*
* @param validatorClient - Validator API client for getting mining round information
* @returns Promise resolving to the domain ID string
* @throws Error if no mining round satisfies the criteria
*/
async function getCurrentMiningRoundDomainId(validatorClient) {
const miningRoundContext = await getCurrentMiningRoundContext(validatorClient);
return miningRoundContext.openMiningRoundContract.synchronizerId;
}
/**
* Gets the current mining round number by fetching the latest open mining round
*
* @param validatorClient Validator API client to fetch round information
* @returns Promise resolving to the current round number
* @throws Error if no open mining rounds are found
*/
async function getCurrentRoundNumber(validatorClient) {
const miningRoundsResponse = await validatorClient.getOpenAndIssuingMiningRounds();
const currentOpenMiningRounds = miningRoundsResponse.open_mining_rounds;
if (currentOpenMiningRounds.length === 0) {
throw new Error('No open mining rounds found');
}
const latestRound = findLatestMiningRound(currentOpenMiningRounds);
if (!latestRound) {
throw new Error('No valid mining rounds found');
}
return getRoundNumber(latestRound);
}
/**
* Wait until the mining round has actually changed, confirming the change
*
* @param validatorClient Validator API client to fetch round information
* @param maxWaitTime Maximum time to wait in milliseconds (default: 20 minutes)
* @returns Promise that resolves when the round has changed
*/
async function waitForRoundChange(validatorClient, maxWaitTime = 20 * 60 * 1000 // 20 minutes default
) {
const startTime = Date.now();
const checkInterval = 20000; // Check every 20 seconds
const initialRoundNumber = await getCurrentRoundNumber(validatorClient);
while (Date.now() - startTime < maxWaitTime) {
try {
const miningRoundsResponse = await validatorClient.getOpenAndIssuingMiningRounds();
const currentOpenMiningRounds = miningRoundsResponse.open_mining_rounds;
if (currentOpenMiningRounds.length === 0) {
await sleep(checkInterval);
continue;
}
const latestRound = findLatestMiningRound(currentOpenMiningRounds);
if (!latestRound) {
await sleep(checkInterval);
continue;
}
const currentRoundNumber = getRoundNumber(latestRound);
process.stdout.write('.');
if (currentRoundNumber > initialRoundNumber) {
return;
}
// Round hasn't changed yet, wait and check again
await sleep(checkInterval);
}
catch {
await sleep(checkInterval);
}
}
throw new Error(`Timeout waiting for mining round to change from ${initialRoundNumber} after ${maxWaitTime / 1000} seconds`);
}
//# sourceMappingURL=mining-rounds.js.map