@base-org/account
Version:
Base Account SDK
85 lines • 3.68 kB
JavaScript
import { spendPermissionManagerAbi, spendPermissionManagerAddress, } from '../../../../sign/base-account/utils/constants.js';
import { getClient } from '../../../../store/chain-clients/utils.js';
import { readContract } from 'viem/actions';
import { timestampInSecondsToDate, toSpendPermissionArgs } from '../utils.js';
import { withTelemetry } from '../withTelemetry.js';
/**
* Gets the current status of a spend permission.
*
* This helper method queries the blockchain to retrieve real-time information
* about a spend permission, including how much can still be spent in the current
* period, when the next period starts, and whether the permission is still active.
*
* The function automatically uses the appropriate blockchain client based on the
* permission's chain ID and calls multiple view functions on the SpendPermissionManager
* contract to gather comprehensive status information.
*
* When the spend permission does not have a chainId, the function will throw an error.
*
* @param permission - The spend permission object to check status for.
*
* @returns A promise that resolves to an object containing permission status details.
*
* @example
* ```typescript
* import { getPermissionStatus } from '@base-org/account/spend-permission';
*
* // Check the status of a permission (no client needed)
* const status = await getPermissionStatus(permission);
*
* console.log(`Remaining spend: ${status.remainingSpend} wei`);
* console.log(`Next period starts: ${new Date(parseInt(status.nextPeriodStart) * 1000)}`);
* console.log(`Is active: ${status.isActive}`);
*
* if (status.isActive && status.remainingSpend > BigInt(0)) {
* console.log('Permission can be used for spending');
* }
* ```
*/
const getPermissionStatusFn = async (permission) => {
const { chainId } = permission;
if (!chainId) {
throw new Error('chainId is missing in the spend permission');
}
const client = getClient(chainId);
if (!client) {
throw new Error(`No client available for chain ID ${chainId}. Make sure the SDK is in connected state.`);
}
const spendPermissionArgs = toSpendPermissionArgs(permission);
const [currentPeriod, isRevoked, isValid] = await Promise.all([
readContract(client, {
address: spendPermissionManagerAddress,
abi: spendPermissionManagerAbi,
functionName: 'getCurrentPeriod',
args: [spendPermissionArgs],
}),
readContract(client, {
address: spendPermissionManagerAddress,
abi: spendPermissionManagerAbi,
functionName: 'isRevoked',
args: [spendPermissionArgs],
}),
readContract(client, {
address: spendPermissionManagerAddress,
abi: spendPermissionManagerAbi,
functionName: 'isValid',
args: [spendPermissionArgs],
}),
]);
// Calculate remaining spend in current period
const allowance = BigInt(permission.permission.allowance);
const spent = currentPeriod.spend;
const remainingSpend = allowance > spent ? allowance - spent : BigInt(0);
// Calculate next period start
// Next period starts immediately after current period ends
const nextPeriodStart = (Number(currentPeriod.end) + 1).toString();
// Permission is active if it's not revoked and is still valid
const isActive = !isRevoked && isValid;
return {
remainingSpend,
nextPeriodStart: timestampInSecondsToDate(Number(nextPeriodStart)),
isActive,
};
};
export const getPermissionStatus = withTelemetry(getPermissionStatusFn);
//# sourceMappingURL=getPermissionStatus.js.map