Skip to content

feat: add offline api docs #51

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
32 changes: 16 additions & 16 deletions docs/pages/client.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ interface PolkadotClient {
getChainSpecData: () => Promise<ChainSpecData>

/**
* Observable that emits `BlockInfo` from the latest known finalized block.
* It's a multicast and stateful observable, that will synchronously replay
* its latest known state.
* Observable that emits `BlockInfo` for every new finalized block. It's a
* multicast and stateful observable, that will synchronously replay its
* latest known state.
*/
finalizedBlock$: Observable<BlockInfo>
/**
Expand All @@ -29,9 +29,8 @@ interface PolkadotClient {
* i.e. a new array is emitted at every event but the reference to its
* children are stable if the children didn't change.
*
* Note that subscribing to this observable already supersedes the need of
* subscribing to `finalizedBlock$`, since the last element of the array will
* be the latest known finalized block.
* Note that some blocks might not get reported, e.g. if they become finalized
* immediately without being part of the best block chain.
*/
bestBlocks$: Observable<BlockInfo[]>
/**
Expand Down Expand Up @@ -67,37 +66,38 @@ interface PolkadotClient {
getBlockHeader: (hash?: string) => Promise<BlockHeader>

/**
* Broadcast a transaction (Promise-based)
* Broadcasts a transaction (Promise-based). The promise will resolve when the
* transaction is found in a finalized block; and will reject if the
* transaction is invalid and can't be broadcasted, or if it is deemed invalid
* later on.
*
* @param transaction SCALE-encoded tx to broadcast.
* @param at It can be a block hash, `"finalized"`, or `"best"`.
* That block will be used to verify the validity of
* the tx, retrieve the next nonce,
* and create the mortality taking that block into
* account.
* the tx.
*/
submit: (
transaction: HexString,
at?: HexString,
) => Promise<TxFinalizedPayload>
/**
* Broadcast a transaction and returns an Observable. The observable will
* complete as soon as the transaction is in a finalized block.
* Broadcasts a transaction and returns an Observable. The observable will
* complete as soon as the transaction is in a finalized block. See
* https://papi.how/typed/tx#signsubmitandwatch to learn about all possible
* events.
*
* @param transaction SCALE-encoded tx to broadcast.
* @param at It can be a block hash, `"finalized"`, or `"best"`.
* That block will be used to verify the validity of
* the tx, retrieve the next nonce,
* and create the mortality taking that block into
* account.
* the tx.
*/
submitAndWatch: (
transaction: HexString,
at?: HexString,
) => Observable<TxBroadcastEvent>

/**
* Returns an instance of a `TypedApi`
* Returns an instance of a `TypedApi`.
*
* @param descriptors Pass descriptors from `@polkadot-api/descriptors`
* generated by `papi` CLI.
Expand Down
62 changes: 62 additions & 0 deletions docs/pages/offline.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Offline API

The rationale behind the offline api is to allow consumers to do certain actions with PAPI without the need of a provider. As expected, this client is more limited than the regular [`PolkadotClient`](/client).

Let's see an example first of all:

```typescript
import { getOfflineApi } from "polkadot-api"
import { dotDescriptors } from "@polkadot-api/descriptors" // you'll need them!

const offline = await getOfflineApi(dotDescriptors) // it is async!

// metadata constants can be easily accessed
const prefix = api.constants.System.SS58Prefix // directly the value; e.g. `0`
const { spec_name, spec_version } = api.constants.System.Version

// transactions can be created and signed
const tx = api.tx.Balances.transfer_keep_alive({
dest: MultiAddress.Id(myAddr),
value: amount,
})

tx.encodedData // we have the encoded callData
tx.decodedCall // and the decodedCall

const tx2 = offline.tx.Utility.batch({
calls: [
offline.tx.System.remark({ remark: Binary.fromText("HELLO!") }).decodedCall,
tx.decodedCall,
],
})

// we can sign txs, but we need to add more stuff than usual!
const signedTx = await tx2.sign(signer, {
nonce: 24, // nonce is always compulsory
mortality: { mortal: false }, // and mortality!
})
```

## Constants

Constants can be accessed easily having the metadata. `api.constants.Pallet.Entry` already gives the decoded value.

## Transactions

This is the main usecase of offline api. It allows to create and encode transactions, and even sign them.
The transactions are created in the exact same way as in the regular API ([see docs](/typed/tx)). Nevertheless, only a subset of the fields are exposed:

- `decodedCall`: it enables to get the _PAPI decoded_ transaction. It is helpful to create other txs that require them as a parameter (e.g. `Utility.batch`).
- `encodedData`: a `Binary` with the encoded call data.
- `sign`: it takes the same arguments as the regular API, but there are two compulsory signed extensions:
- `nonce`: nonce cannot be retrieved anymore from the chain, and therefore has to be passed
- `mortality`: transactions can be signed either mortal or immortal. In case the tx were to be mortal, the block information has to be passed as well.
```typescript
type Mortality =
| { mortal: false }
| {
mortal: true
period: number
startAtBlock: { height: number; hash: HexString }
}
```
8 changes: 2 additions & 6 deletions docs/pages/requirements.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ PAPI is designed to work flawlessly with almost any Polkadot-like chain. Even th

### NodeJS

PAPI is developed using the latest NodeJS LTS (currently `20.x`). The minimum required version is `20.6.0`, while we recommend the latest available release.
PAPI is developed using the latest NodeJS LTS (currently `22.x`). The minimum required version is `20.6.0`, while we recommend the latest available release.

### Bun

Expand Down Expand Up @@ -70,10 +70,6 @@ Besides that, Polkadot-API requires runtimes to implement some basic runtime cal
- In order to get the metadata, it needs `Metadata_metadata_versions` and `Metadata_metadata_at_version`. If they are not present, then `Metadata_metadata` needs to be there and answer a `v14` Metadata.
- To create and broadcast transactions, Polkadot-API needs `AccountNonceApi_account_nonce` and `TaggedTransactionQueue_validate_transaction`. To estimate the fees, it also requires `TransactionPaymentApi_query_info`.

In order to create transactions as well, the following storage entry is required for obtaining the genesis block-hash:

- `System.BlockHash`

And the following constant:
In order to create transactions as well, the following constant is required:

- `System.Version`, having `spec_version` and `transaction_version` fields.
4 changes: 4 additions & 0 deletions vocs.config.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@ export default defineConfig({
},
],
},
{
text: "Offline API",
link: "/offline",
},
{
text: "PAPI SDKs",
link: "/sdks/intro",
Expand Down