Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/shaggy-ravens-kiss.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"viem": minor
---

Added zkSync Extensions.
2 changes: 1 addition & 1 deletion site/pages/op-stack/client.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const publicClient = createPublicClient({
const l1Gas = await publicClient.estimateL1Gas({/* ... */})
```

## Decorators
## Extensions

### `walletActionsL1`

Expand Down
74 changes: 74 additions & 0 deletions site/pages/zksync.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
---
description: Getting started with the zkSync in Viem
---

# Getting started with zkSync

Viem provides first-class support for the [zkSync](https://zksync.io) chain.

zkSync is a Layer-2 protocol that scales Ethereum with cutting-edge ZK tech.

## Quick Start

### 1. Set up your Client & Transport

Firstly, set up your [Client](/docs/clients/intro) with a desired [Transport](/docs/clients/intro) & [zkSync Chain](./zksync/chains.md) and extend it with zkSync EIP712 actions.

```ts twoslash
import 'viem/window'
// ---cut---
import { createWalletClient, custom } from 'viem'
import { zkSync } from 'viem/chains'
import { eip712WalletActions } from 'viem/zksync'

const walletClient = createWalletClient({ // [!code hl]
chain: zkSync, // [!code hl]
transport: custom(window.ethereum!), // [!code hl]
}).extend(eip712WalletActions()) // [!code hl]
```

### 2. Use Actions

Now that you have a Client set up, you can [send a transaction](./zksync/actions/sendTransaction.md) on zkSync using a [paymaster](https://docs.zksync.io/build/developer-reference/account-abstraction.html#paymasters)!

```ts twoslash
import 'viem/window'
import { createWalletClient, custom } from 'viem'
import { zkSync } from 'viem/chains'
import { eip712WalletActions } from 'viem/zksync'

const walletClient = createWalletClient({
chain: zkSync,
transport: custom(window.ethereum!),
}).extend(eip712WalletActions())
// ---cut---
const hash = await walletClient.sendTransaction({
account: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
value: 1000000000000000000n,
paymaster: '0xFD9aE5ebB0F6656f4b77a0E99dCbc5138d54b0BA',
paymasterInput: '0x123abc...'
})
```

...and even write to contracts:

```ts twoslash
import 'viem/window'
import { createWalletClient, custom, parseAbi } from 'viem'
import { zkSync } from 'viem/chains'
import { eip712WalletActions } from 'viem/zksync'

const walletClient = createWalletClient({
account: '0x',
chain: zkSync,
transport: custom(window.ethereum!),
}).extend(eip712WalletActions())
// ---cut---
const hash = await walletClient.writeContract({
address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
abi: parseAbi(['function mint(uint32 tokenId) nonpayable']),
functionName: 'mint',
args: [69420],
})
```
291 changes: 291 additions & 0 deletions site/pages/zksync/actions/sendTransaction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,291 @@
---
description: Creates, signs, and sends a new transaction to the network, with EIP712 transaction support.
---

# sendTransaction

Creates, signs, and sends a new transaction to the network, with EIP712 transaction support.

## Usage

:::code-group

```ts [example.ts]
import { account, walletClient } from './config'

const hash = await walletClient.sendTransaction({ // [!code focus:99]
account,
to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
value: 1000000000000000000n
})
// '0x...'
```

```ts [config.ts]
import { createWalletClient, custom } from 'viem'
import { privateKeyToAccount } from 'viem/accounts'
import { zksync } from 'viem/chains'
import { eip712Actions } from 'viem/zksync'

export const walletClient = createWalletClient({
chain: zksync,
transport: custom(window.ethereum)
}).extend(eip712WalletActions())

// JSON-RPC Account
export const [account] = await walletClient.getAddresses()
// Local Account
export const account = privateKeyToAccount(...)
```

:::

### Account Hoisting

If you do not wish to pass an `account` to every `sendTransaction`, you can also hoist the Account on the Wallet Client (see `config.ts`).

[Learn more](/docs/clients/wallet#account).

:::code-group

```ts [example.ts]
import { walletClient } from './config'

const hash = await walletClient.sendTransaction({ // [!code focus:99]
to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
value: 1000000000000000000n
})
// '0x...'
```

```ts [config.ts (JSON-RPC Account)]
import { createWalletClient, custom } from 'viem'
import { eip712Actions } from 'viem/zksync'

// Retrieve Account from an EIP-712 Provider. // [!code focus]
const [account] = await window.ethereum.request({ // [!code focus]
method: 'eth_requestAccounts' // [!code focus]
}) // [!code focus]

export const walletClient = createWalletClient({
account,
transport: custom(window.ethereum) // [!code focus]
}).extend(eip712WalletActions())
```

```ts [config.ts (Local Account)]
import { createWalletClient, custom } from 'viem'
import { privateKeyToAccount } from 'viem/accounts'
import { eip712Actions } from 'viem/zksync'

export const walletClient = createWalletClient({
account: privateKeyToAccount('0x...'), // [!code focus]
transport: custom(window.ethereum)
}).extend(eip712WalletActions())
```

:::

## Returns

[`Hash`](/docs/glossary/types#hash)

The [Transaction](/docs/glossary/terms#transaction) hash.

## Parameters

### account

- **Type:** `Account | Address`

The Account to send the transaction from.

Accepts a [JSON-RPC Account](/docs/clients/wallet#json-rpc-accounts) or [Local Account (Private Key, etc)](/docs/clients/wallet#local-accounts-private-key-mnemonic-etc).

```ts
const hash = await walletClient.sendTransaction({
account: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266', // [!code focus]
to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
value: 1000000000000000000n
})
```

### to

- **Type:** `0x${string}`

The transaction recipient or contract address.

```ts
const hash = await walletClient.sendTransaction({
account,
to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8', // [!code focus]
value: 1000000000000000000n,
nonce: 69
})
```

### accessList (optional)

- **Type:** [`AccessList`](/docs/glossary/types#accesslist)

The access list.

```ts
const hash = await walletClient.sendTransaction({
accessList: [ // [!code focus:6]
{
address: '0x1',
storageKeys: ['0x1'],
},
],
account,
to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
})
```

### chain (optional)

- **Type:** [`Chain`](/docs/glossary/types#chain)
- **Default:** `walletClient.chain`

The target chain. If there is a mismatch between the wallet's current chain & the target chain, an error will be thrown.

The chain is also used to infer its request type (e.g. the Celo chain has a `gatewayFee` that you can pass through to `sendTransaction`).

```ts
import { zksync } from 'viem/chains' // [!code focus]

const hash = await walletClient.sendTransaction({
chain: zksync, // [!code focus]
account,
to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
value: 1000000000000000000n
})
```

### data (optional)

- **Type:** `0x${string}`

A contract hashed method call with encoded args.

```ts
const hash = await walletClient.sendTransaction({
data: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', // [!code focus]
account,
to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
value: 1000000000000000000n
})
```

### gasPrice (optional)

- **Type:** `bigint`

The price (in wei) to pay per gas. Only applies to [Legacy Transactions](/docs/glossary/terms#legacy-transaction).

```ts
const hash = await walletClient.sendTransaction({
account,
gasPrice: parseGwei('20'), // [!code focus]
to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
value: 1000000000000000000n
})
```

### nonce (optional)

- **Type:** `number`

Unique number identifying this transaction.

```ts
const hash = await walletClient.sendTransaction({
account,
to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
value: 1000000000000000000n,
nonce: 69 // [!code focus]
})
```

### value (optional)

- **Type:** `bigint`

Value in wei sent with this transaction.

```ts
const hash = await walletClient.sendTransaction({
account,
to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
value: parseEther('1'), // [!code focus]
nonce: 69
})
```

### gasPerPubdata (optional)

- **Type:** `bigint`

The amount of gas for publishing one byte of data on Ethereum.

```ts
const hash = await walletClient.sendTransaction({
account,
to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
gasPerPubdata: 50000, // [!code focus]
nonce: 69,
value: 1000000000000000000n
})
```

### factoryDeps (optional)

- **Type:** `[0x${string}]`

Contains bytecode of the deployed contract.

```ts
const hash = await walletClient.sendTransaction({
account,
to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
factoryDeps: ['0xcde...'], // [!code focus]
nonce: 69,
value: 1000000000000000000n
})
```

### paymaster (optional)

- **Type:** `Account | Address`

Address of the paymaster account that will pay the fees. The `paymasterInput` field is required with this one.

```ts
const hash = await walletClient.sendTransaction({
account,
to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
paymaster: '0x4B5DF730c2e6b28E17013A1485E5d9BC41Efe021', // [!code focus]
paymasterInput: '0x8c5a...' // [!code focus]
nonce: 69,
value: 1000000000000000000n
})
```

### paymasterInput (optional)

- **Type:** `0x${string}`

Input data to the paymaster. The `paymaster` field is required with this one.

```ts
const hash = await walletClient.sendTransaction({
account,
to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
paymaster: '0x4B5DF730c2e6b28E17013A1485E5d9BC41Efe021', // [!code focus]
paymasterInput: '0x8c5a...' // [!code focus]
nonce: 69,
value: 1000000000000000000n
})
```
Loading