-
Notifications
You must be signed in to change notification settings - Fork 116
Add api examples to monorepo #1155
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
Changes from 14 commits
d19c507
711be6e
4236c3a
bfa0305
36d510b
9dd1cab
ba05fb5
7081f0f
16687b6
c989f88
9e28c05
67f3baf
4f08ea2
0e3362b
0c3770d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| # Joystream API Examples | ||
|
|
||
| Repo with examples on how to use the @joystream/types package along with @polkadot/api to communicate with a joystream full node. | ||
|
|
||
| ## Examples | ||
|
|
||
| ``` | ||
| yarn | ||
| yarn run status | ||
| ``` | ||
|
|
||
| ## Example code | ||
|
|
||
| ```javascript | ||
| import { types } from '@joystream/types' | ||
| import { ApiPromise, WsProvider } from '@polkadot/api' | ||
|
|
||
| async function main() { | ||
| // Initialise the provider to connect to the local node | ||
| const provider = new WsProvider('ws://127.0.0.1:9944') | ||
|
|
||
| // Create the API and wait until ready | ||
| const api = await ApiPromise.create({ provider, types }) | ||
|
|
||
| await api.isReady | ||
|
|
||
| // Retrieve the chain & node information information via rpc calls | ||
| const [chain, nodeName, nodeVersion] = await Promise.all([ | ||
| api.rpc.system.chain(), | ||
| api.rpc.system.name(), | ||
| api.rpc.system.version(), | ||
| ]) | ||
|
|
||
| console.log(`Chain ${chain} using ${nodeName} v${nodeVersion}`) | ||
| } | ||
|
|
||
| main() | ||
| ``` | ||
|
|
||
| ### Scripts | ||
|
|
||
| You can run scripts that are found in the [./scripts/](./scripts) folder: | ||
|
|
||
| ```sh | ||
| yarn script example | ||
| ``` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| { | ||
| "name": "api-examples", | ||
| "private": true, | ||
| "version": "0.1.0", | ||
| "license": "GPL-3.0-only", | ||
| "scripts": { | ||
| "status": "ts-node src/status", | ||
| "script": "ts-node src/script" | ||
| }, | ||
| "dependencies": { | ||
| "@joystream/types": "^0.13.0", | ||
| "@polkadot/api": "^1.26.1", | ||
| "@polkadot/types": "^1.26.1", | ||
| "@polkadot/keyring": "^3.0.1", | ||
| "@polkadot/util": "^3.0.1", | ||
| "@polkadot/util-crypto": "^3.0.1", | ||
| "@types/bn.js": "^4.11.5", | ||
| "bn.js": "^4.11.8" | ||
| }, | ||
| "devDependencies": { | ||
| "@polkadot/ts": "^0.1.56", | ||
| "typescript": "^3.9.7", | ||
| "ts-node": "^8.6.2" | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| /* global api, hashing, keyring, types, util, joy */ | ||
|
|
||
| // run this script with: | ||
| // yarn script example | ||
| // | ||
| // or copy and paste the code into the pioneer javascript toolbox at: | ||
| // https://testnet.joystream.org/#/js | ||
| // | ||
| // Example works on nicaea release+ | ||
|
|
||
| const script = async ({ api, hashing, keyring, types, util, joy }) => { | ||
| // Retrieve the chain & node information information via rpc calls | ||
| const [chain, nodeName, nodeVersion, runtimeVersion] = await Promise.all([ | ||
| api.rpc.system.chain(), | ||
| api.rpc.system.name(), | ||
| api.rpc.system.version(), | ||
| api.runtimeVersion, | ||
| ]) | ||
|
|
||
| console.log(`Chain: ${chain}`) | ||
| console.log(`Software: ${nodeName} v${nodeVersion}`) | ||
| console.log(`Runtime specVersion: ${runtimeVersion.specVersion}`) | ||
| } | ||
|
|
||
| if (typeof module === 'undefined') { | ||
| // Pioneer js-toolbox | ||
| // Available globals [api, hashing, keyring, types, util] | ||
| script({ api, hashing, keyring, types, util, joy }) | ||
| } else { | ||
| // Node | ||
| module.exports = script | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| /* global api, hashing, keyring, types, util */ | ||
|
|
||
| // run this script with: | ||
| // yarn script exportDataDirectory | ||
| // | ||
| // or copy and paste the code into the pioneer javascript toolbox at: | ||
| // https://testnet.joystream.org/#/js | ||
|
|
||
| const script = async ({ api }) => { | ||
| const ids = await api.query.dataDirectory.knownContentIds() | ||
|
|
||
| // When a BTreeMap is constructed for injection the node will fail to decode | ||
| // it if its not sorted. | ||
| ids.sort() | ||
|
|
||
| const transformed = await Promise.all( | ||
| ids.map(async (id) => { | ||
| let obj = await api.query.dataDirectory.dataObjectByContentId(id) | ||
| if (obj.isNone) { | ||
| return null | ||
| } | ||
| obj = obj.unwrap() | ||
|
|
||
| return [ | ||
| id, | ||
| { | ||
| owner: obj.owner, | ||
| added_at: obj.added_at, | ||
| type_id: obj.type_id, | ||
| size: obj.size_in_bytes, | ||
| liaison: obj.liaison, | ||
| liaison_judgement: obj.liaison_judgement, | ||
| ipfs_content_id: obj.ipfs_content_id, | ||
| }, | ||
| ] | ||
| }) | ||
| ) | ||
|
|
||
| console.log(JSON.stringify(transformed)) | ||
| console.error(`Exported ${transformed.length} objects`) | ||
| } | ||
|
|
||
| if (typeof module === 'undefined') { | ||
| // Pioneer js-toolbox | ||
| script({ api, hashing, keyring, types, util }) | ||
| } else { | ||
| // Node | ||
| module.exports = script | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| const exportedScripts = {} | ||
|
|
||
| exportedScripts.example = require('./example.js') | ||
| exportedScripts.exportDataDirectory = require('./export-data-directory.js') | ||
| exportedScripts.injectDataObjects = require('./inject-data-objects.js') | ||
| exportedScripts.listDataDirectory = require('./list-data-directory.js') | ||
| exportedScripts.testTransfer = require('./transfer.js') | ||
|
|
||
| module.exports = exportedScripts |
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| /* global api, hashing, keyring, types, util, joy */ | ||
|
|
||
| // run this script with: | ||
| // yarn script listDataDirectory | ||
| // | ||
| // or copy and paste the code into the pioneer javascript toolbox at: | ||
| // https://testnet.joystream.org/#/js | ||
| // requires nicaea release+ | ||
|
|
||
| const script = async ({ api, joy }) => { | ||
| const ids = await api.query.dataDirectory.knownContentIds() | ||
|
|
||
| await Promise.all( | ||
| ids.map(async (id) => { | ||
| let obj = await api.query.dataDirectory.dataObjectByContentId(id) | ||
| if (obj.isNone) { | ||
| return | ||
| } | ||
| obj = obj.unwrap() | ||
| console.log(`contentId: ${new joy.media.ContentId(id).encode()}, ipfs: ${obj.ipfs_content_id}`) | ||
| }) | ||
| ) | ||
|
|
||
| console.error(`Data Directory contains ${ids.length} objects`) | ||
| } | ||
|
|
||
| if (typeof module === 'undefined') { | ||
| // Pioneer js-toolbox | ||
| script({ api, hashing, keyring, types, util, joy }) | ||
| } else { | ||
| // Node | ||
| module.exports = script | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| /* global api, hashing, keyring, types, util, window */ | ||
|
|
||
| // run this script with: | ||
| // yarn script testTransfer | ||
| // | ||
| // or copy and paste the code into the pioneer javascript toolbox at: | ||
| // https://testnet.joystream.org/#/js | ||
| // | ||
|
|
||
| const script = async ({ api, keyring }) => { | ||
| const sudoAddress = (await api.query.sudo.key()).toString() | ||
| let sudo | ||
| if (typeof window === 'undefined') { | ||
| // In node, get the keyPair if the keyring was provided | ||
| sudo = keyring.getPair(sudoAddress) | ||
| } else { | ||
| // Pioneer: let the UI Signer handle it | ||
| sudo = sudoAddress | ||
| } | ||
|
|
||
| const transfer = api.tx.balances.transfer(sudoAddress, 100) | ||
| await transfer.signAndSend(sudo) | ||
| } | ||
|
|
||
| if (typeof module === 'undefined') { | ||
| // Pioneer js-toolbox | ||
| script({ api, hashing, keyring, types, util }) | ||
| } else { | ||
| // Node | ||
| module.exports = script | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| import { ApiPromise, WsProvider } from '@polkadot/api' | ||
| import { types } from '@joystream/types' | ||
|
|
||
| async function main() { | ||
| const provider = new WsProvider('ws://127.0.0.1:9944') | ||
|
|
||
| const api = await ApiPromise.create({ provider, types }) | ||
|
|
||
| const currentBlockHash = await api.rpc.chain.getBlockHash(1) | ||
|
|
||
| console.log('getting code as of block hash', currentBlockHash.toString()) | ||
|
|
||
| const substrateWasm = await api.query.substrate.code.at(currentBlockHash) | ||
|
|
||
| console.log(substrateWasm.toHex()) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This gives me just
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes I was surprised by this as well. Does this have anything to do with the limit on the size of Vec you identified?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. While working on #1177 I noticed that in the So i did a little digging and found out that:
|
||
|
|
||
| api.disconnect() | ||
| } | ||
|
|
||
| main() | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| // @ts-check | ||
|
|
||
| import { ApiPromise, WsProvider } from '@polkadot/api' | ||
| import * as types from '@polkadot/types' | ||
| import * as util from '@polkadot/util' | ||
| import joy, { types as joyTypes } from '@joystream/types' | ||
| import * as hashing from '@polkadot/util-crypto' | ||
| import { Keyring } from '@polkadot/keyring' | ||
|
|
||
| // eslint-disable-next-line @typescript-eslint/no-var-requires | ||
| const scripts = require('../scripts') | ||
|
|
||
| async function main() { | ||
| const scriptArg = process.argv[2] | ||
| const script = scripts[scriptArg] | ||
|
|
||
| if (!scriptArg || !script) { | ||
| console.error('Please specify valid script name.') | ||
| console.error('Available scripts:', Object.keys(scripts)) | ||
| return | ||
| } | ||
|
|
||
| const provider = new WsProvider('ws://127.0.0.1:9944') | ||
|
|
||
| const api = await ApiPromise.create({ provider, types: joyTypes }) | ||
|
|
||
| // We don't pass a custom signer to the api so we must use a keyPair | ||
| // when calling signAndSend on transactions | ||
| const keyring = new Keyring() | ||
|
|
||
| // Optional last argument is a SURI for account to use for signing transactions | ||
| const suri = process.argv[3] | ||
| if (suri) { | ||
| keyring.addFromUri(suri, undefined, 'sr25519') | ||
| } | ||
|
|
||
| // Add development well known keys to keyring | ||
| if ((await api.rpc.system.chain()).toString() === 'Development') { | ||
| keyring.addFromUri('//Alice', undefined, 'sr25519') | ||
| keyring.addFromUri('//Bob', undefined, 'sr25519') | ||
| } | ||
|
|
||
| try { | ||
| await script({ api, types, util, hashing, keyring, joy }) | ||
| } catch (err) { | ||
| console.error(err) | ||
| } | ||
|
|
||
| api.disconnect() | ||
| } | ||
|
|
||
| main() |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| // @ts-check | ||
|
|
||
| import { ApiPromise, WsProvider } from '@polkadot/api' | ||
| import { types } from '@joystream/types' | ||
| import { Seat } from '@joystream/types/council' | ||
| import { ValidatorId } from '@polkadot/types/interfaces' | ||
|
|
||
| import BN from 'bn.js' | ||
|
|
||
| async function main() { | ||
| // Initialise the provider to connect to the local node | ||
| const provider = new WsProvider('ws://127.0.0.1:9944') | ||
|
|
||
| // Create the API and wait until ready | ||
| const api = await ApiPromise.create({ provider, types }) | ||
|
|
||
| // Retrieve the chain & node information information via rpc calls | ||
| const [chain, nodeName, nodeVersion] = await Promise.all([ | ||
| api.rpc.system.chain(), | ||
| api.rpc.system.name(), | ||
| api.rpc.system.version(), | ||
| ]) | ||
|
|
||
| console.log(`Chain ${chain} using ${nodeName} v${nodeVersion}`) | ||
|
|
||
| const council = ((await api.query.council.activeCouncil()) as unknown) as Seat[] | ||
| const validators = ((await api.query.session.validators()) as unknown) as ValidatorId[] | ||
| const version = (await api.rpc.state.getRuntimeVersion()) as any | ||
|
|
||
| console.log(`Runtime Version: ${version.authoringVersion}.${version.specVersion}.${version.implVersion}`) | ||
|
|
||
| // let council: QueryableStorageFunction<Seat[], SubscriptionResult> = (await api.query.council.activeCouncil()) as unknown as Seat[] | ||
| // let council = (await api.query.council.activeCouncil()) as unknown as Seat[]; | ||
|
|
||
| // number of council members | ||
| console.log('Council size:', council.length) | ||
|
|
||
| console.log('Validator count:', validators.length) | ||
|
|
||
| if (validators && validators.length > 0) { | ||
| // Retrieve the free balances for all validators | ||
| const validatorBalances = await Promise.all( | ||
| validators.map((authorityId) => api.query.balances.account(authorityId)) | ||
| ) | ||
|
|
||
| const totalValidatorBalances = validatorBalances.reduce((total, value) => total.add(value.free), new BN(0)) | ||
|
|
||
| // TODO: to get the staked amounts we need to read the account lock information. | ||
|
|
||
| console.log('Total Validator Free Balance:', totalValidatorBalances.toString()) | ||
| } | ||
|
|
||
| api.disconnect() | ||
| } | ||
|
|
||
| main() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be
api.createType('ContentId', id).encode()I'm not sure if the
joyglobal is very useful at this point, since we should be able to create any type withapi.createType().There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will fix 👍