Skip to content

Commit

Permalink
feat: signTransaction, sendRawTransaction, `prepareTransactionReq…
Browse files Browse the repository at this point in the history
…uest` (#1058)

* feat: signTranasction, prepareTransactionRequest, sendRawTransaction actions

* refactor

* coverage

* docs

* changeset

* docs
  • Loading branch information
jxom authored Aug 27, 2023
1 parent 3478564 commit 533b590
Show file tree
Hide file tree
Showing 45 changed files with 2,153 additions and 244 deletions.
5 changes: 5 additions & 0 deletions .changeset/brave-dryers-hope.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"viem": minor
---

Added `prepareTransactionRequest`, `signTransaction`, and `sendRawTransaction`.
18 changes: 17 additions & 1 deletion site/.vitepress/sidebar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,10 @@ export const sidebar: DefaultTheme.Sidebar = {
text: 'Transaction',
items: [
{ text: 'call', link: '/docs/actions/public/call' },
{
text: 'prepareTransactionRequest',
link: '/docs/actions/public/prepareTransactionRequest',
},
{
text: 'getTransaction',
link: '/docs/actions/public/getTransaction',
Expand All @@ -184,6 +188,10 @@ export const sidebar: DefaultTheme.Sidebar = {
text: 'getTransactionReceipt',
link: '/docs/actions/public/getTransactionReceipt',
},
{
text: 'sendRawTransaction',
link: '/docs/actions/public/sendRawTransaction',
},
{
text: 'waitForTransactionReceipt',
link: '/docs/actions/public/waitForTransactionReceipt',
Expand Down Expand Up @@ -265,12 +273,20 @@ export const sidebar: DefaultTheme.Sidebar = {
{
text: 'Transaction',
items: [
{
text: 'prepareTransactionRequest',
link: '/docs/actions/wallet/prepareTransactionRequest',
},
{
text: 'sendRawTransaction',
link: '/docs/actions/wallet/sendRawTransaction',
},
{
text: 'sendTransaction',
link: '/docs/actions/wallet/sendTransaction',
},
{
text: 'signTransaction 🚧',
text: 'signTransaction',
link: '/docs/actions/wallet/signTransaction',
},
],
Expand Down
289 changes: 289 additions & 0 deletions site/docs/actions/wallet/prepareTransactionRequest.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,289 @@
---
head:
- - meta
- property: og:title
content: prepareTransactionRequest
- - meta
- name: description
content: Prepares a transaction request for signing.
- - meta
- property: og:description
content: Prepares a transaction request for signing.

---

# prepareTransactionRequest

Prepares a transaction request for signing by populating a nonce, gas limit, fee values, and a transaction type.

## Usage

::: code-group

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

const request = await walletClient.prepareTransactionRequest({ // [!code focus:16]
account,
to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
value: 1000000000000000000n
})
/**
* {
* account: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
* to: '0x70997970C51812dc3A010C7d01b50e0d17dc79C8',
* maxFeePerGas: 150000000000n,
* maxPriorityFeePerGas: 1000000000n,
* nonce: 69,
* type: 'eip1559',
* value: 1000000000000000000n
* }
*/

const signature = await walletClient.signTransaction(request)
const hash = await walletClient.sendRawTransaction(signature)
```

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

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

// 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 `prepareTransactionRequest`, you can also hoist the Account on the Wallet Client (see `config.ts`).

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

::: code-group

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

const request = await walletClient.prepareTransactionRequest({ // [!code focus:16]
to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
value: 1000000000000000000n
})
/**
* {
* account: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
* to: '0x70997970C51812dc3A010C7d01b50e0d17dc79C8',
* maxFeePerGas: 150000000000n,
* maxPriorityFeePerGas: 1000000000n,
* nonce: 69,
* type: 'eip1559',
* value: 1000000000000000000n
* }
*/

const signature = await walletClient.signTransaction(request)
const hash = await walletClient.sendRawTransaction(signature)
```

```ts {4-6,9} [config.ts (JSON-RPC Account)]
import { createWalletClient, custom } from 'viem'

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

export const walletClient = createWalletClient({
account,
transport: custom(window.ethereum)
})
```

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

export const walletClient = createWalletClient({
account: privateKeyToAccount('0x...'),
transport: custom(window.ethereum)
})
```

:::

## Returns

[`TransactionRequest`](/docs/glossary/types#transactionrequest)

The transaction request.

## 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 request = await walletClient.prepareSendTransaction({
account: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266', // [!code focus]
to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
value: 1000000000000000000n
})
```

### to

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

The transaction recipient or contract address.

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

### accessList (optional)

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

The access list.

```ts
const request = await publicClient.prepareSendTransaction({
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 `prepareSendTransaction`).

```ts
import { optimism } from 'viem/chains' // [!code focus]
const request = await walletClient.prepareSendTransaction({
chain: optimism, // [!code focus]
account,
to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
value: 1000000000000000000n
})
```

### data (optional)

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

A contract hashed method call with encoded args.

```ts
const request = await walletClient.prepareSendTransaction({
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 request = await walletClient.prepareSendTransaction({
account,
gasPrice: parseGwei('20'), // [!code focus]
to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
value: parseEther('1')
})
```

### maxFeePerGas (optional)

- **Type:** `bigint`

Total fee per gas (in wei), inclusive of `maxPriorityFeePerGas`. Only applies to [EIP-1559 Transactions](/docs/glossary/terms#eip-1559-transaction)

```ts
const request = await walletClient.prepareSendTransaction({
account,
maxFeePerGas: parseGwei('20'), // [!code focus]
to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
value: parseEther('1')
})
```

### maxPriorityFeePerGas (optional)

- **Type:** `bigint`

Max priority fee per gas (in wei). Only applies to [EIP-1559 Transactions](/docs/glossary/terms#eip-1559-transaction)

```ts
const request = await walletClient.prepareSendTransaction({
account,
maxFeePerGas: parseGwei('20'),
maxPriorityFeePerGas: parseGwei('2'), // [!code focus]
to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
value: parseEther('1')
})
```

### nonce (optional)

- **Type:** `number`

Unique number identifying this transaction.

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

### value (optional)

- **Type:** `bigint`

Value in wei sent with this transaction.

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

1 comment on commit 533b590

@vercel
Copy link

@vercel vercel bot commented on 533b590 Aug 27, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.