@lukasrosario/account
Version:
Base Account SDK
107 lines (93 loc) • 3.17 kB
text/typescript
import { standardErrors } from ':core/error/errors.js';
import { RequestArguments } from ':core/provider/interface.js';
import { OwnerAccount } from ':core/type/index.js';
import { getClient } from ':store/chain-clients/utils.js';
import { store } from ':store/store.js';
import { assertPresence } from ':util/assertPresence.js';
import { decodeAbiParameters, encodeFunctionData, numberToHex, toHex } from 'viem';
import { waitForCallsStatus } from 'viem/experimental';
import { abi } from './constants.js';
import { findOwnerIndex } from './findOwnerIndex.js';
import { presentAddOwnerDialog } from './presentAddOwnerDialog.js';
export async function handleAddSubAccountOwner({
ownerAccount,
globalAccountRequest,
}: {
ownerAccount: OwnerAccount;
globalAccountRequest: (request: RequestArguments) => Promise<unknown>;
}) {
const account = store.account.get();
const subAccount = store.subAccounts.get();
const globalAccount = account.accounts?.find(
(account) => account.toLowerCase() !== subAccount?.address.toLowerCase()
);
assertPresence(globalAccount, standardErrors.provider.unauthorized('no global account'));
assertPresence(account.chain?.id, standardErrors.provider.unauthorized('no chain id'));
assertPresence(subAccount?.address, standardErrors.provider.unauthorized('no sub account'));
const calls = [];
if (ownerAccount.type === 'local' && ownerAccount.address) {
calls.push({
to: subAccount.address,
data: encodeFunctionData({
abi,
functionName: 'addOwnerAddress',
args: [ownerAccount.address] as const,
}),
value: toHex(0),
});
}
if (ownerAccount.publicKey) {
const [x, y] = decodeAbiParameters(
[{ type: 'bytes32' }, { type: 'bytes32' }],
ownerAccount.publicKey
);
calls.push({
to: subAccount.address,
data: encodeFunctionData({
abi,
functionName: 'addOwnerPublicKey',
args: [x, y] as const,
}),
value: toHex(0),
});
}
const request: RequestArguments = {
method: 'wallet_sendCalls',
params: [
{
version: '1',
calls,
chainId: numberToHex(84532),
from: globalAccount,
},
],
};
const selection = await presentAddOwnerDialog();
if (selection === 'cancel') {
throw standardErrors.provider.unauthorized('user cancelled');
}
const callsId = (await globalAccountRequest(request)) as string;
const client = getClient(account.chain.id);
assertPresence(
client,
standardErrors.rpc.internal(`client not found for chainId ${account.chain.id}`)
);
const callsResult = await waitForCallsStatus(client, {
id: callsId,
});
if (callsResult.status !== 'success') {
throw standardErrors.rpc.internal('add owner call failed');
}
const ownerIndex = await findOwnerIndex({
address: subAccount.address,
publicKey:
ownerAccount.type === 'local' && ownerAccount.address
? ownerAccount.address
: ownerAccount.publicKey,
client,
});
if (ownerIndex === -1) {
throw standardErrors.rpc.internal('failed to find owner index');
}
return ownerIndex;
}