@lukasrosario/account
Version:
Base Account SDK
508 lines (448 loc) • 38.2 kB
text/typescript
// pulled from viem, modified for our use case
import { createClient, http } from 'viem';
import { toWebAuthnAccount } from 'viem/account-abstraction';
import { privateKeyToAccount } from 'viem/accounts';
import { baseSepolia } from 'viem/chains';
import { encodeFunctionData, keccak256 } from 'viem/utils';
import { beforeEach, describe, expect, vi } from 'vitest';
import { createSmartAccount, sign, wrapSignature } from './createSmartAccount.js';
const privateKey = '0x8d0ec8aa1f67f8c11db3c191d3d66408e148759acd617fa22ab5d5d677a234e9';
const signer = privateKeyToAccount(privateKey);
const signerWebauthn = toWebAuthnAccount({
credential: { id: 'abc', publicKey: '0xdeadbeef' },
});
const client = createClient({
transport: http(),
chain: baseSepolia,
});
describe('encodeCalls', () => {
it('single', async () => {
const account = await createSmartAccount({
client,
owner: signer,
ownerIndex: 0,
address: '0xBb0c1d5E7f530e8e648150fc7Cf30912575523E8',
factoryData:
'0x3ffba36f0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000170000000000000000000000000000000000000000000000000000000000000001949fc7c88032b9fcb5f6efc7a7b8c63668eae9871b765e23123bb473ff57aa831a7c0d9276168ebcc29f2875a0239cffdf2a9cd1c2007c5c77c071db9264df1d000000000000000000000000000000000000000000000000000000000000002549960de5880e8c687434170f6476605b8fe4aeb9a28632c7995cf3ba831d97630500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008a7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a2273496a396e6164474850596759334b7156384f7a4a666c726275504b474f716d59576f4d57516869467773222c226f726967696e223a2268747470733a2f2f7369676e2e636f696e626173652e636f6d222c2263726f73734f726967696e223a66616c73657d00000000000000000000000000000000000000000000',
});
const callData_1 = await account.encodeCalls([
{ to: '0x0000000000000000000000000000000000000000' },
]);
const callData_2 = await account.encodeCalls([
{ to: '0x0000000000000000000000000000000000000000', value: BigInt(20) },
]);
const callData_3 = await account.encodeCalls([
{
to: '0x0000000000000000000000000000000000000000',
value: BigInt(20),
data: '0xdeadbeef',
},
]);
expect(callData_1).toMatchInlineSnapshot(
`"0xb61d27f60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000"`
);
expect(callData_2).toMatchInlineSnapshot(
`"0xb61d27f60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000"`
);
expect(callData_3).toMatchInlineSnapshot(
`"0xb61d27f60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000004deadbeef00000000000000000000000000000000000000000000000000000000"`
);
});
it('batch', async () => {
const account = await createSmartAccount({
client,
owner: signer,
ownerIndex: 0,
address: '0xBb0c1d5E7f530e8e648150fc7Cf30912575523E8',
factoryData:
'0x3ffba36f0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000170000000000000000000000000000000000000000000000000000000000000001949fc7c88032b9fcb5f6efc7a7b8c63668eae9871b765e23123bb473ff57aa831a7c0d9276168ebcc29f2875a0239cffdf2a9cd1c2007c5c77c071db9264df1d000000000000000000000000000000000000000000000000000000000000002549960de5880e8c687434170f6476605b8fe4aeb9a28632c7995cf3ba831d97630500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008a7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a2273496a396e6164474850596759334b7156384f7a4a666c726275504b474f716d59576f4d57516869467773222c226f726967696e223a2268747470733a2f2f7369676e2e636f696e626173652e636f6d222c2263726f73734f726967696e223a66616c73657d00000000000000000000000000000000000000000000',
});
const callData = await account.encodeCalls([
{ to: '0x0000000000000000000000000000000000000000' },
{ to: '0x0000000000000000000000000000000000000000', value: BigInt(20) },
{
to: '0x0000000000000000000000000000000000000000',
value: BigInt(20),
data: '0xdeadbeef',
},
]);
expect(callData).toMatchInlineSnapshot(
`"0x34fcd5be00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000004deadbeef00000000000000000000000000000000000000000000000000000000"`
);
});
});
describe('decodeCalls', () => {
it('single', async () => {
const account = await createSmartAccount({
client,
owner: signer,
ownerIndex: 0,
address: '0xBb0c1d5E7f530e8e648150fc7Cf30912575523E8',
factoryData:
'0x3ffba36f0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000170000000000000000000000000000000000000000000000000000000000000001949fc7c88032b9fcb5f6efc7a7b8c63668eae9871b765e23123bb473ff57aa831a7c0d9276168ebcc29f2875a0239cffdf2a9cd1c2007c5c77c071db9264df1d000000000000000000000000000000000000000000000000000000000000002549960de5880e8c687434170f6476605b8fe4aeb9a28632c7995cf3ba831d97630500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008a7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a2273496a396e6164474850596759334b7156384f7a4a666c726275504b474f716d59576f4d57516869467773222c226f726967696e223a2268747470733a2f2f7369676e2e636f696e626173652e636f6d222c2263726f73734f726967696e223a66616c73657d00000000000000000000000000000000000000000000',
});
const calls = [
{
to: '0x0000000000000000000000000000000000000000',
value: BigInt(20),
data: '0xdeadbeef',
},
] as const;
const data = await account.encodeCalls(calls);
const decoded = await account.decodeCalls(data);
expect(decoded).toEqual(calls);
});
it('batch', async () => {
const account = await createSmartAccount({
client,
owner: signer,
ownerIndex: 0,
address: '0xBb0c1d5E7f530e8e648150fc7Cf30912575523E8',
factoryData:
'0x3ffba36f0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000170000000000000000000000000000000000000000000000000000000000000001949fc7c88032b9fcb5f6efc7a7b8c63668eae9871b765e23123bb473ff57aa831a7c0d9276168ebcc29f2875a0239cffdf2a9cd1c2007c5c77c071db9264df1d000000000000000000000000000000000000000000000000000000000000002549960de5880e8c687434170f6476605b8fe4aeb9a28632c7995cf3ba831d97630500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008a7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a2273496a396e6164474850596759334b7156384f7a4a666c726275504b474f716d59576f4d57516869467773222c226f726967696e223a2268747470733a2f2f7369676e2e636f696e626173652e636f6d222c2263726f73734f726967696e223a66616c73657d00000000000000000000000000000000000000000000',
});
const calls = [
{
data: '0x',
to: '0x0000000000000000000000000000000000000000',
value: BigInt(0),
},
{
data: '0x',
to: '0x0000000000000000000000000000000000000000',
value: BigInt(20),
},
{
to: '0x0000000000000000000000000000000000000000',
value: BigInt(20),
data: '0xdeadbeef',
},
] as const;
const data = await account.encodeCalls(calls);
const decoded = await account.decodeCalls(data);
expect(decoded).toEqual(calls);
});
it('invalid data', async () => {
const account = await createSmartAccount({
client,
owner: signer,
ownerIndex: 0,
address: '0xBb0c1d5E7f530e8e648150fc7Cf30912575523E8',
factoryData:
'0x3ffba36f0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000170000000000000000000000000000000000000000000000000000000000000001949fc7c88032b9fcb5f6efc7a7b8c63668eae9871b765e23123bb473ff57aa831a7c0d9276168ebcc29f2875a0239cffdf2a9cd1c2007c5c77c071db9264df1d000000000000000000000000000000000000000000000000000000000000002549960de5880e8c687434170f6476605b8fe4aeb9a28632c7995cf3ba831d97630500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008a7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a2273496a396e6164474850596759334b7156384f7a4a666c726275504b474f716d59576f4d57516869467773222c226f726967696e223a2268747470733a2f2f7369676e2e636f696e626173652e636f6d222c2263726f73734f726967696e223a66616c73657d00000000000000000000000000000000000000000000',
});
const data = encodeFunctionData({
abi: account.abi,
functionName: 'entryPoint',
});
await expect(() => account.decodeCalls?.(data)).rejects.toThrowErrorMatchingInlineSnapshot(`
[BaseError: unable to decode calls for "entryPoint"
Version: viem@2.31.7]
`);
});
});
describe('getAddress', () => {
it('default', async () => {
const account = await createSmartAccount({
client,
owner: signer,
ownerIndex: 0,
address: '0xBb0c1d5E7f530e8e648150fc7Cf30912575523E8',
factoryData:
'0x3ffba36f00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000f39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
});
const address = await account.getAddress();
expect(address).toMatchInlineSnapshot(`"0xBb0c1d5E7f530e8e648150fc7Cf30912575523E8"`);
});
});
describe('getStubSignature', () => {
it('default: private key', async () => {
const account = await createSmartAccount({
client,
owner: signer,
ownerIndex: 0,
address: '0xBb0c1d5E7f530e8e648150fc7Cf30912575523E8',
factoryData:
'0x3ffba36f00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000f39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
});
const signature = await account.getStubSignature();
expect(signature).toMatchInlineSnapshot(
`"0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000041fffffffffffffffffffffffffffffff0000000000000000000000000000000007aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1c00000000000000000000000000000000000000000000000000000000000000"`
);
});
it('default: webauthn', async () => {
const account = await createSmartAccount({
client,
owner: signerWebauthn,
ownerIndex: 0,
address: '0xBb0c1d5E7f530e8e648150fc7Cf30912575523E8',
factoryData: '0x',
});
const signature = await account.getStubSignature();
expect(signature).toMatchInlineSnapshot(
`"0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000170000000000000000000000000000000000000000000000000000000000000001949fc7c88032b9fcb5f6efc7a7b8c63668eae9871b765e23123bb473ff57aa831a7c0d9276168ebcc29f2875a0239cffdf2a9cd1c2007c5c77c071db9264df1d000000000000000000000000000000000000000000000000000000000000002549960de5880e8c687434170f6476605b8fe4aeb9a28632c7995cf3ba831d97630500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008a7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a2273496a396e6164474850596759334b7156384f7a4a666c726275504b474f716d59576f4d57516869467773222c226f726967696e223a2268747470733a2f2f7369676e2e636f696e626173652e636f6d222c2263726f73734f726967696e223a66616c73657d00000000000000000000000000000000000000000000"`
);
});
it('custom: ownerIndex', async () => {
{
const account = await createSmartAccount({
client,
owner: signer,
ownerIndex: 0,
address: '0xBb0c1d5E7f530e8e648150fc7Cf30912575523E8',
factoryData: '0x',
});
const signature = await account.getStubSignature();
expect(signature).toMatchInlineSnapshot(
`"0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000041fffffffffffffffffffffffffffffff0000000000000000000000000000000007aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1c00000000000000000000000000000000000000000000000000000000000000"`
);
}
});
});
describe('getNonce', () => {
beforeEach(() => {
vi.useFakeTimers();
vi.setSystemTime(new Date(Date.UTC(2023, 1, 1)));
return () => {
vi.useRealTimers();
};
});
it('default', async () => {
const account = await createSmartAccount({
client,
owner: signer,
ownerIndex: 0,
address: '0xBb0c1d5E7f530e8e648150fc7Cf30912575523E8',
factoryData: '0x',
});
const nonce = await account.getNonce();
expect(nonce).toMatchInlineSnapshot('30902162761021348478818713600000n');
});
it('args: key', async () => {
const account = await createSmartAccount({
client,
owner: signer,
ownerIndex: 0,
address: '0xBb0c1d5E7f530e8e648150fc7Cf30912575523E8',
factoryData: '0x',
});
const nonce = await account.getNonce({ key: BigInt(0) });
expect(nonce).toMatchInlineSnapshot('0n');
});
});
describe('userOperation.estimateGas', () => {
it('default: private key', async () => {
const account = await createSmartAccount({
client,
owner: signer,
ownerIndex: 0,
address: '0xBb0c1d5E7f530e8e648150fc7Cf30912575523E8',
factoryData:
'0x3ffba36f0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000170000000000000000000000000000000000000000000000000000000000000001949fc7c88032b9fcb5f6efc7a7b8c63668eae9871b765e23123bb473ff57aa831a7c0d9276168ebcc29f2875a0239cffdf2a9cd1c2007c5c77c071db9264df1d000000000000000000000000000000000000000000000000000000000000002549960de5880e8c687434170f6476605b8fe4aeb9a28632c7995cf3ba831d97630500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008a7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a2273496a396e6164474850596759334b7156384f7a4a666c726275504b474f716d59576f4d57516869467773222c226f726967696e223a2268747470733a2f2f7369676e2e636f696e626173652e636f6d222c2263726f73734f726967696e223a66616c73657d00000000000000000000000000000000000000000000',
});
const request = await account.userOperation?.estimateGas?.({
callData: '0xdeadbeef',
});
expect(request).toMatchInlineSnapshot('undefined');
});
it('default: webauthn', async () => {
const owner = toWebAuthnAccount({
credential: { id: 'abc', publicKey: '0xdeadbeef' },
});
const account = await createSmartAccount({
client,
owner,
ownerIndex: 0,
address: '0x',
factoryData: '0x',
});
const request = await account.userOperation?.estimateGas?.({
callData: '0xdeadbeef',
});
expect(request).toMatchInlineSnapshot(
`
{
"verificationGasLimit": 800000n,
}
`
);
});
});
describe('sign', () => {
it('default', async () => {
const account = await createSmartAccount({
client,
owner: signer,
ownerIndex: 0,
address: '0xBb0c1d5E7f530e8e648150fc7Cf30912575523E8',
factoryData:
'0x3ffba36f0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000170000000000000000000000000000000000000000000000000000000000000001949fc7c88032b9fcb5f6efc7a7b8c63668eae9871b765e23123bb473ff57aa831a7c0d9276168ebcc29f2875a0239cffdf2a9cd1c2007c5c77c071db9264df1d000000000000000000000000000000000000000000000000000000000000002549960de5880e8c687434170f6476605b8fe4aeb9a28632c7995cf3ba831d97630500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008a7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a2273496a396e6164474850596759334b7156384f7a4a666c726275504b474f716d59576f4d57516869467773222c226f726967696e223a2268747470733a2f2f7369676e2e636f696e626173652e636f6d222c2263726f73734f726967696e223a66616c73657d00000000000000000000000000000000000000000000',
});
const signature = await account.sign({
hash: '0xd9eba16ed0ecae432b71fe008c98cc872bb4cc214d3220a36f365326cf807d68',
});
expect(signature).toBeTruthy();
});
it('counterfactual', async () => {
const account = await createSmartAccount({
client,
owner: signer,
ownerIndex: 0,
address: '0xBb0c1d5E7f530e8e648150fc7Cf30912575523E8',
factoryData:
'0x3ffba36f0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000170000000000000000000000000000000000000000000000000000000000000001949fc7c88032b9fcb5f6efc7a7b8c63668eae9871b765e23123bb473ff57aa831a7c0d9276168ebcc29f2875a0239cffdf2a9cd1c2007c5c77c071db9264df1d000000000000000000000000000000000000000000000000000000000000002549960de5880e8c687434170f6476605b8fe4aeb9a28632c7995cf3ba831d97630500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008a7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a2273496a396e6164474850596759334b7156384f7a4a666c726275504b474f716d59576f4d57516869467773222c226f726967696e223a2268747470733a2f2f7369676e2e636f696e626173652e636f6d222c2263726f73734f726967696e223a66616c73657d00000000000000000000000000000000000000000000',
});
const signature = await account.sign({
hash: '0xd9eba16ed0ecae432b71fe008c98cc872bb4cc214d3220a36f365326cf807d68',
});
expect(signature).toBeTruthy();
});
});
describe('signMessage', () => {
it('default', async () => {
const account = await createSmartAccount({
client,
owner: signer,
ownerIndex: 0,
address: '0xBb0c1d5E7f530e8e648150fc7Cf30912575523E8',
factoryData:
'0x3ffba36f0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000170000000000000000000000000000000000000000000000000000000000000001949fc7c88032b9fcb5f6efc7a7b8c63668eae9871b765e23123bb473ff57aa831a7c0d9276168ebcc29f2875a0239cffdf2a9cd1c2007c5c77c071db9264df1d000000000000000000000000000000000000000000000000000000000000002549960de5880e8c687434170f6476605b8fe4aeb9a28632c7995cf3ba831d97630500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008a7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a2273496a396e6164474850596759334b7156384f7a4a666c726275504b474f716d59576f4d57516869467773222c226f726967696e223a2268747470733a2f2f7369676e2e636f696e626173652e636f6d222c2263726f73734f726967696e223a66616c73657d00000000000000000000000000000000000000000000',
});
const signature = await account.signMessage({
message: 'hello world',
});
expect(signature).toBe(
'0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000411b4612155185a1a24b5588cd001c9e3f8a3dd7afa51db1ef99aed5c2efccc88e466875762b95b6b512f07e5e4b04b92b3da6138fc7a0a76f0697201ffa69ac6f1c00000000000000000000000000000000000000000000000000000000000000'
);
});
it('counterfactual', async () => {
const account = await createSmartAccount({
client,
owner: signer,
ownerIndex: 0,
address: '0xBb0c1d5E7f530e8e648150fc7Cf30912575523E8',
factoryData:
'0x3ffba36f0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000170000000000000000000000000000000000000000000000000000000000000001949fc7c88032b9fcb5f6efc7a7b8c63668eae9871b765e23123bb473ff57aa831a7c0d9276168ebcc29f2875a0239cffdf2a9cd1c2007c5c77c071db9264df1d000000000000000000000000000000000000000000000000000000000000002549960de5880e8c687434170f6476605b8fe4aeb9a28632c7995cf3ba831d97630500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008a7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a2273496a396e6164474850596759334b7156384f7a4a666c726275504b474f716d59576f4d57516869467773222c226f726967696e223a2268747470733a2f2f7369676e2e636f696e626173652e636f6d222c2263726f73734f726967696e223a66616c73657d00000000000000000000000000000000000000000000',
});
const signature = await account.signMessage({
message: 'hello world',
});
expect(signature).toBe(
'0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000411b4612155185a1a24b5588cd001c9e3f8a3dd7afa51db1ef99aed5c2efccc88e466875762b95b6b512f07e5e4b04b92b3da6138fc7a0a76f0697201ffa69ac6f1c00000000000000000000000000000000000000000000000000000000000000'
);
});
});
describe('signUserOperation', () => {
it('default', async () => {
const account = await createSmartAccount({
client,
owner: signer,
ownerIndex: 0,
address: '0xBb0c1d5E7f530e8e648150fc7Cf30912575523E8',
factoryData:
'0x3ffba36f0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000170000000000000000000000000000000000000000000000000000000000000001949fc7c88032b9fcb5f6efc7a7b8c63668eae9871b765e23123bb473ff57aa831a7c0d9276168ebcc29f2875a0239cffdf2a9cd1c2007c5c77c071db9264df1d000000000000000000000000000000000000000000000000000000000000002549960de5880e8c687434170f6476605b8fe4aeb9a28632c7995cf3ba831d97630500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008a7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a2273496a396e6164474850596759334b7156384f7a4a666c726275504b474f716d59576f4d57516869467773222c226f726967696e223a2268747470733a2f2f7369676e2e636f696e626173652e636f6d222c2263726f73734f726967696e223a66616c73657d00000000000000000000000000000000000000000000',
});
const signature = await account.signUserOperation({
callData: '0xdeadbeef',
callGasLimit: BigInt(20),
maxFeePerGas: BigInt(20),
maxPriorityFeePerGas: BigInt(20),
nonce: BigInt(0),
preVerificationGas: BigInt(20),
signature: '0xdeadbeef',
verificationGasLimit: BigInt(20),
});
expect(signature).toMatchInlineSnapshot(
`"0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004165db92565810160e8f5bb6c3ab18e1a3581247c11354972452a6956c5ac7318a051bda6a9048927f5a222e2497389c3de1702b40c98693edccfff3214386a7651c00000000000000000000000000000000000000000000000000000000000000"`
);
});
});
describe('function: sign', () => {
it('private key', async () => {
const signature = await sign({
owner: signer,
hash: keccak256('0xdeadbeef'),
});
expect(signature).toMatchInlineSnapshot(
`"0x23edfbb795637a326d2d80623ee145414953be90e2fb1c095a7d2ad68718b68b3ec55573f4341564efcf9415d2f02f3e0742ce883af7fdeda994f036c11406911c"`
);
});
it('webauthn', async () => {
const credential = {
id: 'm1-bMPuAqpWhCxHZQZTT6e-lSPntQbh3opIoGe7g4Qs',
publicKey:
'0x7da44d4bc972affd138c619a211ef0afe0926b813fec67d15587cf8625b2bf185f5044ae96640a63b32aa1eb6f8f993006bbd26292b81cb07a0672302c69a866',
} as const;
const owner = toWebAuthnAccount({
credential,
getFn() {
return Promise.resolve({
response: {
authenticatorData: [
73, 150, 13, 229, 136, 14, 140, 104, 116, 52, 23, 15, 100, 118, 96, 91, 143, 228, 174,
185, 162, 134, 50, 199, 153, 92, 243, 186, 131, 29, 151, 99, 5, 0, 0, 0, 0,
],
clientDataJSON: [
123, 34, 116, 121, 112, 101, 34, 58, 34, 119, 101, 98, 97, 117, 116, 104, 110, 46,
103, 101, 116, 34, 44, 34, 99, 104, 97, 108, 108, 101, 110, 103, 101, 34, 58, 34, 49,
80, 49, 79, 71, 74, 69, 121, 74, 122, 65, 50, 82, 74, 95, 74, 52, 82, 71, 89, 120,
122, 107, 87, 71, 48, 119, 66, 70, 113, 109, 105, 51, 77, 51, 54, 72, 69, 107, 103,
66, 118, 69, 34, 44, 34, 111, 114, 105, 103, 105, 110, 34, 58, 34, 104, 116, 116, 112,
58, 47, 47, 108, 111, 99, 97, 108, 104, 111, 115, 116, 58, 53, 49, 55, 51, 34, 44, 34,
99, 114, 111, 115, 115, 79, 114, 105, 103, 105, 110, 34, 58, 102, 97, 108, 115, 101,
125,
],
signature: [
48, 69, 2, 33, 0, 198, 106, 113, 129, 35, 170, 51, 12, 13, 0, 67, 158, 211, 55, 188,
103, 33, 194, 2, 152, 190, 159, 181, 11, 176, 232, 114, 59, 99, 64, 167, 220, 2, 32,
101, 188, 55, 216, 145, 203, 39, 137, 83, 114, 45, 10, 147, 246, 218, 247, 132, 221,
228, 225, 57, 110, 143, 87, 172, 198, 76, 141, 30, 169, 166, 2,
],
},
} as any);
},
rpId: '',
});
const signature = await sign({
owner,
hash: keccak256('0xdeadbeef'),
});
expect(signature).toMatchInlineSnapshot(
`"0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000170000000000000000000000000000000000000000000000000000000000000001c66a718123aa330c0d00439ed337bc6721c20298be9fb50bb0e8723b6340a7dc65bc37d891cb278953722d0a93f6daf784dde4e1396e8f57acc64c8d1ea9a602000000000000000000000000000000000000000000000000000000000000002549960de5880e8c687434170f6476605b8fe4aeb9a28632c7995cf3ba831d9763050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000867b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a223150314f474a45794a7a4132524a5f4a34524759787a6b574730774246716d69334d333648456b67427645222c226f726967696e223a22687474703a2f2f6c6f63616c686f73743a35313733222c2263726f73734f726967696e223a66616c73657d0000000000000000000000000000000000000000000000000000"`
);
});
it('error: incompat account', async () => {
await expect(() =>
sign({
// @ts-expect-error type not supported
owner: { address: '0x', type: 'json-rpc' },
hash: keccak256('0xdeadbeef'),
})
).rejects.toMatchInlineSnapshot(`
[BaseError: \`owner\` does not support raw sign.
Version: viem@2.31.7]
`);
});
});
describe('wrapSignature', () => {
it('default: private key', async () => {
expect(
wrapSignature({
signature:
'0xfffffffffffffffffffffffffffffff0000000000000000000000000000000007aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1c',
})
).toMatchInlineSnapshot(
`"0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000041fffffffffffffffffffffffffffffff0000000000000000000000000000000007aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1c00000000000000000000000000000000000000000000000000000000000000"`
);
});
it('default: webauthn', async () => {
expect(
wrapSignature({
signature:
'0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000170000000000000000000000000000000000000000000000000000000000000001949fc7c88032b9fcb5f6efc7a7b8c63668eae9871b765e23123bb473ff57aa831a7c0d9276168ebcc29f2875a0239cffdf2a9cd1c2007c5c77c071db9264df1d000000000000000000000000000000000000000000000000000000000000002549960de5880e8c687434170f6476605b8fe4aeb9a28632c7995cf3ba831d97630500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008a7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a2273496a396e6164474850596759334b7156384f7a4a666c726275504b474f716d59576f4d57516869467773222c226f726967696e223a2268747470733a2f2f7369676e2e636f696e626173652e636f6d222c2263726f73734f726967696e223a66616c73657d00000000000000000000000000000000000000000000',
})
).toMatchInlineSnapshot(
`"0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000170000000000000000000000000000000000000000000000000000000000000001949fc7c88032b9fcb5f6efc7a7b8c63668eae9871b765e23123bb473ff57aa831a7c0d9276168ebcc29f2875a0239cffdf2a9cd1c2007c5c77c071db9264df1d000000000000000000000000000000000000000000000000000000000000002549960de5880e8c687434170f6476605b8fe4aeb9a28632c7995cf3ba831d97630500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008a7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a2273496a396e6164474850596759334b7156384f7a4a666c726275504b474f716d59576f4d57516869467773222c226f726967696e223a2268747470733a2f2f7369676e2e636f696e626173652e636f6d222c2263726f73734f726967696e223a66616c73657d00000000000000000000000000000000000000000000"`
);
});
});