Skip to content

Commit 6e75fd9

Browse files
carlosalavoliva
andauthored
feat: complete rewrite of client docs & papi 1.22 (#80)
Co-authored-by: Victor Oliva <[email protected]>
1 parent 1d5834b commit 6e75fd9

File tree

6 files changed

+299
-312
lines changed

6 files changed

+299
-312
lines changed

docs/pages/client.md

Lines changed: 190 additions & 179 deletions
Original file line numberDiff line numberDiff line change
@@ -1,185 +1,196 @@
1-
# PolkadotClient
1+
# Top-level client
22

33
`PolkadotClient` interface shapes the top-level API for `polkadot-api`. Once we get a client using `createClient` function, we'll find the following:
44

5+
## Create a client
6+
7+
In order to create a client, you only need to have a [provider](/providers).
8+
Optionally, you can pass `getMetadata` and `setMetadata` functions, useful for metadata caching. You can [find a recipe in the docs](/recipes/metadata-caching) on how to use this!
9+
10+
```ts twoslash
11+
// [!include ~/snippets/startSm.ts]
12+
import { getSmProvider } from "polkadot-api/sm-provider"
13+
const provider = getSmProvider(smoldot.addChain({ chainSpec: "" }))
14+
//---cut---
15+
import { createClient } from "polkadot-api"
16+
17+
const client = createClient(provider)
18+
```
19+
20+
## `PolkadotClient`
21+
22+
Let's dive into each part of the `PolkadotClient` interface.
23+
24+
### `getChainSpecData`
25+
26+
Type: `() => Promise<{name: string; genesisHash: string; properties: any}>{:ts}`
27+
28+
Retrieve the ChainSpecData directly as it comes from the [JSON-RPC spec](https://paritytech.github.io/json-rpc-interface-spec/api/chainSpec.html).
29+
30+
The consumer shouldn't make assumptions on this data, as it might change from session to session and it is not strictly typed.
31+
32+
### `getMetadata$`
33+
34+
Type: `(atBlock: HexString) => Observable<Uint8Array>{:ts}`
35+
36+
Retrieves the most modern version of the metadata for a given block. That is, if metadata versions 14, 15 and 16 are available, metadata version 16 will be returned.
37+
38+
The observable will emit once, and immediately complete.
39+
40+
### `getMetadata`
41+
42+
Type: `(atBlock: HexString, signal?: AbortSignal) => Promise<Uint8Array>{:ts}`
43+
44+
Retrieves the most modern version of the metadata for a given block. That is, if metadata versions 14, 15 and 16 are available, metadata version 16 will be returned.
45+
46+
The function accepts an abort signal to make the promise abortable.
47+
48+
### `finalizedBlock$`
49+
50+
Type: `Observable<BlockInfo>{:ts}`
51+
52+
This Observable emits [`BlockInfo`](/types#blockinfo) for every new finalized block. It is multicast and stateful. For a new subscription, it will synchronously repeat its latest known state.
53+
54+
### `getFinalizedBlock`
55+
56+
Type: `() => Promise<BlockInfo>{:ts}`
57+
58+
This function returns [`BlockInfo`](/types#blockinfo) for the latest known finalized block.
59+
60+
### `bestBlocks$`
61+
62+
Type: `Observable<BlockInfo[]>{:ts}`
63+
64+
This Observable emits an array of [`BlockInfo`](/types#blockinfo), being the first element the latest known best block, and the last element the latest known finalized block.
65+
66+
The following guarantees apply:
67+
68+
- It is a multicast and stateful observable. For a new subscription, it will synchronously repeat its latest known state.
69+
- In every emission, the array will have length of at least `1{:ts}`.
70+
- The emitted arrays are immutable data structures; i.e. a new array is emitted at every event but the reference to its children are stable if the children didn't change.
71+
72+
### `getBestBlocks`
73+
74+
Type: `() => Promise<BlockInfo[]>{:ts}`
75+
76+
This function returns the latest known state of [`bestBlocks$`](/client#bestblocks). It holds the same guarantees.
77+
78+
### `blocks$`
79+
80+
Type: `Observable<BlockInfo>{:ts}`
81+
82+
This observable emits [`BlockInfo`](/types#blockinfo) for every block the client discovers. This observable follows the following rules:
83+
84+
- Right after subscription, the observable will emit synchronously the latest finalized block and all its known descendants.
85+
- The emissions are "continuous"; i.e. for every block emitted it is guaranteed that the parent of it has already been emitted.
86+
- The Observable will complete if the continuity of the blocks cannot be guaranteed.
87+
88+
### `hodlBlock`
89+
90+
Type: `(blockHash: HexString) => () => void{:ts}`
91+
92+
This function prevents the block from being unpinned. Returns a function that releases the hold, allowing the block to be unpinned once no other operations remain.
93+
94+
```ts twoslash
95+
import type { PolkadotClient } from "polkadot-api"
96+
const client: PolkadotClient = null as any
97+
// ---cut---
98+
const finalized = await client.getFinalizedBlock()
99+
const releaseFn = client.hodlBlock(finalized.hash)
100+
101+
// the block will not be released!
102+
setTimeout(async () => {
103+
const body = await client.getBlockBody(finalized.hash)
104+
releaseFn()
105+
}, 100_000)
106+
```
107+
108+
### `watchBlockBody`
109+
110+
Type: `(hash: string) => Observable<HexString[]>{:ts}`
111+
112+
Retrieves the body of the block given; which can be a block hash, `"finalized"{:ts}` or `"best"{:ts}`.
113+
114+
The observable will emit once, and immediately complete.
115+
116+
### `getBlockBody`
117+
118+
Type: `(hash: string) => Promise<HexString[]>{:ts}`
119+
120+
Retrieves the body of the block given; which can be a block hash, `"finalized"{:ts}` or `"best"{:ts}`.
121+
122+
### `getBlockHeader`
123+
124+
Type: `(hash?: string) => Promise<BlockHeader>{:ts}`
125+
126+
Retrieves the decoded header of the block given; which can be a block hash, `"finalized"{:ts}` (default) or `"best"{:ts}`.
127+
128+
### `submit`
129+
130+
Type: `(transaction: HexString, at?: HexString) => Promise<TxFinalizedPayload>{:ts}`
131+
132+
Broadcasts a transaction. The promise will resolve when the transaction is found in a finalized block, and will reject if the transaction is deemed invalid (either before or after broadcasting).
133+
134+
This function follows the same logic as the [transaction API `submitAndWatch` function](/typed/tx#signandsubmit), find more information about it there.
135+
136+
### `submitAndWatch`
137+
138+
Type: `(transaction: HexString, at?: HexString) => Observable<TxBroadcastEvent>{:ts}`
139+
140+
Broadcasts a transaction. This function follows the same logic as the [transaction API `signSubmitAndWatch` function](/typed/tx#signsubmitandwatch), find more information about the emitted events there.
141+
142+
### `getTypedApi`
143+
144+
Type: `(descriptors: ChainDefinition) => TypedApi{:ts}`
145+
146+
The Typed API is the entry point to the runtime-specific interactions with Polkadot-API. You can do storage queries, create transactions, run view functions, etc!
147+
148+
[`TypedApi` has its own documentation](/typed). Check it out!
149+
150+
### `getUnsafeApi`
151+
152+
Type: `() => UnsafeApi{:ts}`
153+
154+
The Unsafe API is another way to access the specific interactions of the chain you're connected to. Nevertheless, it has its own caveats, read the docs before using it!
155+
156+
[`UnsafeApi` has its own documentation](/unsafe). Check it out!
157+
158+
### `rawQuery`
159+
160+
Type:
161+
5162
```ts
6-
interface PolkadotClient {
7-
/**
8-
* Retrieve the ChainSpecData as it comes from the [JSON-RPC
9-
* spec](https://paritytech.github.io/json-rpc-interface-spec/api/chainSpec.html)
10-
*/
11-
getChainSpecData: () => Promise<ChainSpecData>
12-
13-
/**
14-
* Retrieves the most modern stable version of the metadata for a given block.
15-
*
16-
* @param atBlock The block-hash of the block.
17-
* @returns Observable that emits the most modern stable version of the
18-
* metadata, and immediately completes.
19-
*/
20-
getMetadata$: (atBlock: HexString) => Observable<Uint8Array>
21-
/**
22-
* Retrieves the most modern stable version of the metadata for a given block.
23-
*
24-
* @param atBlock The block-hash of the block.
25-
* @returns An abortable Promise that resolves into the most modern
26-
* stable version of the metadata.
27-
*/
28-
getMetadata: (atBlock: HexString, signal?: AbortSignal) => Promise<Uint8Array>
29-
30-
/**
31-
* Observable that emits `BlockInfo` for every new finalized block. It's a
32-
* multicast and stateful observable, that will synchronously replay its
33-
* latest known state.
34-
*/
35-
finalizedBlock$: Observable<BlockInfo>
36-
/**
37-
* @returns Latest known finalized block.
38-
*/
39-
getFinalizedBlock: () => Promise<BlockInfo>
40-
41-
/**
42-
* Observable that emits an Array of `BlockInfo`, being the first element the
43-
* latest known best block, and the last element the latest known finalized
44-
* block. It's a multicast and stateful observable, that will synchronously
45-
* replay its latest known state. This array is an immutable data structure;
46-
* i.e. a new array is emitted at every event but the reference to its
47-
* children are stable if the children didn't change.
48-
*
49-
* Note that some blocks might not get reported, e.g. if they become finalized
50-
* immediately without being part of the best block chain.
51-
*/
52-
bestBlocks$: Observable<BlockInfo[]>
53-
/**
54-
* @returns Array of `BlockInfo`, being the first element the latest
55-
* known best block, and the last element the latest known
56-
* finalized block.
57-
*/
58-
getBestBlocks: () => Promise<BlockInfo[]>
59-
60-
/**
61-
* Observable of new blocks that have been discovered by the client.
62-
*/
63-
blocks$: Observable<BlockInfo>
64-
65-
/**
66-
* Ensures that a block stays available, even after it has been finalized and
67-
* no operations are running for that block.
68-
*
69-
* @returns A callback function to release the block.
70-
*/
71-
hodlBlock: (blockHash: HexString) => () => void
72-
73-
/**
74-
* Observable to watch Block Body.
75-
*
76-
* @param hash It can be a block hash, `"finalized"`, or `"best"`
77-
* @returns Observable to watch a block body. There'll be just one event
78-
* with the payload and the observable will complete.
79-
*/
80-
watchBlockBody: (hash: string) => Observable<HexString[]>
81-
/**
82-
* Get Block Body (Promise-based)
83-
*
84-
* @param hash It can be a block hash, `"finalized"`, or `"best"`
85-
* @returns Block body.
86-
*/
87-
getBlockBody: (hash: string) => Promise<HexString[]>
88-
89-
/**
90-
* Get Block Header (Promise-based)
91-
*
92-
* @param hash It can be a block hash, `"finalized"` (default), or
93-
* `"best"`
94-
* @returns Block hash.
95-
*/
96-
getBlockHeader: (hash?: string) => Promise<BlockHeader>
97-
98-
/**
99-
* Broadcasts a transaction (Promise-based). The promise will resolve when the
100-
* transaction is found in a finalized block; and will reject if the
101-
* transaction is invalid and can't be broadcasted, or if it is deemed invalid
102-
* later on.
103-
*
104-
* @param transaction SCALE-encoded tx to broadcast.
105-
* @param at It can be a block hash, `"finalized"`, or `"best"`.
106-
* That block will be used to verify the validity of
107-
* the tx.
108-
*/
109-
submit: (
110-
transaction: HexString,
111-
at?: HexString,
112-
) => Promise<TxFinalizedPayload>
113-
/**
114-
* Broadcasts a transaction and returns an Observable. The observable will
115-
* complete as soon as the transaction is in a finalized block. See
116-
* https://papi.how/typed/tx#signsubmitandwatch to learn about all possible
117-
* events.
118-
*
119-
* @param transaction SCALE-encoded tx to broadcast.
120-
* @param at It can be a block hash, `"finalized"`, or `"best"`.
121-
* That block will be used to verify the validity of
122-
* the tx.
123-
*/
124-
submitAndWatch: (
125-
transaction: HexString,
126-
at?: HexString,
127-
) => Observable<TxBroadcastEvent>
128-
129-
/**
130-
* Returns an instance of a `TypedApi`.
131-
*
132-
* @param descriptors Pass descriptors from `@polkadot-api/descriptors`
133-
* generated by `papi` CLI.
134-
*/
135-
getTypedApi: <D extends ChainDefinition>(descriptors: D) => TypedApi<D>
136-
137-
/**
138-
* Returns an instance of a `UnsafeApi`.
139-
*
140-
* Note that this method is only meant for advanced users that really know
141-
* what are they doing. This API does not provide any runtime compatibility
142-
* checks protection and the consumer should implement them on their own.
143-
*/
144-
getUnsafeApi: <D>() => UnsafeApi<D>
145-
146-
/**
147-
* Returns a Promise that resolves into the encoded value of a storage entry
148-
* or `null` if the key doesn't have a corresponding value.
149-
*
150-
* @param storageKey Either one of the well-known substrate storage keys
151-
* or an hexadecimal storage key.
152-
*/
153-
rawQuery: (
154-
storageKey: HexString | string,
155-
options?: PullOptions,
156-
) => Promise<HexString | null>
157-
158-
/**
159-
* This will `unfollow` the provider, disconnect and error every subscription.
160-
* After calling it nothing can be done with the client.
161-
*/
162-
destroy: () => void
163-
164-
/**
165-
* This API is meant as an "escape hatch" to allow access to debug endpoints
166-
* such as `system_version`, and other useful endpoints that are not spec
167-
* compliant.
168-
*
169-
* @example
170-
*
171-
* const systemVersion = await client._request<string>("system_version", [])
172-
* const myFancyThhing = await client._request<
173-
* { value: string },
174-
* [id: number]
175-
* >("very_fancy", [1714])
176-
*
177-
*/
178-
_request: <Reply = any, Params extends Array<any> = any[]>(
179-
method: string,
180-
params: Params,
181-
) => Promise<Reply>
182-
}
163+
rawQuery: (
164+
storageKey: HexString | string,
165+
options?: { at: string; signal: AbortSignal },
166+
) => Promise<HexString | null>
183167
```
184168

185-
As one can note, `PolkadotClient` heavily relies on rxjs' `Observable`, used as well under the hood of Promise-based methods. Every method is fairly straight-forward and already documented exhaustively, except for `getTypedApi` and `getUnsafeApi`. We will see first of all the `TypedApi`, and afterwards the `UnsafeApi`.
169+
This function allows to access the raw storage value of a given key. It'll return the encoded value, or `null{:ts}` if the value is not found.
170+
171+
Parameters:
172+
173+
- `storageKey`: it can be both an encoded key (as `HexString`) or a well-known Substrate key (such as `":code"{:ts}`).
174+
- `options`: Optionally pass `at` (block hash, `"finalized"{:ts}` (default), or `"best"{:ts}`) and/or `signal`, to make the promise abortable.
175+
176+
### `destroy`
177+
178+
Type: `() => void{:ts}`
179+
180+
This function will unfollow the provider, error every subscription pending and disconnect from the provider. After calling it, nothing else can be done with the client.
181+
182+
### `_request`
183+
184+
Type: `(method: string, params: Array<any>) => Promise<any>{:ts}`
185+
186+
This function allows to call any RPC endpoint through the JSON-RPC provider. This method is not typed by itself, but you can add your own types. It is meant as an escape-hatch for chain-specific nodes, you should use all the other APIs for regular interactions.
187+
188+
For example, with `system_version`:
189+
190+
```ts twoslash
191+
import type { PolkadotClient } from "polkadot-api"
192+
const client: PolkadotClient = null as any
193+
// ---cut---
194+
const nodeVersion = await client._request<string, []>("system_version", [])
195+
// ^?
196+
```

0 commit comments

Comments
 (0)