SDK Version
This Documentation is based upon avail-js version v0.4.2
TS-Node
Save to index.ts
import { SDK } from "avail-js-sdk"
async function main() {}
main()
.catch((e) => {
console.log(e)
process.exit(1)
})
.finally(() => {
console.log("All Good")
process.exit(0)
})
Save to package.json
{
"name": "avail-js-docs",
"version": "0.0.1",
"description": "Avail-js SDK",
"dependencies": {
"avail-js-sdk": "^0.4.2"
},
"resolutions": {
"ws": ">=8.17.1"
}
}
Save to tsconfig.json
{
"compilerOptions": {
"target": "es2016",
"module": "commonjs",
"outDir": "build",
"declaration": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true,
"noUnusedParameters": true
},
"include": ["src"],
"exclude": ["node_modules", "build"]
}
You should now have the following files
- current directory
index.ts
package.json
tsconfig.json
Run the following commands:
npm i
ts-node ./index.ts
Deno
- Install Deno
Save to index.ts
import { SDK } from "avail-js-sdk"
async function main() {}
main()
.catch((e) => {
console.log(e)
process.exit(1)
})
.finally(() => {
console.log("All Good")
process.exit(0)
})
Save to package.json
{
"name": "avail-js-docs",
"version": "0.0.1",
"description": "Avail-js SDK",
"dependencies": {
"avail-js-sdk": "^0.4.2"
},
"resolutions": {
"ws": ">=8.17.1"
}
}
You should now have the following files
- current directory
index.ts
package.json
Run the following commands:
deno install
deno run -A ./index.ts
Bun
- Install Bun
Save to index.ts
import { SDK } from "avail-js-sdk"
async function main() {}
main()
.catch((e) => {
console.log(e)
process.exit(1)
})
.finally(() => {
console.log("All Good")
process.exit(0)
})
Save to package.json
{
"name": "avail-js-docs",
"version": "0.0.1",
"description": "Avail-js SDK",
"dependencies": {
"avail-js-sdk": "^0.4.2"
},
"resolutions": {
"ws": ">=8.17.1"
}
}
You should now have the following files
- current directory
index.ts
package.json
Run the following commands:
bun install
bun run ./index.ts
Data Submission
import { assert_eq, assert_true } from "."
import { Account, SDK, Pallets } from "./../src/index"
export async function runDataSubmission() {
const sdk = await SDK.New(SDK.localEndpoint)
const account = Account.alice()
const key = "" + Math.ceil(Math.random() * 1_000_000_00)
const tx = sdk.tx.dataAvailability.createApplicationKey(key)
const res = await tx.executeWaitForInclusion(account, {})
const isOk = res.isSuccessful()
// If the return value from `IsSuccessful` is undefined, it means that we cannot
// determine if the transaction was successful or not.
assert_true(isOk !== undefined)
// If the value of `IsSuccessful()` is false then the transaction has failed.
assert_eq(isOk, true)
// We might have failed to decode the events so res.events could be None.
if (res.events == undefined) throw new Error()
const event = res.events.findFirst(Pallets.DataAvailabilityEvents.ApplicationKeyCreated)
if (event == undefined) throw new Error()
const appId = event.id
console.log(`Owner: ${event.owner}, Key: ${event.keyToString()}, App Id: ${appId}`)
const tx2 = sdk.tx.dataAvailability.submitData("My Data")
const res2 = await tx2.executeWaitForInclusion(account, { app_id: appId })
assert_eq(res2.isSuccessful(), true)
// Transaction Details
console.log(
`Block Hash: ${res.blockHash}, Block Number: ${res.blockNumber}, Tx Hash: ${res.txHash}, Tx Index: ${res.txIndex}`,
)
// Events
if (res2.events == undefined) throw new Error()
for (const event of res.events.iter()) {
console.log(
`Pallet Name: ${event.palletName()}, Pallet Index: ${event.palletIndex()}, Event Name: ${event.eventName()}, Event Index: ${event.eventIndex()}, Tx Index: ${event.txIndex()}`,
)
}
const event2 = res2.events.findFirst(Pallets.DataAvailabilityEvents.DataSubmitted)
if (event2 == undefined) throw new Error()
console.log(`Who: ${event2.who}, DataHash: ${event2.dataHash}`)
console.log("runDataSubmission finished correctly")
}
Account
Account Creation
import { Account, cryptoWaitReady, AccountId } from "./../src/index"
export async function runAccountCreation() {
await cryptoWaitReady()
// Use `new` to create an account from uri
const alice = Account.new("//Alice")
console.log("Alice Address: ", alice.address)
// Use `generate` to generate a random account
const generated = Account.generate()
console.log("Generated Address: ", generated.address)
// There are predefined testing accounts available to be used on local dev networks.
console.log("Alice Address: ", Account.alice().address)
console.log("Bob Address: ", Account.bob().address)
console.log("Charlie Address: ", Account.charlie().address)
console.log("Eve Address: ", Account.eve().address)
console.log("Ferdie Address: ", Account.ferdie().address)
// SS58 address from Keyring
console.log("SS58 address: ", alice.address)
// Account Id from keyring, ss58 address or accountID32
const rawAccount = alice.publicKey
console.log("Raw Account Id: ", rawAccount)
const accountId1 = new AccountId(rawAccount)
console.log("Account Id SS58 address: ", accountId1.toSS58())
const accountId2 = AccountId.fromSS58(alice.address)
console.log("Account Id SS58 address: ", accountId2.toSS58())
console.log("runAccountCreation finished correctly")
}
Account Nonce
import { SDK, Account, Pallets } from "./../src/index"
export async function runAccountNonce() {
const sdk = await SDK.New(SDK.turingEndpoint)
// Via RPC
const nonce1 = await sdk.client.api.rpc.system.accountNextIndex("5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY")
console.log("Nonce: ", nonce1.toNumber())
// Via Storage RPC
const storageAt = await sdk.client.storageAt()
const storage = await Pallets.SystemStorage.Account.fetch(
storageAt,
"5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
)
console.log("Nonce: ", storage.value.nonce)
// Via Abstraction
const nonce2 = await Account.nonce(sdk.client, "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY")
console.log("Nonce: ", nonce2)
console.log("runAccountNonce finished correctly")
}
Account Balance
import { SDK, Account, Pallets } from "./../src/index"
export async function runAccountBalance() {
const sdk = await SDK.New(SDK.turingEndpoint)
// Via Storage RPC
const storageAt = await sdk.client.storageAt()
const storage = await Pallets.SystemStorage.Account.fetch(
storageAt,
"5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
)
console.log("Free Balance: ", storage.value.accountData.free.toString())
console.log("Reserved Balance: ", storage.value.accountData.reserved.toString())
console.log("Frozen Balance: ", storage.value.accountData.frozen.toString())
// Via Abstraction
const balance = await Account.balance(sdk.client, "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY")
console.log("Free Balance: ", balance.free.toString())
console.log("Reserved Balance: ", balance.reserved.toString())
console.log("Frozen Balance: ", balance.frozen.toString())
console.log("runAccountBalance finished correctly")
}
Block
All Block Transactions
import { assert_eq } from "."
import { SDK, Block, Pallets } from "./../src/index"
export async function runBlockTransactionAll() {
const sdk = await SDK.New(SDK.turingEndpoint)
const block = await Block.New(sdk.client, "0x94746ba186876d7407ee618d10cb6619befc59eeb173cacb00c14d1ff492fc58")
const blockTxs = block.transactions()
assert_eq(blockTxs.length, 9)
// Printout Block Transactions
for (const tx of blockTxs) {
console.log(
`Pallet Name: ${tx.palletName()}, Pallet Index: ${tx.palletIndex()}, Call Name: ${tx.callName()}, Call Index: ${tx.callIndex()}, Tx hash: ${tx.txHash()}, Tx Index: ${tx.txIndex()}`,
)
}
// Convert from Block Transaction to Specific Transaction
const decodedCall = blockTxs[2].decode(Pallets.DataAvailabilityCalls.SubmitData)
if (decodedCall == undefined) throw Error()
console.log(`Data: ${new TextDecoder().decode(decodedCall.data)}`)
// Printout all Transaction Events
const txEvents = blockTxs[2].events()
if (txEvents == undefined) throw Error()
assert_eq(txEvents.len(), 7)
for (const event of txEvents.iter()) {
console.log(
`Pallet Name: ${event.palletName()}, Pallet Index: ${event.palletIndex()}, Event Name: ${event.eventName()}, Event Index: ${event.eventIndex()}, Tx Index: ${event.txIndex()}`,
)
}
// Find DataSubmitted event
const event = txEvents.findFirst(Pallets.DataAvailabilityEvents.DataSubmitted)
if (event == undefined) throw Error()
console.log(`Who: ${event.who}, DataHash: ${event.dataHash}`)
console.log("runBlockTransactionAll finished correctly")
}
Block Transactions Filtered By App Id
import { assert_eq } from "."
import { SDK, Block, Pallets } from "./../src/index"
export async function runBlockTransactionByAppId() {
const sdk = await SDK.New(SDK.turingEndpoint)
const block = await Block.New(sdk.client, "0x94746ba186876d7407ee618d10cb6619befc59eeb173cacb00c14d1ff492fc58")
const appId = 2
const blockTxs = block.transactions({ appId: appId })
assert_eq(blockTxs.length, 2)
// Printout Block Transactions filtered By App Id
for (const tx of blockTxs) {
assert_eq(tx.appId(), appId)
console.log(
`Pallet Name: ${tx.palletName()}, Pallet Index: ${tx.palletIndex()}, Call Name: ${tx.callName()}, Call Index: ${tx.callIndex()}, Tx hash: ${tx.txHash()}, Tx Index: ${tx.txIndex()}`,
)
}
// Convert from Block Transaction to Specific Transaction
const decodedCall = blockTxs[0].decode(Pallets.DataAvailabilityCalls.SubmitData)
if (decodedCall == undefined) throw Error()
console.log(`Data: ${new TextDecoder().decode(decodedCall.data)}`)
// Printout all Transaction Events
const txEvents = blockTxs[0].events()
if (txEvents == undefined) throw Error()
assert_eq(txEvents.len(), 7)
for (const event of txEvents.iter()) {
console.log(
`Pallet Name: ${event.palletName()}, Pallet Index: ${event.palletIndex()}, Event Name: ${event.eventName()}, Event Index: ${event.eventIndex()}, Tx Index: ${event.txIndex()}`,
)
}
// Find DataSubmitted event
const event = txEvents.findFirst(Pallets.DataAvailabilityEvents.DataSubmitted)
if (event == undefined) throw Error()
console.log(`Who: ${event.who}, DataHash: ${event.dataHash}`)
console.log("runBlockTransactionByAppId finished correctly")
}
Block Transactions Filtered By Transaction Hash
import { assert_eq } from "."
import { SDK, Block, Pallets } from "./../src/index"
export async function runBlockTransactionByHash() {
const sdk = await SDK.New(SDK.turingEndpoint)
const block = await Block.New(sdk.client, "0x94746ba186876d7407ee618d10cb6619befc59eeb173cacb00c14d1ff492fc58")
const txHash = "0x19c486e107c926ff4af3fa9b1d95aaba130cb0bc89515d0f5b523ef6bac06338"
const blockTxs = block.transactions({ txHash: txHash })
assert_eq(blockTxs.length, 1)
const tx = blockTxs[0]
// Printout Transaction filtered by Tx Hash
assert_eq(tx.txHash().toString(), txHash)
console.log(
`Pallet Name: ${tx.palletName()}, Pallet Index: ${tx.palletIndex()}, Call Name: ${tx.callName()}, Call Index: ${tx.callIndex()}, Tx hash: ${tx.txHash()}, Tx Index: ${tx.txIndex()}`,
)
// Convert from Block Transaction to Specific Transaction
const decodedCall = tx.decode(Pallets.BalancesCalls.TransferKeepAlive)
if (decodedCall == undefined) throw Error()
console.log(`Dest: ${decodedCall.dest.toString()}, Value: ${decodedCall.value.toString()}`)
// Printout all Transaction Events
const txEvents = tx.events()
if (txEvents == undefined) throw Error()
assert_eq(txEvents.len(), 7)
for (const event of txEvents.iter()) {
console.log(
`Pallet Name: ${event.palletName()}, Pallet Index: ${event.palletIndex()}, Event Name: ${event.eventName()}, Event Index: ${event.eventIndex()}, Tx Index: ${event.txIndex()}`,
)
}
// Find Transfer event
const event = txEvents.findFirst(Pallets.BalancesEvents.Transfer)
if (event == undefined) throw Error()
console.log(`From: ${event.from}, To: ${event.to}, Amount: ${event.amount.toString()}`)
console.log("runBlockTransactionByHash finished correctly")
}
Block Transactions Filtered By Transaction Index
import { assert_eq } from "."
import { SDK, Block, Pallets } from "./../src/index"
export async function runBlockTransactionByIndex() {
const sdk = await SDK.New(SDK.turingEndpoint)
const block = await Block.New(sdk.client, "0x94746ba186876d7407ee618d10cb6619befc59eeb173cacb00c14d1ff492fc58")
const txIndex = 1
const blockTxs = block.transactions({ txIndex: txIndex })
assert_eq(blockTxs.length, 1)
const tx = blockTxs[0]
// Printout Transaction filtered by Tx Index
assert_eq(tx.txIndex(), txIndex)
console.log(
`Pallet Name: ${tx.palletName()}, Pallet Index: ${tx.palletIndex()}, Call Name: ${tx.callName()}, Call Index: ${tx.callIndex()}, Tx hash: ${tx.txHash()}, Tx Index: ${tx.txIndex()}`,
)
// Convert from Block Transaction to Specific Transaction
const decodedCall = tx.decode(Pallets.BalancesCalls.TransferKeepAlive)
if (decodedCall == undefined) throw Error()
console.log(`Dest: ${decodedCall.dest.toString()}, Value: ${decodedCall.value.toString()}`)
// Printout all Transaction Events
const txEvents = tx.events()
if (txEvents == undefined) throw Error()
assert_eq(txEvents.len(), 9)
for (const event of txEvents.iter()) {
console.log(
`Pallet Name: ${event.palletName()}, Pallet Index: ${event.palletIndex()}, Event Name: ${event.eventName()}, Event Index: ${event.eventIndex()}, Tx Index: ${event.txIndex()}`,
)
}
// Find NewAccount event
const event = txEvents.findFirst(Pallets.SystemEvents.NewAccount)
if (event == undefined) throw Error()
console.log(`Account: ${event.account}`)
console.log("runBlockTransactionByIndex finished correctly")
}
Block Transactions Filtered By Signer
import { assert_eq } from "."
import { SDK, Block, Pallets } from "./../src/index"
export async function runBlockTransactionBySigner() {
const sdk = await SDK.New(SDK.turingEndpoint)
const block = await Block.New(sdk.client, "0x94746ba186876d7407ee618d10cb6619befc59eeb173cacb00c14d1ff492fc58")
const singer = "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY"
const blockTxs = block.transactions({ txSigner: singer })
assert_eq(blockTxs.length, 5)
// Printout Block Transactions filtered By Signer
for (const tx of blockTxs) {
assert_eq(tx.ss58Address(), singer)
console.log(
`Pallet Name: ${tx.palletName()}, Pallet Index: ${tx.palletIndex()}, Call Name: ${tx.callName()}, Call Index: ${tx.callIndex()}, Tx hash: ${tx.txHash()}, Tx Index: ${tx.txIndex()}`,
)
}
// Convert from Block Transaction to Specific Transaction
const decodedCall = blockTxs[0].decode(Pallets.DataAvailabilityCalls.CreateApplicationKey)
if (decodedCall == undefined) throw Error()
console.log(`Key: ${new TextDecoder().decode(decodedCall.key)}`)
// Printout all Transaction Events
const txEvents = blockTxs[0].events()
if (txEvents == undefined) throw Error()
assert_eq(txEvents.len(), 7)
for (const event of txEvents.iter()) {
console.log(
`Pallet Name: ${event.palletName()}, Pallet Index: ${event.palletIndex()}, Event Name: ${event.eventName()}, Event Index: ${event.eventIndex()}, Tx Index: ${event.txIndex()}`,
)
}
// Find ApplicationKeyCreated event
const event = txEvents.findFirst(Pallets.DataAvailabilityEvents.ApplicationKeyCreated)
if (event == undefined) throw Error()
console.log(`Owner: ${event.id}, Key: ${event.keyToString()}, App Id: ${event.id}`)
console.log("runBlockTransactionBySigner finished correctly")
}
All Block Data Submissions
import { assert_eq } from "."
import { SDK, Block } from "./../src/index"
export async function runBlockDataSubmissionAll() {
const sdk = await SDK.New(SDK.turingEndpoint)
const block = await Block.New(sdk.client, "0x94746ba186876d7407ee618d10cb6619befc59eeb173cacb00c14d1ff492fc58")
const blobs = block.dataSubmissions()
assert_eq(blobs.length, 4)
for (const blob of blobs) {
console.log(
`Tx Hash: ${blob.txHash}, Tx Index: ${blob.txIndex}, Data: ${blob.toAscii()}, App Id: ${blob.appId}, Signer: ${blob.txSigner}`,
)
}
console.log("runBlockDataSubmissionAll finished correctly")
}
Block Data Submissions Filtered By App Id
import { assert_eq } from "."
import { SDK, Block } from "./../src/index"
export async function runBlockDataSubmissionByAppId() {
const sdk = await SDK.New(SDK.turingEndpoint)
const appId = 2
const block = await Block.New(sdk.client, "0x94746ba186876d7407ee618d10cb6619befc59eeb173cacb00c14d1ff492fc58")
const blobs = block.dataSubmissions({ appId: appId })
assert_eq(blobs.length, 2)
for (const blob of blobs) {
assert_eq(blob.appId, appId)
console.log(
`Tx Hash: ${blob.txHash}, Tx Index: ${blob.txIndex}, Data: ${blob.toAscii()}, App Id: ${blob.appId}, Signer: ${blob.txSigner}`,
)
}
console.log("runBlockDataSubmissionByAppId finished correctly")
}
Block Data Submissions Filtered By Transaction Hash
import { assert_eq } from "."
import { SDK, Block } from "./../src/index"
export async function runBlockDataSubmissionByHash() {
const sdk = await SDK.New(SDK.turingEndpoint)
const txHash = "0xe7efa71363d11bce370fe71a33e5ff296775f37507075c49316132131420f793"
const block = await Block.New(sdk.client, "0x94746ba186876d7407ee618d10cb6619befc59eeb173cacb00c14d1ff492fc58")
const blobs = block.dataSubmissions({ txHash: txHash })
assert_eq(blobs.length, 1)
for (const blob of blobs) {
assert_eq(blob.txHash.toString(), txHash)
console.log(
`Tx Hash: ${blob.txHash}, Tx Index: ${blob.txIndex}, Data: ${blob.toAscii()}, App Id: ${blob.appId}, Signer: ${blob.txSigner}`,
)
}
console.log("runBlockDataSubmissionByHash finished correctly")
}
Block Data Submissions Filtered By Transaction Index
import { assert_eq } from "."
import { SDK, Block } from "./../src/index"
export async function runBlockDataSubmissionByIndex() {
const sdk = await SDK.New(SDK.turingEndpoint)
const txIndex = 6
const block = await Block.New(sdk.client, "0x94746ba186876d7407ee618d10cb6619befc59eeb173cacb00c14d1ff492fc58")
const blobs = block.dataSubmissions({ txIndex: txIndex })
assert_eq(blobs.length, 1)
for (const blob of blobs) {
assert_eq(blob.txIndex, txIndex)
console.log(
`Tx Hash: ${blob.txHash}, Tx Index: ${blob.txIndex}, Data: ${blob.toAscii()}, App Id: ${blob.appId}, Signer: ${blob.txSigner}`,
)
}
console.log("runBlockDataSubmissionByIndex finished correctly")
}
Block Data Submissions Filtered By Signer
import { assert_eq } from "."
import { SDK, Block } from "./../src/index"
export async function runBlockDataSubmissionBySigner() {
const sdk = await SDK.New(SDK.turingEndpoint)
const txSigner = "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty"
const block = await Block.New(sdk.client, "0x94746ba186876d7407ee618d10cb6619befc59eeb173cacb00c14d1ff492fc58")
const blobs = block.dataSubmissions({ txSigner: txSigner })
assert_eq(blobs.length, 1)
for (const blob of blobs) {
assert_eq(blob.txSigner, txSigner)
console.log(
`Tx Hash: ${blob.txHash}, Tx Index: ${blob.txIndex}, Data: ${blob.toAscii()}, App Id: ${blob.appId}, Signer: ${blob.txSigner}`,
)
}
console.log("runBlockDataSubmissionBySigner finished correctly")
}
Block Events
import { assert_eq } from "."
import { SDK, Block, Pallets } from "./../src/index"
export async function runBlockEvents() {
const sdk = await SDK.New(SDK.turingEndpoint)
const block = await Block.New(sdk.client, "0x94746ba186876d7407ee618d10cb6619befc59eeb173cacb00c14d1ff492fc58")
const blockEvents = block.events
if (blockEvents == null) throw Error()
assert_eq(blockEvents.len(), 53)
// Printout All Block Events
for (const event of blockEvents.iter()) {
console.log(
`Pallet Name: ${event.palletName()}, Pallet Index: ${event.palletIndex()}, Event Name: ${event.eventName()}, Event Index: ${event.eventIndex()}, Tx Index: ${event.txIndex()}`,
)
}
// Find Transfer event
const transferEvents = blockEvents.find(Pallets.BalancesEvents.Transfer)
assert_eq(transferEvents.length, 2)
for (const event of transferEvents) {
console.log(`From: ${event.from}, To: ${event.to}, Amount: ${event.amount.toString()}`)
}
// Find ApplicationKeyCreated event
const keyCreatedEvent = blockEvents.findFirst(Pallets.DataAvailabilityEvents.ApplicationKeyCreated)
if (keyCreatedEvent == undefined) throw Error()
console.log(`Owner: ${keyCreatedEvent.owner}, Key: ${keyCreatedEvent.keyToString()}, App Id: ${keyCreatedEvent.id}`)
// Check
assert_eq(blockEvents.find(Pallets.DataAvailabilityEvents.DataSubmitted).length, 4)
assert_eq(blockEvents.find(Pallets.DataAvailabilityEvents.ApplicationKeyCreated).length, 1)
// Events for Specific Transaction
const txIndex = 0
const txEvents = block.eventsForTransaction(txIndex)
if (txEvents == undefined) throw Error()
assert_eq(txEvents.len(), 1)
// Printout All Tx Events
for (const event of txEvents.iter()) {
console.log(
`Pallet Name: ${event.palletName()}, Pallet Index: ${event.palletIndex()}, Event Name: ${event.eventName()}, Event Index: ${event.eventIndex()}, Tx Index: ${event.txIndex()}`,
)
}
// Find ExtrinsicSuccess event
const successEvent = blockEvents.findFirst(Pallets.SystemEvents.ExtrinsicSuccess)
if (successEvent == undefined) throw Error()
console.log(`DispatchInfo Pays:`, successEvent.dispatchInfo.pays.toString())
// Check
const tx2 = block.transactions({ txIndex: txIndex })
assert_eq(tx2.length, 1)
const tx2Events = tx2[0].events()
if (tx2Events == undefined) throw Error()
assert_eq(tx2Events.len(), txEvents.len())
console.log("runBlockEvents finished correctly")
}
Transaction
Transaction Execute
import { assert_eq } from "."
import { Account, SDK, Pallets, Watcher, WaitFor } from "./../src/index"
export async function runTransactionExecute() {
const sdk = await SDK.New(SDK.localEndpoint)
const account = Account.alice()
// Transaction will be signed, and sent.
//
// There is no guarantee that the transaction was executed at all. It might have been
// dropped or discarded for various reasons. The caller is responsible for querying future
// blocks in order to determine the execution status of that transaction.
const tx = sdk.tx.dataAvailability.submitData("My Data")
const txhash = await tx.execute(account, { app_id: 1 })
// Checking if the transaction was included
//
// It's not necessary to use the builtin watcher. A custom watcher
// might yield better results in some cases.
const watcher = new Watcher(sdk.client, txhash, WaitFor.BlockInclusion)
const res = await watcher.run()
if (res == null) throw Error()
assert_eq(res.isSuccessful(), true)
// Transaction Details
console.log(
`Block Hash: ${res.blockHash}, Block Number: ${res.blockNumber}, Tx Hash: ${res.txHash}, Tx Index: ${res.txIndex}`,
)
// Transaction Events
if (res.events == undefined) throw Error()
for (const event of res.events.iter()) {
console.log(
`Pallet Name: ${event.palletName()}, Pallet Index: ${event.palletIndex()}, Event Name: ${event.eventName()}, Event Index: ${event.eventIndex()}, Tx Index: ${event.txIndex()}`,
)
}
// Find DataSubmitted event
const event = res.events.findFirst(Pallets.DataAvailabilityEvents.DataSubmitted)
if (event == undefined) throw new Error()
console.log(`Who: ${event.who}, DataHash: ${event.dataHash}`)
console.log("runTransactionExecute finished correctly")
}
Transaction Execute And Watch Inclusion
import { assert_eq } from "."
import { Account, SDK, Pallets } from "./../src/index"
export async function runTransactionExecuteAndWatchInclusion() {
const sdk = await SDK.New(SDK.localEndpoint)
const account = Account.alice()
// Transaction will be signed, sent, and watched
// If the transaction was dropped or never executed, the system will retry it
// for 2 more times using the same nonce and app id.
//
// Waits for transaction inclusion. Most of the time you would want to call `ExecuteAndWatchFinalization` as
// inclusion doesn't mean that the transaction will be in the canonical chain.
const tx = sdk.tx.dataAvailability.submitData("My Data")
const res = await tx.executeWaitForInclusion(account, { app_id: 1 })
assert_eq(res.isSuccessful(), true)
// Transaction Details
console.log(
`Block Hash: ${res.blockHash}, Block Number: ${res.blockNumber}, Tx Hash: ${res.txHash}, Tx Index: ${res.txIndex}`,
)
// Transaction Events
if (res.events == undefined) throw Error()
for (const event of res.events.iter()) {
console.log(
`Pallet Name: ${event.palletName()}, Pallet Index: ${event.palletIndex()}, Event Name: ${event.eventName()}, Event Index: ${event.eventIndex()}, Tx Index: ${event.txIndex()}`,
)
}
// Find DataSubmitted event
const event = res.events.findFirst(Pallets.DataAvailabilityEvents.DataSubmitted)
if (event == undefined) throw new Error()
console.log(`Who: ${event.who}, DataHash: ${event.dataHash}`)
console.log("runTransactionExecuteAndWatchInclusion finished correctly")
}
Transaction Execute And Watch Finalization
import { assert_eq } from "."
import { Account, SDK, Pallets } from "./../src/index"
export async function runTransactionExecuteAndWatchFinalization() {
const sdk = await SDK.New(SDK.localEndpoint)
const account = Account.alice()
// Transaction will be signed, sent, and watched
// If the transaction was dropped or never executed, the system will retry it
// for 2 more times using the same nonce and app id.
//
// Waits for transaction inclusion. Most of the time you would want to call `ExecuteAndWatchFinalization` as
// inclusion doesn't mean that the transaction will be in the canonical chain.
const tx = sdk.tx.dataAvailability.submitData("My Data")
const res = await tx.executeWaitForFinalization(account, { app_id: 1 })
assert_eq(res.isSuccessful(), true)
// Transaction Details
console.log(
`Block Hash: ${res.blockHash}, Block Number: ${res.blockNumber}, Tx Hash: ${res.txHash}, Tx Index: ${res.txIndex}`,
)
// Transaction Events
if (res.events == undefined) throw Error()
for (const event of res.events.iter()) {
console.log(
`Pallet Name: ${event.palletName()}, Pallet Index: ${event.palletIndex()}, Event Name: ${event.eventName()}, Event Index: ${event.eventIndex()}, Tx Index: ${event.txIndex()}`,
)
}
// Find DataSubmitted event
const event = res.events.findFirst(Pallets.DataAvailabilityEvents.DataSubmitted)
if (event == undefined) throw new Error()
console.log(`Who: ${event.who}, DataHash: ${event.dataHash}`)
console.log("runTransactionExecuteAndWatchFinalization finished correctly")
}
Transaction Options
import { assert_eq } from "."
import { Account, Block, SDK } from "./../src/index"
export async function runTransactionOptions() {
await nonce()
await app_id()
await tip()
await mortality()
console.log("runTransactionOptions finished correctly")
}
export async function nonce() {
const sdk = await SDK.New(SDK.localEndpoint)
const account = Account.alice()
const nonce = await Account.nonce(sdk.client, account.address)
const tx = sdk.tx.dataAvailability.submitData("Data")
const res = await tx.executeWaitForInclusion(account, { nonce: nonce, app_id: 1 })
if (res.isSuccessful() !== true) throw Error()
const block = await Block.New(sdk.client, res.blockHash)
const blockTx = block.transactions({ txIndex: res.txIndex })
assert_eq(blockTx.length, 1)
assert_eq(blockTx[0].nonce(), nonce)
console.log("runTransactionOptionsNonce finished correctly")
}
export async function app_id() {
const sdk = await SDK.New(SDK.localEndpoint)
const account = Account.alice()
const appId = 5
const tx = sdk.tx.dataAvailability.submitData("Data")
const res = await tx.executeWaitForInclusion(account, { app_id: appId })
if (res.isSuccessful() !== true) throw Error()
const block = await Block.New(sdk.client, res.blockHash)
const blockTx = block.transactions({ txIndex: res.txIndex })
assert_eq(blockTx.length, 1)
assert_eq(blockTx[0].appId(), appId)
console.log("runTransactionOptionsAppId finished correctly")
}
export async function tip() {
const sdk = await SDK.New(SDK.localEndpoint)
const account = Account.alice()
const tip = SDK.oneAvail()
const tx = sdk.tx.dataAvailability.submitData("Data")
const res = await tx.executeWaitForInclusion(account, { tip: tip })
if (res.isSuccessful() !== true) throw Error()
const block = await Block.New(sdk.client, res.blockHash)
const blockTx = block.transactions({ txIndex: res.txIndex })
assert_eq(blockTx.length, 1)
assert_eq(blockTx[0].tip()?.toString(), tip.toString())
console.log("runTransactionOptionsTips finished correctly")
}
export async function mortality() {
const sdk = await SDK.New(SDK.localEndpoint)
const account = Account.alice()
const mortality = 16
const tx = sdk.tx.dataAvailability.submitData("Data")
const res = await tx.executeWaitForInclusion(account, { mortality: mortality })
if (res.isSuccessful() !== true) throw Error()
const block = await Block.New(sdk.client, res.blockHash)
const blockTx = block.transactions({ txIndex: res.txIndex })
assert_eq(blockTx.length, 1)
assert_eq(blockTx[0].mortality()?.asMortalEra.period.toNumber(), mortality)
console.log("runTransactionOptionsMortality finished correctly")
}
Transaction Payment
import { assert_eq } from "."
import { Account, SDK } from "./../src/index"
export async function runTransactionPayment() {
const sdk = await SDK.New(SDK.localEndpoint)
const account = Account.alice()
const tx = sdk.tx.dataAvailability.submitData("0123")
{
// payment_query_fee_details
const fee_details = await tx.paymentQueryFeeDetails(account.address)
const inclusionFee = fee_details.inclusionFee
if (inclusionFee == null) throw Error()
console.log("Base Fee: ", inclusionFee.baseFee.toString())
console.log("Len Fee: ", inclusionFee.lenFee.toString())
console.log("Adjusted weight Fee: ", inclusionFee.adjustedWeightFee.toString())
const totalFee = inclusionFee.adjustedWeightFee.add(inclusionFee.baseFee).add(inclusionFee.lenFee)
console.log("Total Fee: ", totalFee.toString())
// payment_query_info
const info = await tx.paymentQueryInfo(account.address)
console.log("Partial Fee: ", info.partialFee.toString())
assert_eq(info.partialFee.toString(), totalFee.toString())
}
{
// payment_query_call_fee_details
const fee_details = await tx.paymentQueryCallFeeDetails()
const inclusionFee = fee_details.inclusionFee
if (inclusionFee == null) throw Error()
console.log("Base Fee: ", inclusionFee.baseFee.toString())
console.log("Len Fee: ", inclusionFee.lenFee.toString())
console.log("Adjusted weight Fee: ", inclusionFee.adjustedWeightFee.toString())
const totalFee = inclusionFee.adjustedWeightFee.add(inclusionFee.baseFee).add(inclusionFee.lenFee)
console.log("Total Fee: ", totalFee.toString())
// payment_query_call_info
const info = await tx.paymentQueryCallInfo()
console.log("Partial Fee: ", info.partialFee.toString())
assert_eq(info.partialFee.toString(), totalFee.toString())
}
console.log("runTransactionPayment finished correctly")
}
Storage
import { assert_eq, assert_true } from "."
import { Pallets, SDK } from "./../src/index"
export async function runStorage() {
const sdk = await SDK.New(SDK.turingEndpoint)
const storageAt = await sdk.client.storageAt("0x9e813bb85fca217f8f3967bd4b550b05f7d559412571ca1dd621aa37343b300b")
// Simple Storage
{
const value = await Pallets.StakingStorage.MinValidatorBond.fetch(storageAt)
assert_eq(value.toString(), "100000000000000000000000")
}
// Simple Storage that can return null
{
const value = await Pallets.StakingStorage.CurrentEra.fetch(storageAt)
assert_true(value != null && value == 301)
}
// Fetch Map Storage
{
const key = "5C869t2dWzmmYkE8NT1oocuEEdwqNnAm2XhvnuHcavNUcTTT"
const entry = await Pallets.SystemStorage.Account.fetch(storageAt, key)
assert_eq(entry.key.toSS58(), key)
assert_eq(entry.value.nonce, 11)
}
// Fetch Map Storage 2
{
const key = "Reserved-3"
const entry = await Pallets.DataAvailabilityStorage.AppKeys.fetch(storageAt, key)
if (entry == undefined) throw Error()
assert_eq(entry.value.appId, 3)
assert_eq(entry.value.owner.toSS58(), "5CK87QdvhcSJvVa7ZACcEfd5i7J1GqoqbEFB2kzNn3Ms13fE")
}
// Fetch All Map Storage
{
const entires = await Pallets.DataAvailabilityStorage.AppKeys.fetchAll(storageAt)
assert_eq(entires.length, 232)
}
console.log("runStorage finished correctly")
}
Batch
import { assert_eq } from "."
import { BN, SDK, Account, Pallets } from "./../src/index"
export async function runBatch() {
const sdk = await SDK.New(SDK.localEndpoint)
const account = Account.alice()
const value1 = SDK.oneAvail()
const value2 = SDK.oneAvail().mul(new BN("100000000"))
const destBob = "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty"
const destCharlie = "5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y"
const call1 = sdk.tx.balances.transferKeepAlive(destBob, value1)
const call2 = sdk.tx.balances.transferKeepAlive(destCharlie, value1)
const calls = [call1.tx, call2.tx]
//
// Happy Path
//
// Batch call
{
const tx = sdk.tx.utility.batch(calls)
const res = await tx.executeWaitForInclusion(account, {})
assert_eq(res.isSuccessful(), true)
if (res.events == undefined) throw new Error("")
const events1 = res.events.find(Pallets.UtilityEvents.BatchCompleted)
assert_eq(events1.length, 1)
const events2 = res.events.find(Pallets.UtilityEvents.ItemCompleted)
assert_eq(events2.length, 2)
}
// Batch All call
{
const tx = sdk.tx.utility.batchAll(calls)
const res = await tx.executeWaitForInclusion(account, {})
assert_eq(res.isSuccessful(), true)
if (res.events == undefined) throw new Error("")
const events1 = res.events.find(Pallets.UtilityEvents.BatchCompleted)
assert_eq(events1.length, 1)
const events2 = res.events.find(Pallets.UtilityEvents.ItemCompleted)
assert_eq(events2.length, 2)
}
// Force Batch call
{
const tx = sdk.tx.utility.forceBatch(calls)
const res = await tx.executeWaitForInclusion(account, {})
assert_eq(res.isSuccessful(), true)
if (res.events == undefined) throw new Error("")
const events1 = res.events.find(Pallets.UtilityEvents.BatchCompleted)
assert_eq(events1.length, 1)
const events2 = res.events.find(Pallets.UtilityEvents.ItemCompleted)
assert_eq(events2.length, 2)
}
//
// Things differ when we introduce a call that will fail
//
const call3 = sdk.tx.balances.transferKeepAlive(destBob, value2)
const call4 = sdk.tx.balances.transferKeepAlive(destCharlie, value1)
calls.push(call3.tx)
calls.push(call4.tx)
// Batch call
{
const tx = sdk.tx.utility.batch(calls)
const res = await tx.executeWaitForInclusion(account, {})
assert_eq(res.isSuccessful(), true)
if (res.events == undefined) throw new Error("")
const events1 = res.events.find(Pallets.UtilityEvents.BatchInterrupted)
assert_eq(events1.length, 1)
const events2 = res.events.find(Pallets.UtilityEvents.BatchCompleted)
assert_eq(events2.length, 0)
const events3 = res.events.find(Pallets.UtilityEvents.ItemCompleted)
assert_eq(events3.length, 2)
}
// Batch All call
{
const tx = sdk.tx.utility.batchAll(calls)
const res = await tx.executeWaitForInclusion(account, {})
assert_eq(res.isSuccessful(), false)
}
// Force Batch call
{
const tx = sdk.tx.utility.forceBatch(calls)
const res = await tx.executeWaitForInclusion(account, {})
assert_eq(res.isSuccessful(), true)
if (res.events == undefined) throw new Error("")
const events1 = res.events.find(Pallets.UtilityEvents.BatchCompletedWithErrors)
assert_eq(events1.length, 1)
const events3 = res.events.find(Pallets.UtilityEvents.ItemCompleted)
assert_eq(events3.length, 3)
const events2 = res.events.find(Pallets.UtilityEvents.ItemFailed)
assert_eq(events2.length, 1)
}
console.log("runBatch finished correctly")
}
RPC
import { BN, SDK } from "./../src/index"
export async function runRpc() {
await normalRpcs()
await kateRpcs()
}
async function normalRpcs() {
const sdk = await SDK.New(SDK.localEndpoint)
// chain.getBlock
const block = await sdk.client.api.rpc.chain.getBlock()
console.log("getBlock")
console.log(block.toJSON())
/*
Output
{
block: {
header: {
parentHash: '0x42670561b854f78e6a4e08d5d3f5971f6057e215467fb0684f1a2af17fe8b369',
number: 707,
stateRoot: '0xa32347f3ae7ae6d0c534e6cbe0b19148b5a971eb860cdd682428ecf623401a1e',
extrinsicsRoot: '0x3c9492204d29fc822f5a046d252119f6be0236767c8b16afedfd8457eafd5ec3',
digest: [Object],
extension: [Object]
},
extrinsics: [ '0x280403000bb0037bf09301', '0x1004270b00' ]
},
justifications: null
}
*/
// chain.getBlockHash
const hash = await sdk.client.api.rpc.chain.getBlockHash()
console.log("getBlockHash")
console.log(hash.toJSON())
/*
Output
0x2079190e8bf27a01687b3ecdfdbbee4cc4246695b5dc3d40fdd62aa4a2b4a0be
*/
// chain.getFinalizedHead
const hash2 = await sdk.client.api.rpc.chain.getFinalizedHead()
console.log("getFinalizedHead")
console.log(hash2.toJSON())
/*
Output
{
parentHash: '0x42670561b854f78e6a4e08d5d3f5971f6057e215467fb0684f1a2af17fe8b369',
number: 707,
stateRoot: '0xa32347f3ae7ae6d0c534e6cbe0b19148b5a971eb860cdd682428ecf623401a1e',
extrinsicsRoot: '0x3c9492204d29fc822f5a046d252119f6be0236767c8b16afedfd8457eafd5ec3',
digest: { logs: [ [Object], [Object] ] },
extension: { v3: { appLookup: [Object], commitment: [Object] } }
}
*/
// chain.getHeader
const header = await sdk.client.api.rpc.chain.getHeader()
console.log("getHeader")
console.log(header.toJSON())
/*
Output
0x1c1bdd7d76d4366c736e1c6a591fdd9f14ddef87b5ffc0fc2df4a81f3e2b00e6
*/
// system.accountNextIndex
const address = "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY"
const nodeNonce: BN = await sdk.client.api.rpc.system.accountNextIndex(address)
console.log("accountNextIndex")
console.log(nodeNonce.toNumber())
/*
Output
44
*/
// system.chain
const chain = await sdk.client.api.rpc.system.chain()
console.log("chain")
console.log(chain.toJSON())
/*
Output
Avail Development Network
*/
// system_chainType
const chainType = await sdk.client.api.rpc.system.chainType()
console.log("chainType")
console.log(chainType.toString())
/*
Output
Development
*/
// system.health
const health = await sdk.client.api.rpc.system.health()
console.log("health")
console.log(health.peers.toNumber())
console.log(health.isSyncing.toString())
console.log(health.shouldHavePeers.toString())
/*
Output
0
false
false
*/
// system.localListenAddresses
const localListenAddresses = await sdk.client.api.rpc.system.localListenAddresses()
console.log("localListenAddresses")
localListenAddresses.forEach((e) => console.log(e.toString()))
/*
Output
/ip6/fe80::a333:1e13:2097:7c0a/tcp/30333/p2p/12D3KooWNb38SjUDDGAJxytmPPEV1t9Fz65JTw3C87poFFdF5x3n
/ip4/192.168.1.103/tcp/30333/p2p/12D3KooWNb38SjUDDGAJxytmPPEV1t9Fz65JTw3C87poFFdF5x3n
/ip4/127.0.0.1/tcp/30333/p2p/12D3KooWNb38SjUDDGAJxytmPPEV1t9Fz65JTw3C87poFFdF5x3n
/ip6/::1/tcp/30333/p2p/12D3KooWNb38SjUDDGAJxytmPPEV1t9Fz65JTw3C87poFFdF5x3n
*/
// system.localPeerId
const localPeerId = await sdk.client.api.rpc.system.localPeerId()
console.log("localPeerId")
console.log(localPeerId.toJSON())
/*
Output
12D3KooWNb38SjUDDGAJxytmPPEV1t9Fz65JTw3C87poFFdF5x3n
*/
// system.name
const name = await sdk.client.api.rpc.system.name()
console.log("name")
console.log(name.toJSON())
/*
Output
Avail Node
*/
// system.nodeRoles
const nodeRoles = await sdk.client.api.rpc.system.nodeRoles()
console.log("nodeRoles")
nodeRoles.forEach((e) => console.log(e.toString()))
/*
Output
Authority
*/
// system.peers
const peers = await sdk.client.api.rpc.system.peers()
console.log("peers")
peers.forEach((e) => console.log(e.toString()))
/*
Output
[]
*/
// system.properties
const properties = await sdk.client.api.rpc.system.properties()
console.log("properties")
console.log("isEthereum: " + properties.isEthereum.toString())
console.log("ss58Format: " + properties.ss58Format.toString())
if (properties.tokenDecimals.isSome) {
properties.tokenDecimals.value.forEach((e) => console.log(e.toString()))
}
if (properties.tokenSymbol.isSome) {
properties.tokenSymbol.value.forEach((e) => console.log(e.toString()))
}
/*
Output
isEthereum: false
ss58Format: 42
18
AVAIL
*/
// system.syncState
const syncState = await sdk.client.api.rpc.system.syncState()
console.log("syncState")
console.log("startingBlock: " + syncState.startingBlock.toNumber())
console.log("currentBlock: " + syncState.currentBlock.toNumber())
if (syncState.highestBlock.isSome) {
console.log("highestBlock:" + syncState.highestBlock.value.toNumber())
}
/*
Output
startingBlock: 0
currentBlock: 707
highestBlock:707
*/
// system.version
const version = await sdk.client.api.rpc.system.version()
console.log("version")
console.log("Version: " + version.toString())
/*
Output
Version: 2.2.1-4f0439f4448
*/
}
async function kateRpcs() {
const sdk = await SDK.New(SDK.turingEndpoint)
// kate.blockLength
const [txIndex, blockHash] = [1, "0xbb39ac467ad71293c212d3a9689226828d0c442d2e9d5e70e0bf7bc9c3a61115"]
const blockLength = await (sdk.client.api.rpc as any).kate.blockLength(blockHash)
console.log("blockLength")
console.log("Normal: " + blockLength.max.normal.toNumber())
console.log("Operational: " + blockLength.max.operational.toNumber())
console.log("Mandatory:" + blockLength.max.mandatory.toNumber())
console.log("Cols: " + blockLength.cols.toNumber())
console.log("Rows: " + blockLength.rows.toNumber())
console.log("ChunkSize: " + blockLength.chunkSize.toNumber())
/*
Output
Normal: 2097152
Operational: 2097152
Mandatory: 2097152
Cols: 256
Rows: 256
ChunkSize: 32
*/
// kate.queryDataProof
const dataProof = await (sdk.client.api.rpc as any).kate.queryDataProof(txIndex, blockHash)
console.log("queryDataProof")
console.log("DataRoot: " + dataProof.dataProof.roots.dataRoot.toString())
console.log("BlobRoot: " + dataProof.dataProof.roots.blobRoot.toString())
console.log("BridgeRoot: " + dataProof.dataProof.roots.bridgeRoot.toString())
dataProof.dataProof.proof.forEach((e: any) => console.log(e))
console.log("NumberOfLeaves: " + dataProof.dataProof.numberOfLeaves.toNumber())
console.log("LeafIndex: " + dataProof.dataProof.leafIndex.toNumber())
console.log("Leaf: " + dataProof.dataProof.leaf.toString())
console.log("Message: " + dataProof.message.toString())
/*
Output
DataRoot: 0xd6e516bbf0b0d964a6a6a41a18c58a2eac4757001c2338a8601c4cc961332fda
BlobRoot: 0x29c73490baca9fe2b11095a69294de4b4a86bcb3a2eb3cd04b51dfdd0b4030f9
BridgeRoot: 0x0000000000000000000000000000000000000000000000000000000000000000
NumberOfLeaves: 1
LeafIndex: 0
Leaf: 0x47a59a7805e0bfe350ee0395d426c15770edc03fee72aa6532b5bbcffaf28030
Message:
*/
// kate.queryProof
const cell = [[0, 0]]
const proof = await (sdk.client.api.rpc as any).kate.queryProof(cell, blockHash)
console.log("proof")
proof.forEach((e: any) => e.forEach((g: any) => console.log(g.toString())))
/*
Output
2178534751726990040338027377623275511556638494274780568875624948149315822336
0xb7be11461735c1c52a96c3319def842092b51b54142d1e7e6f307cade9b3966897e8b8499e1c2fe9f3213c337560e5bb
*/
// kate.queryRows
const rows = [0]
const rowsResult = await (sdk.client.api.rpc as any).kate.queryRows(rows, blockHash)
console.log("queryRows")
rowsResult.forEach((e: any) => e.forEach((g: any) => console.log(g.toString())))
/*
Output
2178534751726990040338027377623275511556638494274780568875624948149315822336
69809044805081050561184934886915677873289200296740001199394424254799507156224
4352252970560996938972626135851379325521790154040731149679347419805560005632
104879959288272688727650528319334922080558860381160795517508406844350550507520
*/
}
Validator
import { SDK, Account, Pallets, BN } from "./../src/index"
export async function runValidator() {
const sdk = await SDK.New(SDK.localEndpoint)
const account = Account.generate()
// Min Bond Value
const storageAt = await sdk.client.storageAt()
let minValidatorBond = await Pallets.StakingStorage.MinValidatorBond.fetch(storageAt)
minValidatorBond = minValidatorBond.add(SDK.oneAvail())
// Fund Random Account
{
const tx = sdk.tx.balances.transferKeepAlive(account.address, minValidatorBond.add(SDK.oneAvail().mul(new BN(10))))
const res = await tx.executeWaitForInclusion(Account.alice(), {})
const isOk = res.isSuccessful()
if (isOk == undefined || isOk == false) throw Error()
}
// Bond
{
const tx = sdk.tx.staking.bond(minValidatorBond, "Staked")
const res = await tx.executeWaitForInclusion(account, {})
const isOk = res.isSuccessful()
if (isOk == undefined || isOk == false) throw Error()
}
// Generate Session Keys
const sessionKeys = await sdk.client.rotateKeys()
// Set Session Keys
{
const tx = sdk.tx.session.setKeys(sessionKeys, new Uint8Array())
const res = await tx.executeWaitForInclusion(account, {})
const isOk = res.isSuccessful()
if (isOk == undefined || isOk == false) throw Error()
}
// Validate
{
const tx = sdk.tx.staking.validate(50, false)
const res = await tx.executeWaitForInclusion(account, {})
const isOk = res.isSuccessful()
if (isOk == undefined || isOk == false) throw Error()
}
console.log("runValidator finished correctly")
}
Proxy
import { Account, Pallets, SDK, AccountId } from "./../src/index"
import { assert_eq } from "."
export async function runProxy() {
await runProxyNormal()
await runProxyPure()
await runProxyFailure()
console.log("runProxy finished correctly")
}
export async function runProxyNormal() {
const sdk = await SDK.New(SDK.localEndpoint)
const proxyAccount = Account.bob()
const mainAccount = Account.ferdie()
// Creating Proxy
{
const tx = sdk.tx.proxy.addProxy(proxyAccount.address, "Any", 0)
const res = await tx.executeWaitForInclusion(mainAccount, {})
assert_eq(res.isSuccessful(), true)
if (res.events == undefined) throw Error()
const event = res.events.findFirst(Pallets.ProxyEvents.ProxyAdded)
if (event == undefined) throw Error()
console.log(
`Delegatee: ${event.delegatee.toSS58()}, Delegator: ${event.delegator.toSS58()}, ProxyType: ${event.proxyType.toString()}, Delay: ${event.delay}`,
)
}
// Executing the Proxy.Proxy() call
{
const call = sdk.tx.balances.transferKeepAlive(proxyAccount.address, SDK.oneAvail()).tx
const tx = sdk.tx.proxy.proxy(mainAccount.address, null, call)
const res = await tx.executeWaitForInclusion(proxyAccount, {})
assert_eq(res.isSuccessful(), true)
if (res.events == undefined) throw Error()
const event = res.events.findFirst(Pallets.ProxyEvents.ProxyExecuted)
if (event == undefined) throw Error()
assert_eq(event.result.variantIndex, 0)
console.log(`Result: ${event.result.toString()}`)
}
// Removing Proxy
{
const tx = sdk.tx.proxy.removeProxy(proxyAccount.address, "Any", 0)
const res = await tx.executeWaitForInclusion(mainAccount, {})
assert_eq(res.isSuccessful(), true)
if (res.events == undefined) throw Error()
const event = res.events.findFirst(Pallets.ProxyEvents.ProxyRemoved)
if (event == undefined) throw Error()
console.log(
`Delegatee: ${event.delegatee.toSS58()}, Delegator: ${event.delegator.toSS58()}, ProxyType: ${event.proxyType.toString()}, Delay: ${event.delay}`,
)
}
console.log("runProxyNormal finished correctly")
}
export async function runProxyPure() {
const sdk = await SDK.New(SDK.localEndpoint)
const mainAccount = Account.bob()
const proxyType = "Any"
const index = 0
let proxyAccountId: AccountId
// Creating Pure Proxy
{
const tx = sdk.tx.proxy.createPure(proxyType, 0, index)
const res = await tx.executeWaitForInclusion(mainAccount, {})
assert_eq(res.isSuccessful(), true)
if (res.events == undefined) throw Error()
const event = res.events.findFirst(Pallets.ProxyEvents.PureCreated)
if (event == undefined) throw Error()
console.log(
`Pure: ${event.pure.toSS58()}, Who: ${event.who.toSS58()}, ProxyType: ${event.proxyType.toString()}, Index: ${event.disambiguationIndex}`,
)
proxyAccountId = event.pure
}
// Executing the Proxy.Proxy() call
{
const key = "" + Math.ceil(Math.random() * 1_000_000_00)
const call = sdk.tx.dataAvailability.createApplicationKey(key).tx
const tx = sdk.tx.proxy.proxy(proxyAccountId, null, call)
const res = await tx.executeWaitForInclusion(mainAccount, {})
assert_eq(res.isSuccessful(), true)
if (res.events == undefined) throw Error()
const event = res.events.findFirst(Pallets.ProxyEvents.ProxyExecuted)
if (event == undefined) throw Error()
assert_eq(event.result.variantIndex, 0)
console.log(`Result: ${event.result.toString()}`)
}
console.log("runProxyPure finished correctly")
}
export async function runProxyFailure() {
const sdk = await SDK.New(SDK.localEndpoint)
const proxyAccount = Account.bob()
const mainAccount = Account.ferdie()
// Creating Proxy
{
const tx = sdk.tx.proxy.addProxy(proxyAccount.address, "NonTransfer", 0)
const res = await tx.executeWaitForInclusion(mainAccount, {})
assert_eq(res.isSuccessful(), true)
if (res.events == undefined) throw Error()
}
// Executing the Proxy.Proxy() call
{
const call = sdk.tx.balances.transferKeepAlive(proxyAccount.address, SDK.oneAvail()).tx
const tx = sdk.tx.proxy.proxy(mainAccount.address, null, call)
const res = await tx.executeWaitForInclusion(proxyAccount, {})
assert_eq(res.isSuccessful(), true)
if (res.events == undefined) throw Error()
const event = res.events.findFirst(Pallets.ProxyEvents.ProxyExecuted)
if (event == undefined) throw Error()
assert_eq(event.result.variantIndex, 1)
console.log(`Result: ${event.result.toString()}`)
}
// Removing Proxy
{
const tx = sdk.tx.proxy.removeProxy(proxyAccount.address, "NonTransfer", 0)
const res = await tx.executeWaitForInclusion(mainAccount, {})
assert_eq(res.isSuccessful(), true)
if (res.events == undefined) throw Error()
}
console.log("runProxyFailure finished correctly")
}
Multisig
import { assert_eq } from "."
import { SDK, BN, KeyringPair, TransactionDetails, utils, Account, Metadata, Pallets } from "./../src/index"
export async function runMultisig() {
const sdk = await SDK.New(SDK.localEndpoint)
// Multisig Signatures
const [alice, bob, charlie] = [Account.alice(), Account.bob(), Account.charlie()]
// Create Multisig Account
const threshold = 3
const multisigAddress = utils.generateMultisig([alice.address, bob.address, charlie.address], threshold)
await fundMultisigAccount(sdk, alice, multisigAddress)
// Define what action will be taken by the multisig account
const amount = SDK.oneAvail()
const call = sdk.tx.balances.transferKeepAlive(multisigAddress, amount)
// Data needed for multisig approval and execution
const callHash = call.tx.method.hash.toString()
const callData = call.tx.unwrap().toHex()
const maxWeight = (await call.paymentQueryCallInfo()).weight
/*
The first signature creates and approves the multisig transaction. All the next signatures (besides the last one) should
use the `nextApproval` function to approve the tx. The last signature should use the `lastApproval` function to approve
and execute the multisig tx.
In practice it means the following:
- If the threshold is 2 do the following:
- firstApproval
- lastApproval
- If the threshold is 4 do the following:
- firstApproval
- nextApproval
- nextApproval
- lastApproval
*/
// Create New Multisig
const call1signatures = utils.sortMultisigAddresses([bob.address, charlie.address])
const firstResult = await firstApproval(sdk, alice, threshold, call1signatures, callHash, maxWeight)
{
const event = firstResult.events?.findFirst(Pallets.MultisigEvents.NewMultisig)
if (event == undefined) throw Error()
console.log(
`Approving: ${event.approving.toSS58()}, Multisig: ${event.multisig.toSS58()}, Call Hash: ${event.callHash.toHex()}`,
)
}
// Approve existing Multisig
const timepoint: Metadata.TimepointBlocknumber = { height: firstResult.blockNumber, index: firstResult.txIndex }
const call2signatures = utils.sortMultisigAddresses([alice.address, charlie.address])
const secondResult = await nextApproval(sdk, bob, threshold, call2signatures, timepoint, callHash, maxWeight)
{
const event = secondResult.events?.findFirst(Pallets.MultisigEvents.MultisigApproval)
if (event == undefined) throw Error()
console.log(
`Approving: ${event.approving.toSS58()}, Timepoint Height: ${event.timepoint.height}, Timepoint Index: ${event.timepoint.index}, Multisig: ${event.multisig.toSS58()}, Call Hash: ${event.callHash.toHex()}`,
)
}
// Execute Multisig
const call3signatures = utils.sortMultisigAddresses([alice.address, bob.address])
const thirdResult = await lastApproval(sdk, charlie, threshold, call3signatures, timepoint, callData, maxWeight)
{
const event = thirdResult.events?.findFirst(Pallets.MultisigEvents.MultisigExecuted)
if (event == undefined) throw Error()
assert_eq(event.result.variantIndex, 0)
console.log(
`Approving: ${event.approving.toSS58()}, Timepoint Height: ${event.timepoint.height}, Timepoint Index: ${event.timepoint.index}, Multisig: ${event.multisig.toSS58()}, Call Hash: ${event.callHash.toHex()}, Result: ${event.result.toString()}`,
)
}
console.log("runMultisig finished correctly")
}
async function fundMultisigAccount(sdk: SDK, alice: KeyringPair, multisigAddress: string): Promise<string> {
console.log("Funding multisig account...")
const amount = SDK.oneAvail().mul(new BN(100)) // 100 Avail
const tx = sdk.tx.balances.transferKeepAlive(multisigAddress, amount)
const res = await tx.executeWaitForInclusion(alice, {})
assert_eq(res.isSuccessful(), true)
if (res.events == undefined) throw Error()
return multisigAddress
}
async function firstApproval(
sdk: SDK,
account: KeyringPair,
threshold: number,
otherSignatures: string[],
callHash: string,
maxWeight: Metadata.Weight,
): Promise<TransactionDetails> {
console.log("Alice is creating a Multisig Transaction...")
const tx = sdk.tx.multisig.approveAsMulti(threshold, otherSignatures, null, callHash, maxWeight)
const res = await tx.executeWaitForInclusion(account, {})
assert_eq(res.isSuccessful(), true)
if (res.events == undefined) throw Error()
return res
}
async function nextApproval(
sdk: SDK,
account: KeyringPair,
threshold: number,
otherSignatures: string[],
timepoint: Metadata.TimepointBlocknumber,
callHash: string,
maxWeight: Metadata.Weight,
): Promise<TransactionDetails> {
console.log("Bob is approving the existing Multisig Transaction...")
const tx = sdk.tx.multisig.approveAsMulti(threshold, otherSignatures, timepoint, callHash, maxWeight)
const res = await tx.executeWaitForInclusion(account, {})
assert_eq(res.isSuccessful(), true)
if (res.events == undefined) throw Error()
return res
}
async function lastApproval(
sdk: SDK,
account: KeyringPair,
threshold: number,
otherSignatures: string[],
timepoint: Metadata.TimepointBlocknumber,
callData: string,
maxWeight: Metadata.Weight,
): Promise<TransactionDetails> {
console.log("Charlie is approving and executing the existing Multisig Transaction...")
const tx = sdk.tx.multisig.asMulti(threshold, otherSignatures, timepoint, callData, maxWeight)
const res = await tx.executeWaitForInclusion(account, {})
assert_eq(res.isSuccessful(), true)
if (res.events == undefined) throw Error()
return res
}
Transaction State
import { assert_eq } from "."
import { Account, Metadata, SDK } from "./../src/index"
export async function runTransactionState() {
const sdk = await SDK.New(SDK.localEndpoint)
const account = Account.alice()
const tx = sdk.tx.dataAvailability.submitData("My Data")
const txhash = await tx.execute(account, { app_id: 1 })
let states: Metadata.TransactionState[] = []
while (true) {
states = await sdk.client.transactionState(txhash)
if (states.length != 0) {
break
}
await sleep(1_000)
}
assert_eq(states.length, 1)
for (const state of states) {
console.log(
`Block Hash: ${state.blockHash.toHuman()}, Block Height: ${state.blockHeight}, Tx Hash: ${state.txHash.toHuman()}, Tx Index: ${state.txIndex}`,
)
console.log(
`Pallet Index: ${state.palletIndex}, Call Index: ${state.callIndex}, Tx Successful: ${state.txSuccess}, Is Finalized: ${state.isFinalized}`,
)
}
console.log("runTransactionState finished correctly")
}
function sleep(ms: number) {
return new Promise((resolve) => setTimeout(resolve, ms))
}
Indexer
import { SDK, Block, H256, UnsubscribePromise } from "./../src/index"
export async function runIndexer() {
const sdk = await SDK.New(SDK.turingEndpoint)
const indexer = new Indexer(sdk)
indexer.run(Kind.Manual)
// Fetching blocks in procedural way
const sub = await indexer.subscribe()
for (let i = 0; i < 3; i++) {
const block = await sub.fetch()
console.log(`Current: Block Height: ${block.height}, Block Hash: ${block.hash}`)
}
// Fetching historical blocks
sub.blockHeight = sub.blockHeight - 100
for (let i = 0; i < 3; i++) {
const block = await sub.fetch()
console.log(`Historical: Block Height: ${block.height}, Block Hash: ${block.hash}`)
}
// Callback
const sub2 = await indexer.callback(callback)
await sleep(25000)
sub2.stop()
await indexer.stop()
}
async function callback(block: IndexedBlock) {
console.log(`Callback: Block Height: ${block.height}, Block Hash: ${block.hash}`)
}
interface IndexedBlock {
hash: H256
height: number
block: Block
}
enum Kind {
Manual,
Stream,
}
class Indexer {
sdk: SDK
block: IndexedBlock | null
unsub: UnsubscribePromise | null
shutdown: boolean
constructor(sdk: SDK) {
this.sdk = sdk
this.block = null
this.unsub = null
this.shutdown = false
}
public async run(kind: Kind) {
if (this.unsub != null) {
return
}
if (kind == Kind.Manual) {
console.log("Manual")
this.taskManual()
} else if (kind == Kind.Stream) {
console.log("Stream")
this.taskStream()
}
}
public async taskManual() {
new Promise(() => {
;(async () => {
for (;;) {
if (this.shutdown) {
return
}
const hash = await this.sdk.client.finalizedBlockHash()
if (this.block != null && this.block.hash == hash) {
await sleep(15000)
continue
}
const height = await this.sdk.client.blockNumber(hash)
const block = await Block.New(this.sdk.client, hash)
this.block = { hash: hash, height: height, block }
}
})()
})
}
public async taskStream() {
const unsub = this.sdk.client.api.rpc.chain.subscribeFinalizedHeads(async (header) => {
const height = header.number.toNumber()
const hash = await this.sdk.client.blockHash(header.number.toNumber())
const block = await Block.New(this.sdk.client, hash)
this.block = { hash: hash, height: height, block }
})
this.unsub = unsub
}
public async getBlock(blockHeight: number): Promise<IndexedBlock> {
for (;;) {
if (this.block == null) {
await sleep(1000)
continue
}
const block = this.block
if (this.shutdown) {
return block
}
if (blockHeight > block.height) {
await sleep(15000)
continue
}
if (blockHeight == block.height) {
return { ...block }
}
const oldHash = await this.sdk.client.blockHash(blockHeight)
const oldBlock = await Block.New(this.sdk.client, oldHash)
return { hash: oldHash, height: blockHeight, block: oldBlock }
}
}
public async subscribe(): Promise<Subscription> {
for (;;) {
if (this.block == null) {
await sleep(1000)
continue
}
return new Subscription(this, this.block.height)
}
}
public async callback(fn: (arg0: IndexedBlock) => Promise<void>): Promise<Subscription> {
const sub = await this.subscribe()
new Promise(() => {
;(async () => {
for (;;) {
const block = await sub.fetch()
if (sub.state.shutdown == true) {
return
}
await fn(block)
}
})()
})
return sub
}
public async stop() {
this.shutdown = true
if (this.unsub != null) {
;(await this.unsub)()
}
this.unsub = null
}
}
class Subscription {
private indexer: Indexer
blockHeight: number
state: { shutdown: boolean }
constructor(indexer: Indexer, blockHeight: number) {
this.indexer = indexer
this.blockHeight = blockHeight
this.state = { shutdown: false }
}
public async fetch(): Promise<IndexedBlock> {
let block = this.indexer.getBlock(this.blockHeight)
this.blockHeight += 1
return block
}
public stop() {
this.state.shutdown = true
}
}
function sleep(ms: number) {
return new Promise((resolve) => setTimeout(resolve, ms))
}