dedot 0.4.2-next.5d9d02c1.7 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +46 -766
- package/package.json +11 -11
package/README.md
CHANGED
|
@@ -14,806 +14,86 @@ Delightful JavaScript/TypeScript client for [Polkadot](https://polkadot.network/
|
|
|
14
14
|
[ico-version]: https://img.shields.io/github/package-json/v/dedotdev/dedot?filename=packages%2Fapi%2Fpackage.json&style=flat-square
|
|
15
15
|
[ico-license]: https://img.shields.io/github/license/dedotdev/dedot?style=flat-square
|
|
16
16
|
|
|
17
|
-
[link-telegram]: https://t.me
|
|
17
|
+
[link-telegram]: https://t.me/JoinDedot
|
|
18
18
|
|
|
19
19
|
---
|
|
20
20
|
|
|
21
|
+
[Dedot](https://dedot.dev) is the next-generation JavaScript client for Polkadot and Substrate-based blockchains. Designed to elevate the dapp development experience, Dedot is built & optimized to be lightweight and tree-shakable, offering precise Types & APIs suggestions for individual Substrate-based blockchains and ink! Smart Contracts. Dedot also helps dapps efficiently connect to multiple chains simultaneously as we head toward a seamless multi-chain future.
|
|
22
|
+
|
|
21
23
|
### Features
|
|
22
24
|
|
|
23
25
|
- ✅ Small bundle size, tree-shakable (no more bn.js or wasm-blob tight dependencies)
|
|
24
26
|
- ✅ Types & APIs suggestions for each individual Substrate-based blockchain
|
|
25
27
|
network ([@dedot/chaintypes](https://github.com/dedotdev/chaintypes))
|
|
26
|
-
- ✅ Familiar api style with `@polkadot/api`, [easy & fast migration!](
|
|
27
|
-
- ✅ Native [TypeScript type system](#type-system) for scale-codec
|
|
28
|
+
- ✅ Familiar api style with `@polkadot/api`, [easy & fast migration!](https://docs.dedot.dev/getting-started/pjs-to-dedot)
|
|
29
|
+
- ✅ Native [TypeScript type system](https://docs.dedot.dev/getting-started/pjs-to-dedot#type-system) for scale-codec
|
|
28
30
|
- ✅ Compatible with `@polkadot/extension`-based wallets
|
|
29
31
|
- ✅ Support Metadata V14, V15 (latest)
|
|
30
|
-
- ✅ Built-in metadata caching
|
|
31
|
-
- ✅ Build on top of both the [new](https://paritytech.github.io/json-rpc-interface-spec/introduction.html) & legacy (
|
|
32
|
+
- ✅ Built-in metadata optimization ([caching](https://docs.dedot.dev/getting-started/connect-to-network#caching-metadata), [compact mode](https://github.com/dedotdev/dedot/issues/45) ⏳)
|
|
33
|
+
- ✅ Build on top of both the [new](https://paritytech.github.io/json-rpc-interface-spec/introduction.html) & [legacy](https://github.com/w3f/PSPs/blob/master/PSPs/drafts/psp-6.md) (
|
|
32
34
|
deprecated soon) JSON-RPC APIs
|
|
33
|
-
- ✅ Support light clients (e.g: [smoldot](https://www.npmjs.com/package/smoldot))
|
|
34
|
-
- ✅ [Typed Contract APIs](
|
|
35
|
-
- ✅ Fully-typed low-level [JSON-RPC client](
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
- [
|
|
41
|
-
- [
|
|
42
|
-
- [
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
- [Runtime APIs](#runtime-apis)
|
|
47
|
-
- [Submit Transactions](#transaction-apis)
|
|
48
|
-
- [Events](#events)
|
|
49
|
-
- [Errors](#errors)
|
|
50
|
-
- [Interact with ink! Smart Contracts](#interact-with-ink-smart-contracts)
|
|
51
|
-
- [`@polkadot/api` -> `dedot`](#migration-from-polkadotapi-to-dedot)
|
|
52
|
-
- [Packages Structure](#packages-structure)
|
|
53
|
-
- [Credit](#credit)
|
|
54
|
-
|
|
55
|
-
### Example Dapps & Scripts
|
|
56
|
-
- Try Dedot! - https://try.dedot.dev - [Source Code](https://github.com/dedotdev/trydedot)
|
|
57
|
-
- Tiny Url - https://link.dedot.dev - [Source Code](https://github.com/dedotdev/link)
|
|
58
|
-
- [Simple Playground Script](https://stackblitz.com/edit/try-dedot?file=main.ts&view=editor)
|
|
59
|
-
- [Interact with PSP22 ink! Contract](https://stackblitz.com/edit/psp22-dedot?file=main.ts&view=editor)
|
|
60
|
-
- Add yours?
|
|
61
|
-
|
|
62
|
-
### Getting started
|
|
63
|
-
|
|
64
|
-
Follow the below steps to install Dedot to your project.
|
|
65
|
-
|
|
66
|
-
- Install `dedot` package
|
|
67
|
-
|
|
68
|
-
```shell
|
|
69
|
-
# via yarn
|
|
70
|
-
yarn add dedot
|
|
71
|
-
|
|
72
|
-
# via npm
|
|
73
|
-
npm i dedot
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
- Install `@dedot/chaintypes` package for chain types & APIs suggestion. Skip this step if you don't use TypeScript.
|
|
77
|
-
|
|
78
|
-
```shell
|
|
79
|
-
# via yarn
|
|
80
|
-
yarn add -D @dedot/chaintypes
|
|
81
|
-
|
|
82
|
-
# via npm
|
|
83
|
-
npm i -D @dedot/chaintypes
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
- Initialize `DedotClient` and start interacting with Polkadot network
|
|
87
|
-
|
|
88
|
-
```typescript
|
|
89
|
-
// main.ts
|
|
90
|
-
import { DedotClient, WsProvider } from 'dedot';
|
|
91
|
-
import type { PolkadotApi } from '@dedot/chaintypes';
|
|
92
|
-
|
|
93
|
-
const run = async () => {
|
|
94
|
-
const provider = new WsProvider('wss://rpc.polkadot.io');
|
|
95
|
-
const api = await DedotClient.new<PolkadotApi>(provider);
|
|
96
|
-
|
|
97
|
-
// Call rpc `state_getMetadata` to fetch raw scale-encoded metadata and decode it.
|
|
98
|
-
const metadata = await api.rpc.state_getMetadata();
|
|
99
|
-
console.log('Metadata:', metadata);
|
|
100
|
-
|
|
101
|
-
// Query on-chain storage
|
|
102
|
-
const balance = await api.query.system.account(<address>);
|
|
103
|
-
console.log('Balance:', balance);
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
// Subscribe to on-chain storage changes
|
|
107
|
-
const unsub = await api.query.system.number((blockNumber) => {
|
|
108
|
-
console.log(`Current block number: ${blockNumber}`);
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
// Get pallet constants
|
|
112
|
-
const ss58Prefix = api.consts.system.ss58Prefix;
|
|
113
|
-
console.log('Polkadot ss58Prefix:', ss58Prefix);
|
|
114
|
-
|
|
115
|
-
// Call runtime api
|
|
116
|
-
const pendingRewards = await api.call.nominationPoolsApi.pendingRewards(<address>)
|
|
117
|
-
console.log('Pending rewards:', pendingRewards);
|
|
118
|
-
|
|
119
|
-
// await unsub();
|
|
120
|
-
// await api.disconnect();
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
run().catch(console.error);
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
- You can also import `dedot` using `require`.
|
|
127
|
-
|
|
128
|
-
```js
|
|
129
|
-
// main.js
|
|
130
|
-
const { DedotClient, WsProvider } = require('dedot');
|
|
131
|
-
// ...
|
|
132
|
-
const provider = new WsProvider('wss://rpc.polkadot.io');
|
|
133
|
-
const api = await DedotClient.new(provider);
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
- If the JSON-RPC server doesn't support [new](https://paritytech.github.io/json-rpc-interface-spec/introduction.html) JSON-RPC APIs yet, you can connect using the `LegacyClient` which build on top of the legacy JSON-RPC APIs.
|
|
137
|
-
|
|
138
|
-
```typescript
|
|
139
|
-
import { LegacyClient, WsProvider } from 'dedot';
|
|
140
|
-
|
|
141
|
-
const provider = new WsProvider('wss://rpc.polkadot.io');
|
|
142
|
-
const api = await LegacyClient.new(provider);
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
### Chain Types & APIs
|
|
146
|
-
|
|
147
|
-
Each Substrate-based blockchain has their own set of data types & APIs to interact with, so being aware of those types & APIs when working with a blockchain will greatly improve the overall development experience. `dedot` exposes TypeScript's types & APIs for each individual Substrate-based blockchain, we recommend using TypeScript for your project to have the best experience.
|
|
148
|
-
|
|
149
|
-
Types & APIs for each Substrate-based blockchains are defined in package [`@dedot/chaintypes`](https://github.com/dedotdev/chaintypes):
|
|
150
|
-
|
|
35
|
+
- ✅ Support [light clients](https://docs.dedot.dev/getting-started/connect-to-network#initializing-dedotclient-and-interact-with-polkadot-network) (e.g: [smoldot](https://www.npmjs.com/package/smoldot))
|
|
36
|
+
- ✅ [Typed Contract APIs](https://docs.dedot.dev/ink-smart-contracts/intro)
|
|
37
|
+
- ✅ Fully-typed low-level [JSON-RPC client](https://docs.dedot.dev/clients-and-providers/clients#jsonrpcclient)
|
|
38
|
+
|
|
39
|
+
### Documentation
|
|
40
|
+
Check out Dedot documentation on the website: https://dedot.dev
|
|
41
|
+
- [Getting started](https://docs.dedot.dev/getting-started/installation)
|
|
42
|
+
- [Interact with ink! smart contracts](https://docs.dedot.dev/ink-smart-contracts/intro)
|
|
43
|
+
- [CLI](https://docs.dedot.dev/cli)
|
|
44
|
+
- [Build with Dedot](https://docs.dedot.dev/help-and-faq/built-with-dedot)
|
|
45
|
+
|
|
46
|
+
### Example
|
|
47
|
+
1. Install packages
|
|
151
48
|
```shell
|
|
152
|
-
#
|
|
153
|
-
yarn add -D @dedot/chaintypes
|
|
49
|
+
npm i dedot # or yarn, pnpm
|
|
154
50
|
|
|
155
|
-
# via npm
|
|
156
51
|
npm i -D @dedot/chaintypes
|
|
157
52
|
```
|
|
158
|
-
|
|
159
|
-
Initialize `DedotClient` instance using the `ChainApi` interface for a target chain to enable types & APIs suggestion/autocompletion for that particular chain:
|
|
160
|
-
|
|
53
|
+
2. Connect to the network
|
|
161
54
|
```typescript
|
|
162
55
|
import { DedotClient, WsProvider } from 'dedot';
|
|
163
|
-
import type { PolkadotApi, KusamaApi, MoonbeamApi, AstarApi } from '@dedot/chaintypes';
|
|
164
|
-
|
|
165
|
-
// ...
|
|
166
|
-
|
|
167
|
-
const polkadotApi = await DedotClient.new<PolkadotApi>(new WsProvider('wss://rpc.polkadot.io'));
|
|
168
|
-
console.log(await polkadotApi.query.babe.authorities());
|
|
169
|
-
|
|
170
|
-
const kusamaApi = await DedotClient.new<KusamaApi>(new WsProvider('wss://kusama-rpc.polkadot.io'));
|
|
171
|
-
console.log(await kusamaApi.query.society.memberCount());
|
|
172
|
-
|
|
173
|
-
const moonbeamApi = await DedotClient.new<MoonbeamApi>(new WsProvider('wss://wss.api.moonbeam.network'));
|
|
174
|
-
console.log(await moonbeamApi.query.ethereumChainId.chainId());
|
|
175
|
-
|
|
176
|
-
const astarApi = await DedotClient.new<AstarApi>(new WsProvider('wss://rpc.astar.network'));
|
|
177
|
-
console.log(await astarApi.query.dappsStaking.blockRewardAccumulator());
|
|
178
|
-
|
|
179
|
-
const genericApi = await DedotClient.new(new WsProvider('ws://localhost:9944'));
|
|
180
|
-
|
|
181
|
-
// ...
|
|
182
|
-
```
|
|
183
|
-
|
|
184
|
-
Supported `ChainApi` interfaces are defined [here](https://github.com/dedotdev/chaintypes/blob/main/packages/chaintypes/src/index.ts), you can also generate the `ChainApi` interface for the chain you want to connect with using `dedot` cli.
|
|
185
|
-
|
|
186
|
-
```shell
|
|
187
|
-
# Generate ChainApi interface for Polkadot network via rpc endpoint: wss://rpc.polkadot.io
|
|
188
|
-
npx dedot chaintypes -w wss://rpc.polkadot.io
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
### Execute JSON-RPC Methods
|
|
192
|
-
|
|
193
|
-
RPCs can be executed via `api.rpc` entry point. After creating a `DedotClient` instance with a `ChainApi` interface of the network you want to interact with, all RPC methods of the network will be exposed in the autocompletion/suggestion with format: `api.rpc.method_name(param1, param2, ...)`. E.g: you can find all supported RPC methods for Polkadot network [here](https://github.com/dedotdev/chaintypes/blob/main/packages/chaintypes/src/polkadot/json-rpc.d.ts), similarly for other networks as well.
|
|
194
|
-
|
|
195
|
-
Examples:
|
|
196
|
-
|
|
197
|
-
```typescript
|
|
198
|
-
// Call rpc: `state_getMetadata`
|
|
199
|
-
const metadata = await api.rpc.state_getMetadata();
|
|
200
|
-
|
|
201
|
-
// Call an arbitrary rpc: `module_rpc_name` with arguments ['param1', 'param2']
|
|
202
|
-
const result = await api.rpc.module_rpc_name('param1', 'param2');
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
For advanced users who want to interact directly with server/node via raw JSON-RPC APIs, you can use a light-weight `JsonRpcClient` for this purpose without having to use `DedotClient` or `LegacyClient`.
|
|
206
|
-
|
|
207
|
-
```typescript
|
|
208
|
-
import { JsonRpcClient, WsProvider } from 'dedot';
|
|
209
56
|
import type { PolkadotApi } from '@dedot/chaintypes';
|
|
210
57
|
|
|
211
58
|
const provider = new WsProvider('wss://rpc.polkadot.io');
|
|
212
|
-
const client = await
|
|
213
|
-
const chain = await client.rpc.system_chain();
|
|
214
|
-
|
|
215
|
-
// ...
|
|
216
|
-
```
|
|
217
|
-
|
|
218
|
-
### Query On-chain Storage
|
|
219
|
-
|
|
220
|
-
On-chain storage can be queried via `api.query` entry point. All the available storage entries for a chain are exposed in the `ChainApi` interface for that chain and can be executed with format: `api.query.<pallet>.<storgeEntry>`. E.g: You can find all the available storage queries of Polkadot network [here](https://github.com/dedotdev/chaintypes/blob/main/packages/chaintypes/src/polkadot/query.d.ts), similarly for other networks as well.
|
|
221
|
-
|
|
222
|
-
Examples:
|
|
223
|
-
|
|
224
|
-
```typescript
|
|
225
|
-
// Query account balance
|
|
226
|
-
const balance = await api.query.system.account(<address>);
|
|
227
|
-
|
|
228
|
-
// Get all events of current block
|
|
229
|
-
const events = await api.query.system.events();
|
|
230
|
-
```
|
|
231
|
-
|
|
232
|
-
### Constants
|
|
233
|
-
|
|
234
|
-
Runtime constants (parameter types) are defined in metadata, and can be inspected via `api.consts` entry point with format: `api.consts.<pallet>.<constantName>`. All available constants are also exposed in the `ChainApi` interface. E.g: Available constants for Polkadot network is defined [here](https://github.com/dedotdev/chaintypes/blob/main/packages/chaintypes/src/polkadot/consts.d.ts), similarly for other networks.
|
|
235
|
-
|
|
236
|
-
Examples:
|
|
237
|
-
|
|
238
|
-
```typescript
|
|
239
|
-
// Get runtime version
|
|
240
|
-
const runtimeVersion = api.consts.system.version;
|
|
241
|
-
|
|
242
|
-
// Get existential deposit in pallet balances
|
|
243
|
-
const existentialDeposit = api.consts.balances.existentialDeposit;
|
|
244
|
-
```
|
|
245
|
-
|
|
246
|
-
### Runtime APIs
|
|
247
|
-
|
|
248
|
-
The latest stable Metadata V15 now includes all the runtime apis type information. So for chains that are supported Metadata V15, we can now execute all available runtime apis with syntax `api.call.<runtimeApi>.<methodName>`, those apis are exposed in `ChainApi` interface. E.g: Runtime Apis for Polkadot network is defined [here](https://github.com/dedotdev/chaintypes/blob/main/packages/chaintypes/src/polkadot/runtime.d.ts), similarly for other networks as well.
|
|
249
|
-
|
|
250
|
-
Examples:
|
|
251
|
-
|
|
252
|
-
```typescript
|
|
253
|
-
// Get account nonce
|
|
254
|
-
const nonce = await api.call.accountNonceApi.accountNonce(<address>);
|
|
255
|
-
|
|
256
|
-
// Query transaction payment info
|
|
257
|
-
const tx = api.tx.balances.transferKeepAlive(<address>, 2_000_000_000_000n);
|
|
258
|
-
const queryInfo = await api.call.transactionPaymentApi.queryInfo(tx.toU8a(), tx.length);
|
|
259
|
-
|
|
260
|
-
// Get runtime version
|
|
261
|
-
const runtimeVersion = await api.call.core.version();
|
|
262
|
-
```
|
|
263
|
-
|
|
264
|
-
For chains that only support Metadata V14, we need to bring in the Runtime Api definitions when initializing the DedotClient instance to encode & decode the calls. You can find all supported Runtime Api definitions in [`dedot/runtime-specs`](https://github.com/dedotdev/dedot/blob/fefe71cf4a04d1433841f5cfc8400a1e2a8db112/packages/runtime-specs/src/all.ts#L21-L39) package.
|
|
265
|
-
|
|
266
|
-
Examples:
|
|
267
|
-
|
|
268
|
-
```typescript
|
|
269
|
-
import { RuntimeApis } from 'dedot/runtime-specs';
|
|
270
|
-
|
|
271
|
-
const api = await DedotClient.new({ provider: new WsProvider('wss://rpc.mynetwork.com'), runtimeApis: RuntimeApis });
|
|
272
|
-
|
|
273
|
-
// Or bring in only the Runtime Api definition that you want to interact with
|
|
274
|
-
import { AccountNonceApi } from 'dedot/runtime-specs';
|
|
275
|
-
const api = await DedotClient.new({ provider: new WsProvider('wss://rpc.mynetwork.com'), runtimeApis: { AccountNonceApi } });
|
|
276
|
-
|
|
277
|
-
// Get account nonce
|
|
278
|
-
const nonce = await api.call.accountNonceApi.accountNonce(<address>);
|
|
279
|
-
```
|
|
280
|
-
|
|
281
|
-
You absolutely can define your own Runtime Api definition if you don't find it in the [supported list](https://github.com/dedotdev/dedot/blob/fefe71cf4a04d1433841f5cfc8400a1e2a8db112/packages/runtime-specs/src/all.ts#L21-L39).
|
|
282
|
-
|
|
283
|
-
### Transaction APIs
|
|
284
|
-
|
|
285
|
-
Transaction apis are designed to be compatible with [`IKeyringPair`](https://github.com/polkadot-js/api/blob/3bdf49b0428a62f16b3222b9a31bfefa43c1ca55/packages/types/src/types/interfaces.ts#L15-L21) and [`Signer`](https://github.com/polkadot-js/api/blob/3bdf49b0428a62f16b3222b9a31bfefa43c1ca55/packages/types/src/types/extrinsic.ts#L135-L150) interfaces, so you can sign the transactions with accounts created by a [`Keyring`](https://github.com/polkadot-js/common/blob/22aab4a4e62944a2cf8c885f50be2c1b842813ec/packages/keyring/src/keyring.ts#L41-L40) or from any [Polkadot{.js}-based](https://github.com/polkadot-js/extension?tab=readme-ov-file#api-interface) wallet extensions.
|
|
286
|
-
|
|
287
|
-
All transaction apis are exposed in `ChainApi` interface and can be access with syntax: `api.tx.<pallet>.<transactionName>`. E.g: Available transaction apis for Polkadot network are defined [here](https://github.com/dedotdev/chaintypes/blob/main/packages/chaintypes/src/polkadot/tx.d.ts), similarly for other networks as well.
|
|
288
|
-
|
|
289
|
-
Example 1: Sign transaction with a Keying account
|
|
290
|
-
|
|
291
|
-
```typescript
|
|
292
|
-
import { cryptoWaitReady } from '@polkadot/util-crypto';
|
|
293
|
-
import { Keyring } from '@polkadot/keyring';
|
|
294
|
-
|
|
295
|
-
// ...
|
|
296
|
-
|
|
297
|
-
await cryptoWaitReady();
|
|
298
|
-
const keyring = new Keyring({ type: 'sr25519' });
|
|
299
|
-
const alice = keyring.addFromUri('//Alice');
|
|
300
|
-
|
|
301
|
-
const unsub = await api.tx.balances
|
|
302
|
-
.transferKeepAlive(<destAddress>, 2_000_000_000_000n)
|
|
303
|
-
.signAndSend(alice, async ({ status }) => {
|
|
304
|
-
console.log('Transaction status', status.type);
|
|
305
|
-
if (status.type === 'BestChainBlockIncluded') { // or status.type === 'Finalized'
|
|
306
|
-
console.log(`Transaction completed at block hash ${status.value.blockHash}`);
|
|
307
|
-
await unsub();
|
|
308
|
-
}
|
|
309
|
-
});
|
|
310
|
-
```
|
|
311
|
-
|
|
312
|
-
Example 2: Sign transaction using `Signer` from Polkadot{.js} wallet extension
|
|
313
|
-
|
|
314
|
-
```typescript
|
|
315
|
-
const injected = await window.injectedWeb3['polkadot-js'].enable('A cool dapp');
|
|
316
|
-
const account = (await injected.accounts.get())[0];
|
|
317
|
-
const signer = injected.signer;
|
|
318
|
-
|
|
319
|
-
const unsub = await api.tx.balances
|
|
320
|
-
.transferKeepAlive(<destAddress>, 2_000_000_000_000n)
|
|
321
|
-
.signAndSend(account.address, { signer }, async ({ status }) => {
|
|
322
|
-
console.log('Transaction status', status.type);
|
|
323
|
-
if (status.type === 'BestChainBlockIncluded') { // or status.type === 'Finalized'
|
|
324
|
-
console.log(`Transaction completed at block hash ${status.value.blockHash}`);
|
|
325
|
-
await unsub();
|
|
326
|
-
}
|
|
327
|
-
});
|
|
328
|
-
```
|
|
329
|
-
|
|
330
|
-
Example 3: Submit a batch transaction
|
|
331
|
-
|
|
332
|
-
```typescript
|
|
333
|
-
import type { PolkadotRuntimeRuntimeCallLike } from '@dedot/chaintypes/polkadot';
|
|
334
|
-
|
|
335
|
-
// Omit the detail for simplicity
|
|
336
|
-
const account = ...;
|
|
337
|
-
const signer = ...;
|
|
338
|
-
|
|
339
|
-
const transferTx = api.tx.balances.transferKeepAlive(<destAddress>, 2_000_000_000_000n);
|
|
340
|
-
const remarkCall: PolkadotRuntimeRuntimeCallLike = {
|
|
341
|
-
pallet: 'System',
|
|
342
|
-
palletCall: {
|
|
343
|
-
name: 'RemarkWithEvent',
|
|
344
|
-
params: {
|
|
345
|
-
remark: 'Hello Dedot!',
|
|
346
|
-
},
|
|
347
|
-
},
|
|
348
|
-
};
|
|
349
|
-
|
|
350
|
-
const unsub = api.tx.utility.batch([transferTx.call, remarkCall])
|
|
351
|
-
.signAndSend(account.address, { signer }, async ({ status }) => {
|
|
352
|
-
console.log('Transaction status', status.type);
|
|
353
|
-
if (status.type === 'BestChainBlockIncluded') { // or status.type === 'Finalized'
|
|
354
|
-
console.log(`Transaction completed at block hash ${status.value.blockHash}`);
|
|
355
|
-
await unsub();
|
|
356
|
-
}
|
|
357
|
-
});
|
|
358
|
-
```
|
|
359
|
-
|
|
360
|
-
<details>
|
|
361
|
-
<summary>Example 4: Teleport WND from Westend Asset Hub to Westend via XCM</summary>
|
|
362
|
-
|
|
363
|
-
```typescript
|
|
364
|
-
import { WestendAssetHubApi, XcmVersionedLocation, XcmVersionedAssets, XcmV3WeightLimit } from '@dedot/chaintypes/westendAssetHub';
|
|
365
|
-
import { AccountId32 } from 'dedot/codecs';
|
|
366
|
-
|
|
367
|
-
const TWO_TOKENS = 2_000_000_000_000n;
|
|
368
|
-
const destAddress = <bobAddress>;
|
|
59
|
+
const client = await DedotClient.new<PolkadotApi>(provider);
|
|
369
60
|
|
|
370
|
-
|
|
61
|
+
// Call rpc `state_getMetadata` to fetch raw scale-encoded metadata and decode it.
|
|
62
|
+
const metadata = await client.rpc.state_getMetadata();
|
|
63
|
+
console.log('Metadata:', metadata);
|
|
371
64
|
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
};
|
|
376
|
-
|
|
377
|
-
const beneficiary: XcmVersionedLocation = {
|
|
378
|
-
type: 'V3',
|
|
379
|
-
value: {
|
|
380
|
-
parents: 0,
|
|
381
|
-
interior: {
|
|
382
|
-
type: 'X1',
|
|
383
|
-
value: {
|
|
384
|
-
type: 'AccountId32',
|
|
385
|
-
value: { id: new AccountId32(destAddress).raw },
|
|
386
|
-
},
|
|
387
|
-
},
|
|
388
|
-
},
|
|
389
|
-
};
|
|
390
|
-
|
|
391
|
-
const assets: XcmVersionedAssets = {
|
|
392
|
-
type: 'V3',
|
|
393
|
-
value: [
|
|
394
|
-
{
|
|
395
|
-
id: {
|
|
396
|
-
type: 'Concrete',
|
|
397
|
-
value: {
|
|
398
|
-
parents: 1,
|
|
399
|
-
interior: { type: 'Here' },
|
|
400
|
-
},
|
|
401
|
-
},
|
|
402
|
-
fun: {
|
|
403
|
-
type: 'Fungible',
|
|
404
|
-
value: TWO_TOKENS,
|
|
405
|
-
},
|
|
406
|
-
},
|
|
407
|
-
],
|
|
408
|
-
};
|
|
409
|
-
|
|
410
|
-
const weight: XcmV3WeightLimit = { type: 'Unlimited' };
|
|
411
|
-
|
|
412
|
-
api.tx.polkadotXcm
|
|
413
|
-
.limitedTeleportAssets(dest, beneficiary, assets, 0, weight)
|
|
414
|
-
.signAndSend(alice, { signer, tip: 1_000_000n }, (result) => {
|
|
415
|
-
console.dir(result, { depth: null });
|
|
416
|
-
});
|
|
417
|
-
```
|
|
418
|
-
|
|
419
|
-
</details>
|
|
420
|
-
|
|
421
|
-
### Events
|
|
422
|
-
|
|
423
|
-
Events for each pallet emit during runtime operations and are defined in the medata. Available events are also exposed in `ChainApi` interface so we can get information of an event through syntax `api.events.<pallet>.<eventName>`. E.g: Events for Polkadot network can be found [here](https://github.com/dedotdev/chaintypes/blob/main/packages/chaintypes/src/polkadot/events.d.ts), similarly for other network as well.
|
|
424
|
-
|
|
425
|
-
This `api.events` is helpful when we want quickly check if an event matches with an event that we're expecting in a list of events, the API also comes with type narrowing for the matched event, so event name & related data of the event are fully typed.
|
|
426
|
-
|
|
427
|
-
Example to list new accounts created in each block:
|
|
428
|
-
|
|
429
|
-
```typescript
|
|
430
|
-
// ...
|
|
431
|
-
const ss58Prefix = api.consts.system.ss58Prefix;
|
|
432
|
-
await api.query.system.events(async (eventRecords) => {
|
|
433
|
-
const newAccountEvents = api.events.system.NewAccount.filter(eventRecords);
|
|
434
|
-
|
|
435
|
-
console.log(newAccountEvents.length, 'account(s) was created in block', await api.query.system.number());
|
|
436
|
-
|
|
437
|
-
newAccountEvents.forEach((event, index) => {
|
|
438
|
-
console.log(`New Account ${index + 1}:`, event.palletEvent.data.account.address(ss58Prefix));
|
|
439
|
-
});
|
|
440
|
-
});
|
|
441
|
-
// ...
|
|
442
|
-
```
|
|
443
|
-
|
|
444
|
-
### Errors
|
|
445
|
-
|
|
446
|
-
Pallet errors are thrown out when things go wrong in the runtime, those are defined in the metadata. Available errors for each pallet are also exposed in `ChainApi` interface, so we can get information an error through this syntax: `api.errors.<pallet>.<errorName>`. E.g: Available errors for Polkadot network can be found [here](https://github.com/dedotdev/chaintypes/blob/main/packages/chaintypes/src/polkadot/errors.d.ts).
|
|
447
|
-
|
|
448
|
-
Similar to events API, this API is helpful when we want to check if an error maches with an error that we're expecting.
|
|
449
|
-
|
|
450
|
-
Example if an error is `AlreadyExists` from `Assets` pallet:
|
|
451
|
-
|
|
452
|
-
```typescript
|
|
453
|
-
// ...
|
|
454
|
-
await api.query.system.events(async (eventRecords) => {
|
|
455
|
-
for (const tx of eventRecords) {
|
|
456
|
-
if (api.events.system.ExtrinsicFailed.is(tx.event)) {
|
|
457
|
-
const { dispatchError } = tx.event.palletEvent.data;
|
|
458
|
-
if (api.errors.assets.AlreadyExists.is(dispatchError)) {
|
|
459
|
-
console.log('Assets.AlreadyExists error occurred!');
|
|
460
|
-
} else {
|
|
461
|
-
console.log('Other error occurred', dispatchError);
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
}
|
|
65
|
+
// Listen to best blocks
|
|
66
|
+
client.chainHead.on('bestBlock', (block: PinnedBlock) => { // or 'finalizedBlock'
|
|
67
|
+
console.log(`Current best block number: ${block.number}, hash: ${block.hash}`);
|
|
465
68
|
});
|
|
466
|
-
// ...
|
|
467
|
-
```
|
|
468
|
-
|
|
469
|
-
### Interact with ink! Smart Contracts
|
|
470
|
-
Dedot offers type-safe APIs to interact with ink! smart contracts. Primitives to work with contracts are exposed in `dedot/contract` package.
|
|
471
|
-
|
|
472
|
-
#### Generate Types & APIs from contract metadata
|
|
473
|
-
Before interacting with a contract, you need to generate Types & APIs from the contract metadata to interact with. You can do that using `dedot` cli:
|
|
474
|
-
|
|
475
|
-
```shell
|
|
476
|
-
dedot typink -m ./path/to/metadata.json # or metadata.contract
|
|
477
|
-
|
|
478
|
-
# use option -o to customize folder to put generated types
|
|
479
|
-
dedot typink -m ./path/to/metadata.json -o ./where/to-put/generated-types
|
|
480
|
-
```
|
|
481
|
-
After running the command, Types & APIs of the contract will be generated.
|
|
482
|
-
E.g: if the contract's name is `flipper`, the Types & APIs will be put in a folder named `flipper`, the entry-point interface for the contract will be `FlipperContractApi` in `flipper/index.d.ts` file. An example of Types & APIs for flipper contract can be found [here](https://github.com/dedotdev/dedot/tree/main/zombienet-tests/src/contracts/flipper).
|
|
483
|
-
|
|
484
|
-
#### Deploy contracts
|
|
485
|
-
|
|
486
|
-
Whether it's to deploy a contract from a wasm code or using an existing wasm code hash. You can do it using the `ContractDeployer`.
|
|
487
|
-
|
|
488
|
-
```typescript
|
|
489
|
-
import { DedotClient, WsProvider } from 'dedot';
|
|
490
|
-
import { ContractDeployer } from 'dedot/contract';
|
|
491
|
-
import { stringToHex } from 'dedot/utils'
|
|
492
|
-
import { FlipperContractApi } from './flipper';
|
|
493
|
-
import flipperMetadata from './flipper.json' assert { type: 'json' };
|
|
494
|
-
|
|
495
|
-
// instanciate an api client
|
|
496
|
-
const client = await DedotClient.new(new WsProvider('...'));
|
|
497
|
-
|
|
498
|
-
// load contract wasm or prepare a wasm codeHash
|
|
499
|
-
const wasm = '0x...';
|
|
500
|
-
const existingCodeHash = '0x...' // uploaded wasm
|
|
501
|
-
|
|
502
|
-
// create a ContractDeployer instance
|
|
503
|
-
const deployer = new ContractDeployer<FlipperContractApi>(client, flipperMetadata, wasm);
|
|
504
|
-
|
|
505
|
-
// OR from existingCodeHash
|
|
506
|
-
// const deployer = new ContractDeployer<FlipperContractApi>(client, flipperMetadata, existingCodeHash);
|
|
507
|
-
|
|
508
|
-
const ALICE = '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY'; // Alice
|
|
509
|
-
|
|
510
|
-
// Some random salt to prevent duplication issue
|
|
511
|
-
// Salt is optional, you can skip this to use an empty salt
|
|
512
|
-
const salt = stringToHex('random-salt');
|
|
513
|
-
|
|
514
|
-
// Dry run the constructor call for validation and gas estimation
|
|
515
|
-
// An Error will be thrown out if there's a DispatchError or LangError (contract level error)
|
|
516
|
-
// More on this in the handling error section below
|
|
517
|
-
const dryRun = await deployer.query.new(true, { caller: ALICE, salt })
|
|
518
|
-
const { raw: { gasRequired } } = dryRun;
|
|
519
|
-
|
|
520
|
-
// Submitting the transaction to instanciate the contract
|
|
521
|
-
await deployer.tx.new(true, { gasLimit: gasRequired, salt })
|
|
522
|
-
.signAndSend(ALICE, ({ status, events}) => {
|
|
523
|
-
if (status.type === 'BestChainBlockIncluded' || status.type === 'Finalized') {
|
|
524
|
-
// fully-typed event
|
|
525
|
-
const instantiatedEvent = client.events.contracts.Instantiated.find(events);
|
|
526
|
-
const contractAddress = instantiatedEvent.palletEvent.data.contract.address();
|
|
527
|
-
}
|
|
528
|
-
});
|
|
529
|
-
```
|
|
530
|
-
|
|
531
|
-
In case the contract constructor returning a `Result<Self, Error>`, you can also check the see if the instantiation get any errors before submitting the transaction.
|
|
532
|
-
|
|
533
|
-
```typescript
|
|
534
|
-
const { data } = await deployer.query.new(true, { caller: ALICE, salt })
|
|
535
|
-
if (data.isErr) {
|
|
536
|
-
console.log('Contract instantiation returning an error:', data.err);
|
|
537
|
-
} else {
|
|
538
|
-
// submitting the transaction
|
|
539
|
-
}
|
|
540
|
-
```
|
|
541
|
-
|
|
542
|
-
An example of this case can be found [here](https://github.com/dedotdev/dedot/blob/005ac48f5dcc5259da4a20fd5e87e4990bd773b3/zombienet-tests/src/0001-verify-contract-errors.ts#L43-L44).
|
|
543
|
-
|
|
544
|
-
#### Query contracts
|
|
545
|
-
|
|
546
|
-
The `Contract` interface will be using to interact with a contract with syntax `contract.query.<message>`.
|
|
547
|
-
|
|
548
|
-
```typescript
|
|
549
|
-
import { Contract } from 'dedot/contract';
|
|
550
|
-
import { FlipperContractApi } from './flipper';
|
|
551
|
-
import flipperMetadata from './flipper.json' assert { type: 'json' };
|
|
552
|
-
|
|
553
|
-
// ... initializing DedotClient
|
|
554
|
-
|
|
555
|
-
const ALICE = '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY'; // Alice
|
|
556
|
-
const contractAddress = '...';
|
|
557
|
-
|
|
558
|
-
// create a contract instace from its metadata & address
|
|
559
|
-
const contract = new Contract<FlipperContractApi>(client, flipperMetadata, contractAddress);
|
|
560
|
-
|
|
561
|
-
// Making call to get the current value of the flipper contract
|
|
562
|
-
const result = await contract.query.get({ caller: ALICE });
|
|
563
|
-
|
|
564
|
-
// Typescipt can inspect the type of value as `boolean` with the support of FlipperContractApi interface
|
|
565
|
-
const value: boolean = result.data;
|
|
566
|
-
|
|
567
|
-
// You can also have access to the detailed/raw result of the call
|
|
568
|
-
const rawResult = result.raw;
|
|
569
|
-
```
|
|
570
|
-
|
|
571
|
-
#### Submitting transactions
|
|
572
|
-
|
|
573
|
-
Similarly to query contracts, the `Contract` interface will also be using to submitting transactions with syntax: `contract.tx.<message>`
|
|
574
|
-
|
|
575
|
-
```typescript
|
|
576
|
-
import { Contract } from 'dedot/contract';
|
|
577
|
-
import { FlipperContractApi } from './flipper';
|
|
578
|
-
import flipperMetadata from './flipper.json' assert { type: 'json' };
|
|
579
|
-
|
|
580
|
-
// ... initializing DedotClient
|
|
581
69
|
|
|
582
|
-
|
|
583
|
-
const
|
|
70
|
+
// Query on-chain storage
|
|
71
|
+
const balance = await client.query.system.account(<address>);
|
|
72
|
+
console.log('Balance:', balance);
|
|
584
73
|
|
|
585
|
-
//
|
|
586
|
-
const
|
|
74
|
+
// Get pallet constants
|
|
75
|
+
const ss58Prefix = client.consts.system.ss58Prefix;
|
|
76
|
+
console.log('Polkadot ss58Prefix:', ss58Prefix);
|
|
587
77
|
|
|
588
|
-
//
|
|
589
|
-
const
|
|
78
|
+
// Call runtime api
|
|
79
|
+
const pendingRewards = await client.call.nominationPoolsApi.pendingRewards(<address>)
|
|
80
|
+
console.log('Pending rewards:', pendingRewards);
|
|
590
81
|
|
|
591
|
-
//
|
|
592
|
-
//
|
|
593
|
-
if (data.isErr) {
|
|
594
|
-
console.log('Cannot make transaction due to error:', data.err);
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
// Submitting the transaction after passing validation
|
|
598
|
-
await contract.tx.flip({ gasLimit: raw.gasRequired })
|
|
599
|
-
.signAndSend(ALICE, ({ status, events }) => {
|
|
600
|
-
if (status.type === 'BestChainBlockIncluded' || status.type === 'Finalized') {
|
|
601
|
-
// fully-typed event
|
|
602
|
-
const flippedEvent = contract.events.Flipped.find(events);
|
|
603
|
-
console.log('Old value', flippedEvent.data.old);
|
|
604
|
-
console.log('New value', flippedEvent.data.new);
|
|
605
|
-
}
|
|
606
|
-
})
|
|
607
|
-
|
|
608
|
-
```
|
|
609
|
-
|
|
610
|
-
#### Contract events
|
|
611
|
-
|
|
612
|
-
The `Contract` interface also have APIs to help you work with contract events easily and smoothly.
|
|
613
|
-
|
|
614
|
-
```typescript
|
|
615
|
-
import { ContractEvent } from 'dedot/contract';
|
|
616
|
-
|
|
617
|
-
// Initialize Contract instance
|
|
618
|
-
const contract = new Contract<FlipperContractApi>(client, flipperMetadata, contractAddress);
|
|
619
|
-
|
|
620
|
-
// Extracting contract events from transaction events
|
|
621
|
-
await contract.tx.flip({ gasLimit: raw.gasRequired })
|
|
622
|
-
.signAndSend(ALICE, ({ status, events }) => {
|
|
623
|
-
if (status.type === 'BestChainBlockIncluded' || status.type === 'Finalized') {
|
|
624
|
-
// fully-typed event
|
|
625
|
-
const flippedEvent = contract.events.Flipped.find(events);
|
|
626
|
-
console.log('Old value', flippedEvent.data.old);
|
|
627
|
-
console.log('New value', flippedEvent.data.new);
|
|
628
|
-
|
|
629
|
-
// an array of Flipped event
|
|
630
|
-
const flippedEvents = contract.events.Flipped.filter(events);
|
|
631
|
-
|
|
632
|
-
// Get all contract events from current transactions
|
|
633
|
-
const contractEvents: ContractEvent[] = contract.decodeEvents(events);
|
|
634
|
-
|
|
635
|
-
// Another way to get the Flipper event
|
|
636
|
-
const flippedEvent2 = contractEvents.find(contract.events.Flipped.is);
|
|
637
|
-
}
|
|
638
|
-
});
|
|
639
|
-
|
|
640
|
-
// Extracting contract events from system events
|
|
641
|
-
await client.query.system.events((events) => {
|
|
642
|
-
// fully-typed event
|
|
643
|
-
const flippedEvent = contract.events.Flipped.find(events);
|
|
644
|
-
|
|
645
|
-
// get all events of this contract from current block
|
|
646
|
-
const contractEvents: ContractEvent[] = contract.decodeEvents(events);
|
|
647
|
-
})
|
|
648
|
-
```
|
|
649
|
-
|
|
650
|
-
#### Handling errors
|
|
651
|
-
|
|
652
|
-
Interacting with a contract often resulting in errors at runtime level ([DispatchError](https://docs.rs/frame-support/latest/frame_support/pallet_prelude/enum.DispatchError.html)) or contract-level ([LangError](https://use.ink/4.x/faq/migrating-from-ink-3-to-4#add-support-for-language-level-errors-langerror)).
|
|
653
|
-
Whenever running into these errors, Dedot will throw an Error containing specific context about the problem so developers can handle this accordingly.
|
|
654
|
-
|
|
655
|
-
```typescript
|
|
656
|
-
import {
|
|
657
|
-
isContractInstantiateDispatchError, isContractInstantiateLangError,
|
|
658
|
-
isContractDispatchError, isContractLangError
|
|
659
|
-
} from "dedot/contracts";
|
|
660
|
-
import { FlipperContractApi } from "./flipper";
|
|
661
|
-
|
|
662
|
-
const ALICE = '...';
|
|
663
|
-
|
|
664
|
-
try {
|
|
665
|
-
// Dry-run contract construction
|
|
666
|
-
const dryRun = await deployer.query.new(true, { caller: ALICE })
|
|
667
|
-
|
|
668
|
-
// ...
|
|
669
|
-
} catch (e: any) {
|
|
670
|
-
if (isContractInstantiateDispatchError<FlipperContractApi>(e)) {
|
|
671
|
-
// Getting a runtime level error (e.g: Module error, Overflow error ...)
|
|
672
|
-
const { dispatchError, raw } = e;
|
|
673
|
-
const errorMeta = client.registy.findErrorMeta(dispatchError);
|
|
674
|
-
// ...
|
|
675
|
-
}
|
|
676
|
-
|
|
677
|
-
if (isContractInstantiateLangError<FlipperContractApi>(e)) {
|
|
678
|
-
const { langError, raw } = e;
|
|
679
|
-
console.log('LangError', langError);
|
|
680
|
-
}
|
|
681
|
-
|
|
682
|
-
// Other errors ...
|
|
683
|
-
}
|
|
684
|
-
|
|
685
|
-
try {
|
|
686
|
-
// Dry-run mutable contract message
|
|
687
|
-
const dryRun = await contract.query.flip({ caller: ALICE })
|
|
688
|
-
|
|
689
|
-
// ...
|
|
690
|
-
} catch (e: any) {
|
|
691
|
-
if (isContractDispatchError<FlipperContractApi>(e)) {
|
|
692
|
-
// Getting a runtime level error (e.g: Module error, Overflow error ...)
|
|
693
|
-
const { dispatchError, raw } = e;
|
|
694
|
-
const errorMeta = client.registy.findErrorMeta(dispatchError);
|
|
695
|
-
// ...
|
|
696
|
-
}
|
|
697
|
-
|
|
698
|
-
if (isContractLangError<FlipperContractApi>(e)) {
|
|
699
|
-
const { langError, raw } = e;
|
|
700
|
-
console.log('LangError', langError);
|
|
701
|
-
}
|
|
702
|
-
|
|
703
|
-
// Other errors ...
|
|
704
|
-
}
|
|
705
|
-
```
|
|
706
|
-
|
|
707
|
-
### Migration from `@polkadot/api` to `dedot`
|
|
708
|
-
`dedot` is inspired by `@polkadot/api`, so both are sharing some common patterns and api styling (eg: api syntax `api.<type>.<module>.<section>`). Although we have experimented some other different api stylings but to our findings and development experience, we find that the api style of `@polkadot/api` is very intuiative and easy to use. We decide the use a similar api styling with `@polkadot/api`, this also helps the migration from `@polkadot/api` to `dedot` easier & faster.
|
|
709
|
-
|
|
710
|
-
While the api style are similar, but there're also some differences you might need to be aware of when switching to use `dedot`.
|
|
711
|
-
|
|
712
|
-
#### Initialize api client
|
|
713
|
-
|
|
714
|
-
- `@polkadot/api`
|
|
715
|
-
|
|
716
|
-
```typescript
|
|
717
|
-
import { ApiPromise, WsProvider } from '@polkadot/api';
|
|
718
|
-
|
|
719
|
-
const api = await ApiPromise.create({ provider: new WsProvider('wss://rpc.polkadot.io') });
|
|
82
|
+
// await unsub();
|
|
83
|
+
// await client.disconnect();
|
|
720
84
|
```
|
|
721
85
|
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
import { DedotClient, WsProvider } from 'dedot';
|
|
726
|
-
import type { PolkadotApi } from '@dedot/chaintypes';
|
|
727
|
-
|
|
728
|
-
const api = await DedotClient.new<PolkadotApi>(new WsProvider('wss://rpc.polkadot.io')); // or DedotClient.create(...) if you prefer
|
|
729
|
-
|
|
730
|
-
// OR
|
|
731
|
-
const api = await DedotClient.new<PolkadotApi>({ provider: new WsProvider('wss://rpc.polkadot.io') });
|
|
732
|
-
```
|
|
733
|
-
|
|
734
|
-
- Notes:
|
|
735
|
-
- `dedot` only supports provider can make subscription request (e.g: via Websocket).
|
|
736
|
-
- We recommend specifying the `ChainApi` interface (e.g: [`PolkadotApi`](https://github.com/dedotdev/chaintypes/blob/main/packages/chaintypes/src/polkadot/index.d.ts) in the example above) of the chain that you want to interact with. This enable apis & types suggestion/autocompletion for that particular chain (via IntelliSense). If you don't specify a `ChainApi` interface, the default [`SubstrateApi`](https://github.com/dedotdev/dedot/blob/a762faf8f6af40d3e4ef163bd538b270a5ca31e8/packages/chaintypes/src/substrate/index.d.ts) interface will be used.
|
|
737
|
-
- `WsProvider` from `dedot` and `@polkadot/api` are different, they cannot be used interchangeable.
|
|
738
|
-
|
|
739
|
-
#### Type system
|
|
740
|
-
|
|
741
|
-
Unlike `@polkadot/api` where data are wrapped inside a [codec types](https://polkadot.js.org/docs/api/start/types.basics), so we always need to unwrap the data before using it (e.g: via `.unwrap()`, `.toNumber()`, `.toString()`, `.toJSON()` ...). `dedot` leverages the native TypeScript type system to represent scale-codec types, so you can use the data directly without extra handling/unwrapping. The table below is a mapping between scale-codec types and TypeScript types that we're using for `dedot`:
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
| Scale Codec | TypeScript (`dedot`) |
|
|
745
|
-
|---------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------|
|
|
746
|
-
| `u8`, `u16`, `u32`, `i8`, `i16`, `i32` | `number` |
|
|
747
|
-
| `u64`, `u128`, `u256`, `i64`, `i128`, `i256` | `bigint` (native [BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt), not bn.js) |
|
|
748
|
-
| `bool` | `boolean` (true, false) |
|
|
749
|
-
| `Option<T>` | `T \| undefined` |
|
|
750
|
-
| `Result<Ok, Err>` | `{ isOk: true; isErr?: false; value: Ok } \| { isOk?: false; isErr: true; err: Err }` |
|
|
751
|
-
| `Vec<T>` | `Array<T>` |
|
|
752
|
-
| `str` | `string` |
|
|
753
|
-
| Tuple: `(A, B)`, `()` | `[A, B]`, `[]` |
|
|
754
|
-
| Struct: `struct { field_1: u8, field_2: str }` | `{ field_1: number, field_2: string}` |
|
|
755
|
-
| Enum: `enum { Variant1(u8), Variant2(bool), Variant3 }` | `{ type: 'Variant1', value: number } \| { type: 'Variant2', value: boolean } \| { type: 'Variant2' }` |
|
|
756
|
-
| FlatEnum: `enum { Variant1, Variant2 }` | `'Variant1' \| 'Variant2'` |
|
|
757
|
-
|
|
758
|
-
E.g 1:
|
|
759
|
-
|
|
760
|
-
```typescript
|
|
761
|
-
const runtimeVersion = api.consts.system.version;
|
|
762
|
-
|
|
763
|
-
// @polkadot/api
|
|
764
|
-
const specName: string = runtimeVersion.toJSON().specName; // OR runtimeVersion.specName.toString()
|
|
765
|
-
|
|
766
|
-
// dedot
|
|
767
|
-
const specName: string = runtimeVersion.specName;
|
|
768
|
-
```
|
|
769
|
-
|
|
770
|
-
E.g 2:
|
|
771
|
-
|
|
772
|
-
```typescript
|
|
773
|
-
const balance = await api.query.system.account(<address>);
|
|
774
|
-
|
|
775
|
-
// @polkadot/api
|
|
776
|
-
const freeBalance: bigint = balance.data.free.toBigInt();
|
|
777
|
-
|
|
778
|
-
// dedot
|
|
779
|
-
const freeBalance: bigint = balance.data.free;
|
|
780
|
-
```
|
|
781
|
-
|
|
782
|
-
E.g 3:
|
|
783
|
-
|
|
784
|
-
```typescript
|
|
785
|
-
// @polkadot/api
|
|
786
|
-
const proposalBondMaximum: bigint | undefined = api.consts.treasury.proposalBondMaximum.unwrapOr(undefined)?.toBigInt();
|
|
787
|
-
|
|
788
|
-
// dedot
|
|
789
|
-
const proposalBondMaximum: bigint | undefined = api.consts.treasury.proposalBondMaximum;
|
|
790
|
-
```
|
|
791
|
-
|
|
792
|
-
### Packages Structure
|
|
793
|
-
|
|
794
|
-
| Package name | Description |
|
|
795
|
-
|--------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------|
|
|
796
|
-
| [@dedot/api](https://github.com/dedotdev/dedot/tree/main/packages/api) | High-level abstraction apis (clients, API executors...) |
|
|
797
|
-
| [@dedot/providers](https://github.com/dedotdev/dedot/tree/main/packages/providers) | Providers for connection to JSON-RPC servers (WsProvider, SmoldotProvider) |
|
|
798
|
-
| [@dedot/types](https://github.com/dedotdev/dedot/tree/main/packages/types) | Generic shared types across the packages |
|
|
799
|
-
| [@dedot/runtime-specs](https://github.com/dedotdev/dedot/tree/main/packages/runtime-specs) | Explicit Runtime API definitions to use for chains only supports Metadata V14 |
|
|
800
|
-
| [@dedot/shape](https://github.com/dedotdev/dedot/tree/main/packages/shape) | Basic codecs/shapes for scale-codec encode/decode |
|
|
801
|
-
| [@dedot/contracts](https://github.com/dedotdev/dedot/tree/main/packages/contracts) | APIs to interact with ink! smart contracts |
|
|
802
|
-
| [@dedot/codecs](https://github.com/dedotdev/dedot/tree/main/packages/codecs) | Known codecs for generic purposes ($Metadata, $AccountId32, $Extrinsic ...) |
|
|
803
|
-
| [@dedot/utils](https://github.com/dedotdev/dedot/tree/main/packages/utils) | Useful utility functions |
|
|
804
|
-
| [@dedot/storage](https://github.com/dedotdev/dedot/tree/main/packages/storage) | Storage API for different purposes (caching, ...) |
|
|
805
|
-
| [@dedot/codegen](https://github.com/dedotdev/dedot/tree/main/packages/codegen) | Types & APIs generation engine for chaintypes & ink! smart contracts |
|
|
806
|
-
| [@dedot/cli](https://github.com/dedotdev/dedot/tree/main/packages/cli) | Dedot's CLI |
|
|
807
|
-
| [dedot](https://github.com/dedotdev/dedot/tree/main/packages/dedot) | Umbrella package re-exporting API from other packages |
|
|
808
|
-
|
|
86
|
+
### Resources & announcements
|
|
87
|
+
- [Introducing Dedot](https://forum.polkadot.network/t/introducing-dedot-a-delightful-javascript-client-for-polkadot-substrate-based-blockchains/8956)
|
|
88
|
+
- [Type-safe APIs to interact with ink! Smart Contracts](https://forum.polkadot.network/t/type-safe-apis-to-interact-with-ink-smart-contracts-dedot/9485)
|
|
809
89
|
|
|
810
|
-
###
|
|
90
|
+
### Acknowledment
|
|
811
91
|
|
|
812
|
-
|
|
92
|
+
[Dedot](https://dedot.dev) take a lot of inspirations from project [@polkadot/api](https://github.com/polkadot-js/api). A big thank to all the maintainers/contributors of this awesome library.
|
|
813
93
|
|
|
814
94
|
Proudly supported by Web3 Foundation Grants Program.
|
|
815
95
|
<p align="left">
|
|
816
|
-
<img width="
|
|
96
|
+
<img width="250" src="https://user-images.githubusercontent.com/6867026/227230786-0796214a-3e3f-42af-94e9-d4122c730b62.png">
|
|
817
97
|
</p>
|
|
818
98
|
|
|
819
99
|
### License
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dedot",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "A delightful JavaScript/TypeScript client for Polkadot & Substrate",
|
|
5
5
|
"author": "Thang X. Vu <thang@coongcrafts.io>",
|
|
6
6
|
"homepage": "https://github.com/dedotdev/dedot",
|
|
@@ -21,15 +21,15 @@
|
|
|
21
21
|
"clean": "rm -rf ./dist && rm -rf ./tsconfig.tsbuildinfo ./tsconfig.build.tsbuildinfo"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@dedot/api": "0.
|
|
25
|
-
"@dedot/cli": "0.
|
|
26
|
-
"@dedot/codecs": "0.
|
|
27
|
-
"@dedot/contracts": "0.
|
|
28
|
-
"@dedot/providers": "0.
|
|
29
|
-
"@dedot/runtime-specs": "0.
|
|
30
|
-
"@dedot/shape": "0.
|
|
31
|
-
"@dedot/types": "0.
|
|
32
|
-
"@dedot/utils": "0.
|
|
24
|
+
"@dedot/api": "0.6.0",
|
|
25
|
+
"@dedot/cli": "0.6.0",
|
|
26
|
+
"@dedot/codecs": "0.6.0",
|
|
27
|
+
"@dedot/contracts": "0.6.0",
|
|
28
|
+
"@dedot/providers": "0.6.0",
|
|
29
|
+
"@dedot/runtime-specs": "0.6.0",
|
|
30
|
+
"@dedot/shape": "0.6.0",
|
|
31
|
+
"@dedot/types": "0.6.0",
|
|
32
|
+
"@dedot/utils": "0.6.0"
|
|
33
33
|
},
|
|
34
34
|
"exports": {
|
|
35
35
|
".": {
|
|
@@ -92,7 +92,7 @@
|
|
|
92
92
|
"directory": "dist"
|
|
93
93
|
},
|
|
94
94
|
"license": "Apache-2.0",
|
|
95
|
-
"gitHead": "
|
|
95
|
+
"gitHead": "80e64c7da483c4f5b757f6af7259aa4fdd5397fc",
|
|
96
96
|
"module": "./index.js",
|
|
97
97
|
"types": "./index.d.ts"
|
|
98
98
|
}
|