Skip to content
Merged
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
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
"pioneer",
"pioneer/packages/apps*",
"pioneer/packages/page*",
"pioneer/packages/react*"
"pioneer/packages/react*",
"utils/api-examples"
],
"resolutions": {
"@polkadot/api": "1.26.1",
Expand Down
46 changes: 46 additions & 0 deletions utils/api-examples/README.md
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
```
25 changes: 25 additions & 0 deletions utils/api-examples/package.json
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"
}
}
32 changes: 32 additions & 0 deletions utils/api-examples/scripts/example.js
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
}
49 changes: 49 additions & 0 deletions utils/api-examples/scripts/export-data-directory.js
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
}
9 changes: 9 additions & 0 deletions utils/api-examples/scripts/index.js
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
60 changes: 60 additions & 0 deletions utils/api-examples/scripts/inject-data-objects.js

Large diffs are not rendered by default.

33 changes: 33 additions & 0 deletions utils/api-examples/scripts/list-data-directory.js
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: ${api.createType('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
}
31 changes: 31 additions & 0 deletions utils/api-examples/scripts/transfer.js
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
}
20 changes: 20 additions & 0 deletions utils/api-examples/src/get-code.ts
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())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This gives me just 0x as output (but also happens in Pioneer via Extrinsics tab)

Copy link
Member Author

Choose a reason for hiding this comment

The 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?

Copy link
Contributor

@Lezek123 Lezek123 Aug 19, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While working on #1177 I noticed that in the augment-api.ts auto-generated by @polkadot/typegen based on runtime metadata there is no substrate module at all.

So i did a little digging and found out that:

  • This module is not part of the metadata retrieved via api.rpc.state.getMetadata() (even when I get it from our current testnet node)
  • The same query also outputs 0x on current Kusama
  • It doesn't throw any errors (which happens in case of the Vec size limit issue that I ran into)


api.disconnect()
}

main()
52 changes: 52 additions & 0 deletions utils/api-examples/src/script.ts
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()
56 changes: 56 additions & 0 deletions utils/api-examples/src/status.ts
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()
Loading