Skip to content

Commit 1d2a2bc

Browse files
feat: Add wagmi adapter for in-app wallet
1 parent 0aa2416 commit 1d2a2bc

File tree

9 files changed

+349
-5
lines changed

9 files changed

+349
-5
lines changed

.changeset/strong-panthers-notice.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
---
2+
"@thirdweb-dev/wagmi-adapter": major
3+
---
4+
5+
Wagmi connector for in-app wallets
6+
7+
You can now connect to an in-app wallet in your wagmi applications.
8+
9+
```ts
10+
import { http, createConfig } from "wagmi";
11+
import { inAppWalletConnector } from "@thirdweb-dev/wagmi-adapter";
12+
13+
export const config = createConfig({
14+
chains: [sepolia],
15+
connectors: [
16+
inAppWalletConnector({
17+
clientId: "...",
18+
strategy: "google",
19+
}),
20+
],
21+
transports: {
22+
[sepolia.id]: http(),
23+
},
24+
});
25+
```

packages/wagmi-adapter/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Wagmi Adapter
2+
3+
This package enables the use of thirdweb's in-app wallets with wagmi.

packages/wagmi-adapter/package.json

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
{
2+
"name": "@thirdweb-dev/wagmi-adapter",
3+
"version": "1.0.0",
4+
"repository": {
5+
"type": "git",
6+
"url": "git+https://github.com/thirdweb-dev/js.git#main"
7+
},
8+
"license": "Apache-2.0",
9+
"bugs": {
10+
"url": "https://github.com/thirdweb-dev/js/issues"
11+
},
12+
"author": "thirdweb eng <eng@thirdweb.com>",
13+
"type": "module",
14+
"main": "./dist/cjs/exports/thirdweb.js",
15+
"module": "./dist/esm/exports/thirdweb.js",
16+
"types": "./dist/types/exports/thirdweb.d.ts",
17+
"typings": "./dist/types/exports/thirdweb.d.ts",
18+
"exports": {
19+
".": {
20+
"types": "./dist/types/exports/thirdweb.d.ts",
21+
"import": "./dist/esm/exports/thirdweb.js",
22+
"default": "./dist/cjs/exports/thirdweb.js"
23+
},
24+
"./package.json": "./package.json"
25+
},
26+
"files": ["dist/*", "src/*"],
27+
"devDependencies": {
28+
"@wagmi/core": "2.15.2",
29+
"rimraf": "6.0.1",
30+
"thirdweb": "workspace:*"
31+
},
32+
"peerDependencies": {
33+
"@wagmi/core": "^2",
34+
"thirdweb": "^5",
35+
"typescript": ">=5.0.4"
36+
},
37+
"peerDependenciesMeta": {
38+
"typescript": {
39+
"optional": true
40+
}
41+
},
42+
"scripts": {
43+
"format": "biome format ./src --write",
44+
"lint": "biome check ./src",
45+
"fix": "biome check ./src --fix",
46+
"build": "pnpm clean && pnpm build:cjs && pnpm build:esm && pnpm build:types",
47+
"build:cjs": "tsc --project ./tsconfig.build.json --module commonjs --outDir ./dist/cjs --verbatimModuleSyntax false && printf '{\"type\":\"commonjs\"}' > ./dist/cjs/package.json",
48+
"build:esm": "tsc --project ./tsconfig.build.json --module es2020 --outDir ./dist/esm && printf '{\"type\": \"module\",\"sideEffects\":false}' > ./dist/esm/package.json",
49+
"build:types": "tsc --project ./tsconfig.build.json --module esnext --declarationDir ./dist/types --emitDeclarationOnly --declaration --declarationMap",
50+
"clean": "rimraf dist"
51+
},
52+
"engines": {
53+
"node": ">=18"
54+
}
55+
}
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
import { type CreateConnectorFn, createConnector } from "@wagmi/core";
2+
import type { Prettify } from "@wagmi/core/chains";
3+
import { createThirdwebClient, defineChain, getAddress } from "thirdweb";
4+
import {
5+
EIP1193,
6+
type InAppWalletConnectionOptions,
7+
ecosystemWallet,
8+
inAppWallet as thirdwebInAppWallet,
9+
} from "thirdweb/wallets";
10+
import type { InAppWalletCreationOptions } from "thirdweb/wallets/in-app";
11+
12+
export type InAppWalletParameters = Prettify<
13+
Omit<InAppWalletConnectionOptions, "client"> &
14+
InAppWalletCreationOptions & {
15+
clientId: string;
16+
ecosystemId?: `ecosystem.${string}`;
17+
}
18+
>;
19+
20+
type Provider = EIP1193.EIP1193Provider | undefined;
21+
type Properties = Record<string, unknown>;
22+
type StorageItem = { "tw.lastChainId": number };
23+
24+
/**
25+
* Connect to an in-app wallet using the auth strategy of your choice.
26+
* @param args - Options for the in-app wallet connection.
27+
* @returns A wagmi connector.
28+
* @example
29+
* ```ts
30+
* import { http, createConfig } from "wagmi";
31+
* import { inAppWalletConnector } from "@thirdweb-dev/wagmi-adapter";
32+
*
33+
* export const config = createConfig({
34+
* chains: [sepolia],
35+
* connectors: [
36+
* inAppWalletConnector({
37+
* clientId: "...",
38+
* strategy: "google",
39+
* }),
40+
* ],
41+
* transports: {
42+
* [sepolia.id]: http(),
43+
* },
44+
* });
45+
* ```
46+
*/
47+
export function inAppWalletConnector(
48+
args: InAppWalletParameters,
49+
): CreateConnectorFn<Provider, Properties, StorageItem> {
50+
const client = createThirdwebClient({ clientId: args.clientId });
51+
const wallet = args.ecosystemId
52+
? ecosystemWallet(args.ecosystemId, { partnerId: args.partnerId })
53+
: thirdwebInAppWallet(args);
54+
return createConnector((config) => ({
55+
id: "in-app-wallet",
56+
name: "In-App wallet",
57+
type: "in-app",
58+
connect: async (params) => {
59+
const lastChainId = await config.storage?.getItem("tw.lastChainId");
60+
const chain = defineChain(params?.chainId || lastChainId || 1);
61+
const options = {
62+
client,
63+
chain,
64+
...args,
65+
} as unknown as InAppWalletConnectionOptions;
66+
const account = params?.isReconnecting
67+
? await wallet.autoConnect({
68+
client,
69+
chain,
70+
})
71+
: await wallet.connect(options);
72+
await config.storage?.setItem("tw.lastChainId", chain.id);
73+
return { accounts: [getAddress(account.address)], chainId: chain.id };
74+
},
75+
disconnect: async () => {
76+
await wallet.disconnect();
77+
},
78+
getAccounts: async () => {
79+
const account = wallet.getAccount();
80+
if (!account) {
81+
throw new Error("Wallet not connected");
82+
}
83+
return [getAddress(account.address)];
84+
},
85+
getChainId: async () => {
86+
return wallet.getChain()?.id || 1;
87+
},
88+
getProvider: async (params) => {
89+
return EIP1193.toProvider({
90+
wallet,
91+
client,
92+
chain: wallet.getChain() || defineChain(params?.chainId || 1),
93+
});
94+
},
95+
isAuthorized: async () => !!wallet.getAccount(),
96+
switchChain: async (params) => {
97+
const chain = config.chains.find((x) => x.id === params.chainId);
98+
if (!chain) {
99+
throw new Error(`Chain ${params.chainId} not supported`);
100+
}
101+
await wallet.switchChain(defineChain(chain.id));
102+
return chain;
103+
},
104+
onAccountsChanged: () => {
105+
// no-op
106+
},
107+
onChainChanged: () => {
108+
// no-op
109+
},
110+
onDisconnect: () => {
111+
// no-op
112+
},
113+
}));
114+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export {
2+
inAppWalletConnector,
3+
type InAppWalletParameters,
4+
} from "../connector.js";
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
{
2+
// This tsconfig file contains the shared config for the build (tsconfig.build.json) and type checking (tsconfig.json) config.
3+
"include": [],
4+
"compilerOptions": {
5+
// Incremental builds
6+
// NOTE: Enabling incremental builds speeds up `tsc`. Keep in mind though that it does not reliably bust the cache when the `tsconfig.json` file changes.
7+
"incremental": false,
8+
9+
// Type checking
10+
"strict": true,
11+
"useDefineForClassFields": true, // Not enabled by default in `strict` mode unless we bump `target` to ES2022.
12+
"noFallthroughCasesInSwitch": true, // Not enabled by default in `strict` mode.
13+
"noImplicitReturns": true, // Not enabled by default in `strict` mode.
14+
"useUnknownInCatchVariables": true, // TODO: This would normally be enabled in `strict` mode but would require some adjustments to the codebase.
15+
"noImplicitOverride": true, // Not enabled by default in `strict` mode.
16+
"noUnusedLocals": true, // Not enabled by default in `strict` mode.
17+
"noUnusedParameters": true, // Not enabled by default in `strict` mode.
18+
"exactOptionalPropertyTypes": false, // Not enabled by default in `strict` mode.
19+
"noUncheckedIndexedAccess": true, // Not enabled by default in `strict` mode.
20+
21+
// JavaScript support
22+
"allowJs": false,
23+
"checkJs": false,
24+
25+
// Interop constraints
26+
"esModuleInterop": false,
27+
"allowSyntheticDefaultImports": true,
28+
"forceConsistentCasingInFileNames": true,
29+
"verbatimModuleSyntax": true,
30+
"importHelpers": true, // This is only used for build validation. Since we do not have `tslib` installed, this will fail if we accidentally make use of anything that'd require injection of helpers.
31+
32+
// Language and environment
33+
"moduleResolution": "NodeNext",
34+
"module": "NodeNext",
35+
"target": "ES2021", // Setting this to `ES2021` enables native support for `Node v16+`: https://github.com/microsoft/TypeScript/wiki/Node-Target-Mapping.
36+
"lib": [
37+
"ES2022", // By using ES2022 we get access to the `.cause` property on `Error` instances.
38+
"DOM" // We are adding `DOM` here to get the `fetch`, etc. types. This should be removed once these types are available via DefinitelyTyped.
39+
],
40+
41+
// Skip type checking for node modules
42+
"skipLibCheck": true,
43+
44+
// jsx for "/react" portion
45+
"jsx": "react-jsx"
46+
}
47+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"extends": "./tsconfig.base.json",
3+
"include": ["src"],
4+
"exclude": [
5+
"src/**/*.test.ts",
6+
"src/**/*.test.tsx",
7+
"src/**/*.test-d.ts",
8+
"src/**/*.bench.ts",
9+
"src/**/*.macro.ts"
10+
],
11+
"compilerOptions": {
12+
"moduleResolution": "node",
13+
"sourceMap": true,
14+
"rootDir": "./src"
15+
}
16+
}

packages/wagmi-adapter/tsconfig.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
// This configuration is used for local development and type checking.
3+
"extends": "./tsconfig.base.json",
4+
"include": ["src", "test"],
5+
"exclude": [],
6+
// "references": [{ "path": "./scripts/tsconfig.json" }],
7+
"compilerOptions": {
8+
"baseUrl": ".",
9+
"paths": {
10+
"~test/*": ["./test/src/*"]
11+
}
12+
}
13+
}

0 commit comments

Comments
 (0)