Skip to content

Commit

Permalink
wip: styling tweaks; subheading plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
jxom committed Oct 20, 2023
1 parent cb8df98 commit 115f2ca
Show file tree
Hide file tree
Showing 8 changed files with 332 additions and 12 deletions.
18 changes: 17 additions & 1 deletion playground/pages/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import { Example } from '../components/Example'

[Go to Viem example](./viem)

# Heading 1
[Go to Public Client example](./public-client)

# Heading 1 [This is a subheading]

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce vestibulum ante non neque convallis tempor. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nam a iaculis libero. Suspendisse bibendum placerat enim, vitae iaculis sapien tincidunt vel. Nunc nunc dui, varius eget diam vitae, sagittis rutrum ante. Vestibulum ut nulla in ante tincidunt lacinia. Suspendisse ex orci, elementum vitae enim sed, pellentesque fermentum tortor. In bibendum sapien at nisi pharetra tincidunt. Etiam eleifend lacus dictum lorem ornare euismod. Nunc ullamcorper nunc mi, ut volutpat libero gravida id. Pellentesque cursus mi id tortor convallis eleifend.

Expand Down Expand Up @@ -187,6 +189,20 @@ const client = createPublicClient({
const blockNumber = await client.getBlockNumber()
```

```ts twoslash
interface IdLabel {id: number, /* some fields */ }
interface NameLabel {name: string, /* other fields */ }
type NameOrId<T extends number | string> = T extends number ? IdLabel : NameLabel;
// This comment should not be included

// ---cut---
function createLabel<T extends number | string>(idOrName: T): NameOrId<T> {
throw "unimplemented"
}

let a = createLabel("typescript");
```

## Code group

:::code-group
Expand Down
229 changes: 229 additions & 0 deletions playground/pages/public-client.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
# Public Client

A Public Client is an interface to "public" [JSON-RPC API](https://ethereum.org/en/developers/docs/apis/json-rpc/) methods such as retrieving block numbers, transactions, reading from smart contracts, etc through [Public Actions](/docs/actions/public/introduction).

The `createPublicClient` function sets up a Public Client with a given [Transport](/docs/clients/intro) configured for a [Chain](/docs/clients/chains).

## Import

```ts
import { createPublicClient } from 'viem'
```

## Usage

Initialize a Client with your desired [Chain](/docs/clients/chains) (e.g. `mainnet`) and [Transport](/docs/clients/intro) (e.g. `http`).

```ts
import { createPublicClient, http } from 'viem'
import { mainnet } from 'viem/chains'

const client = createPublicClient({
chain: mainnet,
transport: http()
})
```

Then you can consume [Public Actions](/docs/actions/public/introduction):

```ts
const blockNumber = await client.getBlockNumber() // [!code focus:10]
```

## Optimization

The Public Client also supports [`eth_call` Aggregation](#multicall) for improved performance.

### `eth_call` Aggregation (via Multicall)

The Public Client supports the aggregation of `eth_call` requests into a single multicall (`aggregate3`) request.

This means for every Action that utilizes an `eth_call` request (ie. `readContract`), the Public Client will batch the requests (over a timed period) and send it to the RPC Provider in a single multicall request. This can dramatically improve network performance, and decrease the amount of [Compute Units (CU)](https://docs.alchemy.com/reference/compute-units) used by RPC Providers like Alchemy, Infura, etc.

The Public Client schedules the aggregation of `eth_call` requests over a given time period. By default, it executes the batch request at the end of the current [JavaScript message queue](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Event_loop#queue) (a [zero delay](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Event_loop#zero_delays)), however, consumers can specify a custom `wait` period (in ms).

You can enable `eth_call` aggregation by setting the `batch.multicall` flag to `true`:

```ts
const client = createPublicClient({
batch: {
multicall: true, // [!code focus]
},
chain: mainnet,
transport: http(),
})
```

> You can also [customize the `multicall` options](#batch-multicall-batchsize-optional).
Now, when you start to utilize `readContract` Actions, the Public Client will batch and send over those requests at the end of the message queue (or custom time period) in a single `eth_call` multicall request:

```ts
const contract = getContract({ address, abi })

// The below will send a single request to the RPC Provider.
const [name, totalSupply, symbol, tokenUri, balance] = await Promise.all([
contract.read.name(),
contract.read.totalSupply(),
contract.read.symbol(),
contract.read.tokenURI([420n]),
contract.read.balanceOf([address]),
])
```

> Read more on [Contract Instances](/docs/contract/getContract.html).
## Parameters

### transport

- **Type:** [Transport](/docs/glossary/types#transport)

The [Transport](/docs/clients/intro) of the Public Client.

```ts
const client = createPublicClient({
chain: mainnet,
transport: http(), // [!code focus]
})
```

### chain (optional)

- **Type:** [Chain](/docs/glossary/types#chain)

The [Chain](/docs/clients/chains) of the Public Client.

```ts
const client = createPublicClient({
chain: mainnet, // [!code focus]
transport: http(),
})
```

### batch (optional)

Flags for batch settings.

### batch.multicall (optional)

- **Type:** `boolean | MulticallBatchOptions`
- **Default:** `false`

Toggle to enable `eth_call` multicall aggregation.

```ts
const client = createPublicClient({
batch: {
multicall: true, // [!code focus]
},
chain: mainnet,
transport: http(),
})
```

### batch.multicall.batchSize (optional)

- **Type:** `number`
- **Default:** `1_024`

The maximum size (in bytes) for each multicall (`aggregate3`) calldata chunk.

> Note: Some RPC Providers limit the amount of calldata that can be sent in a single request. It is best to check with your RPC Provider to see if there are any calldata size limits to `eth_call` requests.
```ts
const client = createPublicClient({
batch: {
multicall: {
batchSize: 512, // [!code focus]
},
},
chain: mainnet,
transport: http(),
})
```

### batch.multicall.wait (optional)

- **Type:** `number`
- **Default:** `0` ([zero delay](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Event_loop#zero_delays))

The maximum number of milliseconds to wait before sending a batch.

```ts
const client = createPublicClient({
batch: {
multicall: {
wait: 16, // [!code focus]
},
},
chain: mainnet,
transport: http(),
})
```

### cacheTime (optional)

- **Type:** `number`
- **Default:** `client.pollingInterval`

Time (in ms) that cached data will remain in memory.

```ts
const client = createPublicClient({
cacheTime: 10_000, // [!code focus]
chain: mainnet,
transport: http(),
})
```

### key (optional)

- **Type:** `string`
- **Default:** `"public"`

A key for the Client.

```ts
const client = createPublicClient({
chain: mainnet,
key: 'public', // [!code focus]
transport: http(),
})
```

### name (optional)

- **Type:** `string`
- **Default:** `"Public Client"`

A name for the Client.

```ts
const client = createPublicClient({
chain: mainnet,
name: 'Public Client', // [!code focus]
transport: http(),
})
```

### pollingInterval (optional)

- **Type:** `number`
- **Default:** `4_000`

Frequency (in ms) for polling enabled Actions.

```ts
const client = createPublicClient({
chain: mainnet,
pollingInterval: 10_000, // [!code focus]
transport: http(),
})
```

## Live Example

Check out the usage of `createPublicClient` in the live [Public Client Example](https://stackblitz.com/github/wagmi-dev/viem/tree/main/examples/clients_public-client) below.

<iframe frameborder="0" width="100%" height="500px" src="https://stackblitz.com/github/wagmi-dev/viem/tree/main/examples/clients_public-client?embed=1&file=index.ts&hideNavigation=1&hideDevTools=true&terminalHeight=0&ctl=1"></iframe>
2 changes: 1 addition & 1 deletion playground/pages/viem.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ title: Viem Example
---


# Getting Started
# Getting Started [How to get up and running with Viem]

## Overview

Expand Down
3 changes: 2 additions & 1 deletion src/app/components/A.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ export function A(
props: React.DetailedHTMLProps<React.AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>,
) {
const { href } = props
if (href?.match(/^#/)) return <a {...props} />
if (href?.match(/^www|https?/)) return <a {...props} target="_blank" rel="noopener noreferrer" />
const [before, after] = props.href!.split('#')
const to = `${before}.html${after || ''}`
const to = `${before ? `${before}.html` : ''}${after ? `#${after}` : ''}`
return <Link {...(props as LinkProps)} to={to} />
}
49 changes: 49 additions & 0 deletions src/remark-plugins/subheading.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/// <reference types="mdast-util-to-hast" />
/// <reference types="mdast-util-directive" />

import type { Root } from 'mdast'
import { visit } from 'unist-util-visit'

export function remarkSubheading() {
return (tree: Root) => {
visit(tree, 'heading', (node, index, parent) => {
if (!index) return
if (node.depth !== 1) return
if (node.children.length === 0) return

const subheadingRegex = / \[(.*)\]$/
const subheadingChild = node.children.find(
(child) =>
'value' in child && typeof child.value === 'string' && child.value.match(subheadingRegex),
) as any
const [match, subheading] = subheadingChild?.value?.match(subheadingRegex) ?? []
if (subheadingChild) subheadingChild.value = subheadingChild?.value?.replace(match, '')

// remove original heading
parent?.children.splice(index, 1)

const header = {
type: 'paragraph',
data: {
hName: 'header',
},
children: [
node,
subheading
? {
type: 'paragraph',
children: [{ type: 'text', value: subheading }],
data: {
hName: 'div',
hProperties: {
role: 'doc-subtitle',
},
},
}
: undefined,
].filter(Boolean),
} as any
parent?.children.splice(index, 0, header)
})
}
}
Loading

0 comments on commit 115f2ca

Please sign in to comment.