Skip to content

Commit b54573d

Browse files
committed
⬆️ Upgrade wagmi + fix types + simplify provider
1 parent 437566a commit b54573d

File tree

7 files changed

+130
-89
lines changed

7 files changed

+130
-89
lines changed

apps/wallet/app/module/recovery/hook/usePerformRecovery.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { UseMutationOptions } from "@tanstack/react-query";
22
import { type DefaultError, useMutation } from "@tanstack/react-query";
3-
import { createSmartAccountClient } from "permissionless";
3+
import { smartAccountActions } from "permissionless";
44
import { getUserOperationGasPrice } from "permissionless/actions/pimlico";
55
import {
66
encodeFunctionData,
@@ -9,6 +9,7 @@ import {
99
type LocalAccount,
1010
toHex,
1111
} from "viem";
12+
import { createBundlerClient } from "viem/account-abstraction";
1213
import { useClient } from "wagmi";
1314
import {
1415
getPimlicoClient,
@@ -67,10 +68,10 @@ export function usePerformRecovery(
6768
const pimlicoClient = getPimlicoClient();
6869

6970
// Build the smart wallet client
70-
const accountClient = createSmartAccountClient({
71+
const accountClient = createBundlerClient({
7172
account: smartAccount,
7273
chain: client.chain,
73-
bundlerTransport: pimlicoTransport,
74+
transport: pimlicoTransport,
7475
// Get the right gas fees for the user operation
7576
userOperation: {
7677
estimateFeesPerGas: async () => {
@@ -81,7 +82,7 @@ export function usePerformRecovery(
8182
},
8283
},
8384
paymaster: true,
84-
});
85+
}).extend(smartAccountActions);
8586

8687
// Build the function data
8788
const fnData = encodeFunctionData({

apps/wallet/app/module/wallet/smartWallet/connector.ts

Lines changed: 39 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,37 @@
1-
import type { Address, Hex, Transport } from "viem";
2-
import { createConnector } from "wagmi";
1+
import type { Address, Hex } from "viem";
2+
import { type CreateConnectorFn, createConnector } from "wagmi";
33
import { currentChain } from "@/module/blockchain/provider";
4-
import { getSmartAccountProvider } from "@/module/wallet/smartWallet/provider";
4+
import {
5+
getSmartAccountProvider,
6+
type SmartAccountProviderType,
7+
} from "@/module/wallet/smartWallet/provider";
58

69
smartAccountConnector.type = "frakSmartAccountConnector" as const;
710

8-
export type FrakWalletConnector = ReturnType<typeof smartAccountConnector> & {
9-
setEcdsaSigner: (
10-
signer:
11-
| ((args: { hash: Hex; address: Address }) => Promise<Hex>)
12-
| undefined
13-
) => void;
14-
};
11+
export type FrakWalletConnector = ReturnType<FrakWalletConnectorFn>;
12+
export type FrakWalletConnectorFn = CreateConnectorFn<
13+
SmartAccountProviderType,
14+
{
15+
setEcdsaSigner: (
16+
signer: (args: { hash: Hex; address: Address }) => Promise<Hex>
17+
) => void;
18+
}
19+
>;
1520

1621
/**
1722
* Create a connector for the smart account
1823
*/
19-
export function smartAccountConnector<
20-
transport extends Transport = Transport,
21-
>() {
22-
// A few types shortcut
23-
type Provider = ReturnType<typeof getSmartAccountProvider<transport>>;
24-
25-
// The current provider
26-
let provider: Provider | undefined;
24+
export function smartAccountConnector(): FrakWalletConnectorFn {
25+
// The current provider (cached)
26+
let cachedProvider: SmartAccountProviderType | undefined;
2727

2828
// The current ecdsa signer
2929
let ecdsaSigner:
3030
| ((args: { hash: Hex; address: Address }) => Promise<Hex>)
3131
| undefined;
3232

3333
// Create the wagmi connector itself
34-
return createConnector<
35-
Provider,
36-
{
37-
setEcdsaSigner: (signer: typeof ecdsaSigner) => void;
38-
}
39-
>((config) => ({
34+
return createConnector((config) => ({
4035
id: "frak-wallet-connector",
4136
name: "Frak Smart Account",
4237
type: smartAccountConnector.type,
@@ -55,25 +50,27 @@ export function smartAccountConnector<
5550
*/
5651
async connect({ chainId } = {}) {
5752
// Fetch the provider
58-
const provider = await this.getProvider();
53+
const accountProvider = await this.getProvider();
5954

6055
// If the chain id is not provided, use the current chain
6156
if (chainId && chainId !== currentChain.id) {
6257
throw new Error("Invalid chain id");
6358
}
6459

6560
// If we got it in cache return it
66-
if (provider.currentSmartAccountClient) {
61+
if (accountProvider.currentSmartAccountClient) {
6762
return {
6863
accounts: [
69-
provider.currentSmartAccountClient.account.address,
64+
accountProvider.currentSmartAccountClient.account
65+
.address,
7066
],
7167
chainId: currentChain.id,
7268
};
7369
}
7470

7571
// Ask the provider to build it
76-
const smartAccountClient = await provider.getSmartAccountClient();
72+
const smartAccountClient =
73+
await accountProvider.getSmartAccountClient();
7774
return {
7875
accounts: smartAccountClient
7976
? [smartAccountClient.account.address]
@@ -93,12 +90,15 @@ export function smartAccountConnector<
9390
* Fetch the current accounts
9491
*/
9592
async getAccounts() {
96-
const provider = await this.getProvider();
97-
if (provider.currentSmartAccountClient) {
98-
return [provider.currentSmartAccountClient.account.address];
93+
const accountProvider = await this.getProvider();
94+
if (accountProvider.currentSmartAccountClient) {
95+
return [
96+
accountProvider.currentSmartAccountClient.account.address,
97+
];
9998
}
10099
// Otherwise, get the account for the default chain (could be the case just after the login)
101-
const smartAccountClient = await provider.getSmartAccountClient();
100+
const smartAccountClient =
101+
await accountProvider.getSmartAccountClient();
102102
if (!smartAccountClient) {
103103
return [];
104104
}
@@ -116,7 +116,7 @@ export function smartAccountConnector<
116116
},
117117

118118
async getClient(parameters?: { chainId?: number }) {
119-
const provider = await this.getProvider();
119+
const accountProvider = await this.getProvider();
120120

121121
if (
122122
parameters?.chainId &&
@@ -125,17 +125,17 @@ export function smartAccountConnector<
125125
throw new Error("Invalid chain id");
126126
}
127127

128-
const client = await provider.getSmartAccountClient();
128+
const client = await accountProvider.getSmartAccountClient();
129129
if (!client) {
130130
throw new Error("No client found for the given chain");
131131
}
132132
return client;
133133
},
134134

135-
async getProvider(): Promise<Provider> {
136-
if (!provider) {
135+
async getProvider() {
136+
if (!cachedProvider) {
137137
// Create the provider
138-
provider = getSmartAccountProvider({
138+
cachedProvider = getSmartAccountProvider({
139139
onAccountChanged: (wallet) => {
140140
console.log("Wagmi provider account changed", {
141141
wallet,
@@ -162,7 +162,7 @@ export function smartAccountConnector<
162162
},
163163
});
164164
}
165-
return provider;
165+
return cachedProvider;
166166
},
167167
onAccountsChanged() {
168168
// Not relevant
@@ -180,5 +180,5 @@ export function smartAccountConnector<
180180
setEcdsaSigner(signer: typeof ecdsaSigner) {
181181
ecdsaSigner = signer;
182182
},
183-
}));
183+
})) satisfies FrakWalletConnectorFn;
184184
}

apps/wallet/app/module/wallet/smartWallet/provider.ts

Lines changed: 31 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
11
import { jotaiStore } from "@frak-labs/ui/atoms/store";
2-
import {
3-
createSmartAccountClient,
4-
type SmartAccountClient,
5-
} from "permissionless";
2+
import { smartAccountActions } from "permissionless";
63
import { getUserOperationGasPrice } from "permissionless/actions/pimlico";
7-
import type { Address, Hex, Transport } from "viem";
8-
import type { SmartAccount } from "viem/account-abstraction";
4+
import type { Address, Hex } from "viem";
5+
import { createBundlerClient } from "viem/account-abstraction";
96
import {
107
getPimlicoClient,
118
getPimlicoTransport,
@@ -43,21 +40,14 @@ type SmartAccountProviderParameters = {
4340
/**
4441
* Get the smart account provider for our wagmi connector
4542
*/
46-
export function getSmartAccountProvider<
47-
transport extends Transport = Transport,
48-
>({ onAccountChanged, signViaEcdsa }: SmartAccountProviderParameters) {
43+
export function getSmartAccountProvider({
44+
onAccountChanged,
45+
signViaEcdsa,
46+
}: SmartAccountProviderParameters): SmartAccountProviderType {
4947
console.log("Building a new smart account provider");
50-
// A few types shortcut
51-
type ConnectorClient = SmartAccountClient<
52-
transport,
53-
typeof currentChain,
54-
SmartAccount<BaseFrakSmartAccount>
55-
> & {
56-
estimateGas?: () => undefined | bigint;
57-
};
5848

5949
// The current smart account
60-
let currentSmartAccountClient: ConnectorClient | undefined;
50+
let currentSmartAccountClient: SmartAccountConnectorClient | undefined;
6151

6252
// The current session
6353
let currentWebAuthNWallet = getSafeSession();
@@ -134,19 +124,13 @@ export function getSmartAccountProvider<
134124
* @param chainId
135125
* @param wallet
136126
*/
137-
async function buildSmartAccount<transport extends Transport = Transport>({
127+
async function buildSmartAccount({
138128
wallet,
139129
signViaEcdsa,
140130
}: {
141131
wallet: WebAuthNWallet | EcdsaWallet | DistantWebAuthnWallet;
142132
signViaEcdsa: (data: Hex, address: Address) => Promise<Hex>;
143-
}): Promise<
144-
SmartAccountClient<
145-
transport,
146-
typeof currentChain,
147-
SmartAccount<BaseFrakSmartAccount>
148-
>
149-
> {
133+
}) {
150134
let smartAccount: BaseFrakSmartAccount;
151135
if (wallet.type === "ecdsa") {
152136
// That's a ecdsa wallet
@@ -182,10 +166,10 @@ async function buildSmartAccount<transport extends Transport = Transport>({
182166
const pimlicoClient = getPimlicoClient();
183167

184168
// Build the smart wallet client
185-
return createSmartAccountClient({
169+
return createBundlerClient({
186170
account: smartAccount,
187171
chain: currentChain,
188-
bundlerTransport: pimlicoTransport,
172+
transport: pimlicoTransport,
189173
// Get the right gas fees for the user operation
190174
userOperation: {
191175
estimateFeesPerGas: async () => {
@@ -196,9 +180,23 @@ async function buildSmartAccount<transport extends Transport = Transport>({
196180
},
197181
// Get the right paymaster datas
198182
paymaster: true,
199-
}) as SmartAccountClient<
200-
transport,
201-
typeof currentChain,
202-
SmartAccount<BaseFrakSmartAccount>
203-
>;
183+
}).extend(smartAccountActions);
204184
}
185+
186+
/**
187+
* Exported types for connector usage
188+
*/
189+
export type SmartAccountConnectorClient = Awaited<
190+
ReturnType<typeof buildSmartAccount>
191+
> & {
192+
estimateGas?: () => undefined | bigint;
193+
};
194+
195+
export type SmartAccountProviderType = {
196+
isAuthorized: () => boolean;
197+
currentSmartAccountClient: SmartAccountConnectorClient | undefined;
198+
getSmartAccountClient: () => Promise<
199+
SmartAccountConnectorClient | undefined
200+
>;
201+
disconnect: () => Promise<void>;
202+
};

apps/wallet/package.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,13 @@
4242
"@radix-ui/react-slot": "^1.2.3",
4343
"@react-router/node": "^7.9.4",
4444
"@react-router/serve": "^7.9.4",
45-
"@simplewebauthn/browser": "^13.1.0",
46-
"@simplewebauthn/server": "^13.1.1",
45+
"@simplewebauthn/browser": "catalog:",
46+
"@simplewebauthn/server": "catalog:",
4747
"@tanstack/query-sync-storage-persister": "^5.90.5",
4848
"@tanstack/react-query": "^5.90.3",
4949
"@tanstack/react-query-devtools": "^5.90.2",
5050
"@tanstack/react-query-persist-client": "^5.90.5",
51-
"@wagmi/core": "2.17.3",
51+
"@wagmi/core": "^2.22.1",
5252
"class-variance-authority": "^0.7.1",
5353
"cuer": "^0.0.2",
5454
"dexie": "^4.2.1",
@@ -78,7 +78,7 @@
7878
"ua-parser-js": "^2.0.6",
7979
"vaul": "^1.1.2",
8080
"viem": "catalog:",
81-
"wagmi": "2.15.6"
81+
"wagmi": "^2.18.1"
8282
},
8383
"devDependencies": {
8484
"@frak-labs/backend-elysia": "workspace:*",
@@ -91,6 +91,7 @@
9191
"@types/react": "catalog:",
9292
"@types/react-avatar-editor": "^13.0.4",
9393
"@types/react-dom": "catalog:",
94+
"@typescript/native-preview": "^7.0.0-dev.20251019.1",
9495
"bun-types": "latest",
9596
"cbor": "^10.0.11",
9697
"esbuild": "^0.25.11",

0 commit comments

Comments
 (0)