Skip to content

Commit c2dee9f

Browse files
feat: support smart account options for ecosystem wallets
1 parent df128bf commit c2dee9f

File tree

5 files changed

+84
-5
lines changed

5 files changed

+84
-5
lines changed

.changeset/silver-candles-float.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"thirdweb": patch
3+
---
4+
5+
Support smart account options for ecosystem wallets

packages/thirdweb/src/react/web/wallets/shared/ConnectWalletSocialOptions.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { useMemo, useState } from "react";
55
import type { Chain } from "../../../../chains/types.js";
66
import type { ThirdwebClient } from "../../../../client/client.js";
77
import { webLocalStorage } from "../../../../utils/storage/webStorage.js";
8-
import { getEcosystemWalletAuthOptions } from "../../../../wallets/ecosystem/get-ecosystem-wallet-auth-options.js";
8+
import { getEcosystemOptions } from "../../../../wallets/ecosystem/get-ecosystem-wallet-auth-options.js";
99
import { isEcosystemWallet } from "../../../../wallets/ecosystem/is-ecosystem-wallet.js";
1010
import type { Profile } from "../../../../wallets/in-app/core/authentication/types.js";
1111
import { linkProfile } from "../../../../wallets/in-app/web/lib/auth/index.js";
@@ -121,7 +121,8 @@ export const ConnectWalletSocialOptions = (
121121
queryKey: ["auth-options", wallet.id],
122122
queryFn: async () => {
123123
if (isEcosystemWallet(wallet)) {
124-
return getEcosystemWalletAuthOptions(wallet.id);
124+
const options = await getEcosystemOptions(wallet.id);
125+
return options?.authOptions ?? null;
125126
}
126127
return null;
127128
},

packages/thirdweb/src/wallets/ecosystem/get-ecosystem-wallet-auth-options.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,26 @@ import { getThirdwebBaseUrl } from "../../utils/domains.js";
22
import type { AuthOption } from "../types.js";
33
import type { EcosystemWalletId } from "../wallet-types.js";
44

5+
export type EcosystemOptions = {
6+
authOptions: AuthOption[];
7+
smartAccountOptions: SmartAccountOptions;
8+
};
9+
10+
type SmartAccountOptions = {
11+
chainIds: number[];
12+
sponsorGas: boolean;
13+
accountFactoryAddress: string;
14+
};
15+
516
/**
617
* Retrieves the specified auth options for a given ecosystem wallet, if any.
718
* @param walletId The ecosystem wallet ID.
819
* @returns {AuthOption[] | undefined} The auth options for the ecosystem wallet.
920
* @internal
1021
*/
11-
export async function getEcosystemWalletAuthOptions(
22+
export async function getEcosystemOptions(
1223
walletId: EcosystemWalletId,
13-
): Promise<AuthOption[] | undefined> {
24+
): Promise<EcosystemOptions | null> {
1425
const res = await fetch(
1526
`${getThirdwebBaseUrl("inAppWallet")}/api/2024-05-05/ecosystem-wallet`,
1627
{
@@ -29,5 +40,5 @@ export async function getEcosystemWalletAuthOptions(
2940
);
3041
}
3142

32-
return data.authOptions ?? undefined;
43+
return data ?? null;
3344
}

packages/thirdweb/src/wallets/in-app/core/wallet/in-app-core.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ export function createInAppWallet(args: {
7070
options,
7171
createOptions,
7272
connector,
73+
ecosystem,
7374
);
7475

7576
// set the states
@@ -96,6 +97,7 @@ export function createInAppWallet(args: {
9697
options,
9798
createOptions,
9899
connector,
100+
ecosystem,
99101
);
100102
// set the states
101103
client = options.client;
@@ -142,6 +144,7 @@ export function createInAppWallet(args: {
142144
},
143145
createOptions,
144146
connector,
147+
ecosystem,
145148
);
146149
account = connectedAccount;
147150
chain = connectedChain;

packages/thirdweb/src/wallets/in-app/core/wallet/index.ts

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import { ethereum } from "../../../../chains/chain-definitions/ethereum.js";
22
import type { Chain } from "../../../../chains/types.js";
3+
import { getCachedChain } from "../../../../chains/utils.js";
34
import type { ThirdwebClient } from "../../../../client/client.js";
45
import {
56
type SocialAuthOption,
67
socialAuthOptions,
78
} from "../../../../wallets/types.js";
9+
import { getEcosystemOptions } from "../../../ecosystem/get-ecosystem-wallet-auth-options.js";
810
import type { Account, Wallet } from "../../../interfaces/wallet.js";
911
import type { EcosystemWalletId, WalletId } from "../../../wallet-types.js";
1012
import type {
@@ -13,6 +15,7 @@ import type {
1315
WalletConnectionOption,
1416
} from "../../../wallet-types.js";
1517
import type { InAppConnector } from "../interfaces/connector.js";
18+
import type { Ecosystem } from "./types.js";
1619

1720
/**
1821
* Checks if the provided wallet is an in-app wallet.
@@ -37,6 +40,7 @@ export async function connectInAppWallet(
3740
| CreateWalletArgs<"inApp">[1]
3841
| CreateWalletArgs<EcosystemWalletId>[1],
3942
connector: InAppConnector,
43+
ecosystem: Ecosystem | undefined,
4044
): Promise<[Account, Chain]> {
4145
if (
4246
// if auth mode is not specified, the default is popup
@@ -73,6 +77,33 @@ export async function connectInAppWallet(
7377
});
7478
}
7579

80+
if (ecosystem) {
81+
const ecosystemOptions = await getEcosystemOptions(ecosystem.id);
82+
const smartAccountOptions = ecosystemOptions?.smartAccountOptions;
83+
if (smartAccountOptions) {
84+
const allowedChains = smartAccountOptions.chainIds;
85+
const firstAllowedChain = allowedChains[0];
86+
if (!firstAllowedChain) {
87+
throw new Error(
88+
"At least one chain must be allowed for ecosystem smart account",
89+
);
90+
}
91+
const preferredChain =
92+
options.chain && allowedChains.includes(options.chain.id)
93+
? options.chain
94+
: getCachedChain(firstAllowedChain);
95+
return convertToSmartAccount({
96+
client: options.client,
97+
authAccount,
98+
smartAccountOptions: {
99+
chain: preferredChain,
100+
sponsorGas: smartAccountOptions.sponsorGas,
101+
factoryAddress: smartAccountOptions.accountFactoryAddress,
102+
},
103+
});
104+
}
105+
}
106+
76107
return [authAccount, options.chain || ethereum] as const;
77108
}
78109

@@ -87,6 +118,7 @@ export async function autoConnectInAppWallet(
87118
| CreateWalletArgs<"inApp">[1]
88119
| CreateWalletArgs<EcosystemWalletId>[1],
89120
connector: InAppConnector,
121+
ecosystem: Ecosystem | undefined,
90122
): Promise<[Account, Chain]> {
91123
if (options.authResult && connector.loginWithAuthToken) {
92124
await connector.loginWithAuthToken(options.authResult);
@@ -112,6 +144,33 @@ export async function autoConnectInAppWallet(
112144
});
113145
}
114146

147+
if (ecosystem) {
148+
const ecosystemOptions = await getEcosystemOptions(ecosystem.id);
149+
const smartAccountOptions = ecosystemOptions?.smartAccountOptions;
150+
if (smartAccountOptions) {
151+
const allowedChains = smartAccountOptions.chainIds;
152+
const firstAllowedChain = allowedChains[0];
153+
if (!firstAllowedChain) {
154+
throw new Error(
155+
"At least one chain must be allowed for ecosystem smart account",
156+
);
157+
}
158+
const preferredChain =
159+
options.chain && allowedChains.includes(options.chain.id)
160+
? options.chain
161+
: getCachedChain(firstAllowedChain);
162+
return convertToSmartAccount({
163+
client: options.client,
164+
authAccount,
165+
smartAccountOptions: {
166+
chain: preferredChain,
167+
sponsorGas: smartAccountOptions.sponsorGas,
168+
factoryAddress: smartAccountOptions.accountFactoryAddress,
169+
},
170+
});
171+
}
172+
}
173+
115174
return [authAccount, options.chain || ethereum] as const;
116175
}
117176

0 commit comments

Comments
 (0)