Turnkey signer
Turnkey is a key infrastructure provider with a powerful developer API and a robust security policy engine, enabling secure and flexible key management for blockchain applications.
By integrating Turnkey with Connect 4337, you can create custodial Account Abstraction (AA) wallets, where Turnkey ensures the security of private keys while using Cometh Connect’s smart wallets to sponsor gas, batch transactions, and enhance overall dApp functionality.
Setup
To use Turnkey with Connect 4337, first create an application that integrates with Turnkey.
Refer to the Turnkey documentation site for instructions on setting up an application with the Turnkey.
For a quick start, Turnkey provides examples, available here.
Integration
After following the Turnkey documentation, you will have access to a TurnkeyClient
object as shown below that you can pass as an owner to createSafeSmartAccount
:
import { TurnkeyClient } from "@turnkey/http"
import { createAccount } from "@turnkey/viem"
// Param options here will be specific to your project. See the Turnkey docs for more info.
const turnkeyClient = new TurnkeyClient({ baseUrl: "" }, stamper)
const turnkeySigner = await createAccount({
client: turnkeyClient,
organizationId: subOrganizationId, // Your subOrganization id
signWith: signWith, // Your suborganization `signWith` param.
})
Use it with Connect 4337:
import {
createComethPaymasterClient,
createSafeSmartAccount,
createSmartAccountClient,
} from "@cometh/connect-sdk-4337";
import { type Hex, type PublicClient, createPublicClient, http } from "viem";
import { arbitrumSepolia } from "viem/chains";
const apiKey = process.env.COMETH_API_KEY;
const bundlerUrl = process.env.4337_BUNDLER_URL;
const paymasterUrl = process.env.NEXT_PUBLIC_4337_PAYMASTER_URL;
const publicClient = createPublicClient({
chain: arbitrumSepolia,
transport: http(),
cacheTime: 60_000,
batch: {
multicall: { wait: 50 },
},
}) as PublicClient;
const smartAccount = await createSafeSmartAccount({
apiKey,
signer: turnkeySigner,
chain: arbitrumSepolia,
publicClient,
smartAccountAddress //if smart account already exists
});
const walletAddress = smartAccount.address
const paymasterClient = await createComethPaymasterClient({
transport: http(paymasterUrl),
chain: arbitrumSepolia,
publicClient,
});
const smartAccountClient = createSmartAccountClient({
account: smartAccount,
chain: arbitrumSepolia,
bundlerTransport: http(bundlerUrl, {
retryCount: 5,
retryDelay: 1000,
timeout: 20_000,
}),
paymaster: paymasterClient,
userOperation: {
estimateFeesPerGas: async () => {
return await paymasterClient.getUserOperationGasPrice();
},
},
});
Last updated