UNPKG

@lukasrosario/account

Version:

Base Account SDK

508 lines (448 loc) 38.2 kB
// 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"` ); }); });