Skip to content

Commit b058f68

Browse files
authored
[SDK] Feature: Adds deploySmartAccount and re-adds 1271 signatures (#5845)
1 parent 66f1337 commit b058f68

File tree

15 files changed

+2942
-4317
lines changed

15 files changed

+2942
-4317
lines changed

.changeset/polite-trains-kick.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
"thirdweb": minor
3+
---
4+
5+
Feature: Adds `deploySmartAccount` function to force the deployment of a smart account.
6+
7+
```ts
8+
const account = await deploySmartAccount({
9+
smartAccount,
10+
chain,
11+
client,
12+
accountContract,
13+
});
14+
```
15+
16+
Fix: Uses 1271 signatures if the smart account is already deployed.

packages/thirdweb/src/auth/verify-hash.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,7 @@ export async function verifyHash({
129129
try {
130130
const result = await eth_call(rpcRequest, verificationData);
131131
return hexToBool(result);
132-
} catch (err) {
133-
console.error("Error verifying ERC-6492 signature", err);
132+
} catch {
134133
// Some chains do not support the eth_call simulation and will fail, so we fall back to regular EIP1271 validation
135134
const validEip1271 = await verifyEip1271Signature({
136135
hash,
@@ -154,7 +153,7 @@ export async function verifyHash({
154153
}
155154

156155
const EIP_1271_MAGIC_VALUE = "0x1626ba7e";
157-
async function verifyEip1271Signature({
156+
export async function verifyEip1271Signature({
158157
hash,
159158
signature,
160159
contract,
@@ -163,10 +162,14 @@ async function verifyEip1271Signature({
163162
signature: Hex;
164163
contract: ThirdwebContract;
165164
}): Promise<boolean> {
166-
const result = await isValidSignature({
167-
hash,
168-
signature,
169-
contract,
170-
});
171-
return result === EIP_1271_MAGIC_VALUE;
165+
try {
166+
const result = await isValidSignature({
167+
hash,
168+
signature,
169+
contract,
170+
});
171+
return result === EIP_1271_MAGIC_VALUE;
172+
} catch {
173+
return false;
174+
}
172175
}

packages/thirdweb/src/exports/thirdweb.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,3 +302,5 @@ export {
302302
type VerifyTypedDataParams,
303303
verifyTypedData,
304304
} from "../auth/verify-typed-data.js";
305+
306+
export { deploySmartAccount } from "../wallets/smart/lib/signing.js";

packages/thirdweb/src/exports/wallets.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,3 +160,5 @@ export * as EIP1193 from "../adapters/eip1193/index.js";
160160
export { injectedProvider } from "../wallets/injected/mipdStore.js";
161161

162162
export type { ConnectionManager } from "../wallets/manager/index.js";
163+
164+
export { deploySmartAccount } from "../wallets/smart/lib/signing.js";

packages/thirdweb/src/utils/abi/decodeError.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { type Abi, AbiError } from "ox";
1+
import type * as ox__Abi from "ox/Abi";
2+
import * as ox__AbiError from "ox/AbiError";
23
import { resolveContractAbi } from "../../contract/actions/resolve-abi.js";
34
import type { ThirdwebContract } from "../../contract/contract.js";
45
import type { Hex } from "../encoding/hex.js";
@@ -17,7 +18,7 @@ import type { Hex } from "../encoding/hex.js";
1718
*
1819
* @utils
1920
*/
20-
export async function decodeError<abi extends Abi.Abi>(options: {
21+
export async function decodeError<abi extends ox__Abi.Abi>(options: {
2122
contract: ThirdwebContract<abi>;
2223
data: Hex;
2324
}) {
@@ -31,6 +32,6 @@ export async function decodeError<abi extends Abi.Abi>(options: {
3132
`No ABI found for contract ${contract.address} on chain ${contract.chain.id}`,
3233
);
3334
}
34-
const abiError = AbiError.fromAbi(abi, data) as AbiError.AbiError;
35-
return AbiError.decode(abiError, data);
35+
const abiError = ox__AbiError.fromAbi(abi, data) as ox__AbiError.AbiError;
36+
return ox__AbiError.decode(abiError, data);
3637
}

packages/thirdweb/src/utils/abi/decodeFunctionData.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
import { type Abi, AbiFunction, type Hex } from "ox";
1+
import type * as ox__Abi from "ox/Abi";
2+
import * as ox__AbiFunction from "ox/AbiFunction";
3+
import type * as ox__Hex from "ox/Hex";
24
import { resolveContractAbi } from "../../contract/actions/resolve-abi.js";
35
import type { ThirdwebContract } from "../../contract/contract.js";
46

@@ -16,9 +18,9 @@ import type { ThirdwebContract } from "../../contract/contract.js";
1618
*
1719
* @utils
1820
*/
19-
export async function decodeFunctionData<abi extends Abi.Abi>(options: {
21+
export async function decodeFunctionData<abi extends ox__Abi.Abi>(options: {
2022
contract: ThirdwebContract<abi>;
21-
data: Hex.Hex;
23+
data: ox__Hex.Hex;
2224
}) {
2325
const { contract, data } = options;
2426
let abi = contract?.abi;
@@ -30,6 +32,6 @@ export async function decodeFunctionData<abi extends Abi.Abi>(options: {
3032
`No ABI found for contract ${contract.address} on chain ${contract.chain.id}`,
3133
);
3234
}
33-
const abiFunction = AbiFunction.fromAbi(abi, data);
34-
return AbiFunction.decodeData(abiFunction, data);
35+
const abiFunction = ox__AbiFunction.fromAbi(abi, data);
36+
return ox__AbiFunction.decodeData(abiFunction, data);
3537
}

packages/thirdweb/src/utils/abi/decodeFunctionResult.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
import { type Abi, AbiFunction, type Hex } from "ox";
1+
import type * as ox__Abi from "ox/Abi";
2+
import * as ox__AbiFunction from "ox/AbiFunction";
3+
import type * as ox__Hex from "ox/Hex";
24
import { resolveContractAbi } from "../../contract/actions/resolve-abi.js";
35
import type { ThirdwebContract } from "../../contract/contract.js";
46

@@ -16,9 +18,9 @@ import type { ThirdwebContract } from "../../contract/contract.js";
1618
*
1719
* @utils
1820
*/
19-
export async function decodeFunctionResult<abi extends Abi.Abi>(options: {
21+
export async function decodeFunctionResult<abi extends ox__Abi.Abi>(options: {
2022
contract: ThirdwebContract<abi>;
21-
data: Hex.Hex;
23+
data: ox__Hex.Hex;
2224
}) {
2325
const { contract, ...rest } = options;
2426
let abi = contract?.abi;
@@ -30,6 +32,6 @@ export async function decodeFunctionResult<abi extends Abi.Abi>(options: {
3032
`No ABI found for contract ${contract.address} on chain ${contract.chain.id}`,
3133
);
3234
}
33-
const abiFunction = AbiFunction.fromAbi(abi, rest.data);
34-
return AbiFunction.decodeResult(abiFunction, rest.data);
35+
const abiFunction = ox__AbiFunction.fromAbi(abi, rest.data);
36+
return ox__AbiFunction.decodeResult(abiFunction, rest.data);
3537
}

packages/thirdweb/src/utils/hashing/hashMessage.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Bytes as ox__Bytes } from "ox";
1+
import * as ox__Bytes from "ox/Bytes";
22
import type { Hex } from "../encoding/hex.js";
33
import { stringToBytes, toBytes } from "../encoding/to-bytes.js";
44
import type { SignableMessage } from "../types.js";

packages/thirdweb/src/wallets/create-wallet.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,22 @@ import { createWalletEmitter } from "./wallet-emitter.js";
116116
*
117117
* [View Coinbase wallet creation options](https://portal.thirdweb.com/references/typescript/v5/CoinbaseWalletCreationOptions)
118118
*
119+
* ## Connecting with a smart wallet
120+
*
121+
* ```ts
122+
* import { createWallet } from "thirdweb/wallets";
123+
*
124+
* const wallet = createWallet("smart", {
125+
* chain: sepolia,
126+
* sponsorGas: true,
127+
* });
128+
*
129+
* const account = await wallet.connect({
130+
* client,
131+
* personalAccount, // pass the admin account
132+
* });
133+
* ```
134+
*
119135
* @wallet
120136
*/
121137
export function createWallet<const ID extends WalletId>(

packages/thirdweb/src/wallets/smart/index.ts

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ async function createSmartAccount(
210210
}
211211
}
212212

213-
const { accountContract } = options;
213+
let accountContract = options.accountContract;
214214
const account: Account = {
215215
address: getAddress(accountContract.address),
216216
async sendTransaction(transaction: SendTransactionOption) {
@@ -237,21 +237,17 @@ async function createSmartAccount(
237237
paymasterOverride = options.overrides?.paymaster;
238238
}
239239

240-
const accountContractForTransaction = (() => {
241-
// If this transaction is for a different chain than the initial one, get the account contract for that chain
242-
if (transaction.chainId !== accountContract.chain.id) {
243-
return getContract({
244-
address: account.address,
245-
chain: getCachedChain(transaction.chainId),
246-
client: options.client,
247-
});
248-
}
249-
// Default to the existing account contract
250-
return accountContract;
251-
})();
240+
// If this transaction is for a different chain than the initial one, get the account contract for that chain
241+
if (transaction.chainId !== accountContract.chain.id) {
242+
accountContract = getContract({
243+
address: account.address,
244+
chain: getCachedChain(transaction.chainId),
245+
client: options.client,
246+
});
247+
}
252248

253249
const executeTx = prepareExecute({
254-
accountContract: accountContractForTransaction,
250+
accountContract: accountContract,
255251
transaction,
256252
executeOverride: options.overrides?.execute,
257253
});
@@ -260,6 +256,7 @@ async function createSmartAccount(
260256
options: {
261257
...options,
262258
chain: getCachedChain(transaction.chainId),
259+
accountContract,
263260
overrides: {
264261
...options.overrides,
265262
paymaster: paymasterOverride,
@@ -275,7 +272,11 @@ async function createSmartAccount(
275272
});
276273
return _sendUserOp({
277274
executeTx,
278-
options,
275+
options: {
276+
...options,
277+
chain: getCachedChain(transactions[0]?.chainId ?? options.chain.id),
278+
accountContract,
279+
},
279280
});
280281
},
281282
async signMessage({ message }: { message: SignableMessage }) {
@@ -288,8 +289,8 @@ async function createSmartAccount(
288289
});
289290
}
290291

291-
const { deployAndSignMessage } = await import("./lib/signing.js");
292-
return deployAndSignMessage({
292+
const { smartAccountSignMessage } = await import("./lib/signing.js");
293+
return smartAccountSignMessage({
293294
accountContract,
294295
factoryContract: options.factoryContract,
295296
options,
@@ -309,8 +310,8 @@ async function createSmartAccount(
309310
});
310311
}
311312

312-
const { deployAndSignTypedData } = await import("./lib/signing.js");
313-
return deployAndSignTypedData({
313+
const { smartAccountSignTypedData } = await import("./lib/signing.js");
314+
return smartAccountSignTypedData({
314315
accountContract,
315316
factoryContract: options.factoryContract,
316317
options,

0 commit comments

Comments
 (0)