> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dynamic.xyz/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# zkSync

<Card title="Recommended: JavaScript SDK with React Hooks" icon="react" color="#4779FE">
  For new React apps, we recommend the JavaScript SDK with React Hooks (`@dynamic-labs-sdk/react-hooks`) instead of the legacy React SDK documented here. The JS SDK comes with many benefits such as a much smaller bundle size and other optimizations. Use the [React quickstart (JavaScript SDK)](/javascript/reference/react-quickstart) to get started.
</Card>

<Note>This guide is currently React only.</Note>

Introducing account abstraction for zkSync enabled chains. This guide will walk you through the setup of zkSync account abstraction with comprehensive method references and transaction examples.

## Dashboard Setup

<Steps>
  <Step title="Enable zkSync Chain">
    Navigate to [the EVM section of your Dynamic Dashboard](https://app.dynamic.xyz/dashboard/chains-and-networks#evm) and toggle on a zkSync enabled chain, then click **Save**.

    <Tip>
      When using zkSync with global wallets, ensure that the zkSync enabled chain is the only one selected.
    </Tip>
  </Step>

  <Step title="Configure Account Abstraction">
    Go to [the Account Abstraction section](https://app.dynamic.xyz/dashboard/configurations#accountabstraction) and:

    1. Enter the optional `factoryAddress`, `paymasterAddress` and `sessionKeyAddress` (if available)
    2. Save the settings
    3. Enable the toggle next to the **ZkSync** section

    <Warning>
      Make sure to test your configuration on testnet before deploying to mainnet.
    </Warning>
  </Step>

  <Step title="Configure Smart Contract Wallet Distribution">
    Choose your SCW distribution strategy:

    **Wallet Level Configuration:**

    * **All Wallets**: Issue SCWs to all connected wallets (requires custom UI handling)
    * **Embedded Wallets Only**: Issue SCWs only to Dynamic's embedded wallets

    **User Level Configuration:**

    * **All Users**: Issue SCWs to all users (existing users get SCWs on next login)
    * **New Users Only**: Issue SCWs only to newly registered users

    <Info>
      For most applications, we recommend starting with **Embedded Wallets Only** and **New Users Only** to ensure a smooth rollout.
    </Info>
  </Step>

  <Step title="Configure Wallet Display Options">
    Choose how users interact with their wallets:

    * **Show Smart Wallet Only**: Users interact directly with the smart wallet
    * **Show Smart Wallet & Signer**: Users can switch between the smart wallet and signer
  </Step>
</Steps>

## Installation & Setup

Install the required packages:

```bash theme={"system"}
npm install @dynamic-labs/sdk-react-core @dynamic-labs/ethereum @dynamic-labs/ethereum-aa-zksync
```

Then configure your application:

```jsx theme={"system"}
import { DynamicContextProvider, DynamicWidget } from "@dynamic-labs/sdk-react-core";
import { EthereumWalletConnectors } from "@dynamic-labs/ethereum";
import { ZkSyncSmartWalletConnectors } from "@dynamic-labs/ethereum-aa-zksync";

const App = () => (
  <DynamicContextProvider
    settings={{
      environmentId: "YOUR_ENVIRONMENT_ID",
      walletConnectors: [
        EthereumWalletConnectors,
        ZkSyncSmartWalletConnectors
      ],
    }}
  >
    <DynamicWidget />
  </DynamicContextProvider>
);

export default App;
```

<Tip>
  Use the latest compatible versions of the Dynamic SDK and provider packages. Grab your environment ID from the Dynamic Dashboard under Developer > SDK & API Keys.
</Tip>

## ZKsync Connector Methods

The ZKsync connector provides several key methods for interacting with smart accounts:

### getAccountAbstractionProvider

Returns a smart account client or session client based on the provided parameters. This method is the primary way to interact with zkSync smart accounts.

```jsx theme={"system"}
import { isZKsyncConnector } from '@dynamic-labs/ethereum-aa-zksync';

// Get the smart account provider
const provider = wallet.connector.getAccountAbstractionProvider();

// Get a session-based provider
const sessionProvider = wallet.connector.getAccountAbstractionProvider({
  sessionId: 'your-session-id',
  origin: 'https://your-app.com'
});
```

### getWalletClient

Creates a wallet client with custom transport for RPC methods.

```jsx theme={"system"}
const walletClient = await wallet.getWalletClient(chainId.toString());
```

## Transaction Examples

### Basic Transaction

Send a simple transaction using the account abstraction provider:

```jsx theme={"system"}
import { isZKsyncConnector } from '@dynamic-labs/ethereum-aa-zksync';
import { useDynamicContext } from '@dynamic-labs/sdk-react-core';
import { parseEther } from 'viem';

const sendBasicTransaction = async () => {
  const { primaryWallet } = useDynamicContext();

  if (!primaryWallet?.connector || !isZKsyncConnector(primaryWallet.connector)) {
    throw new Error('ZKsync connector not found');
  }

  // Get the account abstraction provider
  const client = primaryWallet.connector.getAccountAbstractionProvider();

  if (!client) {
    throw new Error('Account abstraction client not found');
  }

  try {
    const hash = await client.sendTransaction({
      to: '0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8b6',
      value: parseEther('0.001'),
      data: '0x'
    });

    console.log('Transaction hash:', hash);
    return hash;
  } catch (error) {
    console.error('Transaction failed:', error);
    throw error;
  }
};
```

#### Create a session

Create a session in order to make transactions on the users behalf

```jsx theme={"system"}
import { isZKsyncConnector } from '@dynamic-labs/ethereum-aa-zksync';

const generateSessionConfig = () => {
  const currentTime = BigInt(Math.floor(Date.now() / 1000));
  const oneDayPeriod = BigInt(86400);
  const defaultExpiryTime = (currentTime + oneDayPeriod).toString();

  return {
    // expiration for the whole session. If not specified, defaults to 24hrs
    expiresAt: defaultExpiryTime,
    callPolicies: [],
    feeLimit: {
      limit: parseEther('1'), // maximum fees allowed to be covered during this session
      limitType: 2, // 0 = UNLIMITED, 1 = LIFETIME, 2 = ALLOWANCE
      period: defaultExpiryTime // time before the feeLimit resets
    },
    transferPolicies: [
      {
        maxValuePerUse: parseEther('10'), // maximum amount of ETH that can be sent in a single transaction
        target: '0x....', // to address for the transfer requests
        valueLimit: parseEther('10'), // maximum amount of ETH that can be sent during the period defined below
        limitType: 2, // 0 = UNLIMITED, 1 = LIFETIME, 2 = ALLOWANCE
        period: defaultExpiryTime // time before the valueLimit resets
      }
    ]
  }
}

const createSession = async () => {
  if (!primaryWallet?.connector || !isZKsyncConnector(primaryWallet.connector)) {
    throw new Error('ZKsync connector not found');
  }

  const {
    sessionId, // session hash
    expiresAt,
    session: {
      sessionConfiguration, // session configuration w/ bigints as string
      sessionKey, // registered session private key
      sessionKeyValidator // session key validator contract address
    }
   } = await primaryWallet.connector.createSession({
    sessionConfig: generateSessionConfig(),
  });

  // ...
}
```

### Session-Based Transaction

#### Send a transaction using the session client from getAccountAbstractionProvider:

```jsx theme={"system"}
import { isZKsyncConnector } from '@dynamic-labs/ethereum-aa-zksync';
import { parseEther } from 'viem';

const sendSessionTransaction = async (sessionId, origin) => {
  if (!primaryWallet?.connector || !isZKsyncConnector(primaryWallet.connector)) {
    throw new Error('ZKsync connector not found');
  }

  // Get session-based client
  const client = primaryWallet.connector.getAccountAbstractionProvider({
    sessionId,
    origin
  });

  if (!client) {
    throw new Error('Session client not found');
  }

  try {
    const hash = await client.sendTransaction({
      to: '0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8b6',
      value: parseEther('0.001'),
      data: '0x'
    });

    return hash;
  } catch (error) {
    console.error('Session transaction failed:', error);
    throw error;
  }
};
```

#### Send a transaction using the session client (w/o getAccountAbstractionProvider)

```jsx theme={"system"}
import { isZKsyncConnector } from '@dynamic-labs/ethereum-aa-zksync';
import { parseEther } from 'viem';

const sendSessionTransaction = async (sessionPrivateKey, sessionConfiguration) => {
  if (!primaryWallet?.connector || !isZKsyncConnector(primaryWallet.connector)) {
    throw new Error('ZKsync connector not found');
  }

  // Get session-based client
  const client = await primaryWallet.connector.createSessionClient(sessionPrivateKey, sessionConfiguration);

  if (!client) {
    throw new Error('Session client not found');
  }

  try {
    const hash = await client.sendTransaction({
      to: '0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8b6',
      value: parseEther('0.001'),
      data: '0x'
    });

    return hash;
  } catch (error) {
    console.error('Session transaction failed:', error);
    throw error;
  }
};
```

### Message Signing

Sign messages using the smart account:

```jsx theme={"system"}
const signMessage = async (message) => {
  if (!primaryWallet?.connector || !isZKsyncConnector(primaryWallet.connector)) {
    throw new Error('ZKsync connector not found');
  }

  const client = primaryWallet.connector.getAccountAbstractionProvider();

  if (!client) {
    throw new Error('Account abstraction client not found');
  }

  try {
    const signature = await client.signMessage({
      message: message
    });

    console.log('Message signature:', signature);
    return signature;
  } catch (error) {
    console.error('Message signing failed:', error);
    throw error;
  }
};
```
