@lukasrosario/account
Version:
Base Account SDK
94 lines (83 loc) • 2.36 kB
text/typescript
import { standardErrors } from ':core/error/errors.js';
import { Address, Client, Hex, decodeFunctionData, isAddress, pad } from 'viem';
import { getCode, readContract } from 'viem/actions';
import { abi, factoryAbi } from './constants.js';
type FindOwnerIndexParams = {
/**
* The address of the account to get the owner index for
*/
address: `0x${string}`;
/**
* The client to use to get the code and read the contract
*/
client: Client;
/**
* The public key of the owner
*/
publicKey: Hex;
/**
* The address of the factory
*/
factory?: `0x${string}`;
/**
* The data of the factory
*/
factoryData?: Hex;
};
export async function findOwnerIndex({
address,
client,
publicKey,
factory,
factoryData,
}: FindOwnerIndexParams): Promise<number> {
const code = await getCode(client, {
address,
});
// Check index of owner in the factoryData
// Note: importing an undeployed contract might need to be handled differently
// The implemention will likely require the signer to tell us the index
if (!code && factory && factoryData) {
const initData = decodeFunctionData({
abi: factoryAbi,
data: factoryData,
});
if (initData.functionName !== 'createAccount') {
throw standardErrors.rpc.internal('unknown factory function');
}
const [owners] = initData.args;
return owners.findIndex((owner: Hex | Address) => {
return owner.toLowerCase() === formatPublicKey(publicKey).toLowerCase();
});
}
const ownerCount = await readContract(client, {
address,
abi,
functionName: 'ownerCount',
});
// Iterate from highest index down and return early when found
for (let i = Number(ownerCount) - 1; i >= 0; i--) {
const owner = await readContract(client, {
address,
abi,
functionName: 'ownerAtIndex',
args: [BigInt(i)],
});
const formatted = formatPublicKey(publicKey);
if (owner.toLowerCase() === formatted.toLowerCase()) {
return i;
}
}
return -1;
}
/**
* Formats 20 byte addresses to 32 byte public keys. Contract uses 32 byte keys for owners.
* @param publicKey - The public key to format
* @returns The formatted public key
*/
export function formatPublicKey(publicKey: Hex): Hex {
if (isAddress(publicKey)) {
return pad(publicKey);
}
return publicKey;
}