Skip to content

Commit 22f2152

Browse files
authored
fix: wallet_addSubAccount keys population if not provided (#1649)
1 parent c831acc commit 22f2152

File tree

4 files changed

+109
-1
lines changed

4 files changed

+109
-1
lines changed
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { Box, Button } from '@chakra-ui/react';
2+
import { createCoinbaseWalletSDK, getCryptoKeyAccount } from '@coinbase/wallet-sdk';
3+
import { useCallback, useState } from 'react';
4+
import { numberToHex } from 'viem';
5+
6+
type AddSubAccountWithoutKeysProps = {
7+
sdk: ReturnType<typeof createCoinbaseWalletSDK>;
8+
onAddSubAccount: (address: string) => void;
9+
signerFn: typeof getCryptoKeyAccount;
10+
};
11+
12+
export function AddSubAccountWithoutKeys({
13+
sdk,
14+
onAddSubAccount,
15+
signerFn,
16+
}: AddSubAccountWithoutKeysProps) {
17+
const [subAccount, setSubAccount] = useState<string>();
18+
19+
const handleAddSubAccount = useCallback(async () => {
20+
if (!sdk) {
21+
return;
22+
}
23+
24+
const { account } = await signerFn();
25+
26+
if (!account) {
27+
throw new Error('Could not get owner account');
28+
}
29+
30+
const provider = sdk.getProvider();
31+
await provider.request({
32+
method: 'wallet_switchEthereumChain',
33+
params: [{ chainId: numberToHex(84532) }],
34+
});
35+
36+
const response = (await provider.request({
37+
method: 'wallet_addSubAccount',
38+
params: [
39+
{
40+
version: '1',
41+
account: {
42+
type: 'create',
43+
},
44+
},
45+
],
46+
})) as { address: string };
47+
48+
console.info('response', response);
49+
setSubAccount(response.address);
50+
onAddSubAccount(response.address);
51+
}, [sdk, onAddSubAccount, signerFn]);
52+
53+
return (
54+
<>
55+
<Button w="full" onClick={handleAddSubAccount}>
56+
Add Address (Without Keys)
57+
</Button>
58+
{subAccount && (
59+
<Box
60+
as="pre"
61+
w="full"
62+
p={2}
63+
bg="gray.900"
64+
borderRadius="md"
65+
border="1px solid"
66+
borderColor="gray.700"
67+
>
68+
{JSON.stringify(subAccount, null, 2)}
69+
</Box>
70+
)}
71+
</>
72+
);
73+
}

examples/testapp/src/pages/add-sub-account/index.page.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { useEIP1193Provider } from '../../context/EIP1193ProviderContextProvider
1616
import { unsafe_generateOrLoadPrivateKey } from '../../utils/unsafe_generateOrLoadPrivateKey';
1717
import { AddOwner } from './components/AddOwner';
1818
import { AddSubAccount } from './components/AddSubAccount';
19+
import { AddSubAccountWithoutKeys } from './components/AddSubAccountWithoutKeys';
1920
import { Connect } from './components/Connect';
2021
import { GenerateNewSigner } from './components/GenerateNewSigner';
2122
import { GrantSpendPermission } from './components/GrantSpendPermission';
@@ -80,6 +81,11 @@ export default function SubAccounts() {
8081
onAddSubAccount={setSubAccountAddress}
8182
signerFn={getSubAccountSigner}
8283
/>
84+
<AddSubAccountWithoutKeys
85+
sdk={sdk}
86+
onAddSubAccount={setSubAccountAddress}
87+
signerFn={getSubAccountSigner}
88+
/>
8389
<PersonalSign sdk={sdk} subAccountAddress={subAccountAddress} />
8490
<SendCalls sdk={sdk} subAccountAddress={subAccountAddress} />
8591
<GrantSpendPermission sdk={sdk} subAccountAddress={subAccountAddress} />

packages/wallet-sdk/src/sign/scw/SCWSigner.test.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -865,6 +865,10 @@ describe('SCWSigner', () => {
865865
},
866866
});
867867

868+
// Clear previous mock calls to isolate the wallet_addSubAccount call
869+
mockCommunicator.postRequestAndWaitForResponse.mockClear();
870+
(encryptContent as Mock).mockClear();
871+
868872
await signer.request({
869873
method: 'wallet_addSubAccount',
870874
params: [
@@ -877,6 +881,31 @@ describe('SCWSigner', () => {
877881
],
878882
});
879883

884+
// Verify that encryptContent was called with a request containing populated keys
885+
expect(encryptContent).toHaveBeenCalledWith(
886+
expect.objectContaining({
887+
action: expect.objectContaining({
888+
method: 'wallet_addSubAccount',
889+
params: [
890+
{
891+
version: '1',
892+
account: {
893+
type: 'create',
894+
keys: expect.arrayContaining([
895+
expect.objectContaining({
896+
type: expect.any(String),
897+
publicKey: expect.any(String),
898+
}),
899+
]),
900+
},
901+
},
902+
],
903+
}),
904+
chainId: expect.any(Number),
905+
}),
906+
mockCryptoKey
907+
);
908+
880909
const accounts = await signer.request({ method: 'eth_accounts' });
881910
expect(accounts).toEqual([subAccountAddress, globalAccountAddress]);
882911
});

packages/wallet-sdk/src/sign/scw/SCWSigner.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -496,7 +496,7 @@ export class SCWSigner implements Signer {
496496
Array.isArray(request.params) &&
497497
request.params.length > 0 &&
498498
request.params[0].account &&
499-
request.params[0].type === 'create'
499+
request.params[0].account.type === 'create'
500500
) {
501501
let keys: { type: string; publicKey: string }[];
502502
if (request.params[0].account.keys && request.params[0].account.keys.length > 0) {

0 commit comments

Comments
 (0)