Turnkey
Upgrade existing Turnkey wallets to Smart Wallets to enable gasless transactions, batching, and more in under 10 minutes. Keep Turnkey for key management, no wallet migration needed. Add battle-tested transaction infrastructure using EIP-7702 to upgrade EOAs to Smart Wallets:
- #1 gas abstraction infrastructure on the market
- 370M+ sponsored transactions
- 99.9% SLAs
- Trusted by Worldcoin, JP Morgan, Gensyn, and more
Don’t have a wallet set up yet? Start with the Smart Wallet Quickstart to create one in minutes.
JavaScript
Setup
Use Turnkey’s @turnkey/sdk-server package with Smart Wallets infrastructure in a server environment.
Installation
Prerequisites: Get your keys
- Alchemy API Key:
- Go to the dashboard
- Create or select an app and copy the API key
- Gas sponsorship Policy ID:
- Create a gas sponsorship policy in the dashboard and copy its Policy ID
- Turnkey Credentials:
- Go to the Turnkey Dashboard
- Create or select an organization and copy the Organization ID
- Create an API key pair and copy the API Public Key and Private Key
- Create or import a private key and copy the Private Key ID (UUID)
- Note the Ethereum address associated with that private key
Both the Smart Wallets configuration and the gas sponsorship policy must be linked to the application behind your API key for sponsorship to work.
Create Smart Wallet Client from Turnkey
Create a helper function that converts a Turnkey wallet into an Alchemy Smart Wallet client:
import { class WalletClientSignerRepresents a wallet client signer for smart accounts, providing methods to get the address, sign messages, sign typed data, and sign 7702 authorizations.
WalletClientSigner } from "@aa-sdk/core";
import { function alchemy(config: AlchemyTransportConfig): AlchemyTransportCreates an Alchemy transport with the specified configuration options. When sending all traffic to Alchemy, you must pass in one of rpcUrl, apiKey, or jwt. If you want to send Bundler and Paymaster traffic to Alchemy and Node traffic to a different RPC, you must pass in alchemyConnection and nodeRpcUrl.
alchemy, const baseSepolia: ChainbaseSepolia } from "@account-kit/infra";
import { function createSmartWalletClient<TAccount extends Address | undefined = undefined>(params: SmartWalletClientParams<TAccount>): SmartWalletClient<TAccount>Creates a smart wallet client that can be used to interact with a smart account.
createSmartWalletClient } from "@account-kit/wallet-client";
import { class TurnkeyTurnkey } from "@turnkey/sdk-server";
import { function createAccount(input: {
client: TurnkeyClient | TurnkeyBrowserClient | TurnkeyServerClient;
organizationId: string;
signWith: string;
ethereumAddress?: string;
}): Promise<LocalAccount>createAccount } from "@turnkey/viem";
import { function createWalletClient<transport extends Transport, chain extends Chain | undefined = undefined, accountOrAddress extends Account | Address | undefined = undefined, rpcSchema extends RpcSchema | undefined = undefined>(parameters: WalletClientConfig<transport, chain, accountOrAddress, rpcSchema>): WalletClient<transport, chain, ParseAccount<accountOrAddress>, rpcSchema>Creates a Wallet Client with a given Transport configured for a Chain.
Docs: https://viem.sh/docs/clients/wallet
A Wallet Client is an interface to interact with Ethereum Account(s) and provides the ability to retrieve accounts, execute transactions, sign messages, etc. through Wallet Actions.
The Wallet Client supports signing over:
JSON-RPC Accounts (e.g. Browser Extension Wallets, WalletConnect, etc).
Local Accounts (e.g. private key/mnemonic wallets).
createWalletClient } from "viem";
const const ALCHEMY_API_KEY: "your-alchemy-api-key"ALCHEMY_API_KEY = "your-alchemy-api-key";
const const ALCHEMY_GAS_POLICY_ID: "your-gas-policy-id"ALCHEMY_GAS_POLICY_ID = "your-gas-policy-id";
const const TURNKEY_ORGANIZATION_ID: "your-turnkey-org-id"TURNKEY_ORGANIZATION_ID = "your-turnkey-org-id";
const const TURNKEY_API_PRIVATE_KEY: "your-turnkey-api-private-key"TURNKEY_API_PRIVATE_KEY = "your-turnkey-api-private-key";
const const TURNKEY_API_PUBLIC_KEY: "your-turnkey-api-public-key"TURNKEY_API_PUBLIC_KEY = "your-turnkey-api-public-key";
async function function createTurnkeySmartWalletClient({ privateKeyId, walletAddress, }: {
privateKeyId: any;
walletAddress: any;
}): Promise<SmartWalletClient<undefined>>createTurnkeySmartWalletClient({
privateKeyId: anyprivateKeyId,
walletAddress: anywalletAddress,
}) {
// Initialize Turnkey SDK
const const turnkey: Turnkeyturnkey = new new Turnkey(config: TurnkeySDKServerConfig): TurnkeyTurnkey({
TurnkeySDKServerConfig.defaultOrganizationId: stringdefaultOrganizationId: const TURNKEY_ORGANIZATION_ID: "your-turnkey-org-id"TURNKEY_ORGANIZATION_ID,
TurnkeySDKServerConfig.apiBaseUrl: stringapiBaseUrl: "https://api.turnkey.com",
TurnkeySDKServerConfig.apiPrivateKey: stringapiPrivateKey: const TURNKEY_API_PRIVATE_KEY: "your-turnkey-api-private-key"TURNKEY_API_PRIVATE_KEY,
TurnkeySDKServerConfig.apiPublicKey: stringapiPublicKey: const TURNKEY_API_PUBLIC_KEY: "your-turnkey-api-public-key"TURNKEY_API_PUBLIC_KEY,
});
// Create a viem account using Turnkey's signing capabilities
const const baseTurnkeyAccount: {
address: Address;
nonceManager?: NonceManager | undefined;
sign?: ((parameters: {
hash: Hash;
}) => Promise<Hex>) | undefined | undefined;
signAuthorization?: ((parameters: AuthorizationRequest) => Promise<SignAuthorizationReturnType>) | undefined | undefined;
signMessage: ({ message }: {
message: SignableMessage;
}) => Promise<Hex>;
... 4 more ...;
type: "local";
}baseTurnkeyAccount = await function createAccount(input: {
client: TurnkeyClient | TurnkeyBrowserClient | TurnkeyServerClient;
organizationId: string;
signWith: string;
ethereumAddress?: string;
}): Promise<LocalAccount>createAccount({
client: TurnkeyClient | TurnkeyBrowserClient | TurnkeyServerClientclient: const turnkey: Turnkeyturnkey.TurnkeyServerSDK.apiClient: (apiCredentials?: ApiCredentials) => TurnkeyApiClientapiClient(),
organizationId: stringorganizationId: const TURNKEY_ORGANIZATION_ID: "your-turnkey-org-id"TURNKEY_ORGANIZATION_ID,
signWith: stringsignWith: privateKeyId: anyprivateKeyId,
ethereumAddress?: string | undefinedethereumAddress: walletAddress: anywalletAddress,
});
// Wrap the account to fix the double 0x prefix bug in @turnkey/viem 0.14.8
const const turnkeyAccount: {
signAuthorization: (authorization: any) => Promise<{
r: string;
s: string;
address: Address;
chainId: number;
nonce: number;
v: bigint;
yParity?: undefined;
} | {
r: string;
s: string;
address: Address;
chainId: number;
nonce: number;
v: bigint;
yParity?: number | undefined;
} | {
r: string;
s: string;
address: Address;
chainId: number;
nonce: number;
v?: bigint | undefined;
yParity: number;
}>;
address: Address;
nonceManager?: NonceManager | undefined;
sign?: ((parameters: {
hash: Hash;
}) => Promise<Hex>) | undefined | undefined;
... 5 more ...;
type: "local";
}turnkeyAccount = {
...const baseTurnkeyAccount: {
address: Address;
nonceManager?: NonceManager | undefined;
sign?: ((parameters: {
hash: Hash;
}) => Promise<Hex>) | undefined | undefined;
signAuthorization?: ((parameters: AuthorizationRequest) => Promise<SignAuthorizationReturnType>) | undefined | undefined;
signMessage: ({ message }: {
message: SignableMessage;
}) => Promise<Hex>;
... 4 more ...;
type: "local";
}baseTurnkeyAccount,
signAuthorization: (authorization: any) => Promise<{
r: string;
s: string;
address: Address;
chainId: number;
nonce: number;
v: bigint;
yParity?: undefined;
} | {
r: string;
s: string;
address: Address;
chainId: number;
nonce: number;
v: bigint;
yParity?: number | undefined;
} | {
r: string;
s: string;
address: Address;
chainId: number;
nonce: number;
v?: bigint | undefined;
yParity: number;
}>signAuthorization: async (authorization: anyauthorization) => {
if (!const baseTurnkeyAccount: {
address: Address;
nonceManager?: NonceManager | undefined;
sign?: ((parameters: {
hash: Hash;
}) => Promise<Hex>) | undefined | undefined;
signAuthorization?: ((parameters: AuthorizationRequest) => Promise<SignAuthorizationReturnType>) | undefined | undefined;
signMessage: ({ message }: {
message: SignableMessage;
}) => Promise<Hex>;
... 4 more ...;
type: "local";
}baseTurnkeyAccount.signAuthorization?: ((parameters: AuthorizationRequest) => Promise<SignAuthorizationReturnType>) | undefinedsignAuthorization) {
throw new var Error: ErrorConstructor
new (message?: string) => ErrorError("signAuthorization not available on Turnkey account");
}
const const result: SignAuthorizationReturnTyperesult = await const baseTurnkeyAccount: {
address: Address;
nonceManager?: NonceManager | undefined;
sign?: ((parameters: {
hash: Hash;
}) => Promise<Hex>) | undefined | undefined;
signAuthorization?: ((parameters: AuthorizationRequest) => Promise<SignAuthorizationReturnType>) | undefined | undefined;
signMessage: ({ message }: {
message: SignableMessage;
}) => Promise<Hex>;
... 4 more ...;
type: "local";
}baseTurnkeyAccount.signAuthorization?: (parameters: AuthorizationRequest) => Promise<SignAuthorizationReturnType>signAuthorization(authorization: anyauthorization);
// Strip the extra 0x prefix if present
return {
...const result: SignAuthorizationReturnTyperesult,
r: stringr: const result: SignAuthorizationReturnTyperesult.r: `0x${string}`r.String.replace(searchValue: {
[Symbol.replace](string: string, replaceValue: string): string;
}, replaceValue: string): string (+3 overloads)Passes a string and replaceValue to the [Symbol.replace] method on searchValue. This method is expected to implement its own replacement algorithm.
replace(/^0x0x/, "0x"),
s: strings: const result: SignAuthorizationReturnTyperesult.s: `0x${string}`s.String.replace(searchValue: {
[Symbol.replace](string: string, replaceValue: string): string;
}, replaceValue: string): string (+3 overloads)Passes a string and replaceValue to the [Symbol.replace] method on searchValue. This method is expected to implement its own replacement algorithm.
replace(/^0x0x/, "0x"),
};
},
};
// Create wallet client with Turnkey account
const const walletClient: {
account: Account | {
address: `0x${string}`;
type: "json-rpc";
} | undefined;
batch?: {
multicall?: boolean | Prettify<MulticallBatchOptions> | undefined;
} | undefined;
cacheTime: number;
ccipRead?: false | {
request?: (parameters: CcipRequestParameters) => Promise<CcipRequestReturnType>;
} | undefined;
chain: Chain;
experimental_blockTag?: BlockTag | undefined;
... 34 more ...;
extend: <const client extends {
...;
} & ExactPartial<...>>(fn: (client: Client<...>) => client) => Client<...>;
}walletClient = createWalletClient<AlchemyTransport, Chain, `0x${string}` | Account | undefined, undefined>(parameters: {
account?: `0x${string}` | Account | undefined;
cacheTime?: number | undefined | undefined;
ccipRead?: {
request?: (parameters: CcipRequestParameters) => Promise<CcipRequestReturnType>;
} | false | undefined | undefined;
... 5 more ...;
rpcSchema?: undefined;
}): {
...;
}Creates a Wallet Client with a given Transport configured for a Chain.
Docs: https://viem.sh/docs/clients/wallet
A Wallet Client is an interface to interact with Ethereum Account(s) and provides the ability to retrieve accounts, execute transactions, sign messages, etc. through Wallet Actions.
The Wallet Client supports signing over:
JSON-RPC Accounts (e.g. Browser Extension Wallets, WalletConnect, etc).
Local Accounts (e.g. private key/mnemonic wallets).
createWalletClient({
account?: `0x${string}` | Account | undefinedThe Account to use for the Client. This will be used for Actions that require an account as an argument.
account: const turnkeyAccount: {
signAuthorization: (authorization: any) => Promise<{
r: string;
s: string;
address: Address;
chainId: number;
nonce: number;
v: bigint;
yParity?: undefined;
} | {
r: string;
s: string;
address: Address;
chainId: number;
nonce: number;
v: bigint;
yParity?: number | undefined;
} | {
r: string;
s: string;
address: Address;
chainId: number;
nonce: number;
v?: bigint | undefined;
yParity: number;
}>;
address: Address;
nonceManager?: NonceManager | undefined;
sign?: ((parameters: {
hash: Hash;
}) => Promise<Hex>) | undefined | undefined;
... 5 more ...;
type: "local";
}turnkeyAccount,
chain?: Chain | undefinedChain for the client.
chain: const baseSepolia: ChainbaseSepolia,
transport: AlchemyTransportThe RPC transport
transport: function alchemy(config: AlchemyTransportConfig): AlchemyTransportCreates an Alchemy transport with the specified configuration options. When sending all traffic to Alchemy, you must pass in one of rpcUrl, apiKey, or jwt. If you want to send Bundler and Paymaster traffic to Alchemy and Node traffic to a different RPC, you must pass in alchemyConnection and nodeRpcUrl.
alchemy({ apiKey: stringapiKey: const ALCHEMY_API_KEY: "your-alchemy-api-key"ALCHEMY_API_KEY }),
});
// Create signer from wallet client
const const signer: WalletClientSignersigner = new new WalletClientSigner(client: WalletClient, signerType: string): WalletClientSignerInitializes a signer with a given wallet client and signer type.
WalletClientSigner(const walletClient: {
account: Account | {
address: `0x${string}`;
type: "json-rpc";
} | undefined;
batch?: {
multicall?: boolean | Prettify<MulticallBatchOptions> | undefined;
} | undefined;
cacheTime: number;
ccipRead?: false | {
request?: (parameters: CcipRequestParameters) => Promise<CcipRequestReturnType>;
} | undefined;
chain: Chain;
experimental_blockTag?: BlockTag | undefined;
... 34 more ...;
extend: <const client extends {
...;
} & ExactPartial<...>>(fn: (client: Client<...>) => client) => Client<...>;
}walletClient, "turnkey-custom");
// Create and return the Smart Wallet client
return createSmartWalletClient<undefined>(params: SmartWalletClientParams<undefined>): SmartWalletClient<undefined>Creates a smart wallet client that can be used to interact with a smart account.
createSmartWalletClient({
chain: Chainchain: const baseSepolia: ChainbaseSepolia,
transport: AlchemyTransporttransport: function alchemy(config: AlchemyTransportConfig): AlchemyTransportCreates an Alchemy transport with the specified configuration options. When sending all traffic to Alchemy, you must pass in one of rpcUrl, apiKey, or jwt. If you want to send Bundler and Paymaster traffic to Alchemy and Node traffic to a different RPC, you must pass in alchemyConnection and nodeRpcUrl.
alchemy({ apiKey: stringapiKey: const ALCHEMY_API_KEY: "your-alchemy-api-key"ALCHEMY_API_KEY }),
signer: SmartAccountSigner<any>signer,
policyId?: string | undefinedpolicyId: const ALCHEMY_GAS_POLICY_ID: "your-gas-policy-id"ALCHEMY_GAS_POLICY_ID,
});
}Send Transactions with EIP-7702
Send gasless transactions using EIP-7702 to upgrade the Turnkey wallet to a smart wallet:
const const TURNKEY_PRIVATE_KEY_ID: "your-private-key-uuid"TURNKEY_PRIVATE_KEY_ID = "your-private-key-uuid";
const const TURNKEY_WALLET_ADDRESS: "0x..."TURNKEY_WALLET_ADDRESS = "0x...";
async function function sendTransaction(): Promise<void>sendTransaction() {
var console: ConsoleThe console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.
The module exports two specific components:
- A
Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream. * A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.
Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.
Example using the global console:
const name = 'Will Robinson'; console.warn(`Danger $name! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ```
Example using the `Console` class:
```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err);
myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson'; myConsole.warn(`Danger $name! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```
console.Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).
js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout
See util.format() for more information.
log("Wallet address:", const TURNKEY_WALLET_ADDRESS: "0x..."TURNKEY_WALLET_ADDRESS);
// Create Smart Wallet client from Turnkey wallet
const const client: anyclient = await anycreateTurnkeySmartWalletClient({
privateKeyId: stringprivateKeyId: const TURNKEY_PRIVATE_KEY_ID: "your-private-key-uuid"TURNKEY_PRIVATE_KEY_ID,
walletAddress: stringwalletAddress: const TURNKEY_WALLET_ADDRESS: "0x..."TURNKEY_WALLET_ADDRESS,
});
// Send a gasless transaction with EIP-7702
const const result: anyresult = await const client: anyclient.anysendCalls({
from: stringfrom: const TURNKEY_WALLET_ADDRESS: "0x..."TURNKEY_WALLET_ADDRESS,
calls: {
to: string;
value: string;
data: string;
}[]calls: [
{
to: stringto: "0x0000000000000000000000000000000000000000",
value: stringvalue: "0x0",
data: stringdata: "0x",
},
],
capabilities: {
eip7702Auth: boolean;
paymasterService: {
policyId: any;
};
}capabilities: {
eip7702Auth: booleaneip7702Auth: true,
paymasterService: {
policyId: any;
}paymasterService: {
policyId: anypolicyId: anyALCHEMY_GAS_POLICY_ID,
},
},
});
var console: ConsoleThe console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.
The module exports two specific components:
- A
Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream. * A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.
Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.
Example using the global console:
const name = 'Will Robinson'; console.warn(`Danger $name! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ```
Example using the `Console` class:
```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err);
myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson'; myConsole.warn(`Danger $name! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```
console.Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).
js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout
See util.format() for more information.
log("Transaction sent:", const result: anyresult.anypreparedCallIds[0]);
}Wait for Transaction Confirmation
Wait for the transaction to be confirmed onchain:
async function function sendAndWaitForTransaction(): Promise<void>sendAndWaitForTransaction() {
const const client: anyclient = await anycreateTurnkeySmartWalletClient({
privateKeyId: anyprivateKeyId: anyTURNKEY_PRIVATE_KEY_ID,
walletAddress: anywalletAddress: anyTURNKEY_WALLET_ADDRESS,
});
const const result: anyresult = await const client: anyclient.anysendCalls({
from: anyfrom: anyTURNKEY_WALLET_ADDRESS,
calls: {
to: string;
value: string;
data: string;
}[]calls: [
{
to: stringto: "0x0000000000000000000000000000000000000000",
value: stringvalue: "0x0",
data: stringdata: "0x",
},
],
capabilities: {
eip7702Auth: boolean;
paymasterService: {
policyId: any;
};
}capabilities: {
eip7702Auth: booleaneip7702Auth: true,
paymasterService: {
policyId: any;
}paymasterService: {
policyId: anypolicyId: anyALCHEMY_GAS_POLICY_ID,
},
},
});
var console: ConsoleThe console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.
The module exports two specific components:
- A
Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream. * A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.
Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.
Example using the global console:
const name = 'Will Robinson'; console.warn(`Danger $name! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ```
Example using the `Console` class:
```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err);
myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson'; myConsole.warn(`Danger $name! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```
console.Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).
js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout
See util.format() for more information.
log("Waiting for confirmation...");
// Wait for the transaction to be confirmed
const const txStatus: anytxStatus = await const client: anyclient.anywaitForCallsStatus({
id: anyid: const result: anyresult.anypreparedCallIds[0],
timeout: numbertimeout: 60_000, // 60 seconds
});
const const txnHash: anytxnHash = const txStatus: anytxStatus.anyreceipts?.[0]?.anytransactionHash;
var console: ConsoleThe console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.
The module exports two specific components:
- A
Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream. * A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.
Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.
Example using the global console:
const name = 'Will Robinson'; console.warn(`Danger $name! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ```
Example using the `Console` class:
```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err);
myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson'; myConsole.warn(`Danger $name! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```
console.Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).
js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout
See util.format() for more information.
log("Transaction confirmed!");
var console: ConsoleThe console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.
The module exports two specific components:
- A
Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream. * A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.
Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.
Example using the global console:
const name = 'Will Robinson'; console.warn(`Danger $name! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ```
Example using the `Console` class:
```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err);
myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson'; myConsole.warn(`Danger $name! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```
console.Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).
js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout
See util.format() for more information.
log("Transaction hash:", const txnHash: anytxnHash);
}Batch Multiple Transactions
Send multiple transactions in a single batch:
const const result: anyresult = await anyclient.anysendCalls({
from: anyfrom: anyTURNKEY_WALLET_ADDRESS,
calls: {
to: string;
data: string;
value: string;
}[]calls: [
{ to: stringto: "0x...", data: stringdata: "0x...", value: stringvalue: "0x0" },
{ to: stringto: "0x...", data: stringdata: "0x...", value: stringvalue: "0x0" },
{ to: stringto: "0x...", data: stringdata: "0x...", value: stringvalue: "0x0" },
],
capabilities: {
eip7702Auth: boolean;
paymasterService: {
policyId: any;
};
}capabilities: {
eip7702Auth: booleaneip7702Auth: true,
paymasterService: {
policyId: any;
}paymasterService: {
policyId: anypolicyId: anyALCHEMY_GAS_POLICY_ID,
},
},
});Notes
- EIP-7702: Upgrades the Turnkey wallet to a smart wallet at transaction time without migration
- Gas Sponsorship: Use
paymasterServicewith your policy ID for gasless transactions - Server-Side: This example uses Turnkey’s
@turnkey/sdk-serverpackage which is designed for server environments. However, the@account-kitpackages (@account-kit/wallet-client,@account-kit/infra, etc.) can be used in any JavaScript environment including browsers, React Native, and Node.js