# Authentication Source: https://docs.therootnetwork.com/asset-register/authentication There are two different types of authentication required based on the functionality you are trying to access. This guide will explain to you what they are and show you how to use them. ## Admin Functionality 🔒 Sign In with Ethereum (SIWE) is used to create access tokens to communicate with the authenticated endpoints on the Asset Register API (🔒). You can generate these tokens using [this helper tool](https://ar-docs.futureverse.app/siwe-generator/). The contents generated in the Authorization box, after you sign, should be used as the `Authorization` header when making API calls. ## Asset Register 🔑 Any updates made to the asset register through a transaction (i.e. asset links) will need to be signed by a wallet, similar to any other blockchain transaction (🔑). [Sign and send](/asset-register/guides/asset-link-operations#sign-and-send) the [Asset Link Operations](/asset-register/guides/asset-link-operations) guide explains how you can sign Asset Register transactions. # Getting Started Source: https://docs.therootnetwork.com/asset-register/getting-started Learning how to use the Assets API The Asset Register is a GraphQL API that can be interacted with through existing SDKs on JavaScript environments. ### SDKs **React SDK** The React SDK offers a convenient way to query assets within React-based applications. It leverages React's provider and hook-based approach, simplifying asset retrieval and integration within React projects. [https://www.npmjs.com/package/@futureverse/asset-register-react](https://www.npmjs.com/package/@futureverse/asset-register-react) **Core SDK** The Core SDK is designed for Node.js environments but can also be utilized in frameworks other than React. It provides a versatile means of interacting with the Assets API, offering comprehensive asset querying and manipulation functionality. [https://www.npmjs.com/package/@futureverse/asset-register](https://www.npmjs.com/package/@futureverse/asset-register) #### GraphQL API For developers seeking more customized functionality or specific use cases, direct interaction with the GraphQL API is also supported. The API is fully Relay specification compliant. Using the API directly allows for fine-grained control over asset queries and enables the execution of custom calls. #### Production **Root** and **Ethereum Mainnet** [https://ar-api.futureverse.app/graphql](https://ar-api.futureverse.app/graphql) #### Staging **Porcini** and **Goerli** [https://ar-api.futureverse.cloud/graphql](https://ar-api.futureverse.cloud/graphql) # Asset Link Operations Source: https://docs.therootnetwork.com/asset-register/guides/asset-link-operations Asset links can only be executed through a transaction. This guide will specifically focus on creating these operations using the SDKs. ## Prerequisite readings [Asset Register Transaction](/asset-register/guides/asset-register-transaction) goes into detail about how to create and submit transactions, whereas, this guide will focus on the asset link operations in particular to help you build an asset tree. In the following sections, we will focus on using the [ARTM library](https://www.npmjs.com/package/@futureverse/artm) to create and manipulate an ARTM and its operations. ## Create Asset Links 🔑 The user must own both assets to create links unless it is an off-chain asset, where only the creator of the child asset can create a link. Linking between assets owned on a FuturePass account and FuturePass account owner EOA is allowed. As long as the ownership resolution is satisfied links can be created across chains as well. ```typescript import { Operation } from '@futureverse/artm' const createAssetLinkOperation: Operation = { type: 'asset-link', action: 'create', args: [ 'equipWith_asmBrain', 'did:fv-asset:1:evm:0x6bca6de2dbdc4e0d41f7273011785ea16ba47182:1000', 'did:fv-asset:1:evm:0x1ea66a857de297471bc12dd12d93853ff6617284:21', ], } ``` * The first argument corresponds to the `path` or the `subject` of the link. * The second argument is the parent asset. An asset can have 0 to many links as a parent. * The third argument is the child asset. An asset can have 0 or 1 link as a child. ## Delete Asset Links 🔑 The user must own the parent asset to delete links. ```typescript import { Operation } from '@futureverse/artm' const deleteAssetLinkOperation: Operation = { type: 'asset-link', action: 'delete', args: [ 'equipWith_asmBrain', 'did:fv-asset:1:evm:0x6bca6de2dbdc4e0d41f7273011785ea16ba47182:1000', 'did:fv-asset:1:evm:0x1ea66a857de297471bc12dd12d93853ff6617284:21', ], } ``` You may have noticed that all the arguments look the same. This is because we have to be explicit with exactly which link we are deleting. ## Sign and Send! Using the above operations you can create an ARTM as follows: ```typescript import { ARTM } from '@futureverse/artm' import { ethers } from 'ethers' // Lets get you a wallet to get you started const wallet = new ethers.Wallet(0xc367447789c3d98a0005c48b761ffe7d2802cea44dace8656033b15d90914c1d) const artm = new ARTM({ address: wallet.address, // Custom message to help the user understand the operation statement: "Equip your ASM Brain", operations: [ createAssetLinkOperation, deleteAssetLinkOperation ], nonce: 0 }) artm.setSignature(wallet.signMessage('\x19Ethereum Signed Message:\n' + artm.message) console.log(artm.verify()) // true // Submit the transaction! ``` In the above transaction, we are creating and then deleting the link in the same transaction. This is completely fine to do so but there is no reason to perform it other than for demonstration purposes! Note that any invalid operation will result in the failure of the entire transaction. # Asset Register Transaction Source: https://docs.therootnetwork.com/asset-register/guides/asset-register-transaction Transactions are made to the Asset Register using a messaging standard designed to be human readable and familiar to blockchain users using the Ethereum message standard. ## Asset Register Transaction Message To make changes to the asset register you must make transactions using signed Ethereum messages. An Asset Register Transaction Message (ARTM) can be generated using the [ARTM SDK](https://www.npmjs.com/package/@futureverse/artm) and looks like this: ```bash Asset Registry transaction An update is being made to your inventory Operations: asset-link delete - equipWith_asmBrain - did:fv-asset:1:evm:0x6bca6de2dbdc4e0d41f7273011785ea16ba47182:1000 - did:fv-asset:1:evm:0x1ea66a857de297471bc12dd12d93853ff6617284:20 end asset-link create - equipWith_asmBrain - did:fv-asset:1:evm:0x6bca6de2dbdc4e0d41f7273011785ea16ba47182:1000 - did:fv-asset:1:evm:0x1ea66a857de297471bc12dd12d93853ff6617284:21 end asset-link create - http://schema.futureverse.com/tnl#equipWith_gloves - did:fv-asset:1:evm:0x6bca6de2dbdc4e0d41f7273011785ea16ba47182:1000 - did:fv-asset:1:root:0x1ea66a857de297471bc12dd12d93853ff6617284:21 end delegate delete - 0x6bca6de2dbdc4e0d41f7273011785ea16ba47182 (FPPass address - account 1) - 0x6bca6de2dbdc4e0d41f7273011785ea16ba47183 (FPPass address - account 2) end ownership update - did:fv-asset:1:evm:0x6bca6de2dbdc4e0d41f7273011785ea16ba47182:1000 - 0x6bca6de2dbdc4e0d41f7273011785ea16ba47182 end asset-link create - equipwith_hairStyle - did:fv-asset:1:evm:0x6bca6de2dbdc4e0d41f7273011785ea16ba47182:1000 - did:fv-asset:off-chain:0x6bca6de2dbdc4e0d41f7273011785ea16ba47182:1234 end Operations END Address: 0x854A3E045Ac44a7f4A1726AdAC576029135DFdA7 Nonce:1 ``` ### ARTM Creation #### React - useGetARTM ````tsx import { useGetARTM } from '@futureverse/asset-registry-react' const Page = () => { const { data: artm } = useGetARTM({ address: signer.address, operations, }) // use artm elsewhere in the component } The `artm` object is defined in [ARTM SDK](https://www.npmjs.com/package/@futureverse/artm). Therefore, signing can be done manually and then sent to the Asset Register API using the [Asset Mutation](asset-register-transaction#asset-mutation-graphql-mutation), or it can be used with the [useAssetMutation](asset-register-transaction#react-useassetmutation) hook directly. #### Library - ARTM SDK Under the hood, the React library uses the [ARTM SDK](broken-reference). This library is specifically built to enable the creation, signing, and validation of ARTMs. Creating an ARTM message is described in detail on the [NPM page](https://www.npmjs.com/package/@futureverse/artm). ## Nonce Like a traditional blockchain, the Asset Register uses nonces to prevent replay attacks. The nonce for a chain address can be queried using the Asset Register API as follows: ```graphql query GetNonce($input: NonceInput!) { getNonceForChainAddress(input: $input) } ```` ```json { "input": { "chainAddress": "0xc07Bdbf297Caa9488D194835298eE7037C861143" } } ``` ## Submitting Transactions ### React - useSubmitTransaction ```typescript import { useAssetMutationMutation, useGetARTM } from '@futureverse/asset-registry-react' const Page = () => { const { data: artm } = useGetARTM({ address: signer.address, operations, }) const { mutateAsync: submitTransactionAsync, data } = useSubmitTransaction() const submitARTM = async () => { // Sign transaction and set on the ARTM instance to validate signature const signature = await signer.signMessage(artm.getMessageToSign()) artm.setSignature(signature) // Submit transaction to Asset Registry API submitTransactionAsync({ input: { transaction: artm.message, signature: artm.signature } }) } return ( ) } ``` ### GraphQL - Submit Transaction ```graphql mutation SubmitTransaction($input: SubmitTransactionInput!) { submitTransaction(input: $input) { transactionHash } } ``` ````json { "input": { "transaction": "Asset Registry transaction\n\nAn update is being made to your inventory\n\nOperations:\n\nasset-link create\n- equipWith_asmBrain\n- did:fv-asset:1:evm:0x6bca6de2dbdc4e0d41f7273011785ea16ba47182:1000\n- did:fv-asset:1:evm:0x1ea66a857de297471bc12dd12d93853ff6617284:21\nend\n\nOperations END\n\nAddress: 0x225b5333C2D8EC41F40D6463D44141786C2c4463\nNonce: 0", "signature": "0x282dbd15e2ef7091c8599ce1073e7c0f94cd7a02526b6bc43b84f01f190b457047b34e0d3bb63797872dffa106f33f914d5e6ff6d2e978f39944c6af6efec7691b" } } #### Example Response ```json { "data": { "submitTransaction": { "transactionHash": "0x9aa26c9bfce628b160a43c155a12049c22c74276c28ca250df20df40f78baf1c" } } } ```` ## Viewing Transactions ```typescript import { FC } from 'react' import { useGetTransaction } from '@futureverse/asset-registry-react' import { TransactionHash } from '@futureverse/asset-registry/types' type Props = { transactionHash: string } export const TransactionStatus: FC = ({ transactionHash }) => { const { transaction } = useGetTransaction( { transactionHash: transactionHash as TransactionHash }, { refetchInterval: (data) => (data?.status === 'PENDING' ? 5000 : false), }, ) if (!transaction) return null return (

Transaction Status:

{JSON.stringify(transaction, undefined, 2)}
) } ```
### GraphQL - Transaction ```graphql query Transaction($transactionHash: TransactionHash!) { transaction(transactionHash: $transactionHash) { status id events { action args type } transactionHash } } ``` ```json { "transactionHash": "0xe28a8c0d45eb432093a96f73f70802c6dd7c5047a9a710817233f6b4f1b96615" } ``` ```json { "data": { "transaction": { "status": "SUCCESS", "id": "VHJhbnNhY3Rpb246MHhlOThhOGMwZDQ1ZWI0MzIwOTNhOTZmNzNmNzA4MDJjNmRkN2M1MDQ3YTlhNzEwODE3MjMzZjZiNGYxYjk2NjE1", "events": [ { "action": "create", "args": [ "equipWith_gloves", "did:fv-asset:1:evm:0x59029213099dF720676bf0991a57e49518b00D72:1000", "did:fv-asset:1:evm:0x2308742aa28cc460522ff855d24a365f99deba7b:23" ], "type": "asset-link" } ], "transactionHash": "0xe28a8c0d45eb432093a96f73f70802c6dd7c5047a9a710817233f6b4f1b96615" } } } ```
# Error Messages Source: https://docs.therootnetwork.com/asset-register/guides/error-messages This section explains the error codes that can occur during a transaction and the scenarios in which they might happen. These codes help identify the specific reason a transaction failed. ## Transaction Error Codes
CodeDescriptionScenario
FAIL\_ARTM\_VALIDATION (1)Failed to verify the signature of the Asset Rights Token Metadata (ARTM).This error occurs when the signature on the ARTM message is invalid or cannot be verified. This could happen if the ARTM message is tampered with, the signing key is incorrect, or there's an issue with the signature verification process.
INVALID\_NONCE (2)The provided nonce (a unique value used to prevent replay attacks) is invalid.This error occurs when the provided nonce value is invalid. It could be because the nonce has already been used in a previous transaction (replay attack), the nonce value is not formatted correctly, or it's missing entirely.
FAIL\_NEPTUNE\_TRANSACTION (3)An error occurred while processing the transaction on the Neptune network.This error indicates a problem with processing the transaction on the underlying Neptune network. This could be due to network issues, errors on the Neptune side, or invalid transaction data sent to the network.
FAIL\_NONCE\_UPDATE (4)Failed to update the nonce value.This error occurs when there's an issue updating the system's internal nonce value after a successful transaction. This is typically an internal system error and might require further investigation.
INVALID\_ARTM (5)The ARTM message could not be parsed correctly.This error occurs when the system cannot understand the format of the ARTM message. This could happen if the message is corrupted, missing required fields, or contains invalid data.
INVALID\_ASSET\_OWNER (6)The ownership of the asset could not be validated.This error occurs when the system cannot verify that the sender of the transaction is the rightful owner of the asset involved. This could be due to missing ownership information, invalid ownership claims, or conflicting ownership records.
INVALID\_OPERATION (7)The attempted operation is not allowed for this type of transaction.This error occurs when the user tries to perform an action that's not allowed for the specific transaction type.
INVALID\_ASSET\_PARENT (8)An asset cannot have multiple node parents.This error occurs when a transaction tries to assign an asset multiple parent nodes, which is not allowed in the system.
INVALID\_SIGNATURE (9)The provided signature is invalid.This error occurs when the signature on the transaction is invalid or cannot be verified. This could be similar to FAIL\_ARTM\_VALIDATION but might apply to signatures on other parts of the transaction data.
INVALID\_ASSET\_TYPE (10)The type of asset is not allowed in this context.This error occurs when the transaction involves an asset type that's not allowed for the specific operation. For example, trying to assign an SFT as a parent asset.
MAX\_BALANCE\_ALLOCATED (11)The maximum balance has already been allocated for the Security Fungible Token (SFT).This error occurs specifically for SFTs (Semi-Fungible Tokens) and indicates that the transaction would exceed the maximum allowed balance for that particular SFT.
PARENT\_PATH\_IN\_USE (12)The chosen path is already in use on the parent asset.This error occurs when a transaction tries to assign a path to an asset that's already in use by another child asset under the same parent. This ensures a hierarchical structure with unique paths for child assets.
FAIL\_LINK\_VALIDATION (13)The information provided for linking assets failed validation.This error occurs when the information provided for linking assets (like target asset or link type) is invalid or doesn't meet the system's requirements.
ASSET\_ALREADY\_LINKED (14)The asset is already linked.This error occurs when a transaction tries to link an asset that's already linked to another asset. Linking can only be done once for an asset.
# How to Schema Source: https://docs.therootnetwork.com/asset-register/guides/how-to-schema This guide will take you through registering schemas that are compliant with the Asset Register. These schemas and shapes help ensure that data about assets, NFTs, and other entities adhere to the required structure and constraints. ## Examples ### Futureverse This example defines the core classes and their hierarchies within the Futureverse framework. These definitions create a hierarchy where `fv:Asset` is the root, and the more specific classes like `fv:NFT` and `fv:SFT` inherit from it. Each of these asset types can be further categorized into on-chain or off-chain, depending on where the asset data is stored. ```turtle @prefix sh: . @prefix fv: . @prefix rdf: . @prefix rdfs: . @prefix xml: . fv:Asset a rdfs:Class, sh:NodeShape ; rdfs:comment "An asset" ; . fv:NFT a rdfs:Class, sh:NodeShape ; rdfs:subClassOf fv:Asset ; rdfs:comment "An NFT" ; . fv:SFT a rdfs:Class, sh:NodeShape ; rdfs:subClassOf fv:Asset ; rdfs:comment "An SFT" ; . fv:OnChainNFT a rdfs:Class, sh:NodeShape ; rdfs:subClassOf fv:NFT ; rdfs:comment "An on chain NFT" ; . fv:OffChainNFT a rdfs:Class, sh:NodeShape ; rdfs:subClassOf fv:NFT ; rdfs:comment "An off chain NFT" ; . fv:OnChainSFT a rdfs:Class, sh:NodeShape ; rdfs:subClassOf fv:NFT ; rdfs:comment "An on chain SFT" ; . fv:OffChainSFT a rdfs:Class, sh:NodeShape ; rdfs:subClassOf fv:NFT ; rdfs:comment "An off chain SFT" ; . ``` ### TNL Boxer This example defines a specific instance of an `OnChainNFT`, called `Boxer`, using SHACL (Shapes Constraint Language). ```turtle @prefix sh: . @prefix schema: . @prefix rdfs: . @prefix fv: . @prefix this: . @prefix asm: . this:Boxer a fv:OnChainNft, sh:NodeShape ; rdfs:subClassOf fv:OnChainNft; sh:property [ sh:maxCount 1 ; sh:minCount 0 ; sh:class asm:Brain ; sh:path asm:equippedWith_brain ; ], [ sh:maxCount 1 ; sh:minCount 0 ; sh:class this:HairStyle ; sh:path this:equippedWith_hairStyle ; ], [ sh:maxCount 1 ; sh:minCount 0 ; sh:class this:HairDye ; sh:path this:equippedWith_hairDye ; ], [ sh:maxCount 1 ; sh:minCount 0 ; sh:class this:Bags ; sh:path this:equippedWith_bags ; ], [ sh:maxCount 1 ; sh:minCount 0 ; sh:class this:OutFit ; sh:path this:equippedWith_outfit ; ], [ sh:maxCount 1 ; sh:minCount 0 ; sh:class this:Gloves ; sh:path this:equippedWith_gloves ; ], [ sh:maxCount 1 ; sh:minCount 0 ; sh:class this:Boots ; sh:path this:equippedWith_boots ; ] . ``` #### TNX Boxer properties 1. **`sh:property`**: * The `sh:property` construct defines constraints on a particular property of a node. Inside each `sh:property` block, you specify details about the property, such as its path, type, cardinality, and more. 2. **`sh:maxCount` and `sh:minCount`**: * **`sh:maxCount 1`**: This specifies that the property can have at most one value. It's used to enforce uniqueness or singularity of a particular property in a node. * **`sh:minCount 0`**: This means that the property is optional (it can have zero values). If this were set to 1, the property would be required. Together, these constraints define a property that is optional but can only occur once if present. 3. **`sh:class asm:Brain`**: * The `sh:class` property is used to enforce that the value of the property must be of a specific RDF class, in this case, `asm:Brain`. This ensures that the value of `asm:equippedWith_brain` must be an instance of the `asm:Brain` class. 4. **Targeting Multiple Classes with `sh:class`**: * You can target multiple classes by listing them in a comma-separated list within the `sh:class` property. For example: ```turtle sh:class fv:Gloves, fv:Mittens ; ``` This specifies that the property can be an instance of either `fv:Gloves` or `fv:Mittens`. 5. **`sh:path` Property**: * The `sh:path` statement indicates the exact RDF property within your data model that is subject to the constraints defined in the SHACL shape. ```turtle sh:path asm:equippedWith_brain ; ``` In this case, `asm:equippedWith_brain` is the RDF property that the shape is describing. This property might represent a relationship where a `Boxer` is equipped with a `Brain`. ### ASM Brain This example defines `Brain` as a specialized type of `OnChainNFT`, inheriting properties and constraints from its parent classes. ```turtle @prefix sh: . @prefix schema: . @prefix rdfs: . @prefix fv: . @prefix this: . this:Brain a fv:OnChainNft, sh:NodeShape ; rdfs:subClassOf fv:OnChainNft;. ``` # Off-Chain Assets Source: https://docs.therootnetwork.com/asset-register/guides/off-chain-assets Off-chain assets, as the name implies, lives on an off-chain database and ownership is managed by the creator. ## Identifier Off-chain assets need to be globally unique and identifiable just like on-chain assets. To achieve this for Futureverse assets, we have built an off-chain ownership repository to register any off-chain assets against the Asset Register.
PropertyDescriptionExample
Creator IDRandomly generated UUID for the creator. This will be provided to you and only you will be able access it.40877d72-9957-4de7-af77-1ee9f54a529e
Creator Collection IDA creator’s collection ID. This should be unique for each creator. It can be any string.12 | pb\_1232124| bedde205-5af2-423b-9092-088c8951a2ea
Token ID (optional)The token ID is for uniquely identifying NFT assets in a collection. It will be empty if it is SFT (ERC1155 equivalent). This can be any string (like a UUID), however, it is best practice to stick to a number.4637 | 61d21cf3-6e0d-4b9d-a2c8-55583eb81a84
Asset IDThis is the combination of creatorAddress,creatorCollectionId & tokenId. SFT assets will not have a Token ID.40877d72-9957-4de7-af77-1ee9f54a529e:12:4637
### DID Since ownership resolution needs to be globally unique we can use the `did:fv-asset` DID method directly with the already globally unique Asset ID. #### Example `did:fv-asset:off-chain:40877d72-9957-4de7-af77-1ee9f54a529e:12:4637` *** ## Asset types Just like on-chain assets which are classified as ERC721 (NFT) and ERC1155 (equivalent to an SFT), off-chain assets can be defined in the same way. ### NFT A unique asset just like ERC721. #### Defined by `off-chain:{creatorId}:{creatorCollectionId}:{tokenId}` For example: `off-chain:40877d72-9957-4de7-af77-1ee9f54a529e:12:4637` ### SFT A collection that can store an infinite amount of assets defined by the same asset ID. #### Defined by `off-chain:{creatorId}:{creatorCollectionId}` For example: `off-chain:40877d72-9957-4de7-af77-1ee9f54a529e:12` *** ## Register Off-Chain Asset 🔒 Unlike creating assets on the chain, off-chain assets must be registered with the Asset Register before they can then be [registered with the schema](/asset-register/guides/schema-management/register-asset-with-schema). Assuming the schema for the off-chain asset is already created, the following illustrates the process of fully registering a new off-chain asset with the Asset Register to generate an asset tree. ```mermaid flowchart TD A[Experience Backend] --> B{Is the Off-Chain Asset registered with AR} B -->|Yes| C{Is the Off-Chain Asset linked to a schema?} B ---->|No| E[Register Asset] C --> |Yes| F[Registration Complete] C --> |No| D[Register Off-Chain Asset with schema] E --> C D --> F ``` ### Register Asset - GraphQL Mutation ```graphql mutation RegisterOffChainAsset($input: RegisterOffChainAssetInput!) { registerOffChainAsset(input: $input) { ... on RegisterOffChainAssetSuccess { offChainAsset { assetId creator tokenId creatorCollectionId type } } ... on RegisterOffChainAssetFailure { errors { message extensions { code } } } } } ``` ```json { "input": { "creatorCollectionId": "20001", "creatorId": "eb117567-e455-4abd-b8e1-a7e451b96b23", "tokenId": "1" } } ``` # Schema Management Source: https://docs.therootnetwork.com/asset-register/guides/schema-management/creating-schemas # Creating Schemas Creating schemas is a two-step process. First, you must create the namespace which a schema will live under. A namespace contains a set of schemas that describe something in the same domain. For example the `http://schema.futureverse.com/tnl` the namespace will contain the Boxer, `Gloves`, `HairStyle` and `HairDye` schemas for [The Next Legends](https://thenextlegends.xyz/). ## Schema creation flow We are creating a front-end experience to make this a lot easier instead of going through and making API calls. ```mermaid flowchart TD B{Has the namespace been created?} B -->|Yes| C{Is the schema already created?} B ---->|No| E[Create namespace] C --> |No| D[Create schema] C --> |Yes| F[Create new schema version] E --> C ``` ### Create Namespace 🔒 A namespace can only be created if the namespace owner has been whitelisted under a domain. This functionality is in development. In the meantime, please contact the Customer Success team via [customersuccess@futureverse.com](mailto:customersuccess@futureverse.com) to access a namespace. ### Create Schema 🔒 A valid SIWE token with a signature must be set as the Authorisation Header. ```graphql mutation CreateSchema($input: CreateSchemaInput!) { createSchema(input: $input) { ... on CreateSchemaSuccess { id schema version } ... on CreateSchemaFailure { errors { message } } } } ``` ```json { "input": { "id": "9ad55aa3-6870-4133-8433-285e6a648790", "namespace": "http://schema.futureverse.com/fv", "schema": "@prefix sh: .@prefix schema: .@prefix fvp: .@prefix rdf: .@prefix xml: . fvp:Asset a rdf:Class, sh:NodeShape ; sh:property [ sh:datatype xml:string ; sh:maxCount 1 ; sh:minCount 1 ; sh:path fvp:id ; ] .", "version": 1 } } ``` ### Create a new Schema Version 🔒 When you create a new schema under a pre-existing schema entity it will create a new version. To create a schema it is the same as [above](/asset-register/guides/schema-management/creating-schemas#create-schema). Ensure that the version is incremented by 1 otherwise, it will fail. # Example Source: https://docs.therootnetwork.com/asset-register/guides/schema-management/example Example of Assets with Schemas Here we will use party bears (collectionId 303204 on Porcini) as an example to create schemas, and then equip the party bear dynamically through the schema. ## Schema Creation [https://ar-docs.futureverse.dev/schema/](https://ar-docs.futureverse.dev/schema/) ```tsx const namespace = "http://schema.futureverse.dev/pb" as NamespaceUrl; const bearSchema = ` @prefix this: . @prefix sh: . @prefix fvp: . @prefix path: . this:Bear a fvp:OnChainERC721Asset; sh:property [ sh:minCount 0; sh:maxCount 1; sh:class this:AccessoryEars; sh:path path:equippedWith_accessoryEars ], [ sh:minCount 0; sh:maxCount 1; sh:class this:AccessoryEyewear; sh:path path:equippedWith_accessoryEyewear ]. `; const accessoryEyewearSchema = ` @prefix this: . @prefix sh: . @prefix fvp: . @prefix path: . this:AccessoryEyewear a fvp:OnChainERC721Asset ; . `; const accessoryEarsSchema = ` @prefix this: . @prefix sh: . @prefix fvp: . @prefix path: . this:AccessoryEars a fvp:OnChainERC721Asset ; . `; const SchemaCreation = () => { const { createAsync: createSchemaAsync } = useCreateSchema(); const createPartybearSchema = async () => { await createSchemaAsync({ name: "bear", schema: bearSchema, version: 0, namespace, }); }; const createAccessoryEyewearSchema = async () => { await createSchemaAsync({ name: "accessoryEyewear", schema: accessoryEyewearSchema, version: 0, namespace, }); }; const createAccessoryEarsSchema = async () => { await createSchemaAsync({ name: "AccessoryEars", schema: accessoryEarsSchema, version: 0, namespace, }); }; return (
); }; ```
```graphql mutation CreateSchema($input: CreateSchemaInput!) { createSchema(input: $input) { __typename ... on CreateSchemaSuccess { schema { id name version namespace schema } } } } ``` 1. Partybear schema" ```json { "input": { "name": "bear", "schema": "@prefix this: .\n@prefix sh: .\n@prefix fvp: .\n@prefix path: .\n\nthis:Bear a fvp:OnChainERC721Asset;\n sh:property [\n sh:minCount 0;\n sh:maxCount 1;\n sh:class this:AccessoryEars;\n sh:path path:equippedWith_accessoryEars\n], [\n sh:minCount 0;\n sh:maxCount 1;\n sh:class this:AccessoryEyewear;\n sh:path path:equippedWith_accessoryEyewear\n].\n", "version": 1, "namespace": "http://schema.futureverse.dev/pb" } } ``` 2. AccessoryEyewear schema" fullWidth="true" ```json { "input": { "name": "accessoryEyewear", "schema": "@prefix this: .\n@prefix sh: .\n@prefix fvp: .\n@prefix path: .\n\nthis:AccessoryEyewear a fvp:OnChainERC721Asset ;\n .", "version": 1, "namespace": "http://schema.futureverse.dev/pb" } } ``` 3. AccessoryEars schema" ```json { "input": { "name": "AccessoryEars", "schema": "@prefix this: .\n@prefix sh: .\n@prefix fvp: .\n@prefix path: .\n\nthis:AccessoryEars a fvp:OnChainERC721Asset ;\n .", "version": 1, "namespace": "http://schema.futureverse.dev/pb" } } ```
## Asset Registration with Schema [https://ar-docs.futureverse.dev/collection/](https://ar-docs.futureverse.dev/collection/) ```tsx const SchemaRegistration = () => { const { createAsync } = useRegisterTokenSchema() const register = async (collectionId, schemaId) => { await createAsync({ collectionId, schemaId, }) } return (
) } ```
````graphql mutation RegisterTokenSchema($input: RegisterTokenSchemaInput!) { registerTokenSchema(input: $input) { tokenSchema { collectionId id schemaId tokenId version } } } 1. Party bear input" ```json { "input": { "collectionId": "7672:root:303204", "schemaId": "http://schema.futureverse.dev/pb#bear" } } ```` 2. AccessoryEars input" ```json { "input": { "collectionId": "7672:root:240740", "schemaId": "http://schema.futureverse.dev/pb#AccessoryEars" } } ``` 3. AccessoryEyewear" ```json { "input": { "collectionId": "7672:root:245860", "schemaId": "http://schema.futureverse.dev/pb#AccessoryEyewear" } } ```
## Find equitable slots for the party bear [https://ar-docs.futureverse.dev/manage-assets/QXNzZXQ6NzY3Mjpyb290OjMwMzIwNDoyMzI=](https://ar-docs.futureverse.dev/manage-assets/QXNzZXQ6NzY3Mjpyb290OjMwMzIwNDoyMzI=) ```tsx // An component to display all equitable slots for an party bear const SwappablesRootAsset = ({ address, tokenId, collectionId}) => { const { asset } = useGetAsset( { tokenId, // party bear token id collectionId, addresses: [address], } ) const { assets } = useAssets( { first: 1000, addresses: [address], } ) type Slot = { schemaName: string assets: typeof assets } const [accessorySlots, setAccessorySlots] = useState([]) useEffect(() => { if (!assets || !asset) { return } const updateSlots = async () => { const slotSchemaNames = await getPaths(asset?.schema?.schema) const schemaNamespace = currentAsset?.schema?.namespace const slots = slotSchemaNames.map((schemaName) => { const slotAssets = assets.filter( (asset) => asset?.schema?.name.toLowerCase() === schemaName.toLowerCase() && asset.schema.namespace === schemaNamespace, ) return { assets: slotAssets, schemaName, } }) setAccessorySlots(slots) } updateSlots() }, [assets, asset]) return
display swappable slots for partybear
} ```
## Equip and submit transaction [https://ar-docs.futureverse.dev/manage-assets/QXNzZXQ6NzY3Mjpyb290OjMwMzIwNDoyMzI=](https://ar-docs.futureverse.dev/manage-assets/QXNzZXQ6NzY3Mjpyb290OjMwMzIwNDoyMzI=) ```tsx // accessoryEarsAsset is one of the assets selected from last step's slot.assets const EquipAccessory = (partybearAsset, accessoryEarsAsset) => { const { submitAsync, transaction } = useSignAndSubmitTransaction() const handleSave = async () => { const { data: artm } = await getARTM() artm.operations = [] artm.addOperation({ type: 'asset-link', action: 'create', args: [ `equippedWith_accessoryEars`, partybearAsset.assetTree.nodeId, accessoryEarsAsset.assetTree.nodeId, ], }) submitAsync({ artm }) } return } ``` # Register Asset with Schema Source: https://docs.therootnetwork.com/asset-register/guides/schema-management/register-asset-with-schema Link a collection or specific token to a schema so the Asset Registry can validate and generate the Asset Tree. This guide covers linking: 1. On-chain collections / tokens 2. Off-chain collections / assets (after initial off-chain asset registration) ## Register a Collection Use `registerTokenSchema` to attach a schema at the collection level (omit or set `tokenId` to `null`). This supersedes the deprecated `registerCollection` mutation. Authorization will require the collection/NFT contract owner (or an authorised wallet). Ensure the schema is already created via `createSchema`. ### GraphQL Mutation (Collection-Level) ```graphql mutation RegisterTokenSchema($input: RegisterTokenSchemaInput!) { registerTokenSchema(input: $input) { tokenSchema { id collectionId tokenId schemaId version } } } ``` Example variables (collection-level): ```json { "input": { "collectionId": "1:evm:0x6bca6de2dbdc4e0d41f7273011785ea16ba47182", "tokenId": null, "schemaId": "http://schema.futureverse.dev/fv#TNLBoxer" } } ``` ### Token-Level Override (Optional) Register a specific token to a different schema (falls back to collection-level if token record absent). ```json { "input": { "collectionId": "1:evm:0x6bca6de2dbdc4e0d41f7273011785ea16ba47182", "tokenId": "1234", "schemaId": "http://schema.futureverse.dev/fv#TNLBoxerVariant" } } ``` ### Response Shape On success: ```json { "data": { "registerTokenSchema": { "tokenSchema": { "collectionId": "1:evm:0x6bca6de2dbdc4e0d41f7273011785ea16ba47182", "tokenId": "null", "schemaId": "http://schema.futureverse.dev/fv#TNLBoxer", "version": 1 } } } } ``` ## Register Off-Chain Asset With Schema After creating (or ensuring the existence of) an off-chain asset via `registerOffChainAsset`, link its **collection** (or optionally a specific off-chain NFT token) to a schema using the *same* `registerTokenSchema` mutation. Off-chain collection IDs use the pattern: `off-chain:{creatorId}:{creatorCollectionId}` (collection-wide) and individual NFT tokens may add a token segment when referencing the asset itself, but schema linkage for token-level overrides still supplies the collection ID plus a tokenId value (mirroring on-chain semantics). You do NOT register schema linkage with the full `did:fv-asset:off-chain:...` DID. Use the raw off-chain collection ID (`off-chain:...:...`) and, for token-level overrides, the `tokenId` you used during `registerOffChainAsset`. ### Off-Chain Collection-Level Schema Link ```graphql mutation RegisterTokenSchema($input: RegisterTokenSchemaInput!) { registerTokenSchema(input: $input) { tokenSchema { collectionId tokenId schemaId version } } } ``` Example variables: ```json { "input": { "collectionId": "off-chain:eb117567-e455-4abd-b8e1-a7e451b96b23:20001", "tokenId": null, "schemaId": "http://schema.futureverse.dev/example#OffChainAvatar" } } ``` ### Off-Chain Token-Level Override (Optional) If a specific off-chain NFT (with `tokenId`) requires a divergent schema: ```json { "input": { "collectionId": "off-chain:eb117567-e455-4abd-b8e1-a7e451b96b23:20001", "tokenId": "1", "schemaId": "http://schema.futureverse.dev/example#OffChainAvatarVariant" } } ``` For full off-chain asset registration details, see the dedicated [Off-Chain Assets](/asset-register/guides/off-chain-assets) guide. *** ## (Deprecated) Previous Method `registerCollection` is deprecated and will be / has been removed. Use `registerTokenSchema` for all new integrations. # Subscriptions Source: https://docs.therootnetwork.com/asset-register/guides/subscriptions Like a blockchain, Asset Register is event driven and therefore subscribers must be given real time feedback on what is happening so they can react to them. ## Event When you subscribe to an event you will receive the full transaction that includes the event you are interested in. ```json { "status": "SUCCESS", "signature": "0x00", "message": "", "events": [ { "type": "asset-link", "action": "delete", "args": [ "equipWith_asmBrain", "did:fv-asset:1:evm:0x6bca6de2dbdc4e0d41f7273011785ea16ba47182:1000", "did:fv-asset:1:evm:0x1ea66a857de297471bc12dd12d93853ff6617284:200", ], "collectionId": "1:evm:0x6bca6de2dbdc4e0d41f7273011785ea16ba47182" } ] } ``` ## Webhook Like any other webhook subscription, the Asset Register Subscription Service will forward the events via a POST request with the `API_KEY` set in the headers, ensuring the origination of the request. If an event delivery to a webhook endpoint is attempted and an error occurs, the following takes place: * Events associated with error codes 409, 429, and 5xx are retried. * Events associated with error codes 1xx, 2xx, 3xx, and 4xx (excluding 429) are not retried. We read the standard HTTP response header `Retry-After` to determine how long to wait before making a follow-up request. We then choose the more conservative value between the defined retry policy and the `Retry-After` header. If `Retry-After` value is negative, the event will not be retried. ## Usage You must send a valid SIWE token for the following interactions. Please see [Admin Authentication](/asset-register/authentication#admin-functionality). The following mutations demonstrate the main use cases. However, additional mutations for managing endpoints are available. To explore the complete set of mutations, refer to the GraphQL playground by navigating to the GraphQL URL in your browser. ### Creating a webhook endpoint Before you can create a subscription, a webhook endpoint must be created. This will point all the subscriptions to the correct URL and will set you up with an API Key for request authentication. ```graphql mutation CreateWebhookEndpoint($input: CreateWebhookEndpointInput!) { createWebhookEndpoint(input: $input) { webhookEndpoint { id webhookId subscriber url apiKey retries createdAt } } } ``` ```json { "input": { "url": "https://example.com/webhook", "retries": 5 } } ``` The `retries` property determines the number of times the webhook endpoint will be retried before stopping. The maximum allowable number of retries is set at **20**. The `webhookId` from the response should be used when[creating-a-subscription](/asset-register/guides/subscriptions#creating-a-subscription). ### Creating a subscription ```graphql mutation CreateWebhookSubscription($input: CreateWebhookSubscriptionInput!) { createWebhookSubscription(input: $input) { webhookSubscription { id subscriptionId webhookId type actions collectionId createdAt } } } ``` ```json { "input": { "type": "asset-link", "actions": ["create", "delete"], "collectionId": "1:evm:0x6bca6de2dbdc4e0d41f7273011785ea16ba47182", "webhookId": "8fafd82a-ca5e-4495-9ad4-d28c4ea6adf0" } } ``` ### Querying subscription resources You can use the following queries to get subscription resources created by the requester: * `webhookEndpoint` * `webhookEndpoints` * `webhookSubscription` * `webhookSubscriptions` # View Asset Tree Source: https://docs.therootnetwork.com/asset-register/guides/view-asset-tree This guide will go into detail about querying the asset tree. ## Asset Tree ### Example ```json { "@context": { "@vocab": "http://schema.futureverse.com#", "schema": "http://schema.org/", "fvp": "http://schema.futureverse.com/fvp#", "fv": "http://schema.futureverse.com/fv#", "tnl": "http://schema.futureverse.com/tnl#" }, "@graph": [ { "@id": "did:fv-asset:1:evm:0x6bca6de2dbdc4e0d41f7273011785ea16ba47182:1211", "@type": "tnl:Boxer", "fv:equippedWith_brain": { "@id": "did:fv-asset:1:evm:0xd0318da435dbce0b347cc6faa330b5a9889e3585:1211" }, "fv:equippedWith_hairStyle": { "@id": "did:fv-asset:off-chain:60163ecf-ae7b-4eb5-a78c-31d825322613:2:2" }, "tnl:equippedWith_leftGlove": { "@id": "did:fv-asset:7668:10420:2" }, "tnl:equippedWith_rightGlove": { "@id": "did:fv-asset:7668:10420:1" } }, { "@id": "did:fv-asset:1:evm:0xd0318da435dbce0b347cc6faa330b5a9889e3585:1211", "@type": "fv:ASMBrain", "fv:equippedWith_memory": { "@id": "did:fv-asset:off-chain:60163ecf-ae7b-4eb5-a78c-31d825322613:1:10" } }, { "@id": "did:fv-asset:off-chain:60163ecf-ae7b-4eb5-a78c-31d825322613:1:10", "@type": "fv:ASMMemory" }, { "@id": "did:fv-asset:off-chain:60163ecf-ae7b-4eb5-a78c-31d825322613:2:2", "@type": "tnl:HairStyle" }, { "@id": "did:fv-asset:7668:10420:1", "@type": "tnl:Glove", }, { "@id": "did:fv-asset:7668:10420:2", "@type": "tnl:Glove", } ] } ``` #### Visualisation ## GraphQL Query ```graphql query GetAssetTree($input: AssetTreeInput!) { getAssetTree(input: $input) { ... on AssetTreeResultSuccess { data } ... on AssetTreeResultFailure { errors { message } } } } ``` ```json { "input": { "tokenId": "1000", "collection": { "chainType": "evm", "location": "0x6bca6de2dbdc4e0d41f7273011785ea16ba47182", "chainId": 1 } } } ``` Where, * `tokenId` - The token ID of the NFT you want the asset tree for * `collection.chainType` - Either `evm` or `root` to specify where the asset lives on The Root Network we have both EVM (`evm`) and native substrate (`root`) storage, so this specifies where to look * `collection.location` - The location of the NFT, this is either a contract address if the `chainType` is `evm` or a collection ID (number) if the `chainType` is `root` * `collection.chainId` - The Chain ID of the blockchain the asset lives on # How it works Source: https://docs.therootnetwork.com/asset-register/how-it-works ## Schemas Schemas play a pivotal role in the Asset Register ecosystem. They exist within a specific namespace and provide a comprehensive description of an asset. The goal is to define the capabilities of an asset for linking, ensuring that any applications interacting with these assets can interpret and represent them correctly. These descriptions are crucial for seamless integration between various assets. To achieve this, the Asset Register utilizes schemas. These schemas are registered both on-chain and off-chain through the Asset Register API. This process ensures that information about an asset's properties and compatibility with other assets (i.e. asset links) are globally accessible and permanently stored. ### Asset Schema The Asset Schema is a detailed specification outlining the properties of an asset and its compatibility with other assets through asset links. These schemas should be stored in a globally accessible and permanent location. Moreover, they need to be registered against specific assets. The Asset Register facilitates the registration of these schemas, allowing Futureverse teams to store them on a dedicated namespace. ### Namespace In the Asset Register, a namespace is a container for organizing and presenting schemas. It serves as a centralized mechanism to group related schemas together. This organizational approach is crucial for efficient management, preventing naming conflicts, and improving overall code organization. In the context of Futureverse, namespaces play a vital role in grouping schemas for internal use. ## Asset Linking Asset linking is a fundamental activity within the Asset Register and is executed through transactions. This process is crucial for establishing relationships between different assets. Oracles actively monitor these transactions to ensure that asset links are consistent with the on-chain ownership of assets. This validation guarantees the integrity and accuracy of the linked assets. ## Ownership Resolution Ensuring accurate ownership information within the Asset Register is paramount. The ownership status of assets correlates directly with user access. This correlation is vital for maintaining the security and integrity of the asset ecosystem. Ownership resolution mechanisms are in place to guarantee that asset ownership aligns with the specified user access. ## Transactions Transactions are how actions are committed to the Asset Register. Assets are linked via transactions that are executed in an authenticated and unrepeatable manner. Every action, including those involving oracles, must be explicit. This ensures the security and transparency of the Asset Register, preventing unauthorized or duplicate actions. # Introduction Source: https://docs.therootnetwork.com/asset-register/introduction The Asset Register is where you manage assets across applications in the open metaverse. ## Context The Asset Register is a new ledger system and tool suite that enables developers to establish data parameters for their assets. It is a metadata repository that defines what an asset is, what an asset can do, and the various environments in which an asset can be applied. Assets in web3 are currently restricted by their linear data composition. Each asset typically only has one corresponding metadata file and there is no way to create connections between assets in disparate ecosystems. Current systems tend to rely on specific chains, hindering asset relationships across different networks. Moreover, they primarily cater to on-chain assets, overlooking off-chain ones. Achieving interoperability for both types of assets across various applications is challenging. The Asset Register addresses these challenges, and supports interesting use cases: * Equipping accessories to assets across chains * Linking user metadata to a collectible to show its provenance * Managing which collections are compatible with which accessories * Informing applications about what an object does and what engines it is compatible with The Asset Register has three components: the Asset Register Core Ledger, the Asset Register API, and the Schema Management System, which sits on top for validation and is the main enabler of interoperability. A good understanding of blockchain technology will help you comprehend how it works. ### Asset Register Core The Asset Register Core is similar to layer 2 DLTs and built specifically for asset relationship management. The Asset Register Core facilitates the data relationships between assets and ultimately enables us to create rich, interoperable applications while still adhering to [Web3 design principles](https://www.web3designprinciples.com/) such as: * Consistency * Data transparency The Core provides a blockchain-like transaction experience without the need for network consensus, resulting in improved performance and cost-effectiveness. A user can build relationships between assets using [Asset Linking](/asset-register/how-it-works#asset-linking) which are explicitly created and deleted via a signed [Asset Register Transaction](/asset-register/guides/asset-register-transaction). Transactions can succeed or fail and will emit events accordingly. We have built infrastructure to query transactions; a block explorer could effectively be built on top of this data. #### Why transactions? Good question! * Users need to make decisions that are authenticated by their identity * Actions must be changed together in a logical order to ensure the changes to the state are consistent * Data needs to be readily available and accessible so that many applications can have the same source of truth These are the same reasons blockchains are so good at what they do; every single state change is chained together consistently. We aren't reinventing the wheel. On the identity front, we leverage a user's FuturePass or other existing wallet for authentication. Delegated signing is also something we have scoped for. #### No consensus...how do I trust it? Unlike a regular consensus blockchain that allows you to create assets with corresponding values, the Asset Register is lighter weight. It does not manipulate ownership of assets, relying instead on on-chain activities for this. Since there is no direct value attached to the links created by the Asset Register, the requirement for high trust does not exist in the same way. We realize, however, that applications may ascribe value in the asset links, so the roadmap includes both decentralized data storage and validation of data oracles. This is being done to maximize decentralization and trust while ensuring user experience, cost, and performance are optimized. ### Asset Register API The Asset Register API is used to interact with the Asset Register Core and the Schema Management System. The API is used for **submitting transactions to the Asset Register Core**, **querying transaction results,** and, most importantly, viewing the [Asset Tree](/asset-register/terminology#asset-tree). Schema creation and registration also occur via this service, making it the platform for admin-level interactions by asset creators. ### Schema Management System Schemas merely describe data. We aren't doing anything special here. There is also no requirement to use our Schema Management service, you can host your schemas anywhere you like for increased decentralisation. Our Schema Management System is built to facilitate a seamless onboarding experience for asset creators. It is built using TTL (pronounced 'turtle') files and utilizes the SHACL shape schema to describe assets and their relationships. The system handles the hosting of schemas on a domain under the relevant namespaces. Asset creators can create schemas to describe the assets and the Schema Management System will stitch together multiple schemas on the same namespace. This will be used by people and machines to validate data outputted by systems. ## What can it do? * Create [Asset Linking](/asset-register/how-it-works#asset-linking) between assets that are either [On-Chain Asset](/asset-register/terminology#on-chain-asset) or [Off-Chain Asset](/asset-register/terminology#off-chain-asset) * Generate an [Asset Tree](/asset-register/terminology#asset-tree) describing the links * Emit events based on changes on the Asset Register * Applications can subscribe to changes on the Asset Register **(WIP)** # Terminology Source: https://docs.therootnetwork.com/asset-register/terminology The Asset Register documentation introduces new terminology to describe its usage. A brief review of this document before exploring guides will help you understand them better. ## On-Chain Asset Assets that are created by a third party with the existence attested on a blockchain network supported by the Asset Register. The Asset Register can only interact with these assets through the interface provided by the smart contract or runtime module on the blockchain where the asset is located. Therefore, it is imperative that asset collections deployed on the respective networks adhere to the NFT specifications. *** ## Off-Chain Asset Assets that are created by a third party and attested by the third party’s system. Therefore, the third party is the creator and has superuser access over all their off-chain assets. Each asset must be registered on the Asset Register and registered against a schema to be a valid off-chain asset. *** ## Asset Link A link between two assets (parent and child) based on a relationship path e.g. `equippedWith_gloves`. The Asset Register uses these relationships to build the asset trees that describe an asset. *** ## Asset Schema Describes the properties of an asset and its compatibility with other assets through asset links. Schemas should be stored in a globally accessible and permanent location and be registered against an asset. The Asset Register will provide internal Futureverse teams with the ability to store schemas on a Futureverse namespace. ### HairStyle Example ```mermaid graph TD tnl:HairStyle --> fv:HairStyle fluf:HairStyle --> fv:HairStyle fv:HairStyle --> fvp:OffChainSFTAsset fvp:OffChainSFTAsset --> fvp:OffChainAsset fv:HairStyle --> fvp:OnChainERC1155Asset fvp:OnChainERC1155Asset --> fvp:OnChainAsset ``` ### Turtle Syntax Turtle syntax is used to create the schemas. #### TNL Hair Style ```json @prefix tnl: . @prefix sh: . @prefix fv: <[http://schema.futureverse.com/fv#nf](https://www.notion.so/RFC-NFT-Indexer-df40caae2efc4f45b35c5acd2f1aeb59?pvs=21)> . @prefix rdf: . tnl:HairStyle a rdf:Class, sh:NodeShape ; sh:node fv:HairStyle . ``` #### FV Hair Style ```json @prefix sh: . @prefix fv: . @prefix fvp: . @prefix rdf: . fv:HairStyle a rdf:Class, sh:NodeShape ; sh:or ( [ sh:node fvp:OnChainERC1155Asset ] [ sh:node fvp:OffChainSFTAsset ] ) . ``` ## Asset Tree Describes all the nested asset links for a given asset. ### Root Parent Asset ```mermaid graph LR tnl:Boxer --> |equippedWith_brain| fv:ASMBrain --> |equippedWith_memory| fv:ASMMemory tnl:Boxer --> |equippedWith_gloves| tnl:Gloves tnl:Boxer --> |equippedWith_hairStyle| tnl:HairStyle tnl:Boxer --> |equippedWith_hairDye| tnl:HairDye ``` ```json { "@context": { "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#", "schema": "http://schema.org/", "tnl": "http://schema.futureverse.com/tnl#", "fvp": "http://schema.futureverse.com/fvp#", "fv": "http://schema.futureverse.com/fv#" }, "@graph": [ { "@id": "did:fv-asset:1:evm:0x6bca6de2dbdc4e0d41f7273011785ea16ba47182:1868", "rdf:type": "tnl:Boxer", "fvp:equippedWith_asmBrain": { "@id": "did:fv-asset:1:evm:0xd0318da435dbce0b347cc6faa330b5a9889e3585:1211" }, "fvp:equippedWith_hairStyle": { "@id": "did:fv-asset:off-chain:0x854A3E045Ac44a7f4A1726AdAC576029135DFdA7:533" }, "fvp:equippedWith_hairDye": { "@id": "did:fv-asset:off-chain:0x854A3E045Ac44a7f4A1726AdAC576029135DFdA7:853" }, "fvp:equippedWith_gloves": { "@id": "did:fv-asset:1:evm:0x1ea66a857de297471bc12dd12d93853ff6617284:203" } }, { "@id": "did:fv-asset:1:evm:0xd0318da435dbce0b347cc6faa330b5a9889e3585:1211", "rdf:type": "fv:ASMBrain", "equippedWith_memory": { "@id": "did:fv-asset:off-chain:0x0d2aedB4D26A63143240AE655D6B22627ad9298f:345" } }, { "@id": "did:fv-asset:off-chain:0x0d2aedB4D26A63143240AE655D6B22627ad9298f:345", "rdf:type": "fv:ASMMemory" }, { "@id": "did:fv-asset:off-chain:0x854A3E045Ac44a7f4A1726AdAC576029135DFdA7:533", "rdf:type": "tnl:HairStyle" }, { "@id": "did:fv-asset:off-chain:0x854A3E045Ac44a7f4A1726AdAC576029135DFdA7:853", "rdf:type": "tnl:HairDye" }, { "@id": "did:fv-asset:1:evm:0x1ea66a857de297471bc12dd12d93853ff6617284:203", "rdf:type": "tnl:Gloves" } ] } ``` ### Nested Parent Asset ```mermaid graph TD fv:ASMBrain --> |equippedWith_memory| fv:ASMMemory ``` ```json { "@context": { "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#", "schema": "http://schema.org/", "fvp": "http://schema.futureverse.com/fvp#", "fv": "http://schema.futureverse.com/fv#" }, "@graph": [ { "@id": "did:fv-asset:1:evm:0xd0318da435dbce0b347cc6faa330b5a9889e3585:1211", "rdf:type": "fv:ASMBrain", "equippedWith_memory": { "@id": "did:fv-asset:off-chain:0x0d2aedB4D26A63143240AE655D6B22627ad9298f:345" } }, { "@id": "did:fv-asset:off-chain:0x0d2aedB4D26A63143240AE655D6B22627ad9298f:345", "rdf:type": "fv:ASMMemory" } ] } ``` # Connecting to The Root Network Source: https://docs.therootnetwork.com/build/connecting-to-the-root-network The simplest way to connect to one of the TRN networks is by using [The Root Network Portal](https://portal.rootnet.cloud/#/explorer). This web portal enables communication with a node through WebSocket. You can choose the network to connect to by selecting it from the **Root** dropdown in the top left corner and clicking **Switch**. ## Network Endpoints When connecting to The Root Network through the API, you can choose to connect to a public web socket or a local node. The Root Network RPC servers are not for sustained or business use, and they may become unavailable at anytime. You should run your node or use an RPC Service like Rootscan RPC for regular use. ### Root (Mainnet) ```md wss://root.rootnet.live/archive/ws ``` ```md https://root.rootnet.live/archive ``` ```md https://rootscan.io ``` ```md 7668 ``` ```md XRP ``` ### Porcini (Testnet) ```md wss://porcini.rootnet.app/archive/ws ``` ```md https://porcini.rootnet.app/archive ``` ```md https://porcini.rootscan.io ``` ```md 7672 ``` ```md XRP ``` ### Sprout-1 (Devnet) ```md wss://porcini.devnet.rootnet.app/ws ``` ```md https://porcini.devnet.rootnet.app ``` ```md https://devnet-porcini.rootscan.io/ ``` ```md 17672 ``` ```md XRP ``` # How do I deploy a smart contract on The Root Network using hardhat? Source: https://docs.therootnetwork.com/build/evm/cookbook/smart-contract The code below is the minimum `hardhat` configuration to deploy smart contracts on The Root Network. ``` import { getPublicProviderUrl } from "@therootnetwork/evm"; const config: HardhatUserConfig = { solidity: { version: "0.8.17", }, networks: { porcini: { url: getPublicProviderUrl("porcini"), chainId: 7672, accounts: [...], }, root: { url: getPublicProviderUrl("root"), chainId: 7668, accounts: [...], }, }, }; ``` # Tokens Source: https://docs.therootnetwork.com/build/evm/cookbook/tokens ## ERC-20 ### How do I transfer `ROOT` token? ROOT token contract address is `0xcCcCCccC00000001000000000000000000000000` and it fully supports the ERC-20 standard. ```ts import { Contract, utils } from "ethers"; import { ERC20_PRECOMPILE_ABI } from "@therootnetwork/evm"; const ROOT_ADDRESS = "0xcCcCCccC00000001000000000000000000000000"; const wallet = new Wallet(...); const contract = new Contract(ROOT_ADDRESS, ERC20_PRECOMPILE_ABI); const oneROOT = utils.parseUnits(1, 6); // transfer 1 ROOT to Alice await contract.connect(wallet).transfer("0xE04CC55ebEE1cBCE552f250e85c57B70B2E2625b", oneROOT); ``` ROOT token has **6 decimals** and its ID is `1`. ### How do I transfer `XRP` token or any other ERC-20 tokens? Just like the ROOT token, XRP and any other ERC-20 token contract addresses can be derived from its native asset IDs. ```ts import { Contract, utils } from "ethers"; import { ERC20_PRECOMPILE_ABI, assetIdToERC20Address } from "@therootnetwork/evm"; const XRP_ID = 2; const XRP_ADDRESS = assetIdToERC20Address(2); const wallet = new Wallet(...); const contract = new Contract(XRP_ADDRESS, ERC20_PRECOMPILE_ABI, wallet); const oneXRP = utils.parseUnits(1, await contract.decimals()); // transfer 1 ROOT to Alice await contract.connect(wallet).transfer("0xE04CC55ebEE1cBCE552f250e85c57B70B2E2625b", oneXRP); ``` **Tip**: \ To retrieve a list of available tokens and their asset IDs, check out the Tokens section in our [Rootscan Explorer](../../connecting-to-the-root-network). ## ERC-721 ### How do I create and mint an ERC-721 NFT? It's possible to create an ERC-712 collection by calling `initializeCollection()` method exposed by the [`nft` precompile](../runtime-precompiles/nft-erc-721). ```ts import { Contract, utils } from "ethers"; import { NFT_PRECOMPILE_ABI, NFT_PRECOMPILE_ADDRESS } from "@therootnetwork/evm"; const wallet = new Wallet(...); const contract = new Contract(NFT_PRECOMPILE_ADDRESS, NFT_PRECOMPILE_ABI); const tx = await contract.connect(wallet).initializeCollection( wallet.address, // owner address utils.toUtf8Bytes("My Collection"), // collection name BigNumber.from(0), // no max issuance utils.toUtf8Bytes("https://example.com/nft/metadata/"), // metadataPath [wallet.address], // royaltyAddresses [100_000], // royaltyEntitlements ); const receipt = await tx.wait(); const collectionAddress = (receipt?.events as any)[0].args.precompileAddress; ``` **Caution**: The `royaltyEntitlements` is in permill (parts per million) scaling, so if you want a 10% royalty, that would be `100,000` (as `(100_000 / 1_000_000) * 100 = 10%`). Once the collection is created, use the same `owner` wallet to mint the NFT: ```ts import { Contract, utils } from "ethers"; import { ERC721_PRECOMPILE_ABI } from "@therootnetwork/evm"; const wallet = new Wallet(...); const contract = new Contract(collectionAddress, ERC721_PRECOMPILE_ABI); // Mint 1 NFT for Alice await contract.connect(wallet).mint("0xE04CC55ebEE1cBCE552f250e85c57B70B2E2625b", 1); ``` # Building with EVM API Source: https://docs.therootnetwork.com/build/evm/ethereum-vs-trn ## Dual Token The Root Network uses a dual token system - governance token ROOT and a fee token XRP. The native currency used by Ethereum RPCs on The Root Network for balances, paying gas fees, and value transfers is XRP. XRP is a 6dp token, while Ethereum tooling like MetaMask and Solidity expect native token amounts in wei or 18dp units. To keep compatibility simple, The Root Network protocol takes care of scaling inputs down by `1e-12` and scaling up outputs by `1e12`. Any fractional amounts \< `1e12` / `0.000001 XRP` are always rounded up only by adding `1e12`. ROOT token is available as an ERC-20 token at `0xcCcCCccC00000001000000000000000000000000`. ROOT is also a 6dp token but requires no special handling as per the ERC20 standard. Tip: The `@therootnetwork/evm` package exports a handy method `assetIdToERC20Address` that converts the native asset id to EVM contract address. In ROOT case, it's effectively `assetIdToERC20Address(1)` with ROOT asset id is `1`. ### Transfer Examples 1. Transfers `1 XRP` to `receiver` ``` receiver.call{value: 1 ether}("") ``` 1. Transfers `1.00001 XRP` to `receiver` (i.e. rounds up by `0.00001 XRP`) ``` receiver.call{value: 1 ether + 1 wei}("") ``` Similarly, the following will transfer `0.00001 XRP` to `receiver` ``` await wallet.sendTransaction({ to: receiver, value: 1, }); ``` or transfer `1.2 XRP` to `receiver` ``` await wallet.sendTransaction({ to: receiver, value: ethers.utils.parseEther("1.2"), }); ``` Recap: * XRP is the default "native" currency * Input and output amounts for XRP on EVM are expressed in `wei` (18dp) as normal * Amounts transferred `< 1e12` are always rounded up ## Transaction Fees The Root Network supports EIP-1559 and legacy transaction fee models. Ethereum tooling is able to query fee estimation info accurately out of the box without any special handling required. The `eth_feeHistory` RPC is provided for this purpose. See eth\_feeHistory - Ethereum [documentation](https://docs.alchemy.com/alchemy/apis/ethereum/eth_feehistory) for more details. Fees are charged for deploying and executing smart contracts on The Root Network. Executing a smart contract on The Root Network costs a minimal transaction fee, typically a few XRPs. Deploying a smart contract is slightly more expensive than executing it. This is because each contract deployed to the EVM will be stored on the chain forever. It requires storage space. ## Addresses EVM contract developers on The Root Network can use existing Ethereum wallets and addresses without any changes. The network supports ECDSA addresses by default. ## Solidity Version The Root Network supports Solidity version `v8.20.0 (Shanghai)` and below, with future support for newer version is underway. # Install EVM API Source: https://docs.therootnetwork.com/build/evm/evm-package ## @therootnetwork/evm A utility [package](https://www.npmjs.com/package/@therootnetwork/evm) that simplifies EVM development on The Root Network. ## Install ``` yarn add @therootnetwork/evm ``` ## Usage Import and initialize the functionalities you need: ``` import { collectionIdToERC721Address, ERC721_PRECOMPILE_ABI, getPublicProviderUrl, } from "@therootnetwork/evm"; import { Contract, getDefaultProvider } from "ethers"; const collectionAddress = collectionIdToERC721Address(1); const providerUrl = getPublicProviderUrl("porcini"); const provider = getDefaultProvider(providerUrl); const contract = new Contract(collectionAddress, ERC721_PRECOMPILE_ABI, provider); ``` ## API ### `function assetIdToERC20Address(assetId: string | number)` Converts native asset ID to ERC-20 contract address ### `function collectionIdToERC721Address(collectionId: string | number)` Converts native NFT collection ID to ERC-721 contract address ### `function getPublicProviderUrl(network: NetworkName): HttpProviderUrl` Returns the Public RPC URls for the corresponding `network` ## Constants ### Addresses Constant Description Address `NFT_PRECOMPILE_ADDRESS: string` Precompile address for `nft` pallet `0x00000000000000000000000000000000000006b9` `SFT_PRECOMPILE_ADDRESS: string` Precompile address for `sft` pallet `0x00000000000000000000000000000000000006c3` `FUTUREPASS_REGISTRAR_PRECOMPILE_ADDRESS: string` Precompile address for `futurepass` pallet `0x000000000000000000000000000000000000FFFF` `PEG_PRECOMPILE_ADDRESS: string` Precompile address for `erc20Peg` and `nftPeg` pallets `0x0000000000000000000000000000000000000793` `DEX_PRECOMPILE_ADDRESS: string` Precompile address for `dex` pallet `0x000000000000000000000000000000000000DdDD` `FEE_PROXY_PRECOMPILE_ADDRESS` Precompile address for `feeProxy` pallet `0x00000000000000000000000000000000000004BB` **Info**: The precompile addresses are identical across all networks, including Mainnet, Devnet, and Porcini. ### ABIs Constant Description `ERC20_ABI: string[]` ABI for the ERC-20 standard `ERC721_ABI: string[]` ABI for the ERC-721 standard `ERC1155_ABI: string[]` ABI for the ERC-1155 standard `NFT_PRECOMPILE_ABI: string[]` ABI for the `nft` pallet `SFT_PRECOMPILE_ABI: string[]` ABI for the `sft` pallet `FEE_PROXY_PRECOMPILE_ABI: string[]` ABI for `feeProxy` pallet `FUTUREPASS_PRECOMPILE_ABI: string[]` ABI for `futurepass` account `FUTUREPASS_REGISTRAR_PRECOMPILE_ABI: string[]` ABI for `futurepass` pallet `DEX_PRECOMPILE_ABI: string[]` ABI for the `dex` pallet **Note**: All exported ABIs are in human-readable format. # Assets (ERC-20) Source: https://docs.therootnetwork.com/build/evm/runtime-precompiles/assets-erc-20 ## Asset Precompile ### Contract Address The ERC-20 contract address for The Root Network native tokens uses the following format: ``` 0xCCCCCCCC[4-byte-token-id]000000000000000000000000 ``` To make things easier, the `@therootnetwork/evm` provides a handy function to convert token asset ID to its equivalent contract address. ``` import { assetIdToERC20Address } from "@therootnetwork/evm"; const ROOT_ASSET_ID = 1; const ROOT_CONTRACT_ADDRESS = assetIdToERC20Address(ROOT_ASSET_ID); ``` ### Solidity Interfaces ``` interface IERC165 { function supportsInterface(bytes4 interfaceId) external view returns (bool); } ``` ``` interface IERC20 is IERC165 { event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value); function totalSupply() external view returns (uint256); function balanceOf(address account) external view returns (uint256); function transfer(address to, uint256 amount) external returns (bool); function allowance(address owner, address spender) external view returns (uint256); function approve(address spender, uint256 amount) external returns (bool); function transferFrom(address from, address to, uint256 amount) external returns (bool); } ``` ``` interface IERC20Metadata is IERC20 { function name() external view returns (string memory); function symbol() external view returns (string memory); function decimals() external view returns (uint8); } ``` # Decentralized Exchange Source: https://docs.therootnetwork.com/build/evm/runtime-precompiles/decentralized-exchange ## Pallet Precompile ### Contract Address ``` 0x000000000000000000000000000000000000DdDD ``` ### Solidity Interfaces ``` interface IUniswapV2Pair { event Mint(address indexed sender, uint amount0, uint amount1); event Burn(address indexed sender, uint amount0, uint amount1, address indexed to); event Swap( address indexed sender, uint amount0In, uint amount1In, uint amount0Out, uint amount1Out, address indexed to ); } ``` ``` interface IUniswapV2Router01 { function addLiquidity( address tokenA, address tokenB, uint amountADesired, uint amountBDesired, uint amountAMin, uint amountBMin, address to, uint deadline ) external returns (uint amountA, uint amountB, uint liquidity); function addLiquidityETH( address token, uint amountTokenDesired, uint amountTokenMin, uint amountETHMin, address to, uint deadline ) external payable returns (uint amountToken, uint amountETH, uint liquidity); function removeLiquidity( address tokenA, address tokenB, uint liquidity, uint amountAMin, uint amountBMin, address to, uint deadline ) external returns (uint amountA, uint amountB); function removeLiquidityETH( address token, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline ) external returns (uint amountToken, uint amountETH); function swapExactTokensForTokens( uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline ) external returns (uint[] memory amounts); function swapTokensForExactTokens( uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline ) external returns (uint[] memory amounts); function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline) external payable returns (uint[] memory amounts); function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts); function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts); function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline) external payable returns (uint[] memory amounts); function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB); function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut); function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn); function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts); function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts); } ``` # FeeProxy Source: https://docs.therootnetwork.com/build/evm/runtime-precompiles/feeproxy ## Pallet Precompile ### Contract Address ``` 0x00000000000000000000000000000000000004bb ``` ### Solidity Interfaces ``` interface FeeProxy { function callWithFeePreferences(address asset, uint128 maxPayment, address target, bytes input) } ``` # FuturePass Source: https://docs.therootnetwork.com/build/evm/runtime-precompiles/futurepass ## Pallet Precompile Use this precompile to interact with the `futurepass` runtime pallet to create a FuturePass account. ### Contract Address ``` 0x000000000000000000000000000000000000FFFF ``` ### Solidity Interfaces ``` interface FuturePassRegistrar { event FuturepassCreated(address indexed futurepass, address owner); function futurepassOf(address owner) external view returns (address); function create(address owner) external returns (address); } ``` ## FuturePass Account ### Contract Address The FuturePass account addresses for The Root Network use the following format: ``` 0xFFFFFFFF[16-byte-futurepass-id] ``` ### Solidity Interfaces ``` interface FuturePass { event FuturepassDelegateRegistered(address indexed futurepass, address indexed delegate, uint8 proxyType); event FuturepassDelegateUnregistered(address indexed futurepass, address delegate); event Executed(uint8 indexed callType, address indexed target, uint256 indexed value, bytes4 data); event ContractCreated(uint8 indexed callType, address indexed contractAddress, uint256 indexed value, bytes32 salt); function delegateType(address delegate) external view returns (uint8); function registerDelegate(address delegate, uint8 proxyType) external; function unregisterDelegate(address delegate) external; function proxyCall(uint8 callType, address callTo, uint256 value, bytes memory callData) external payable; } ``` ``` interface Ownable { event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); function owner() external view returns (address); function renounceOwnership() external; function transferOwnership(address owner) external; } ``` # NFT (ERC-721) Source: https://docs.therootnetwork.com/build/evm/runtime-precompiles/nft-erc-721 ## Pallet Precompile Use this precompile to interact with the `nft` runtime pallet to create an ERC-721 collection. ### Contract Address ``` 0x00000000000000000000000000000000000006b9 ``` ### Solidity Interfaces ``` interface TRNNFT { event InitializeCollection(address indexed collectionOwner, address precompileAddress); function initializeCollection(address owner, bytes calldata name, uint32 maxIssuance, bytes calldata metadataPath, address[] calldata royaltyAddresses, uint32[] calldata royaltyEntitlements) external returns (address, uint32); } ``` ## Token Precompile ### Contract Address The ERC-721 contract address for The Root Network native non-fungible token uses the following format: ``` 0xAAAAAAAA[4-byte-collection-id]000000000000000000000000 ``` To make things easier, the `@therootnetwork/evm` provides a handy function to convert token asset ID to its equivalent contract address. ``` import { collectionIdToERC721Address } from "@therootnetwork/evm"; const COLLECTION_ID = 1; const COLLECTION_CONTRACT_ADDRESS = collectionIdToERC721Address(COLLECTION_ID); ``` ### Solidity Interfaces ``` interface IERC165 { function supportsInterface(bytes4 interfaceId) external view returns (bool); } ``` ``` interface IERC721 is IERC165 { event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); event ApprovalForAll(address indexed owner, address indexed operator, bool approved); function balanceOf(address owner) external view returns (uint256 balance); function ownerOf(uint256 tokenId) external view returns (address owner); function safeTransferFrom(address from, address to, uint256 tokenId) external; function transferFrom(address from, address to, uint256 tokenId) external; function approve(address to, uint256 tokenId) external; function getApproved(uint256 tokenId) external view returns (address operator); function setApprovalForAll(address operator, bool _approved) external; function isApprovedForAll(address owner, address operator) external view returns (bool); function safeTransferFrom(address from,address to,uint256 tokenId,bytes calldata data) external; } ``` ``` interface IERC721Metadata is IERC721 { function name() external view returns (string memory); function symbol() external view returns (string memory); function tokenURI(uint256 tokenId) external view returns (string memory); } ``` ``` interface IERC721Burnable is IERC721 { function burn(uint256 tokenId) external; } ``` ``` interface TRN721 is IERC165 { event MaxSupplyUpdated(uint32 maxSupply); event BaseURIUpdated(string baseURI); event PublicMintToggled(bool indexed enabled); event MintFeeUpdated(address indexed paymentAsset, uint256 indexed mintFee); function totalSupply() external view returns (uint256); function mint(address owner, uint32 quantity) external; function setMaxSupply(uint32 maxSupply) external; function setBaseURI(bytes calldata baseURI) external; function ownedTokens(address who, uint16 limit, uint32 cursor) external view returns (uint32, uint32, uint32[] memory); function togglePublicMint(bool enabled) external; function setMintFee(address paymentAsset, uint256 mintFee) external; } ``` ``` interface IERC5484 is IERC165 { enum BurnAuth { IssuerOnly, OwnerOnly, Both, Neither }; event Issued(address indexed from, address indexed to, uint256 indexed tokenId, BurnAuth burnAuth); function burnAuth(uint256 tokenId) external view returns (BurnAuth); } ``` ``` interface Ownable is IERC165 { event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); function owner() external view returns (address); function renounceOwnership() external; function transferOwnership(address owner) external; } ``` ### Soulbound Tokens The ERC721 precompile supports Soulbound token functionality and implements the IERC5484 interface. ``` enum BurnAuth { IssuerOnly, OwnerOnly, Both, Neither }; ``` Soulbound token ABI ``` "event PendingIssuanceCreated(address indexed to, uint256 issuanceId, uint256 quantity, uint8 burnAuth)", "event Issued(address indexed from, address indexed to, uint256 indexed tokenId, uint8 burnAuth)", "function issueSoulbound(address,uint32,uint8)", "function acceptSoulboundIssuance(uint32)", "function pendingIssuances(address) external view returns (uint256[] issuanceIds memory, (uint256 quantity, uint8 burnAuth)[] issuances memory)", "function burnAuth(uint256) external view returns (uint8)", ``` The minting of Soulbound tokens is a two-step process. The collection owner creates a pending issuance via `issueSoulbound`, and states the `burn authority` on this call. The token is only minted once the token owner calls `acceptSoulbound`. ``` // create a pending issuance as the collection owner await erc721Precompile .connect(collectionOwner) .issueSoulbound( tokenOwner.address, // token owner 5, // quantity BurnAuth.Both // burn authority ) .then(tx => tx.wait()); // query all pending issuances for the token owner const [issuanceIds, issuances] = await erc721Precompile.pendingIssuances(tokenOwner.address); // accept pending issuance as token owner await erc721Precompile .connect(tokenOwner) .acceptSoulboundIssuance(issuanceIds[0]) .then(tx => tx.wait()); ``` # SFT (ERC-1155) Source: https://docs.therootnetwork.com/build/evm/runtime-precompiles/sft-erc-1155 ## Pallet Precompile Use this precompile to interact with the `sft` runtime pallet to create an ERC-1155 collection. ### Contract Address ``` 0x00000000000000000000000000000000000006c3 ``` ### Solidity Interfaces ``` interface TRNSFT { event InitializeSftCollection(address indexed collectionOwner, address indexed precompileAddress); function initializeCollection(address owner, bytes calldata name, bytes calldata metadataPath, address[] calldata royaltyAddresses, uint32[] calldata royaltyEntitlements) external returns (address, uint32); } ``` ## Token Precompile ## Contract Address The ERC-1155 contract address for The Root Network native semi-fungible tokens uses the following format: ``` 0xBBBBBBBB[4-byte-collection-id]000000000000000000000000 ``` To make things easier, the `@therootnetwork/evm` provides a handy function to convert token asset ID to its equivalent contract address. ``` import { collectionIdToERC1155Address } from "@therootnetwork/evm"; const COLLECTION_ID = 1; const COLLECTION_CONTRACT_ADDRESS = collectionIdToERC1155Address(COLLECTION_ID); ``` ### Solidity Interfaces ``` interface IERC165 { function supportsInterface(bytes4 interfaceId) external view returns (bool); } ``` ``` interface IERC1155 is IERC165 { event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value); event TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values); event ApprovalForAll(address indexed account, address indexed operator, bool approved); function balanceOf(address owner, uint256 id) external view returns (uint256); function balanceOfBatch(address[] calldata owners, uint256[] calldata ids) external view returns (uint256[] memory); function setApprovalForAll(address operator, bool approved) external; function isApprovedForAll(address account, address operator) external view returns (bool); function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external; function safeBatchTransferFrom(address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data) external; } ``` ``` interface IERC1155Burnable is IERC1155 { function burn(address account, uint256 id, uint256 value) external; function burnBatch(address account, uint256[] calldata ids, uint256[] calldata values) external; } ``` ``` interface IERC1155Supply is IERC1155 { function totalSupply(uint256 id) external view returns (uint256); function exists(uint256 id) external view returns (bool); } ``` ``` interface IERC1155MetadataURI is IERC1155 { function uri(uint256 id) external view returns (string memory); } ``` ``` interface TRN1155 is IERC165 { event TokenCreated(uint32 indexed serialNumber); event MaxSupplyUpdated(uint128 indexed maxSupply); event BaseURIUpdated(string baseURI); event PublicMintToggled(uint256 id, bool indexed enabled); event MintFeeUpdated(uint256 id, address indexed paymentAsset, uint256 indexed mintFee); function createToken(bytes calldata name, uint128 initialIssuance, uint128 maxIssuance, address tokenOwner) external returns (uint32); function mint(address owner, uint256 id, uint256 amount) external; function mintBatch(address owner, uint256[] calldata ids, uint256[] calldata amounts) external; function setMaxSupply(uint256 id, uint32 maxSupply) external; function setBaseURI(bytes calldata baseURI) external; function togglePublicMint(uint256 id, bool enabled) external; function setMintFee(uint256 id, address paymentAsset, uint256 mintFee) external; } ``` ``` interface Ownable is IERC165 { event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); function owner() external view returns (address); function renounceOwnership() external; function transferOwnership(address owner) external; } ``` ### Soulbound Tokens The ERC1155 precompile supports Soulbound token functionality and implements the IERC5484 interface. ``` enum BurnAuth { IssuerOnly, OwnerOnly, Both, Neither }; ``` Soulbound token ABI ``` "event PendingIssuanceCreated(address indexed to, uint256 issuanceId, uint256[] tokenIds, uint256[] balances)", "event Issued(address indexed from, address indexed to, uint256 indexed tokenId, uint8 burnAuth)", "function setBurnAuth(uint256,uint8)", "function issueSoulbound(address,uint256[],uint256[])", "function acceptSoulboundIssuance(uint32)", "function pendingIssuances(address) external view returns (uint256[] memory,(uint256[] memory,uint256[] memory,uint8[] memory)[] memory)", "function burnAuth(uint256) external view returns (uint8)", "function burnAsCollectionOwner(address,uint256[],uint256[])", ``` The minting of Soulbound tokens is a two-step process. The collection owner creates a pending issuance via `issueSoulbound`. However the `burn authority` for a token must already be set prior to calling `issueSoulbound`. The token is only minted once the token owner calls `acceptSoulbound`. ``` // set the burn auth for a token await erc1155Precompile .connect(collectionOwner) .setBurnAuth(token, BurnAuth.TokenOwner).then(tx => tx.wait()); // issue a token as collection owner await erc1155Precompile .connect(collectionOwner) .issueSoulbound( tokenOwner.address, // token owner [token], // list of token ids [1] // quantities for each token ).then((tx: any) => tx.wait()); // fetch all pending issuances const [issuanceIds, issuances] = await erc1155Precompile.pendingIssuances(tokenOwner.address); // accept pending issuance as token owner await erc1155Precompile .connect(tokenOwner) .acceptSoulboundIssuance(issuanceIds[0]) .then(tx => tx.wait()); ``` # Curated Examples Source: https://docs.therootnetwork.com/build/examples Explore real-world use cases and examples to help you get started quickly. # Getting Started Source: https://docs.therootnetwork.com/build/getting-started Root Network is a public blockchain network built on [Substrate](https://substrate.io/), a general-purpose blockchain framework that provides the essential building blocks for blockchain logic. Whether you're new to blockchain development or experienced in the space, The Root Network simplifies dapp development through pre-built modules, runtime pallets, and seamless integration with Ethereum tooling. ## Runtime Pallets The Root Network makes dapp development easy via pre-built [runtime modules](/build/substrate/api-reference/runtime-pallets). These work a bit like plug-and-play components that sit within the blockchain's runtime. Developers can leverage these core pallets, rather than having to code their own essential parts from scratch. Developers can opt to use all, some, or none of these modules within their dapps. ## Ethereum VM Layer One of the core runtime pallets provided by The Root Network is the [`evm` pallet](/build/evm/runtime-precompiles), which provides the environment to deploy and run Ethereum Smart Contracts natively on The Root Network. This gives web3 developers access to smart contract functionality and also means that any code previously written for Ethereum can now run on The Root Network blockchain with minimal changes. The Root Network also exposes functionalities of certain pallets as "precompiles", which allows users/tooling to query/transact with the pallet functions as if they are Solidity functions. This allows native network currencies and NFTs to appear as regular ERC-20s and ERC-721s to Ethereum tooling and contracts alongside other functionality to supercharge contract development, such as Decentralised Exchange (DEX), ERC-1155. ## Native API vs EVM API When building a dapp on The Root Network, developers have the option to either utilize the native Native API, which interacts with the runtime pallets, or they can choose to use the EVM API, which is compatible with several well-known libraries such as `ethers.js`. ### What are the pros and cons of each approach? * The native Native API offers the best efficiency and lower costs than smart contracts. This is because the runtime pallets are written in Rust and are highly optimized. Using the runtime pallets also saves development time because the functionalities are easily accessible through a simple JavaScript API. When designing a new dapp, we recommend searching through the pallets first to check if the problem you are addressing has already been sorted by the provided functionalities. * The EVM pallet and smart contracts offer more flexibility. You can create your custom logic and deploy it at any time. You can also use Solidity (The latest version we support is 0.8.17) and other tools that you may be more familiar with. ## Installation To get started with building on The Root Network, you’ll need to install the appropriate tools depending on whether you're using the Native API or the EVM API. Follow the steps in the provided documentation to correctly set up your development environment. * [Install Native API](/build/substrate/api-package) * [Install EVM API](/build/evm/evm-package) # Mainnet Rootscan Explorer Source: https://docs.therootnetwork.com/build/rootscan-explorer Track transactions and activity on The Root Network mainnet. # Install Native API Source: https://docs.therootnetwork.com/build/substrate/api-package ## @therootnetwork/api A utility package that complements the [`@polkadot/api`](https://www.npmjs.com/package/@polkadot/api) to connect and interact with the Root Network node. ## Install ```ts yarn add @polkadot/api @therootnetwork/api yarn add -D @therootnetwork/api-types # optional, for Typescript support ``` ## Usage 1. Create an API instance ```ts import "@therootnetwork/api-types"; // optional, for Typescript support import { ApiPromise } from "@polkadot/api"; import { getApiOptions, getPublicProvider } from "@therootnetwork/api"; const api = await ApiPromise.create({ ...getApiOptions(), ...getPublicProvider("root"), }); ``` 1. Use `api` instance to interact with node ```ts // query and display account data const data = await api.query.system.account("0xE04CC55ebEE1cBCE552f250e85c57B70B2E2625b"); console.log(data.toHuman()); ``` ## API ### `function getApiOptions()` Returns an `ApiOptions` object that contains necessary types and RPC methods to connect The Root Network. ### `function getPublicProvider(network: NetworkName, useWsProvider?: boolean)` Returns a `provider` instance of either `WsProvider` or `HttpProvider` that connects to TRN mainnet `"root"` or testnet `"porcini"`. # JSON-RPC Source: https://docs.therootnetwork.com/build/substrate/api-reference/json-rpc ## Author ### `hasKey` Returns true if the keystore has private keys for the given public key and key type. This method is only active with appropriate flags. **Interface** ```ts api.rpc.author.hasKey(publicKey: Bytes, keyType: Text): bool ``` **JSON** ```ts { "id":1, "jsonrpc":"2.0", "method":"author_hasKey", "params":[publicKey: Bytes, keyType: Text] } ``` ### `hasSessionKeys` Returns true if the keystore has private keys for the given session public keys. This method is only active with appropriate flags. **Interface** ```ts api.rpc.author.hasSessionKeys(sessionKeys: Bytes): bool ``` **JSON** ```ts { "id":1, "jsonrpc":"2.0", "method":"author_hasSessionKeys", "params":[sessionKeys: Bytes] } ``` ### `insertKey` Insert a key into the keystore. This method is only active with appropriate flags. **Interface** ```ts api.rpc.author.insertKey(keyType: Text, suri: Text, publicKey: Bytes): Bytes ``` **JSON** ```ts { "id":1, "jsonrpc":"2.0", "method":"author_insertKey", "params":[keyType: Text, suri: Text, publicKey: Bytes] } ``` ### `pendingExtrinsics` Returns all pending extrinsics, potentially grouped by sender **Interface** ```ts api.rpc.author.pendingExtrinsics(): Vec ``` **JSON** ```ts { "id":1, "jsonrpc":"2.0", "method":"author_pendingExtrinsics", "params":[] } ``` ### `removeExtrinsic` Remove given extrinsic from the pool and temporarily ban it to prevent reimporting This method is only active with appropriate flags. **Interface** ```ts api.rpc.author.removeExtrinsic(bytesOrHash: Vec): Vec ``` **JSON** ```ts { "id":1, "jsonrpc":"2.0", "method":"author_removeExtrinsic", "params":[bytesOrHash: Vec] } ``` ### `rotateKeys` Generate new session keys and returns the corresponding public keys This method is only active with appropriate flags. **Interface** ``` api.rpc.author.rotateKeys(): Bytes ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"author_rotateKeys", "params":[] } ``` ### `submitAndWatchExtrinsic` Submit and subscribe to watch an extrinsic until unsubscribed **Interface** ``` api.rpc.author.submitAndWatchExtrinsic(extrinsic: Extrinsic): ExtrinsicStatus ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"author_submitAndWatchExtrinsic", "params":[extrinsic: Extrinsic] } ``` ### `submitExtrinsic` Submit a fully formatted extrinsic for block inclusion **Interface** ``` api.rpc.author.submitExtrinsic(extrinsic: Extrinsic): Hash ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"author_submitExtrinsic", "params":[extrinsic: Extrinsic] } ``` ## Babe ### `epochAuthorship` Returns data about which slots (primary or secondary) can be claimed in the current epoch with the keys in the keystore This method is only active with appropriate flags. **Interface** ``` api.rpc.babe.epochAuthorship(): HashMap ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"babe_epochAuthorship", "params":[] } ``` ## Chain ### `getBlock` Get header and body of a relay chain block **Interface** ``` api.rpc.chain.getBlock(hash?: BlockHash): SignedBlock ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"chain_getBlock", "params":[hash?: BlockHash] } ``` ### `getBlockHash` Get the block hash for a specific block **Interface** ``` api.rpc.chain.getBlockHash(blockNumber?: BlockNumber): BlockHash ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"chain_getBlockHash", "params":[blockNumber?: BlockNumber] } ``` ### `getFinalizedHead` Get hash of the last finalized block in the canon chain **Interface** ``` api.rpc.chain.getFinalizedHead(): BlockHash ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"chain_getFinalizedHead", "params":[] } ``` ### `getHeader` Retrieves the header for a specific block **Interface** ``` api.rpc.chain.getHeader(hash?: BlockHash): Header ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"chain_getHeader", "params":[hash?: BlockHash] } ``` ### `subscribeAllHeads` Retrieves the newest header via subscription **Interface** ``` api.rpc.chain.subscribeAllHeads(): Header ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"chain_subscribeAllHeads", "params":[] } ``` ### `subscribeFinalizedHeads` Retrieves the best finalized header via subscription **Interface** ``` api.rpc.chain.subscribeFinalizedHeads(): Header ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"chain_subscribeFinalizedHeads", "params":[] } ``` ### `subscribeNewHeads` Retrieves the best header via subscription **Interface** ``` api.rpc.chain.subscribeNewHeads(): Header ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"chain_subscribeNewHeads", "params":[] } ``` ## Childstate ### `getKeys` Returns the keys with prefix from a child storage, leave empty to get all the keys **Interface** ``` api.rpc.childstate.getKeys(childKey: PrefixedStorageKey, prefix: StorageKey, at?: Hash): Vec ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"childstate_getKeys", "params":[childKey: PrefixedStorageKey, prefix: StorageKey, at?: Hash] } ``` ### `getKeysPaged` Returns the keys with prefix from a child storage with pagination support **Interface** ``` api.rpc.childstate.getKeysPaged(childKey: PrefixedStorageKey, prefix: StorageKey, count: u32, startKey?: StorageKey, at?: Hash): Vec ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"childstate_getKeysPaged", "params":[childKey: PrefixedStorageKey, prefix: StorageKey, count: u32, startKey?: StorageKey, at?: Hash] } ``` ### `getStorage` Returns a child storage entry at a specific block state **Interface** ``` api.rpc.childstate.getStorage(childKey: PrefixedStorageKey, key: StorageKey, at?: Hash): Option ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"childstate_getStorage", "params":[childKey: PrefixedStorageKey, key: StorageKey, at?: Hash] } ``` ### `getStorageEntries` Returns child storage entries for multiple keys at a specific block state **Interface** ``` api.rpc.childstate.getStorageEntries(childKey: PrefixedStorageKey, keys: Vec, at?: Hash): Vec> ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"childstate_getStorageEntries", "params":[childKey: PrefixedStorageKey, keys: Vec, at?: Hash] } ``` ### `getStorageHash` Returns the hash of a child storage entry at a block state **Interface** ``` api.rpc.childstate.getStorageHash(childKey: PrefixedStorageKey, key: StorageKey, at?: Hash): Option ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"childstate_getStorageHash", "params":[childKey: PrefixedStorageKey, key: StorageKey, at?: Hash] } ``` ### `getStorageSize` Returns the size of a child storage entry at a block state **Interface** ``` api.rpc.childstate.getStorageSize(childKey: PrefixedStorageKey, key: StorageKey, at?: Hash): Option ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"childstate_getStorageSize", "params":[childKey: PrefixedStorageKey, key: StorageKey, at?: Hash] } ``` ## Dex ### `getAmountsIn` Given an array of AssetIds, return amounts in for an amount out **Interface** ``` api.rpc.dex.getAmountsIn(amountOut: u128, path: Vec): Json ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"dex_getAmountsIn", "params":[amountOut: u128, path: Vec] } ``` ### `getAmountsOut` Given an array of AssetIds, return amounts out for an amount in **Interface** ``` api.rpc.dex.getAmountsOut(amountIn: u128, path: Vec): Json ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"dex_getAmountsOut", "params":[amountIn: u128, path: Vec] } ``` ### `getLPTokenID` Given two AssetIds, return liquidity token created for the pair **Interface** ``` api.rpc.dex.getLPTokenID(assetA: AssetId, assetB: AssetId): Json ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"dex_getLPTokenID", "params":[assetA: AssetId, assetB: AssetId] } ``` ### `getLiquidity` Given two AssetIds, return liquidity **Interface** ``` api.rpc.dex.getLiquidity(assetA: AssetId, assetB: AssetId): Json ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"dex_getLiquidity", "params":[assetA: AssetId, assetB: AssetId] } ``` ### `getTradingPairStatus` Given two AssetIds, return whether trading pair is enabled or disabled **Interface** ``` api.rpc.dex.getTradingPairStatus(assetA: AssetId, assetB: AssetId): Text ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"dex_getTradingPairStatus", "params":[assetA: AssetId, assetB: AssetId] } ``` ### `quote` Given some amount of an asset and pair reserves, returns an equivalent amount of the other asset **Interface** ``` api.rpc.dex.quote(amountA: u128, reserveA: u128, reserveB: u128): Json ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"dex_quote", "params":[amountA: u128, reserveA: u128, reserveB: u128] } ``` ## Eth ### `accounts` Returns accounts list. **Interface** ``` api.rpc.eth.accounts(): Vec ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"eth_accounts", "params":[] } ``` ### `blockNumber` Returns the blockNumber **Interface** ``` api.rpc.eth.blockNumber(): U256 ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"eth_blockNumber", "params":[] } ``` ### `call` Call contract, returning the output data. **Interface** ``` api.rpc.eth.call(request: EthCallRequest, number?: BlockNumber): Bytes ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"eth_call", "params":[request: EthCallRequest, number?: BlockNumber] } ``` ### `chainId` Returns the chain ID used for transaction signing at the current best block. None is returned if not available. **Interface** ``` api.rpc.eth.chainId(): U64 ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"eth_chainId", "params":[] } ``` ### `coinbase` Returns block author. **Interface** ``` api.rpc.eth.coinbase(): H160 ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"eth_coinbase", "params":[] } ``` ### `estimateGas` Estimate gas needed for execution of given contract. **Interface** ``` api.rpc.eth.estimateGas(request: EthCallRequest, number?: BlockNumber): U256 ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"eth_estimateGas", "params":[request: EthCallRequest, number?: BlockNumber] } ``` ### `feeHistory` Returns fee history for given block count & reward percentiles **Interface** ``` api.rpc.eth.feeHistory(blockCount: U256, newestBlock: BlockNumber, rewardPercentiles: Option>): EthFeeHistory ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"eth_feeHistory", "params":[blockCount: U256, newestBlock: BlockNumber, rewardPercentiles: Option>] } ``` ### `gasPrice` Returns current gas price. **Interface** ``` api.rpc.eth.gasPrice(): U256 ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"eth_gasPrice", "params":[] } ``` ### `getBalance` Returns balance of the given account. **Interface** ``` api.rpc.eth.getBalance(address: H160, number?: BlockNumber): U256 ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"eth_getBalance", "params":[address: H160, number?: BlockNumber] } ``` ### `getBlockByHash` Returns block with given hash. **Interface** ``` api.rpc.eth.getBlockByHash(hash: H256, full: bool): Option ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"eth_getBlockByHash", "params":[hash: H256, full: bool] } ``` ### `getBlockByNumber` Returns block with given number. **Interface** ``` api.rpc.eth.getBlockByNumber(block: BlockNumber, full: bool): Option ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"eth_getBlockByNumber", "params":[block: BlockNumber, full: bool] } ``` ### `getBlockTransactionCountByHash` Returns the number of transactions in a block with given hash. **Interface** ``` api.rpc.eth.getBlockTransactionCountByHash(hash: H256): U256 ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"eth_getBlockTransactionCountByHash", "params":[hash: H256] } ``` ### `getBlockTransactionCountByNumber` Returns the number of transactions in a block with given block number. **Interface** ``` api.rpc.eth.getBlockTransactionCountByNumber(block: BlockNumber): U256 ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"eth_getBlockTransactionCountByNumber", "params":[block: BlockNumber] } ``` ### `getCode` Returns the code at given address at given time (block number). **Interface** ``` api.rpc.eth.getCode(address: H160, number?: BlockNumber): Bytes ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"eth_getCode", "params":[address: H160, number?: BlockNumber] } ``` ### `getFilterChanges` Returns filter changes since last poll. **Interface** ``` api.rpc.eth.getFilterChanges(index: U256): EthFilterChanges ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"eth_getFilterChanges", "params":[index: U256] } ``` ### `getFilterLogs` Returns all logs matching given filter (in a range 'from' - 'to'). **Interface** ``` api.rpc.eth.getFilterLogs(index: U256): Vec ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"eth_getFilterLogs", "params":[index: U256] } ``` ### `getLogs` Returns logs matching given filter object. **Interface** ``` api.rpc.eth.getLogs(filter: EthFilter): Vec ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"eth_getLogs", "params":[filter: EthFilter] } ``` ### `getStorageAt` Returns content of the storage at given address. **Interface** ``` api.rpc.eth.getStorageAt(address: H160, index: U256, number?: BlockNumber): H256 ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"eth_getStorageAt", "params":[address: H160, index: U256, number?: BlockNumber] } ``` ### `getTransactionByBlockHashAndIndex` Returns transaction at given block hash and index. **Interface** ``` api.rpc.eth.getTransactionByBlockHashAndIndex(hash: H256, index: U256): EthTransaction ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"eth_getTransactionByBlockHashAndIndex", "params":[hash: H256, index: U256] } ``` ### `getTransactionByBlockNumberAndIndex` Returns transaction by given block number and index. **Interface** ``` api.rpc.eth.getTransactionByBlockNumberAndIndex(number: BlockNumber, index: U256): EthTransaction ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"eth_getTransactionByBlockNumberAndIndex", "params":[number: BlockNumber, index: U256] } ``` ### `getTransactionByHash` Get transaction by its hash. **Interface** ``` api.rpc.eth.getTransactionByHash(hash: H256): EthTransaction ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"eth_getTransactionByHash", "params":[hash: H256] } ``` ### `getTransactionCount` Returns the number of transactions sent from given address at given time (block number). **Interface** ``` api.rpc.eth.getTransactionCount(address: H160, number?: BlockNumber): U256 ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"eth_getTransactionCount", "params":[address: H160, number?: BlockNumber] } ``` ### `getTransactionReceipt` Returns transaction receipt by transaction hash. **Interface** ``` api.rpc.eth.getTransactionReceipt(hash: H256): EthReceipt ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"eth_getTransactionReceipt", "params":[hash: H256] } ``` ### `getUncleByBlockHashAndIndex` Returns an uncles at given block and index. **Interface** ``` api.rpc.eth.getUncleByBlockHashAndIndex(hash: H256, index: U256): EthRichBlock ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"eth_getUncleByBlockHashAndIndex", "params":[hash: H256, index: U256] } ``` ### `getUncleByBlockNumberAndIndex` Returns an uncles at given block and index. **Interface** ``` api.rpc.eth.getUncleByBlockNumberAndIndex(number: BlockNumber, index: U256): EthRichBlock ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"eth_getUncleByBlockNumberAndIndex", "params":[number: BlockNumber, index: U256] } ``` ### `getUncleCountByBlockHash` Returns the number of uncles in a block with given hash. **Interface** ``` api.rpc.eth.getUncleCountByBlockHash(hash: H256): U256 ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"eth_getUncleCountByBlockHash", "params":[hash: H256] } ``` ### `getUncleCountByBlockNumber` Returns the number of uncles in a block with given block number. **Interface** ``` api.rpc.eth.getUncleCountByBlockNumber(number: BlockNumber): U256 ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"eth_getUncleCountByBlockNumber", "params":[number: BlockNumber] } ``` ### `getWork` Returns the hash of the current block, the seedHash, and the boundary condition to be met. **Interface** ``` api.rpc.eth.getWork(): EthWork ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"eth_getWork", "params":[] } ``` ### `hashrate` Returns the number of hashes per second that the node is mining with. **Interface** ``` api.rpc.eth.hashrate(): U256 ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"eth_hashrate", "params":[] } ``` ### `maxPriorityFeePerGas` Returns max priority fee per gas **Interface** ``` api.rpc.eth.maxPriorityFeePerGas(): U256 ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"eth_maxPriorityFeePerGas", "params":[] } ``` ### `mining` Returns true if client is actively mining new blocks. **Interface** ``` api.rpc.eth.mining(): bool ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"eth_mining", "params":[] } ``` ### `newBlockFilter` Returns id of new block filter. **Interface** ``` api.rpc.eth.newBlockFilter(): U256 ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"eth_newBlockFilter", "params":[] } ``` ### `newFilter` Returns id of new filter. **Interface** ``` api.rpc.eth.newFilter(filter: EthFilter): U256 ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"eth_newFilter", "params":[filter: EthFilter] } ``` ### `newPendingTransactionFilter` Returns id of new block filter. **Interface** ``` api.rpc.eth.newPendingTransactionFilter(): U256 ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"eth_newPendingTransactionFilter", "params":[] } ``` ### `protocolVersion` Returns protocol version encoded as a string (quotes are necessary). **Interface** ``` api.rpc.eth.protocolVersion(): u64 ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"eth_protocolVersion", "params":[] } ``` ### `sendRawTransaction` Sends signed transaction, returning its hash. **Interface** ``` api.rpc.eth.sendRawTransaction(bytes: Bytes): H256 ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"eth_sendRawTransaction", "params":[bytes: Bytes] } ``` ### `sendTransaction` Sends transaction; will block waiting for signer to return the transaction hash **Interface** ``` api.rpc.eth.sendTransaction(tx: EthTransactionRequest): H256 ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"eth_sendTransaction", "params":[tx: EthTransactionRequest] } ``` ### `submitHashrate` Used for submitting mining hashrate. **Interface** ``` api.rpc.eth.submitHashrate(index: U256, hash: H256): bool ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"eth_submitHashrate", "params":[index: U256, hash: H256] } ``` ### `submitWork` Used for submitting a proof-of-work solution. **Interface** ``` api.rpc.eth.submitWork(nonce: H64, headerHash: H256, mixDigest: H256): bool ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"eth_submitWork", "params":[nonce: H64, headerHash: H256, mixDigest: H256] } ``` ### `subscribe` Subscribe to Eth subscription. **Interface** ``` api.rpc.eth.subscribe(kind: EthSubKind, params?: EthSubParams): Null ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"eth_subscribe", "params":[kind: EthSubKind, params?: EthSubParams] } ``` ### `syncing` Returns an object with data about the sync status or false. **Interface** ``` api.rpc.eth.syncing(): EthSyncStatus ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"eth_syncing", "params":[] } ``` ### `uninstallFilter` Uninstalls filter. **Interface** ``` api.rpc.eth.uninstallFilter(index: U256): bool ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"eth_uninstallFilter", "params":[index: U256] } ``` ## Ethy ### `getEventProof` Get ETH event proof for event Id **Interface** ``` api.rpc.ethy.getEventProof(eventId: EventProofId): Option ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"ethy_getEventProof", "params":[eventId: EventProofId] } ``` ### `getXrplTxProof` Get XRPL event proof for event Id **Interface** ``` api.rpc.ethy.getXrplTxProof(eventId: EventProofId): Option ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"ethy_getXrplTxProof", "params":[eventId: EventProofId] } ``` ## Grandpa ### `proveFinality` Prove finality for the given block number, returning the Justification for the last block in the set. **Interface** ``` api.rpc.grandpa.proveFinality(blockNumber: BlockNumber): Option ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"grandpa_proveFinality", "params":[blockNumber: BlockNumber] } ``` ### `roundState` Returns the state of the current best round state as well as the ongoing background rounds **Interface** ``` api.rpc.grandpa.roundState(): ReportedRoundStates ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"grandpa_roundState", "params":[] } ``` ### `subscribeJustifications` Subscribes to grandpa justifications **Interface** ``` api.rpc.grandpa.subscribeJustifications(): JustificationNotification ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"grandpa_subscribeJustifications", "params":[] } ``` ## Net ### `listening` Returns true if client is actively listening for network connections. Otherwise false. **Interface** ``` api.rpc.net.listening(): bool ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"net_listening", "params":[] } ``` ### `peerCount` Returns number of peers connected to node. **Interface** ``` api.rpc.net.peerCount(): Text ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"net_peerCount", "params":[] } ``` ### `version` Returns protocol version. **Interface** ``` api.rpc.net.version(): Text ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"net_version", "params":[] } ``` ## Nft ### `ownedTokens` Get all NFTs owned by an account **Interface** ``` api.rpc.nft.ownedTokens(collectionId: CollectionUuid, who: AccountId, cursor: SerialNumber, limit: u16): Json ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"nft_ownedTokens", "params":[collectionId: CollectionUuid, who: AccountId, cursor: SerialNumber, limit: u16] } ``` ### `tokenUri` Get the URI of a token **Interface** ``` api.rpc.nft.tokenUri(tokenId: TokenId): Json ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"nft_tokenUri", "params":[tokenId: TokenId] } ``` ## Offchain ### `localStorageGet` Get offchain local storage under given key and prefix This method is only active with appropriate flags **Interface** ``` api.rpc.offchain.localStorageGet(kind: StorageKind, key: Bytes): Option ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"offchain_localStorageGet", "params":[kind: StorageKind, key: Bytes] } ``` ### `localStorageSet` Set offchain local storage under given key and prefix This method is only active with appropriate flags **Interface** ``` api.rpc.offchain.localStorageSet(kind: StorageKind, key: Bytes, value: Bytes): Null ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"offchain_localStorageSet", "params":[kind: StorageKind, key: Bytes, value: Bytes] } ``` ## Payment ### `queryFeeDetails` Query the detailed fee of a given encoded extrinsic **Interface** ``` api.rpc.payment.queryFeeDetails(extrinsic: Bytes, at?: BlockHash): FeeDetails ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"payment_queryFeeDetails", "params":[extrinsic: Bytes, at?: BlockHash] } ``` **Deprecated Use** `api.call.transactionPaymentApi.queryFeeDetails` **instead** ### `queryInfo` Retrieves the fee information for an encoded extrinsic **Interface** ``` api.rpc.payment.queryInfo(extrinsic: Bytes, at?: BlockHash): RuntimeDispatchInfoV1 ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"payment_queryInfo", "params":[extrinsic: Bytes, at?: BlockHash] } ``` **Deprecated Use** `api.call.transactionPaymentApi.queryInfo` **instead** ## Rpc ### `methods` Retrieves the list of RPC methods that are exposed by the node **Interface** ``` api.rpc.rpc.methods(): RpcMethods ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"rpc_methods", "params":[] } ``` ## State ### `call` Perform a call to a builtin on the chain **Interface** ``` api.rpc.state.call(method: Text, data: Bytes, at?: BlockHash): Bytes ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"state_call", "params":[method: Text, data: Bytes, at?: BlockHash] } ``` ### `getChildReadProof` Returns proof of storage for child key entries at a specific block state. **Interface** ``` api.rpc.state.getChildReadProof(childStorageKey: PrefixedStorageKey, keys: Vec, at?: BlockHash): ReadProof ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"state_getChildReadProof", "params":[childStorageKey: PrefixedStorageKey, keys: Vec, at?: BlockHash] } ``` ### `getKeys` Retrieves the keys with a certain prefix **Interface** ``` api.rpc.state.getKeys(key: StorageKey, at?: BlockHash): Vec ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"state_getKeys", "params":[key: StorageKey, at?: BlockHash] } ``` **Deprecated Use** `api.rpc.state.getKeysPaged` **to retrieve keys** ### `getKeysPaged` Returns the keys with prefix with pagination support. **Interface** ``` api.rpc.state.getKeysPaged(key: StorageKey, count: u32, startKey?: StorageKey, at?: BlockHash): Vec ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"state_getKeysPaged", "params":[key: StorageKey, count: u32, startKey?: StorageKey, at?: BlockHash] } ``` ### `getMetadata` Returns the runtime metadata **Interface** ``` api.rpc.state.getMetadata(at?: BlockHash): Metadata ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"state_getMetadata", "params":[at?: BlockHash] } ``` ### `getPairs` Returns the keys with prefix, leave empty to get all the keys (deprecated: Use getKeysPaged) This method is only active with appropriate flags **Interface** ``` api.rpc.state.getPairs(prefix: StorageKey, at?: BlockHash): Vec ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"state_getPairs", "params":[prefix: StorageKey, at?: BlockHash] } ``` **Deprecated Use** `api.rpc.state.getKeysPaged` **to retrieve keys** ### `getReadProof` Returns proof of storage entries at a specific block state **Interface** ``` api.rpc.state.getReadProof(keys: Vec, at?: BlockHash): ReadProof ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"state_getReadProof", "params":[keys: Vec, at?: BlockHash] } ``` ### `getRuntimeVersion` Get the runtime version **Interface** ``` api.rpc.state.getRuntimeVersion(at?: BlockHash): RuntimeVersion ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"state_getRuntimeVersion", "params":[at?: BlockHash] } ``` ### `getStorage` Retrieves the storage for a key **Interface** ``` api.rpc.state.getStorage(key: StorageKey, at?: BlockHash): StorageData ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"state_getStorage", "params":[key: StorageKey, at?: BlockHash] } ``` ### `getStorageHash` Retrieves the storage hash **Interface** ``` api.rpc.state.getStorageHash(key: StorageKey, at?: BlockHash): Hash ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"state_getStorageHash", "params":[key: StorageKey, at?: BlockHash] } ``` ### `getStorageSize` Retrieves the storage size **Interface** ``` api.rpc.state.getStorageSize(key: StorageKey, at?: BlockHash): u64 ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"state_getStorageSize", "params":[key: StorageKey, at?: BlockHash] } ``` ### `queryStorage` Query historical storage entries (by key) starting from a start block. This method is only active with appropriate flags. **Interface** ``` api.rpc.state.queryStorage(keys: Vec, fromBlock: Hash, toBlock?: BlockHash): Vec ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"state_queryStorage", "params":[keys: Vec, fromBlock: Hash, toBlock?: BlockHash] } ``` ### `queryStorageAt` Query storage entries (by key) starting at block hash given as the second parameter **Interface** ``` api.rpc.state.queryStorageAt(keys: Vec, at?: BlockHash): Vec ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"state_queryStorageAt", "params":[keys: Vec, at?: BlockHash] } ``` ### `subscribeRuntimeVersion` Retrieves the runtime version via subscription **Interface** ``` api.rpc.state.subscribeRuntimeVersion(): RuntimeVersion ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"state_subscribeRuntimeVersion", "params":[] } ``` ### `subscribeStorage` Subscribes to storage changes for the provided keys **Interface** ``` api.rpc.state.subscribeStorage(keys?: Vec): StorageChangeSet ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"state_subscribeStorage", "params":[keys?: Vec] } ``` ### `traceBlock` Provides a way to trace the re-execution of a single block This method is only active with appropriate flags. **Interface** ``` api.rpc.state.traceBlock(block: Hash, targets: Option, storageKeys: Option, methods: Option): TraceBlockResponse ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"state_traceBlock", "params":[block: Hash, targets: Option, storageKeys: Option, methods: Option] } ``` ## System ### `accountNextIndex` Retrieves the next accountIndex as available on the node **Interface** ``` api.rpc.system.accountNextIndex(accountId: AccountId): Index ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"system_accountNextIndex", "params":[accountId: AccountId] } ``` ### `addLogFilter` Adds the supplied directives to the current log filter. **Info**: This method is only active with appropriate flags. **Interface** ``` api.rpc.system.addLogFilter(directives: Text): Null ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"system_addLogFilter", "params":[directives: Text] } ``` ### `addReservedPeer` Adds a reserved peer This method is only active with appropriate flags. **Interface** ``` api.rpc.system.addReservedPeer(peer: Text): Text ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"system_addReservedPeer", "params":[peer: Text] } ``` ### `chain` Retrieves the chain **Interface** ``` api.rpc.system.chain(): Text ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"system_chain", "params":[] } ``` ### `chainType` Retrieves the chain type **Interface** ``` api.rpc.system.chainType(): ChainType ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"system_chainType", "params":[] } ``` ### `dryRun` Dry run an extrinsic at a given block. This method is only active with appropriate flags. **Interface** ``` api.rpc.system.dryRun(extrinsic: Bytes, at?: BlockHash): ApplyExtrinsicResult ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"system_dryRun", "params":[extrinsic: Bytes, at?: BlockHash] } ``` ### `health` Return health status of the node **Interface** ``` api.rpc.system.health(): Health ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"system_health", "params":[] } ``` ### `localListenAddresses` The addresses include a trailing /p2p/ with the local PeerId, and are thus suitable to be passed to addReservedPeer or as a bootnode address for example **Interface** ``` api.rpc.system.localListenAddresses(): Vec ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"system_localListenAddresses", "params":[] } ``` ### `localPeerId` Returns the base58-encoded PeerId of the node **Interface** ``` api.rpc.system.localPeerId(): Text ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"system_localPeerId", "params":[] } ``` ### `name` Retrieves the node name **Interface** ``` api.rpc.system.name(): Text ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"system_name", "params":[] } ``` ### `nodeRoles` Returns the roles the node is running as **Interface** ``` api.rpc.system.nodeRoles(): Vec ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"system_nodeRoles", "params":[] } ``` ### `peers` Returns the currently connected peers. This method is only active with appropriate flags. **Interface** ``` api.rpc.system.peers(): Vec ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"system_peers", "params":[] } ``` ### `properties` Get a custom set of properties as a JSON object, defined in the chain spec **Interface** ``` api.rpc.system.properties(): ChainProperties ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"system_properties", "params":[] } ``` ### `removeReservedPeer` Remove a reserved peer. This method is only active with appropriate flags. **Interface** ``` api.rpc.system.removeReservedPeer(peerId: Text): Text ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"system_removeReservedPeer", "params":[peerId: Text] } ``` ### `reservedPeers` Returns the list of reserved peers **Interface** ``` api.rpc.system.reservedPeers(): Vec ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"system_reservedPeers", "params":[] } ``` ### `resetLogFilter` Resets the log filter to Substrate defaults This method is only active with appropriate flags. **Interface** ``` api.rpc.system.resetLogFilter(): Null ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"system_resetLogFilter", "params":[] } ``` ### `syncState` Returns the state of the syncing of the node **Interface** ``` api.rpc.system.syncState(): SyncState ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"system_syncState", "params":[] } ``` ### `version` Retrieves the version of the node **Interface** ``` api.rpc.system.version(): Text ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"system_version", "params":[] } ``` ## Web3 ### `clientVersion` Returns current client version. **Interface** ``` api.rpc.web3.clientVersion(): Text ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"web3_clientVersion", "params":[] } ``` ### `sha3` Returns sha3 of the given data **Interface** ``` api.rpc.web3.sha3(data: Bytes): H256 ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"web3_sha3", "params":[data: Bytes] } ``` ## SyloDataPermissions ### `getPermissions` Queries the pallet's storage for all available permissions for a given set data ids that have been granted to the specified account. The response value will include a mapping from each data id to a vector of onchain permissions that relate to that account.It will also include the off-chain permission reference if it exists. Clients can use this RPC call to avoid making multiple separate queries to onchain storage. **Interface** ``` type PermissionReferenceRecord { permission_record_id: String, resolvers: Vec<(String, Vec)>, } type GetPermissionsResult { permissions: Vec<(String, Vec)>, permission_reference: Option, } api.rpc.syloDataPermissions.getPermissions( dataAuthor: AccountId, grantee: AccountId, dataIds: Vec ): GetPermissionsResult ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"syloDataPermissions_getPermissions", "params":[dataAuthor: AccountId, grantee: AccountId, dataIds: Vec] } ``` # Assets Source: https://docs.therootnetwork.com/build/substrate/api-reference/runtime-pallets/assets ## Calls ### approveTransfer Approve an amount of asset for transfer by a delegated third-party account. Origin must be Signed. Ensures that `ApprovalDeposit` worth of `Currency` is reserved from signing account for the purpose of holding the approval. If some non-zero amount of assets is already approved from signing account to `delegate`, then it is topped up or unreserved to meet the right value. NOTE: The signing account does not need to own `amount` of assets at the point of making this call. * `id`: The identifier of the asset. * `delegate`: The account to delegate permission to transfer asset. * `amount`: The amount of asset that may be transferred by `delegate`. If there is already an approval in place, then this acts additively. Emits `ApprovedTransfer` on success. Weight: `O(1)` **Namespace** ``` api.tx.assets.approveTransfer ``` **Type** ``` function approveTransfer( id: Compact, delegate: SeedPrimitivesSignatureAccountId20, amount: Compact ) ``` ### burn Reduce the balance of `who` by as much as possible up to `amount` assets of `id`. Origin must be Signed and the sender should be the Manager of the asset `id`. Bails with `NoAccount` if the `who` is already dead. * `id`: The identifier of the asset to have some amount burned. * `who`: The account to be debited from. * `amount`: The maximum amount by which `who`'s balance should be reduced. Emits `Burned` with the actual amount burned. If this takes the balance to below the minimum for the asset, then the amount burned is increased to take it to zero. Weight: `O(1)` Modes: Post-existence of `who`; Pre & post Zombie-status of `who`. **Namespace** ``` api.tx.assets.burn ``` **Type** ``` function burn( id: Compact, who: SeedPrimitivesSignatureAccountId20, amount: Compact ) ``` ### cancelApproval Cancel all of some asset approved for delegated transfer by a third-party account. Origin must be Signed and there must be an approval in place between signer and `delegate`. Unreserves any deposit previously reserved by `approve_transfer` for the approval. * `id`: The identifier of the asset. * `delegate`: The account delegated permission to transfer asset. Emits `ApprovalCancelled` on success. Weight: `O(1)` **Namespace** ``` api.tx.assets.cancelApproval ``` **Type** ``` function cancelApproval( id: Compact, delegate: SeedPrimitivesSignatureAccountId20 ) ``` ### clearMetadata Clear the metadata for an asset. Origin must be Signed and the sender should be the Owner of the asset `id`. Any deposit is freed for the asset owner. * `id`: The identifier of the asset to clear. Emits `MetadataCleared`. Weight: `O(1)` **Namespace** ``` api.tx.assets.clearMetadata ``` **Type** ``` function clearMetadata( id: Compact ) ``` ### create Issue a new class of fungible assets from a public origin. This new asset class has no assets initially and its owner is the origin. The origin must be Signed and the sender must have sufficient funds free. Funds of sender are reserved by `AssetDeposit`. Parameters: * `id`: The identifier of the new asset. This must not be currently in use to identify an existing asset. * `admin`: The admin of this class of assets. The admin is the initial address of each member of the asset class's admin team. * `min_balance`: The minimum balance of this new asset that any single account must have. If an account's balance is reduced below this, then it collapses to zero. Emits `Created` event when successful. Weight: `O(1)` **Namespace** ``` api.tx.assets.create ``` **Type** ``` function create( id: Compact, admin: SeedPrimitivesSignatureAccountId20, min_balance: u128 ) ``` ### destroy Destroy a class of fungible assets. The origin must conform to `ForceOrigin` or must be Signed and the sender must be the owner of the asset `id`. * `id`: The identifier of the asset to be destroyed. This must identify an existing asset. Emits `Destroyed` event when successful. NOTE: It can be helpful to first freeze an asset before destroying it so that you can provide accurate witness information and prevent users from manipulating state in a way that can make it harder to destroy. Weight: `O(c + p + a)` where: * `c = (witness.accounts - witness.sufficients)` * `s = witness.sufficients` * `a = witness.approvals` **Namespace** ``` api.tx.assets.destroy ``` **Type** ``` function destroy( id: Compact, witness: PalletAssetsDestroyWitness ) ``` ### forceAssetStatus Alter the attributes of a given asset. Origin must be `ForceOrigin`. * `id`: The identifier of the asset. * `owner`: The new Owner of this asset. * `issuer`: The new Issuer of this asset. * `admin`: The new Admin of this asset. * `freezer`: The new Freezer of this asset. * `min_balance`: The minimum balance of this new asset that any single account must have. If an account's balance is reduced below this, then it collapses to zero. * `is_sufficient`: Whether a non-zero balance of this asset is deposit of sufficient value to account for the state bloat associated with its balance storage. If set to `true`, then non-zero balances may be stored without a `consumer` reference (and thus an ED in the Balances pallet or whatever else is used to control user-account state growth). * `is_frozen`: Whether this asset class is frozen except for permissioned/admin instructions. Emits `AssetStatusChanged` with the identity of the asset. Weight: `O(1)` **Namespace** ``` api.tx.assets.forceAssetStatus ``` **Type** ``` function forceAssetStatus( id: Compact, owner: SeedPrimitivesSignatureAccountId20, issuer: SeedPrimitivesSignatureAccountId20, admin: SeedPrimitivesSignatureAccountId20, freezer: SeedPrimitivesSignatureAccountId20, min_balance: Compact, is_sufficient: bool, is_frozen: bool ) ``` ### forceCancelApproval Cancel all of some asset approved for delegated transfer by a third-party account. Origin must be either ForceOrigin or Signed origin with the signer being the Admin account of the asset `id`. Unreserves any deposit previously reserved by `approve_transfer` for the approval. * `id`: The identifier of the asset. * `delegate`: The account delegated permission to transfer asset. Emits `ApprovalCancelled` on success. Weight: `O(1)` **Namespace** ``` api.tx.assets.forceCancelApproval ``` **Type** ``` function forceCancelApproval( id: Compact, owner: SeedPrimitivesSignatureAccountId20, delegate: SeedPrimitivesSignatureAccountId20 ) ``` ### forceClearMetadata Clear the metadata for an asset. Origin must be ForceOrigin. Any deposit is returned. * `id`: The identifier of the asset to clear. Emits `MetadataCleared`. Weight: `O(1)` **Namespace** ``` api.tx.assets.forceClearMetadata ``` **Type** ``` function forceClearMetadata( id: Compact ) ``` ### forceCreate Issue a new class of fungible assets from a privileged origin. This new asset class has no assets initially. The origin must conform to `ForceOrigin`. Unlike `create`, no funds are reserved. * `id`: The identifier of the new asset. This must not be currently in use to identify an existing asset. * `owner`: The owner of this class of assets. The owner has full superuser permissions over this asset, but may later change and configure the permissions using `transfer_ownership` and `set_team`. * `min_balance`: The minimum balance of this new asset that any single account must have. If an account's balance is reduced below this, then it collapses to zero. Emits `ForceCreated` event when successful. Weight: `O(1)` **Namespace** ``` api.tx.assets.forceCreate ``` **Type** ``` function forceCreate( id: Compact, owner: SeedPrimitivesSignatureAccountId20, is_sufficient: bool, min_balance: Compact ) ``` ### forceSetMetadata Force the metadata for an asset to some value. Origin must be ForceOrigin. Any deposit is left alone. * `id`: The identifier of the asset to update. * `name`: The user friendly name of this asset. Limited in length by `StringLimit`. * `symbol`: The exchange symbol for this asset. Limited in length by `StringLimit`. * `decimals`: The number of decimals this asset uses to represent one unit. Emits `MetadataSet`. Weight: `O(N + S)` where N and S are the length of the name and symbol respectively. **Namespace** ``` api.tx.assets.forceSetMetadata ``` **Type** ``` function forceSetMetadata( id: Compact, name: Bytes, symbol: Bytes, decimals: u8, is_frozen: bool ) ``` ### forceTransfer Move some assets from one account to another. Origin must be Signed and the sender should be the Admin of the asset `id`. * `id`: The identifier of the asset to have some amount transferred. * `source`: The account to be debited. * `dest`: The account to be credited. * `amount`: The amount by which the `source`'s balance of assets should be reduced and `dest`'s balance increased. The amount actually transferred may be slightly greater in the case that the transfer would otherwise take the `source` balance above zero but below the minimum balance. Must be greater than zero. Emits `Transferred` with the actual amount transferred. If this takes the source balance to below the minimum for the asset, then the amount transferred is increased to take it to zero. Weight: `O(1)` Modes: Pre-existence of `dest`; Post-existence of `source`; Account pre-existence of `dest`. **Namespace** ``` api.tx.assets.forceTransfer ``` **Type** ``` function forceTransfer( id: Compact, source: SeedPrimitivesSignatureAccountId20, dest: SeedPrimitivesSignatureAccountId20, amount: Compact ) ``` ### freeze Disallow further unprivileged transfers from an account. Origin must be Signed and the sender should be the Freezer of the asset `id`. * `id`: The identifier of the asset to be frozen. * `who`: The account to be frozen. Emits `Frozen`. Weight: `O(1)` **Namespace** ``` api.tx.assets.freeze ``` **Type** ``` function freeze( id: Compact, who: SeedPrimitivesSignatureAccountId20 ) ``` ### freezeAsset Disallow further unprivileged transfers for the asset class. Origin must be Signed and the sender should be the Freezer of the asset `id`. * `id`: The identifier of the asset to be frozen. Emits `Frozen`. Weight: `O(1)` **Namespace** ``` api.tx.assets.freezeAsset ``` **Type** ``` function freezeAsset( id: Compact ) ``` ### mint Mint assets of a particular class. The origin must be Signed and the sender must be the Issuer of the asset `id`. * `id`: The identifier of the asset to have some amount minted. * `beneficiary`: The account to be credited with the minted assets. * `amount`: The amount of the asset to be minted. Emits `Issued` event when successful. Weight: `O(1)` Modes: Pre-existing balance of `beneficiary`; Account pre-existence of `beneficiary`. **Namespace** ``` api.tx.assets.mint ``` **Type** ``` function mint( id: Compact, beneficiary: SeedPrimitivesSignatureAccountId20, amount: Compact ) ``` ### refund Return the deposit (if any) of an asset account. The origin must be Signed. * `id`: The identifier of the asset for the account to be created. * `allow_burn`: If `true` then assets may be destroyed in order to complete the refund. Emits `Refunded` event when successful. **Namespace** ``` api.tx.assets.refund ``` **Type** ``` function refund( id: Compact, allow_burn: bool ) ``` ### setMetadata Set the metadata for an asset. Origin must be Signed and the sender should be the Owner of the asset `id`. Funds of sender are reserved according to the formula: `MetadataDepositBase + MetadataDepositPerByte * (name.len + symbol.len)` taking into account any already reserved funds. * `id`: The identifier of the asset to update. * `name`: The user friendly name of this asset. Limited in length by `StringLimit`. * `symbol`: The exchange symbol for this asset. Limited in length by `StringLimit`. * `decimals`: The number of decimals this asset uses to represent one unit. Emits `MetadataSet`. Weight: `O(1)` **Namespace** ``` api.tx.assets.setMetadata ``` **Type** ``` function setMetadata( id: Compact, name: Bytes, symbol: Bytes, decimals: u8 ) ``` ### setTeam Change the Issuer, Admin and Freezer of an asset. Origin must be Signed and the sender should be the Owner of the asset `id`. * `id`: The identifier of the asset to be frozen. * `issuer`: The new Issuer of this asset. * `admin`: The new Admin of this asset. * `freezer`: The new Freezer of this asset. Emits `TeamChanged`. Weight: `O(1)` **Namespace** ``` api.tx.assets.setTeam ``` **Type** ``` function setTeam( id: Compact, issuer: SeedPrimitivesSignatureAccountId20, admin: SeedPrimitivesSignatureAccountId20, freezer: SeedPrimitivesSignatureAccountId20 ) ``` ### thaw Allow unprivileged transfers from an account again. Origin must be Signed and the sender should be the Admin of the asset `id`. * `id`: The identifier of the asset to be frozen. * `who`: The account to be unfrozen. Emits `Thawed`. Weight: `O(1)` **Namespace** ``` api.tx.assets.thaw ``` **Type** ``` function thaw( id: Compact, who: SeedPrimitivesSignatureAccountId20 ) ``` ### thawAsset Allow unprivileged transfers for the asset again. Origin must be Signed and the sender should be the Admin of the asset `id`. * `id`: The identifier of the asset to be thawed. Emits `Thawed`. Weight: `O(1)` **Namespace** ``` api.tx.assets.thawAsset ``` **Type** ``` function thawAsset( id: Compact ) ``` ### touch Create an asset account for non-provider assets. A deposit will be taken from the signer account. * `origin`: Must be Signed; the signer account must have sufficient funds for a deposit to be taken. * `id`: The identifier of the asset for the account to be created. Emits `Touched` event when successful. **Namespace** ``` api.tx.assets.touch ``` **Type** ``` function touch( id: Compact ) ``` ### transfer Move some assets from the sender account to another. Origin must be Signed. * `id`: The identifier of the asset to have some amount transferred. * `target`: The account to be credited. * `amount`: The amount by which the sender's balance of assets should be reduced and `target`'s balance increased. The amount actually transferred may be slightly greater in the case that the transfer would otherwise take the sender balance above zero but below the minimum balance. Must be greater than zero. Emits `Transferred` with the actual amount transferred. If this takes the source balance to below the minimum for the asset, then the amount transferred is increased to take it to zero. Weight: `O(1)` Modes: Pre-existence of `target`; Post-existence of sender; Account pre-existence of `target`. **Namespace** ``` api.tx.assets.transfer ``` **Type** ``` function transfer( id: Compact, target: SeedPrimitivesSignatureAccountId20, amount: Compact ) ``` ### transferApproved Transfer some asset balance from a previously delegated account to some third-party account. Origin must be Signed and there must be an approval in place by the `owner` to the signer. If the entire amount approved for transfer is transferred, then any deposit previously reserved by `approve_transfer` is unreserved. * `id`: The identifier of the asset. * `owner`: The account which previously approved for a transfer of at least `amount` and from which the asset balance will be withdrawn. * `destination`: The account to which the asset balance of `amount` will be transferred. * `amount`: The amount of assets to transfer. Emits `TransferredApproved` on success. Weight: `O(1)` **Namespace** ``` api.tx.assets.transferApproved ``` **Type** ``` function transferApproved( id: Compact, owner: SeedPrimitivesSignatureAccountId20, destination: SeedPrimitivesSignatureAccountId20, amount: Compact ) ``` ### transferKeepAlive Move some assets from the sender account to another, keeping the sender account alive. Origin must be Signed. * `id`: The identifier of the asset to have some amount transferred. * `target`: The account to be credited. * `amount`: The amount by which the sender's balance of assets should be reduced and `target`'s balance increased. The amount actually transferred may be slightly greater in the case that the transfer would otherwise take the sender balance above zero but below the minimum balance. Must be greater than zero. Emits `Transferred` with the actual amount transferred. If this takes the source balance to below the minimum for the asset, then the amount transferred is increased to take it to zero. Weight: `O(1)` Modes: Pre-existence of `target`; Post-existence of sender; Account pre-existence of `target`. **Namespace** ``` api.tx.assets.transferKeepAlive ``` **Type** ``` function transferKeepAlive( id: Compact, target: SeedPrimitivesSignatureAccountId20, amount: Compact ) ``` ### transferOwnership Change the Owner of an asset. Origin must be Signed and the sender should be the Owner of the asset `id`. * `id`: The identifier of the asset. * `owner`: The new Owner of this asset. Emits `OwnerChanged`. Weight: `O(1)` **Namespace** ``` api.tx.assets.transferOwnership ``` **Type** ``` function transferOwnership( id: Compact, owner: SeedPrimitivesSignatureAccountId20 ) ``` ## Storage ### account The holdings of a specific account for a specific asset. **Namespace** ``` api.query.assets.account ``` **Type** ``` function account( u32, SeedPrimitivesSignatureAccountId20 ): Option ``` ### approvals Approved balance transfers. First balance is the amount approved for transfer. Second is the amount of `T::Currency` reserved for storing this. First key is the asset ID, second key is the owner and third key is the delegate. **Namespace** ``` api.query.assets.approvals ``` **Type** ``` function approvals( u32, SeedPrimitivesSignatureAccountId20, SeedPrimitivesSignatureAccountId20 ): Option ``` ### asset Details of an asset. **Namespace** ``` api.query.assets.asset ``` **Type** ``` function asset( u32 ): Option ``` ### metadata Metadata of an asset. **Namespace** ``` api.query.assets.metadata ``` **Type** ``` function metadata( u32 ): PalletAssetsAssetMetadata ``` ## Events ### ApprovalCancelled An approval for account `delegate` was cancelled by `owner`. **Namespace** ``` api.events.assets.ApprovalCancelled ``` **Type** ``` type ApprovalCancelled = { asset_id: u32, owner: SeedPrimitivesSignatureAccountId20, delegate: SeedPrimitivesSignatureAccountId20 } ``` ### ApprovedTransfer (Additional) funds have been approved for transfer to a destination account. **Namespace** ``` api.events.assets.ApprovedTransfer ``` **Type** ``` type ApprovedTransfer = { asset_id: u32, source: SeedPrimitivesSignatureAccountId20, delegate: SeedPrimitivesSignatureAccountId20, amount: u128 } ``` ### AssetFrozen Some asset `asset_id` was frozen. **Namespace** ``` api.events.assets.AssetFrozen ``` **Type** ``` type AssetFrozen = { asset_id: u32 } ``` ### AssetStatusChanged An asset has had its attributes changed by the `Force` origin. **Namespace** ``` api.events.assets.AssetStatusChanged ``` **Type** ``` type AssetStatusChanged = { asset_id: u32 } ``` ### AssetThawed Some asset `asset_id` was thawed. **Namespace** ``` api.events.assets.AssetThawed ``` **Type** ``` type AssetThawed = { asset_id: u32 } ``` ### Burned Some assets were destroyed. **Namespace** ``` api.events.assets.Burned ``` **Type** ``` type Burned = { asset_id: u32, owner: SeedPrimitivesSignatureAccountId20, balance: u128 } ``` ### Created Some asset class was created. **Namespace** ``` api.events.assets.Created ``` **Type** ``` type Created = { asset_id: u32, creator: SeedPrimitivesSignatureAccountId20, owner: SeedPrimitivesSignatureAccountId20 } ``` ### Destroyed An asset class was destroyed. **Namespace** ``` api.events.assets.Destroyed ``` **Type** ``` type Destroyed = { asset_id: u32 } ``` ### ForceCreated Some asset class was force-created. **Namespace** ``` api.events.assets.ForceCreated ``` **Type** ``` type ForceCreated = { asset_id: u32, owner: SeedPrimitivesSignatureAccountId20 } ``` ### Frozen Some account `who` was frozen. **Namespace** ``` api.events.assets.Frozen ``` **Type** ``` type Frozen = { asset_id: u32, who: SeedPrimitivesSignatureAccountId20 } ``` ### Issued Some assets were issued. **Namespace** ``` api.events.assets.Issued ``` **Type** ``` type Issued = { asset_id: u32, owner: SeedPrimitivesSignatureAccountId20, total_supply: u128 } ``` ### MetadataCleared Metadata has been cleared for an asset. **Namespace** ``` api.events.assets.MetadataCleared ``` **Type** ``` type MetadataCleared = { asset_id: u32 } ``` ### MetadataSet New metadata has been set for an asset. **Namespace** ``` api.events.assets.MetadataSet ``` **Type** ``` type MetadataSet = { asset_id: u32, name: Bytes, symbol: Bytes, decimals: u8, is_frozen: bool } ``` ### OwnerChanged The owner changed. **Namespace** ``` api.events.assets.OwnerChanged ``` **Type** ``` type OwnerChanged = { asset_id: u32, owner: SeedPrimitivesSignatureAccountId20 } ``` ### TeamChanged The management team changed. **Namespace** ``` api.events.assets.TeamChanged ``` **Type** ``` type TeamChanged = { asset_id: u32, issuer: SeedPrimitivesSignatureAccountId20, admin: SeedPrimitivesSignatureAccountId20, freezer: SeedPrimitivesSignatureAccountId20 } ``` ### Thawed Some account `who` was thawed. **Namespace** ``` api.events.assets.Thawed ``` **Type** ``` type Thawed = { asset_id: u32, who: SeedPrimitivesSignatureAccountId20 } ``` ### Transferred Some assets were transferred. **Namespace** ``` api.events.assets.Transferred ``` **Type** ``` type Transferred = { asset_id: u32, from: SeedPrimitivesSignatureAccountId20, to: SeedPrimitivesSignatureAccountId20, amount: u128 } ``` ### TransferredApproved An `amount` was transferred in its entirety from `owner` to `destination` by the approved `delegate`. **Namespace** ``` api.events.assets.TransferredApproved ``` **Type** ``` type TransferredApproved = { asset_id: u32, owner: SeedPrimitivesSignatureAccountId20, delegate: SeedPrimitivesSignatureAccountId20, destination: SeedPrimitivesSignatureAccountId20, amount: u128 } ``` ## Errors ### AlreadyExists The asset-account already exists. **Namespace** ``` api.errors.assets.AlreadyExists ``` ### BadMetadata Invalid metadata given. **Namespace** ``` api.errors.assets.BadMetadata ``` ### BadWitness Invalid witness data given. **Namespace** ``` api.errors.assets.BadWitness ``` ### BalanceLow Account balance must be greater than or equal to the transfer amount. **Namespace** ``` api.errors.assets.BalanceLow ``` ### Frozen The origin account is frozen. **Namespace** ``` api.errors.assets.Frozen ``` ### InUse The asset ID is already taken. **Namespace** ``` api.errors.assets.InUse ``` ### MinBalanceZero Minimum balance should be non-zero. **Namespace** ``` api.errors.assets.MinBalanceZero ``` ### NoAccount The account to alter does not exist. **Namespace** ``` api.errors.assets.NoAccount ``` ### NoDeposit The asset-account doesn't have an associated deposit. **Namespace** ``` api.errors.assets.NoDeposit ``` ### NoPermission The signing account has no permission to do the operation. **Namespace** ``` api.errors.assets.NoPermission ``` ### NoProvider Unable to increment the consumer reference counters on the account. Either no provider reference exists to allow a non-zero balance of a non-self-sufficient asset, or the maximum number of consumers has been reached. **Namespace** ``` api.errors.assets.NoProvider ``` ### Unapproved No approval exists that would allow the transfer. **Namespace** ``` api.errors.assets.Unapproved ``` ### Unknown The given asset ID is unknown. **Namespace** ``` api.errors.assets.Unknown ``` ### WouldBurn The operation would result in funds being burned. **Namespace** ``` api.errors.assets.WouldBurn ``` ### WouldDie The source account would not survive the transfer and it needs to stay alive. **Namespace** ``` api.errors.assets.WouldDie ``` ## Constants ### approvalDeposit The amount of funds that must be reserved when creating a new approval. **Namespace** ``` api.consts.assets.approvalDeposit ``` **Type** ``` type approvalDeposit = u128 ``` ### assetAccountDeposit The amount of funds that must be reserved for a non-provider asset account to be maintained. **Namespace** ``` api.consts.assets.assetAccountDeposit ``` **Type** ``` type assetAccountDeposit = u128 ``` ### assetDeposit The basic amount of funds that must be reserved for an asset. **Namespace** ``` api.consts.assets.assetDeposit ``` **Type** ``` type assetDeposit = u128 ``` ### metadataDepositBase The basic amount of funds that must be reserved when adding metadata to your asset. **Namespace** ``` api.consts.assets.metadataDepositBase ``` **Type** ``` type metadataDepositBase = u128 ``` ### metadataDepositPerByte The additional funds that must be reserved for the number of bytes you store in your metadata. **Namespace** ``` api.consts.assets.metadataDepositPerByte ``` **Type** ``` type metadataDepositPerByte = u128 ``` ### stringLimit The maximum length of a name or symbol stored on-chain. **Namespace** ``` api.consts.assets.stringLimit ``` **Type** ``` type stringLimit = u32 ``` # AssetsExt Source: https://docs.therootnetwork.com/build/substrate/api-reference/runtime-pallets/assetsext ## Calls ### burnFrom Burns an asset from an account. Caller must be the asset owner Attempting to burn ROOT token will throw an error **Namespace** ``` api.tx.assetsExt.burnFrom ``` **Type** ``` function burnFrom( asset_id: u32, who: SeedPrimitivesSignatureAccountId20, amount: Compact ) ``` ### createAsset Creates a new asset with unique ID according to the network asset id scheme. **Namespace** ``` api.tx.assetsExt.createAsset ``` **Type** ``` function createAsset( name: Bytes, symbol: Bytes, decimals: u8, min_balance: Option, owner: Option ) ``` ### mint Mints an asset to an account if the caller is the asset owner Attempting to mint ROOT token will throw an error **Namespace** ``` api.tx.assetsExt.mint ``` **Type** ``` function mint( asset_id: u32, beneficiary: SeedPrimitivesSignatureAccountId20, amount: Compact ) ``` ### setAssetDeposit Sudo call to set the asset deposit for creating assets Note, this does not change the deposit when calling create within the assets pallet However that call is filtered **Namespace** ``` api.tx.assetsExt.setAssetDeposit ``` **Type** ``` function setAssetDeposit( asset_deposit: u128 ) ``` ### transfer Transfers either ROOT or an asset **Namespace** ``` api.tx.assetsExt.transfer ``` **Type** ``` function transfer( asset_id: u32, destination: SeedPrimitivesSignatureAccountId20, amount: Compact, keep_alive: bool ) ``` ## Storage ### assetDeposit The minimum deposit for creating an asset **Namespace** ``` api.query.assetsExt.assetDeposit ``` **Type** ``` function assetDeposit( ): u128 ``` ### holds The holdings of a specific account for a specific asset. **Namespace** ``` api.query.assetsExt.holds ``` **Type** ``` function holds( u32, SeedPrimitivesSignatureAccountId20 ): Vec<([u8;8],u128)> ``` ### nextAssetId The total units issued in the system. **Namespace** ``` api.query.assetsExt.nextAssetId ``` **Type** ``` function nextAssetId( ): u32 ``` ## Events ### AssetDepositSet The asset deposit was set **Namespace** ``` api.events.assetsExt.AssetDepositSet ``` **Type** ``` type AssetDepositSet = { asset_deposit: u128 } ``` ### CreateAsset New asset has been created **Namespace** ``` api.events.assetsExt.CreateAsset ``` **Type** ``` type CreateAsset = { asset_id: u32, creator: SeedPrimitivesSignatureAccountId20, initial_balance: u128 } ``` ### InternalDeposit Assets were deposited into this account by the system e.g. refunding gas **Namespace** ``` api.events.assetsExt.InternalDeposit ``` **Type** ``` type InternalDeposit = { asset_id: u32, who: SeedPrimitivesSignatureAccountId20, amount: u128 } ``` ### InternalWithdraw Assets were withdrawn from this account by the system e.g. paying tx fees **Namespace** ``` api.events.assetsExt.InternalWithdraw ``` **Type** ``` type InternalWithdraw = { asset_id: u32, who: SeedPrimitivesSignatureAccountId20, amount: u128 } ``` ### PlaceHold Some assets have been placed on hold by a pallet **Namespace** ``` api.events.assetsExt.PlaceHold ``` **Type** ``` type PlaceHold = { asset_id: u32, who: SeedPrimitivesSignatureAccountId20, amount: u128, pallet_id: [u8;8] } ``` ### ReleaseHold Some held assets have been released by a pallet **Namespace** ``` api.events.assetsExt.ReleaseHold ``` **Type** ``` type ReleaseHold = { asset_id: u32, who: SeedPrimitivesSignatureAccountId20, amount: u128, pallet_id: [u8;8] } ``` ### SpendHold Some held assets were spend by a pallet **Namespace** ``` api.events.assetsExt.SpendHold ``` **Type** ``` type SpendHold = { asset_id: u32, who: SeedPrimitivesSignatureAccountId20, spends: Vec<(SeedPrimitivesSignatureAccountId20,u128)>, pallet_id: [u8;8] } ``` ### SplitTransfer Multi-part transfer of assets from who **Namespace** ``` api.events.assetsExt.SplitTransfer ``` **Type** ``` type SplitTransfer = { asset_id: u32, who: SeedPrimitivesSignatureAccountId20, transfers: Vec<(SeedPrimitivesSignatureAccountId20,u128)> } ``` ## Errors ### BalanceLow Hold balance is less then the required amount **Namespace** ``` api.errors.assetsExt.BalanceLow ``` ### CreateAssetFailed Failed to create a new asset **Namespace** ``` api.errors.assetsExt.CreateAssetFailed ``` ### DecimalsTooHigh Decimals cannot be higher than 18 **Namespace** ``` api.errors.assetsExt.DecimalsTooHigh ``` ### MaxHolds Maximum holds placed on this asset/account pair **Namespace** ``` api.errors.assetsExt.MaxHolds ``` ### NoAccount The account to alter does not exist **Namespace** ``` api.errors.assetsExt.NoAccount ``` ### NoAvailableIds No more Ids are available, they've been exhausted **Namespace** ``` api.errors.assetsExt.NoAvailableIds ``` ### NoPermission The signer does not have permission to perform this action **Namespace** ``` api.errors.assetsExt.NoPermission ``` ### Overflow Operation would overflow **Namespace** ``` api.errors.assetsExt.Overflow ``` ## Constants ### maxHolds The maximum \* of holds per asset & account **Namespace** ``` api.consts.assetsExt.maxHolds ``` **Type** ``` type maxHolds = u32 ``` ### nativeAssetId The native token asset Id (managed by pallet-balances) **Namespace** ``` api.consts.assetsExt.nativeAssetId ``` **Type** ``` type nativeAssetId = u32 ``` ### palletId This pallet's Id, used for deriving a sovereign account ID **Namespace** ``` api.consts.assetsExt.palletId ``` **Type** ``` type palletId = FrameSupportPalletId ``` # Authorship Source: https://docs.therootnetwork.com/build/substrate/api-reference/runtime-pallets/authorship ## Calls ### setUncles Provide a set of uncles. **Namespace** ``` api.tx.authorship.setUncles ``` **Type** ``` function setUncles( new_uncles: Vec ) ``` ## Storage ### author Author of current block. **Namespace** ``` api.query.authorship.author ``` **Type** ``` function author( ): Option ``` ### didSetUncles Whether uncles were already set in this block. **Namespace** ``` api.query.authorship.didSetUncles ``` **Type** ``` function didSetUncles( ): bool ``` ### uncles Uncles **Namespace** ``` api.query.authorship.uncles ``` **Type** ``` function uncles( ): Vec ``` undefined## Errors ### GenesisUncle The uncle is genesis. **Namespace** ``` api.errors.authorship.GenesisUncle ``` ### InvalidUncleParent The uncle parent not in the chain. **Namespace** ``` api.errors.authorship.InvalidUncleParent ``` ### OldUncle The uncle isn't recent enough to be included. **Namespace** ``` api.errors.authorship.OldUncle ``` ### TooHighUncle The uncle is too high in chain. **Namespace** ``` api.errors.authorship.TooHighUncle ``` ### TooManyUncles Too many uncles. **Namespace** ``` api.errors.authorship.TooManyUncles ``` ### UncleAlreadyIncluded The uncle is already included. **Namespace** ``` api.errors.authorship.UncleAlreadyIncluded ``` ### UnclesAlreadySet Uncles already set in the block. **Namespace** ``` api.errors.authorship.UnclesAlreadySet ``` ## Constants ### uncleGenerations The number of blocks back we should accept uncles. This means that we will deal with uncle-parents that are `UncleGenerations + 1` before `now`. **Namespace** ``` api.consts.authorship.uncleGenerations ``` **Type** ``` type uncleGenerations = u32 ``` # Babe Source: https://docs.therootnetwork.com/build/substrate/api-reference/runtime-pallets/babe ## Calls ### planConfigChange Plan an epoch config change. The epoch config change is recorded and will be enacted on the next call to `enact_epoch_change`. The config will be activated one epoch after. Multiple calls to this method will replace any existing planned config change that had not been enacted yet. **Namespace** ``` api.tx.babe.planConfigChange ``` **Type** ``` function planConfigChange( config: SpConsensusBabeDigestsNextConfigDescriptor ) ``` ### reportEquivocation Report authority equivocation/misbehavior. This method will verify the equivocation proof and validate the given key ownership proof against the extracted offender. If both are valid, the offence will be reported. **Namespace** ``` api.tx.babe.reportEquivocation ``` **Type** ``` function reportEquivocation( equivocation_proof: SpConsensusSlotsEquivocationProof, key_owner_proof: SpSessionMembershipProof ) ``` ### reportEquivocationUnsigned Report authority equivocation/misbehavior. This method will verify the equivocation proof and validate the given key ownership proof against the extracted offender. If both are valid, the offence will be reported. This extrinsic must be called unsigned and it is expected that only block authors will call it (validated in `ValidateUnsigned`), as such if the block author is defined it will be defined as the equivocation reporter. **Namespace** ``` api.tx.babe.reportEquivocationUnsigned ``` **Type** ``` function reportEquivocationUnsigned( equivocation_proof: SpConsensusSlotsEquivocationProof, key_owner_proof: SpSessionMembershipProof ) ``` ## Storage ### authorities Current epoch authorities. **Namespace** ``` api.query.babe.authorities ``` **Type** ``` function authorities( ): Vec<(SpConsensusBabeAppPublic,u64)> ``` ### authorVrfRandomness This field should always be populated during block processing unless secondary plain slots are enabled (which don't contain a VRF output). It is set in `on_finalize`, before it will contain the value from the last block. **Namespace** ``` api.query.babe.authorVrfRandomness ``` **Type** ``` function authorVrfRandomness( ): Option<[u8;32]> ``` ### currentSlot Current slot number. **Namespace** ``` api.query.babe.currentSlot ``` **Type** ``` function currentSlot( ): u64 ``` ### epochConfig The configuration for the current epoch. Should never be `None` as it is initialized in genesis. **Namespace** ``` api.query.babe.epochConfig ``` **Type** ``` function epochConfig( ): Option ``` ### epochIndex Current epoch index. **Namespace** ``` api.query.babe.epochIndex ``` **Type** ``` function epochIndex( ): u64 ``` ### epochStart The block numbers when the last and current epoch have started, respectively `N-1` and `N`. NOTE: We track this is in order to annotate the block number when a given pool of entropy was fixed (i.e. it was known to chain observers). Since epochs are defined in slots, which may be skipped, the block numbers may not line up with the slot numbers. **Namespace** ``` api.query.babe.epochStart ``` **Type** ``` function epochStart( ): (u32,u32) ``` ### genesisSlot The slot at which the first epoch actually started. This is 0 until the first block of the chain. **Namespace** ``` api.query.babe.genesisSlot ``` **Type** ``` function genesisSlot( ): u64 ``` ### initialized Temporary value (cleared at block finalization) which is `Some` if per-block initialization has already been called for current block. **Namespace** ``` api.query.babe.initialized ``` **Type** ``` function initialized( ): Option> ``` ### lateness How late the current block is compared to its parent. This entry is populated as part of block execution and is cleaned up on block finalization. Querying this storage entry outside of block execution context should always yield zero. **Namespace** ``` api.query.babe.lateness ``` **Type** ``` function lateness( ): u32 ``` ### nextAuthorities Next epoch authorities. **Namespace** ``` api.query.babe.nextAuthorities ``` **Type** ``` function nextAuthorities( ): Vec<(SpConsensusBabeAppPublic,u64)> ``` ### nextEpochConfig The configuration for the next epoch, `None` if the config will not change (you can fallback to `EpochConfig` instead in that case). **Namespace** ``` api.query.babe.nextEpochConfig ``` **Type** ``` function nextEpochConfig( ): Option ``` ### nextRandomness Next epoch randomness. **Namespace** ``` api.query.babe.nextRandomness ``` **Type** ``` function nextRandomness( ): [u8;32] ``` ### pendingEpochConfigChange Pending epoch configuration change that will be applied when the next epoch is enacted. **Namespace** ``` api.query.babe.pendingEpochConfigChange ``` **Type** ``` function pendingEpochConfigChange( ): Option ``` ### randomness The epoch randomness for the *current* epoch. **Security** This MUST NOT be used for gambling, as it can be influenced by a malicious validator in the short term. It MAY be used in many cryptographic protocols, however, so long as one remembers that this (like everything else on-chain) it is public. For example, it can be used where a number is needed that cannot have been chosen by an adversary, for purposes such as public-coin zero-knowledge proofs. **Namespace** ``` api.query.babe.randomness ``` **Type** ``` function randomness( ): [u8;32] ``` ### segmentIndex Randomness under construction. We make a trade-off between storage accesses and list length. We store the under-construction randomness in segments of up to `UNDER_CONSTRUCTION_SEGMENT_LENGTH`. Once a segment reaches this length, we begin the next one. We reset all segments and return to `0` at the beginning of every epoch. **Namespace** ``` api.query.babe.segmentIndex ``` **Type** ``` function segmentIndex( ): u32 ``` ### underConstruction TWOX-NOTE: `SegmentIndex` is an increasing integer, so this is okay. **Namespace** ``` api.query.babe.underConstruction ``` **Type** ``` function underConstruction( u32 ): Vec<[u8;32]> ``` undefined## Errors ### DuplicateOffenceReport A given equivocation report is valid but already previously reported. **Namespace** ``` api.errors.babe.DuplicateOffenceReport ``` ### InvalidConfiguration Submitted configuration is invalid. **Namespace** ``` api.errors.babe.InvalidConfiguration ``` ### InvalidEquivocationProof An equivocation proof provided as part of an equivocation report is invalid. **Namespace** ``` api.errors.babe.InvalidEquivocationProof ``` ### InvalidKeyOwnershipProof A key ownership proof provided as part of an equivocation report is invalid. **Namespace** ``` api.errors.babe.InvalidKeyOwnershipProof ``` ## Constants ### epochDuration The amount of time, in slots, that each epoch should last. NOTE: Currently it is not possible to change the epoch duration after the chain has started. Attempting to do so will brick block production. **Namespace** ``` api.consts.babe.epochDuration ``` **Type** ``` type epochDuration = u64 ``` ### expectedBlockTime The expected average block time at which BABE should be creating blocks. Since BABE is probabilistic it is not trivial to figure out what the expected average block time should be based on the slot duration and the security parameter `c` (where `1 - c` represents the probability of a slot being empty). **Namespace** ``` api.consts.babe.expectedBlockTime ``` **Type** ``` type expectedBlockTime = u64 ``` ### maxAuthorities Max number of authorities allowed **Namespace** ``` api.consts.babe.maxAuthorities ``` **Type** ``` type maxAuthorities = u32 ``` ## JSON-RPC Methods ### `epochAuthorship` Returns data about which slots (primary or secondary) can be claimed in the current epoch with the keys in the keystore. **Info**: This method is only active with appropriate flags. **Interface** ``` api.rpc.babe.epochAuthorship(): HashMap ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"babe_epochAuthorship", "params":[] } ``` # Balances Source: https://docs.therootnetwork.com/build/substrate/api-reference/runtime-pallets/balances ## Calls ### forceTransfer Exactly as `transfer`, except the origin must be root and the source account may be specified. **Namespace** ``` api.tx.balances.forceTransfer ``` **Type** ``` function forceTransfer( source: SeedPrimitivesSignatureAccountId20, dest: SeedPrimitivesSignatureAccountId20, value: Compact ) ``` ### forceUnreserve Unreserve some balance from a user by force. Can only be called by ROOT. **Namespace** ``` api.tx.balances.forceUnreserve ``` **Type** ``` function forceUnreserve( who: SeedPrimitivesSignatureAccountId20, amount: u128 ) ``` ### setBalance Set the balances of a given account. This will alter `FreeBalance` and `ReservedBalance` in storage. it will also alter the total issuance of the system (`TotalIssuance`) appropriately. If the new free or reserved balance is below the existential deposit, it will reset the account nonce (`frame_system::AccountNonce`). The dispatch origin for this call is `root`. **Namespace** ``` api.tx.balances.setBalance ``` **Type** ``` function setBalance( who: SeedPrimitivesSignatureAccountId20, new_free: Compact, new_reserved: Compact ) ``` ### transfer Transfer some liquid-free balance to another account. `transfer` will set the `FreeBalance` of the sender and receiver. If the sender's account is below the existential deposit as a result of the transfer, the account will be reaped. The dispatch origin for this call must be `Signed` by the transactor. **Namespace** ``` api.tx.balances.transfer ``` **Type** ``` function transfer( dest: SeedPrimitivesSignatureAccountId20, value: Compact ) ``` ### transferAll Transfer the entire transferable balance from the caller account. NOTE: This function only attempts to transfer *transferable* balances. This means that any locked, reserved, or existential deposits (when `keep_alive` is `true`), will not be transferred by this function. To ensure that this function results in a killed account, you might need to prepare the account by removing any reference counters, storage deposits, etc. The dispatch origin of this call must be Signed. * `dest`: The recipient of the transfer. * `keep_alive`: A boolean to determine if the `transfer_all` operation should send all of the funds the account has, causing the sender account to be killed (false), or transfer everything except at least the existential deposit, which will guarantee to keep the sender account alive (true). # **Namespace** ``` api.tx.balances.transferAll ``` **Type** ``` function transferAll( dest: SeedPrimitivesSignatureAccountId20, keep_alive: bool ) ``` ### transferKeepAlive Same as the `transfer` call, but with a check that the transfer will not kill the origin account. 99% of the time you want `transfer` instead. **Namespace** ``` api.tx.balances.transferKeepAlive ``` **Type** ``` function transferKeepAlive( dest: SeedPrimitivesSignatureAccountId20, value: Compact ) ``` ## Storage ### account The Balances pallet example of storing the balance of an account. **Example** `nocompile impl pallet_balances::Config for Runtime { type AccountStore = StorageMapShim, frame_system::Provider, AccountId, Self::AccountData> }` You can also store the balance of an account in the `System` pallet. **Example** `nocompile impl pallet_balances::Config for Runtime { type AccountStore = System }` But this comes with tradeoffs, storing account balances in the system pallet stores `frame_system` data alongside the account data contrary to storing account balances in the `Balances` pallet, which uses a `StorageMap` to store balances data only. NOTE: This is only used in the case that this pallet is used to store balances. **Namespace** ``` api.query.balances.account ``` **Type** ``` function account( SeedPrimitivesSignatureAccountId20 ): PalletBalancesAccountData ``` ### locks Any liquidity locks on some account balances. NOTE: Should only be accessed when setting, changing and freeing a lock. **Namespace** ``` api.query.balances.locks ``` **Type** ``` function locks( SeedPrimitivesSignatureAccountId20 ): Vec ``` ### reserves Named reserves on some account balances. **Namespace** ``` api.query.balances.reserves ``` **Type** ``` function reserves( SeedPrimitivesSignatureAccountId20 ): Vec ``` ### storageVersion Storage version of the pallet. This is set to v2.0.0 for new networks. **Namespace** ``` api.query.balances.storageVersion ``` **Type** ``` function storageVersion( ): PalletBalancesReleases ``` ### totalIssuance The total units issued in the system. **Namespace** ``` api.query.balances.totalIssuance ``` **Type** ``` function totalIssuance( ): u128 ``` ## Events ### BalanceSet A balance was set by root. **Namespace** ``` api.events.balances.BalanceSet ``` **Type** ``` type BalanceSet = { who: SeedPrimitivesSignatureAccountId20, free: u128, reserved: u128 } ``` ### Deposit Some amount was deposited (e.g. for transaction fees). **Namespace** ``` api.events.balances.Deposit ``` **Type** ``` type Deposit = { who: SeedPrimitivesSignatureAccountId20, amount: u128 } ``` ### DustLost An account was removed whose balance was non-zero but below ExistentialDeposit, resulting in an outright loss. **Namespace** ``` api.events.balances.DustLost ``` **Type** ``` type DustLost = { account: SeedPrimitivesSignatureAccountId20, amount: u128 } ``` ### Endowed An account was created with some free balance. **Namespace** ``` api.events.balances.Endowed ``` **Type** ``` type Endowed = { account: SeedPrimitivesSignatureAccountId20, free_balance: u128 } ``` ### Reserved Some balance was reserved (moved from free to reserved). **Namespace** ``` api.events.balances.Reserved ``` **Type** ``` type Reserved = { who: SeedPrimitivesSignatureAccountId20, amount: u128 } ``` ### ReserveRepatriated Some balance was moved from the reserve of the first account to the second account. Final argument indicates the destination balance type. **Namespace** ``` api.events.balances.ReserveRepatriated ``` **Type** ``` type ReserveRepatriated = { from: SeedPrimitivesSignatureAccountId20, to: SeedPrimitivesSignatureAccountId20, amount: u128, destination_status: FrameSupportTokensMiscBalanceStatus } ``` ### Slashed Some amount was removed from the account (e.g. for misbehavior). **Namespace** ``` api.events.balances.Slashed ``` **Type** ``` type Slashed = { who: SeedPrimitivesSignatureAccountId20, amount: u128 } ``` ### Transfer Transfer succeeded. **Namespace** ``` api.events.balances.Transfer ``` **Type** ``` type Transfer = { from: SeedPrimitivesSignatureAccountId20, to: SeedPrimitivesSignatureAccountId20, amount: u128 } ``` ### Unreserved Some balance was unreserved (moved from reserved to free). **Namespace** ``` api.events.balances.Unreserved ``` **Type** ``` type Unreserved = { who: SeedPrimitivesSignatureAccountId20, amount: u128 } ``` ### Withdraw Some amount was withdrawn from the account (e.g. for transaction fees). **Namespace** ``` api.events.balances.Withdraw ``` **Type** ``` type Withdraw = { who: SeedPrimitivesSignatureAccountId20, amount: u128 } ``` ## Errors ### DeadAccount Beneficiary account must pre-exist **Namespace** ``` api.errors.balances.DeadAccount ``` ### ExistentialDeposit Value too low to create account due to existential deposit **Namespace** ``` api.errors.balances.ExistentialDeposit ``` ### ExistingVestingSchedule A vesting schedule already exists for this account **Namespace** ``` api.errors.balances.ExistingVestingSchedule ``` ### InsufficientBalance Balance too low to send value **Namespace** ``` api.errors.balances.InsufficientBalance ``` ### KeepAlive Transfer/payment would kill account **Namespace** ``` api.errors.balances.KeepAlive ``` ### LiquidityRestrictions Account liquidity restrictions prevent withdrawal **Namespace** ``` api.errors.balances.LiquidityRestrictions ``` ### TooManyReserves Number of named reserves exceed MaxReserves **Namespace** ``` api.errors.balances.TooManyReserves ``` ### VestingBalance Vesting balance too high to send value **Namespace** ``` api.errors.balances.VestingBalance ``` ## Constants ### existentialDeposit The minimum amount required to keep an account open. **Namespace** ``` api.consts.balances.existentialDeposit ``` **Type** ``` type existentialDeposit = u128 ``` ### maxLocks The maximum number of locks that should exist on an account. Not strictly enforced, but used for weight estimation. **Namespace** ``` api.consts.balances.maxLocks ``` **Type** ``` type maxLocks = u32 ``` ### maxReserves The maximum number of named reserves that can exist on an account. **Namespace** ``` api.consts.balances.maxReserves ``` **Type** ``` type maxReserves = u32 ``` # Dex Source: https://docs.therootnetwork.com/build/substrate/api-reference/runtime-pallets/dex ## Calls ### addLiquidity Add liquidity to Enabled trading pair, or add provision to Provisioning trading pair. * Add liquidity success will issue shares in current price which decided by the liquidity scale. Shares are temporarily not allowed to transfer and trade, it represents the proportion of assets in liquidity pool. * Add provision success will record the provision, issue shares to caller in the initial price when trading pair convert to Enabled. * Creates and enables TradingPair LP token if it does not exist for trading pair. * Fails to add liquidity for `NotEnabled` trading pair. * `token_a`: Asset id A. * `token_b`: Asset id B. * `amount_a_desired`: amount a desired to add. * `amount_b_desired`: amount b desired to add. * `amount_a_min`: amount a minimum willing to add. * `amount_b_min`: amount b minimum willing to add. * `to`: The recipient of the LP token. The caller is the default recipient if it is set to None. * `deadline`: The deadline of executing this extrinsic. The deadline won't be checked if it is set to None **Namespace** ``` api.tx.dex.addLiquidity ``` **Type** ``` function addLiquidity( token_a: u32, token_b: u32, amount_a_desired: Compact, amount_b_desired: Compact, amount_a_min: Compact, amount_b_min: Compact, to: Option, deadline: Option ) ``` ### disableTradingPair Disable an `Enabled` trading pair. * Requires LP token to be created and in the `Enabled` status * Only root can disable trading pair * `token_a`: Asset id A. * `token_b`: Asset id B. **Namespace** ``` api.tx.dex.disableTradingPair ``` **Type** ``` function disableTradingPair( token_a: u32, token_b: u32 ) ``` ### reenableTradingPair Re enable a `NotEnabled` trading pair. * Requires LP token to be created and in the `NotEnabled` status * Only root can enable a disabled trading pair * `token_a`: Asset id A. * `token_b`: Asset id B. **Namespace** ``` api.tx.dex.reenableTradingPair ``` **Type** ``` function reenableTradingPair( token_a: u32, token_b: u32 ) ``` ### removeLiquidity Remove liquidity from specific liquidity pool in the form of burning shares, and withdrawing currencies in trading pairs from liquidity pool in proportion, and withdraw liquidity incentive interest. * note: liquidity can still be withdrawn for `NotEnabled` trading pairs. * `token_a`: Asset id A. * `token_b`: Asset id B. * `liquidity`: liquidity amount to remove. * `amount_a_min`: minimum amount of asset A to be withdrawn from LP token. * `amount_b_min`: minimum amount of asset B to be withdrawn from LP token. * `to`: The recipient of the withdrawn token assets. The caller is the default recipient if it is set to None. * `deadline`: The deadline of executing this extrinsic. The deadline won't be checked if it is set to None **Namespace** ``` api.tx.dex.removeLiquidity ``` **Type** ``` function removeLiquidity( token_a: u32, token_b: u32, liquidity: Compact, amount_a_min: Compact, amount_b_min: Compact, to: Option, deadline: Option ) ``` ### setFeeTo Set the `FeeTo` account. This operation requires root access. * note: analogous to Uniswapv2 `setFeeTo` * `fee_to`: the new account or None assigned to FeeTo. **Namespace** ``` api.tx.dex.setFeeTo ``` **Type** ``` function setFeeTo( fee_to: Option ) ``` ### swapWithExactSupply Trading with DEX, swap with exact supply amount. Specify your input; retrieve variable output. * note: analogous to Uniswapv2 `swapExactTokensForTokens` * `path`: trading path. * `amount_in`: exact supply amount. * `amount_out_min`: acceptable minimum target amount. * `to`: The recipient of the swapped token asset. The caller is the default recipient if it is set to None. * `deadline`: The deadline of executing this extrinsic. The deadline won't be checked if it is set to None **Namespace** ``` api.tx.dex.swapWithExactSupply ``` **Type** ``` function swapWithExactSupply( amount_in: Compact, amount_out_min: Compact, path: Vec, to: Option, deadline: Option ) ``` ### swapWithExactTarget Trading with DEX, swap with exact target amount. Specify your output; supply variable input. * note: analogous to Uniswapv2 `swapTokensForExactTokens` * `amount_out`: exact target amount. * `amount_in_max`: acceptable maximum supply amount. * `path`: trading path. * `to`: The recipient of the swapped token asset. The caller is the default recipient if it is set to None. * `deadline`: The deadline of executing this extrinsic. The deadline won't be checked if it is set to None **Namespace** ``` api.tx.dex.swapWithExactTarget ``` **Type** ``` function swapWithExactTarget( amount_out: Compact, amount_in_max: Compact, path: Vec, to: Option, deadline: Option ) ``` ## Storage ### feeTo FeeTo account where network fees are deposited **Namespace** ``` api.query.dex.feeTo ``` **Type** ``` function feeTo( ): Option ``` ### liquidityPool **Namespace** ``` api.query.dex.liquidityPool ``` **Type** ``` function liquidityPool( PalletDexTradingPair ): (u128,u128) ``` ### liquidityPoolLastK **Namespace** ``` api.query.dex.liquidityPoolLastK ``` **Type** ``` function liquidityPoolLastK( u32 ): U256 ``` ### tradingPairLPToken **Namespace** ``` api.query.dex.tradingPairLPToken ``` **Type** ``` function tradingPairLPToken( PalletDexTradingPair ): Option ``` ### tradingPairStatuses **Namespace** ``` api.query.dex.tradingPairStatuses ``` **Type** ``` function tradingPairStatuses( PalletDexTradingPair ): PalletDexTradingPairStatus ``` ## Events ### AddLiquidity Add liquidity success. \[who, asset\_id\_0, reserve\_0\_increment, asset\_id\_1, reserve\_1\_increment, share\_increment, to] **Namespace** ``` api.events.dex.AddLiquidity ``` **Type** ``` type AddLiquidity = { param0: SeedPrimitivesSignatureAccountId20, param1: u32, param2: u128, param3: u32, param4: u128, param5: u128, param6: SeedPrimitivesSignatureAccountId20 } ``` ### AddProvision Add provision success. \[who, asset\_id\_0, contribution\_0, asset\_id\_1, contribution\_1] **Namespace** ``` api.events.dex.AddProvision ``` **Type** ``` type AddProvision = { param0: SeedPrimitivesSignatureAccountId20, param1: u32, param2: u128, param3: u32, param4: u128 } ``` ### DisableTradingPair Disable trading pair. \[trading\_pair] **Namespace** ``` api.events.dex.DisableTradingPair ``` **Type** ``` type DisableTradingPair = { param0: PalletDexTradingPair } ``` ### EnableTradingPair Enable trading pair. \[trading\_pair] **Namespace** ``` api.events.dex.EnableTradingPair ``` **Type** ``` type EnableTradingPair = { param0: PalletDexTradingPair } ``` ### FeeToSet Set FeeTo account success. \[fee\_to] **Namespace** ``` api.events.dex.FeeToSet ``` **Type** ``` type FeeToSet = { param0: Option } ``` ### ProvisioningToEnabled Provisioning trading pair convert to Enabled. \[trading\_pair, pool\_0\_amount, pool\_1\_amount, total\_share\_amount] **Namespace** ``` api.events.dex.ProvisioningToEnabled ``` **Type** ``` type ProvisioningToEnabled = { param0: PalletDexTradingPair, param1: u128, param2: u128, param3: u128 } ``` ### RemoveLiquidity Remove liquidity from the trading pool success. \[who, asset\_id\_0, reserve\_0\_decrement, asset\_id\_1, reserve\_1\_decrement, share\_decrement, to] **Namespace** ``` api.events.dex.RemoveLiquidity ``` **Type** ``` type RemoveLiquidity = { param0: SeedPrimitivesSignatureAccountId20, param1: u32, param2: u128, param3: u32, param4: u128, param5: u128, param6: SeedPrimitivesSignatureAccountId20 } ``` ### Swap Use supply Asset to swap target Asset. \[trader, trading\_path, supply\_Asset\_amount, target\_Asset\_amount, to] **Namespace** ``` api.events.dex.Swap ``` **Type** ``` type Swap = { param0: SeedPrimitivesSignatureAccountId20, param1: Vec, param2: u128, param3: u128, param4: SeedPrimitivesSignatureAccountId20 } ``` ## Errors ### ExcessiveSupplyAmount Supply amount is more than max\_supply\_amount **Namespace** ``` api.errors.dex.ExcessiveSupplyAmount ``` ### ExpiredDeadline The deadline has been missed **Namespace** ``` api.errors.dex.ExpiredDeadline ``` ### IdenticalTokenAddress **Namespace** ``` api.errors.dex.IdenticalTokenAddress ``` ### InsufficientAmount Insufficent amount **Namespace** ``` api.errors.dex.InsufficientAmount ``` ### InsufficientAmountA Insufficient asset\_a liquidity amount **Namespace** ``` api.errors.dex.InsufficientAmountA ``` ### InsufficientAmountB Insufficient asset\_b liquidity amount **Namespace** ``` api.errors.dex.InsufficientAmountB ``` ### InsufficientInputAmount Insufficient input amount **Namespace** ``` api.errors.dex.InsufficientInputAmount ``` ### InsufficientLiquidity Liquidity is not enough **Namespace** ``` api.errors.dex.InsufficientLiquidity ``` ### InsufficientLiquidityBurnt Insufficient liquidity burnt **Namespace** ``` api.errors.dex.InsufficientLiquidityBurnt ``` ### InsufficientOutputAmount Insufficient output amount **Namespace** ``` api.errors.dex.InsufficientOutputAmount ``` ### InsufficientTargetAmount Target amount is less to min\_target\_amount **Namespace** ``` api.errors.dex.InsufficientTargetAmount ``` ### InsufficientWithdrawnAmountA Insufficient withdraw amount for token A **Namespace** ``` api.errors.dex.InsufficientWithdrawnAmountA ``` ### InsufficientWithdrawnAmountB Insufficient withdraw amount for token B **Namespace** ``` api.errors.dex.InsufficientWithdrawnAmountB ``` ### InvalidAssetId Invalid Asset id **Namespace** ``` api.errors.dex.InvalidAssetId ``` ### InvalidConstantProduct Invalid constant product K **Namespace** ``` api.errors.dex.InvalidConstantProduct ``` ### InvalidInputAmounts Must provide non-zero amount of liquidity **Namespace** ``` api.errors.dex.InvalidInputAmounts ``` ### InvalidLiquidityIncrement The increment of liquidity is invalid **Namespace** ``` api.errors.dex.InvalidLiquidityIncrement ``` ### InvalidTradingPathLength Invalid trading path length **Namespace** ``` api.errors.dex.InvalidTradingPathLength ``` ### LiquidityProviderTokenNotCreated The Liquidity Provider token does not exist **Namespace** ``` api.errors.dex.LiquidityProviderTokenNotCreated ``` ### MustBeEnabled Trading pair must be in Enabled status **Namespace** ``` api.errors.dex.MustBeEnabled ``` ### MustBeNotEnabled Trading pair must be in NotEnabled status **Namespace** ``` api.errors.dex.MustBeNotEnabled ``` ### ZeroSupplyAmount The supply amount is zero **Namespace** ``` api.errors.dex.ZeroSupplyAmount ``` ### ZeroTargetAmount The target amount is zero **Namespace** ``` api.errors.dex.ZeroTargetAmount ``` ## Constants ### defaultFeeTo The default FeeTo account **Namespace** ``` api.consts.dex.defaultFeeTo ``` **Type** ``` type defaultFeeTo = Option ``` ### dexBurnPalletId The DEX's burn id, to provide for a redundant, unredeemable minter/burner address. **Namespace** ``` api.consts.dex.dexBurnPalletId ``` **Type** ``` type dexBurnPalletId = FrameSupportPalletId ``` ### getExchangeFee Trading fee rate The first item of the tuple is the numerator of the fee rate, second item is the denominator, fee\_rate = numerator / denominator, use (u32, u32) over `Rate` type to minimize internal division operation. **Namespace** ``` api.consts.dex.getExchangeFee ``` **Type** ``` type getExchangeFee = (u32,u32) ``` ### lpTokenDecimals Liquidity pair default token decimals **Namespace** ``` api.consts.dex.lpTokenDecimals ``` **Type** ``` type lpTokenDecimals = u8 ``` ### tradingPathLimit The limit for length of trading path **Namespace** ``` api.consts.dex.tradingPathLimit ``` **Type** ``` type tradingPathLimit = u32 ``` ## JSON-RPC Methods ### `getAmountsIn` Given an array of AssetIds, return amounts in for an amount out **Interface** ``` api.rpc.dex.getAmountsIn(amountOut: u128, path: Vec): Json ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"dex_getAmountsIn", "params":[amountOut: u128, path: Vec] } ``` ### `getAmountsOut` Given an array of AssetIds, return amounts out for an amount in **Interface** ``` api.rpc.dex.getAmountsOut(amountIn: u128, path: Vec): Json ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"dex_getAmountsOut", "params":[amountIn: u128, path: Vec] } ``` ### `getLPTokenID` Given two AssetIds, return liquidity token created for the pair **Interface** ``` api.rpc.dex.getLPTokenID(assetA: AssetId, assetB: AssetId): Json ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"dex_getLPTokenID", "params":[assetA: AssetId, assetB: AssetId] } ``` ### `getLiquidity` Given two AssetIds, return liquidity **Interface** ``` api.rpc.dex.getLiquidity(assetA: AssetId, assetB: AssetId): Json ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"dex_getLiquidity", "params":[assetA: AssetId, assetB: AssetId] } ``` ### `getTradingPairStatus` Given two AssetIds, return whether trading pair is enabled or disabled **Interface** ``` api.rpc.dex.getTradingPairStatus(assetA: AssetId, assetB: AssetId): Text ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"dex_getTradingPairStatus", "params":[assetA: AssetId, assetB: AssetId] } ``` ### `quote` Given some amount of an asset and pair reserves, returns an equivalent amount of the other asset **Interface** ``` api.rpc.dex.quote(amountA: u128, reserveA: u128, reserveB: u128): Json ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"dex_quote", "params":[amountA: u128, reserveA: u128, reserveB: u128] } ``` # Echo Source: https://docs.therootnetwork.com/build/substrate/api-reference/runtime-pallets/echo ## Calls ### ping Ping extrinsic sends an event to the bridge containing a message **Namespace** ``` api.tx.echo.ping ``` **Type** ``` function ping( destination: H160 ) ``` ## Storage ### nextSessionId The next available offer\_id **Namespace** ``` api.query.echo.nextSessionId ``` **Type** ``` function nextSessionId( ): u64 ``` ## Events ### PingReceived A ping was received from Ethereum **Namespace** ``` api.events.echo.PingReceived ``` **Type** ``` type PingReceived = { session_id: u64, source: H160, data: Bytes } ``` ### PingSent A ping message was sent to Ethereum **Namespace** ``` api.events.echo.PingSent ``` **Type** ``` type PingSent = { session_id: u64, source: H160, destination: H160, event_proof_id: u64 } ``` ### PongReceived A pong response was received from Ethereum **Namespace** ``` api.events.echo.PongReceived ``` **Type** ``` type PongReceived = { session_id: u64, source: H160, data: Bytes } ``` ### PongSent A pong message was sent to Ethereum **Namespace** ``` api.events.echo.PongSent ``` **Type** ``` type PongSent = { session_id: u64, source: H160, destination: H160, event_proof_id: u64 } ``` ## Errors ### InvalidAbiEncoding The abi received does not match the encoding scheme **Namespace** ``` api.errors.echo.InvalidAbiEncoding ``` ### InvalidParameter Invalid ping\_or\_pong parameter, must be 0 or 1 **Namespace** ``` api.errors.echo.InvalidParameter ``` ### NoAvailableIds There are no remaining session ids **Namespace** ``` api.errors.echo.NoAvailableIds ``` ## Constants ### palletId This pallet's Id, used for deriving a sovereign account ID **Namespace** ``` api.consts.echo.palletId ``` **Type** ``` type palletId = FrameSupportPalletId ``` # ElectionProviderMultiPhase Source: https://docs.therootnetwork.com/build/substrate/api-reference/runtime-pallets/electionprovidermultiphase ## constraintsCalls ### governanceFallback Trigger the governance fallback. This can only be called when \[`Phase::Emergency`] is enabled, as an alternative to calling \[`Call::set_emergency_election_result`]. **Namespace** ``` api.tx.electionProviderMultiPhase.governanceFallback ``` **Type** ``` function governanceFallback( maybe_max_voters: Option, maybe_max_targets: Option ) ``` ### setEmergencyElectionResult Set a solution in the queue, to be handed out to the client of this pallet in the next call to `ElectionProvider::elect`. This can only be set by `T::ForceOrigin`, and only when the phase is `Emergency`. The solution is not checked for any feasibility and is assumed to be trustworthy, as any feasibility check itself can in principle cause the election process to fail (due to memory/weight constrains). **Namespace** ``` api.tx.electionProviderMultiPhase.setEmergencyElectionResult ``` **Type** ``` function setEmergencyElectionResult( supports: Vec<(SeedPrimitivesSignatureAccountId20,SpNposElectionsSupport)> ) ``` ### setMinimumUntrustedScore Set a new value for `MinimumUntrustedScore`. Dispatch origin must be aligned with `T::ForceOrigin`. This check can be turned off by setting the value to `None`. **Namespace** ``` api.tx.electionProviderMultiPhase.setMinimumUntrustedScore ``` **Type** ``` function setMinimumUntrustedScore( maybe_next_score: Option ) ``` ### submit Submit a solution for the signed phase. The dispatch origin for this call must be **signed**. The solution is potentially queued, based on the claimed score and processed at the end of the signed phase. A deposit is reserved and recorded for the solution. Based on the outcome, the solution might be rewarded, slashed, or get all or a part of the deposit back. **Namespace** ``` api.tx.electionProviderMultiPhase.submit ``` **Type** ``` function submit( raw_solution: PalletElectionProviderMultiPhaseRawSolution ) ``` ### submitUnsigned Submit a solution for the unsigned phase. The dispatch origin for this call must be **none**. This submission is checked on the fly. Moreover, this unsigned solution is only validated when submitted to the pool from the **local** node. Effectively, this means that only active validators can submit this transaction when authoring a block (similar to an inherent). To prevent any incorrect solution (and thus wasted time/weight), this transaction will panic if the solution submitted by the validator is invalid in any way, effectively putting their authoring reward at risk. No deposit or reward is associated with this submission. **Namespace** ``` api.tx.electionProviderMultiPhase.submitUnsigned ``` **Type** ``` function submitUnsigned( raw_solution: PalletElectionProviderMultiPhaseRawSolution, witness: PalletElectionProviderMultiPhaseSolutionOrSnapshotSize ) ``` ## Storage ### currentPhase Current phase. **Namespace** ``` api.query.electionProviderMultiPhase.currentPhase ``` **Type** ``` function currentPhase( ): PalletElectionProviderMultiPhasePhase ``` ### desiredTargets Desired number of targets to elect for this round. Only exists when \[`Snapshot`] is present. **Namespace** ``` api.query.electionProviderMultiPhase.desiredTargets ``` **Type** ``` function desiredTargets( ): Option ``` ### minimumUntrustedScore The minimum score that each 'untrusted' solution must attain in order to be considered feasible. Can be set via `set_minimum_untrusted_score`. **Namespace** ``` api.query.electionProviderMultiPhase.minimumUntrustedScore ``` **Type** ``` function minimumUntrustedScore( ): Option ``` ### queuedSolution Current best solution, signed or unsigned, queued to be returned upon `elect`. **Namespace** ``` api.query.electionProviderMultiPhase.queuedSolution ``` **Type** ``` function queuedSolution( ): Option ``` ### round Internal counter for the number of rounds. This is useful for de-duplication of transactions submitted to the pool, and general diagnostics of the pallet. This is merely incremented once every time that an upstream `elect` is called. **Namespace** ``` api.query.electionProviderMultiPhase.round ``` **Type** ``` function round( ): u32 ``` ### signedSubmissionIndices A sorted, bounded set of `(score, index)`, where each `index` points to a value in `SignedSubmissions`. We never need to process more than a single signed submission at a time. Signed submissions can be quite large, so we're willing to pay the cost of multiple database accesses to access them one at a time instead of reading and decoding all of them at once. **Namespace** ``` api.query.electionProviderMultiPhase.signedSubmissionIndices ``` **Type** ``` function signedSubmissionIndices( ): BTreeMap ``` ### signedSubmissionNextIndex The next index is to be assigned to an incoming signed submission. Every accepted submission is assigned a unique index; that index is bound to that particular submission for the duration of the election. On election finalization, the next index is reset to 0. We can't just use `SignedSubmissionIndices.len()`, because that's a bounded set; past its capacity, it will simply saturate. We can't just iterate over `SignedSubmissionsMap`, because iteration is slow. Instead, we store the value here. **Namespace** ``` api.query.electionProviderMultiPhase.signedSubmissionNextIndex ``` **Type** ``` function signedSubmissionNextIndex( ): u32 ``` ### signedSubmissionsMap Unchecked, signed solutions. Together with `SubmissionIndices`, this stores a bounded set of `SignedSubmissions` while allowing us to keep only a single one in memory at a time. Twox note: the key of the map is an auto-incrementing index which users cannot inspect or affect; we shouldn't need a cryptographically secure hasher. **Namespace** ``` api.query.electionProviderMultiPhase.signedSubmissionsMap ``` **Type** ``` function signedSubmissionsMap( u32 ): Option ``` ### snapshot Snapshot data of the round. This is created at the beginning of the signed phase and cleared upon calling `elect`. **Namespace** ``` api.query.electionProviderMultiPhase.snapshot ``` **Type** ``` function snapshot( ): Option ``` ### snapshotMetadata The metadata of the \[`RoundSnapshot`] Only exists when \[`Snapshot`] is present. **Namespace** ``` api.query.electionProviderMultiPhase.snapshotMetadata ``` **Type** ``` function snapshotMetadata( ): Option ``` ## Events ### ElectionFailed An election failed. Not much can be said about which computes failed in the process. **Namespace** ``` api.events.electionProviderMultiPhase.ElectionFailed ``` **Type** ``` type ElectionFailed = { } ``` ### ElectionFinalized The election has been finalized, with the given computation and score. **Namespace** ``` api.events.electionProviderMultiPhase.ElectionFinalized ``` **Type** ``` type ElectionFinalized = { compute: PalletElectionProviderMultiPhaseElectionCompute, score: SpNposElectionsElectionScore } ``` ### Rewarded An account has been rewarded for their signed submission being finalized. **Namespace** ``` api.events.electionProviderMultiPhase.Rewarded ``` **Type** ``` type Rewarded = { account: SeedPrimitivesSignatureAccountId20, value: u128 } ``` ### SignedPhaseStarted The signed phase of the given round has started. **Namespace** ``` api.events.electionProviderMultiPhase.SignedPhaseStarted ``` **Type** ``` type SignedPhaseStarted = { round: u32 } ``` ### Slashed An account has been slashed for submitting an invalid signed submission. **Namespace** ``` api.events.electionProviderMultiPhase.Slashed ``` **Type** ``` type Slashed = { account: SeedPrimitivesSignatureAccountId20, value: u128 } ``` ### SolutionStored A solution was stored with the given compute. If the solution is signed, this means that it hasn't yet been processed. If the solution is unsigned, this means that it has also been processed. The `bool` is `true` when a previous solution was ejected to make room for this one. **Namespace** ``` api.events.electionProviderMultiPhase.SolutionStored ``` **Type** ``` type SolutionStored = { compute: PalletElectionProviderMultiPhaseElectionCompute, prev_ejected: bool } ``` ### UnsignedPhaseStarted The unsigned phase of the given round has started. **Namespace** ``` api.events.electionProviderMultiPhase.UnsignedPhaseStarted ``` **Type** ``` type UnsignedPhaseStarted = { round: u32 } ``` ## Errors ### CallNotAllowed The call is not allowed at this point. **Namespace** ``` api.errors.electionProviderMultiPhase.CallNotAllowed ``` ### FallbackFailed The fallback failed **Namespace** ``` api.errors.electionProviderMultiPhase.FallbackFailed ``` ### InvalidSubmissionIndex `Self::insert_submission` returned an invalid index. **Namespace** ``` api.errors.electionProviderMultiPhase.InvalidSubmissionIndex ``` ### MissingSnapshotMetadata Snapshot metadata should exist but didn't. **Namespace** ``` api.errors.electionProviderMultiPhase.MissingSnapshotMetadata ``` ### OcwCallWrongEra OCW submitted solution for wrong round **Namespace** ``` api.errors.electionProviderMultiPhase.OcwCallWrongEra ``` ### PreDispatchEarlySubmission Submission was too early. **Namespace** ``` api.errors.electionProviderMultiPhase.PreDispatchEarlySubmission ``` ### PreDispatchWeakSubmission Submission was too weak, score-wise. **Namespace** ``` api.errors.electionProviderMultiPhase.PreDispatchWeakSubmission ``` ### PreDispatchWrongWinnerCount Wrong number of winners presented. **Namespace** ``` api.errors.electionProviderMultiPhase.PreDispatchWrongWinnerCount ``` ### SignedCannotPayDeposit The origin failed to pay the deposit. **Namespace** ``` api.errors.electionProviderMultiPhase.SignedCannotPayDeposit ``` ### SignedInvalidWitness Witness data to dispatchable is invalid. **Namespace** ``` api.errors.electionProviderMultiPhase.SignedInvalidWitness ``` ### SignedQueueFull The queue was full, and the solution was not better than any of the existing ones. **Namespace** ``` api.errors.electionProviderMultiPhase.SignedQueueFull ``` ### SignedTooMuchWeight The signed submission consumes too much weight **Namespace** ``` api.errors.electionProviderMultiPhase.SignedTooMuchWeight ``` ## Constants ### betterSignedThreshold The minimum amount of improvement to the solution score that defines a solution as "better" in the Signed phase. **Namespace** ``` api.consts.electionProviderMultiPhase.betterSignedThreshold ``` **Type** ``` type betterSignedThreshold = Perbill ``` ### betterUnsignedThreshold The minimum amount of improvement to the solution score that defines a solution as "better" in the Unsigned phase. **Namespace** ``` api.consts.electionProviderMultiPhase.betterUnsignedThreshold ``` **Type** ``` type betterUnsignedThreshold = Perbill ``` ### maxElectableTargets The maximum number of electable targets to put in the snapshot. **Namespace** ``` api.consts.electionProviderMultiPhase.maxElectableTargets ``` **Type** ``` type maxElectableTargets = u16 ``` ### maxElectingVoters The maximum number of electing voters to put in the snapshot. At the moment, snapshots are only over a single block, but once multi-block elections are introduced they will take place over multiple blocks. **Namespace** ``` api.consts.electionProviderMultiPhase.maxElectingVoters ``` **Type** ``` type maxElectingVoters = u32 ``` ### minerMaxLength **Namespace** ``` api.consts.electionProviderMultiPhase.minerMaxLength ``` **Type** ``` type minerMaxLength = u32 ``` ### minerMaxVotesPerVoter **Namespace** ``` api.consts.electionProviderMultiPhase.minerMaxVotesPerVoter ``` **Type** ``` type minerMaxVotesPerVoter = u32 ``` ### minerMaxWeight **Namespace** ``` api.consts.electionProviderMultiPhase.minerMaxWeight ``` **Type** ``` type minerMaxWeight = WeightV1 ``` ### minerTxPriority The priority of the unsigned transaction submitted in the unsigned-phase **Namespace** ``` api.consts.electionProviderMultiPhase.minerTxPriority ``` **Type** ``` type minerTxPriority = u64 ``` ### offchainRepeat The repeat threshold of the offchain worker. For example, if it is 5, that means that at least 5 blocks will elapse between attempts to submit the worker's solution. **Namespace** ``` api.consts.electionProviderMultiPhase.offchainRepeat ``` **Type** ``` type offchainRepeat = u32 ``` ### signedDepositBase Base deposit for a signed solution. **Namespace** ``` api.consts.electionProviderMultiPhase.signedDepositBase ``` **Type** ``` type signedDepositBase = u128 ``` ### signedDepositByte Per-byte deposit for a signed solution. **Namespace** ``` api.consts.electionProviderMultiPhase.signedDepositByte ``` **Type** ``` type signedDepositByte = u128 ``` ### signedDepositWeight Per-weight deposit for a signed solution. **Namespace** ``` api.consts.electionProviderMultiPhase.signedDepositWeight ``` **Type** ``` type signedDepositWeight = u128 ``` ### signedMaxRefunds The maximum amount of unchecked solutions to refund the call fee for. **Namespace** ``` api.consts.electionProviderMultiPhase.signedMaxRefunds ``` **Type** ``` type signedMaxRefunds = u32 ``` ### signedMaxSubmissions Maximum number of signed submissions that can be queued. It is best to avoid adjusting this during an election, as it impacts downstream data structures. In particular, `SignedSubmissionIndices` is bounded on this value. If you update this value during an election, you *must* ensure that `SignedSubmissionIndices.len()` is less than or equal to the new value. Otherwise, attempts to submit new solutions may cause a runtime panic. **Namespace** ``` api.consts.electionProviderMultiPhase.signedMaxSubmissions ``` **Type** ``` type signedMaxSubmissions = u32 ``` ### signedMaxWeight Maximum weight of a signed solution. If \[`Config::MinerConfig`] is being implemented to submit signed solutions (outside of this pallet), then \[`MinerConfig::solution_weight`] is used to compare against this value. **Namespace** ``` api.consts.electionProviderMultiPhase.signedMaxWeight ``` **Type** ``` type signedMaxWeight = WeightV1 ``` ### signedPhase Duration of the signed phase. **Namespace** ``` api.consts.electionProviderMultiPhase.signedPhase ``` **Type** ``` type signedPhase = u32 ``` ### signedRewardBase Base reward for a signed solution **Namespace** ``` api.consts.electionProviderMultiPhase.signedRewardBase ``` **Type** ``` type signedRewardBase = u128 ``` ### unsignedPhase Duration of the unsigned phase. **Namespace** ``` api.consts.electionProviderMultiPhase.unsignedPhase ``` **Type** ``` type unsignedPhase = u32 ``` # Erc20Peg Source: https://docs.therootnetwork.com/build/substrate/api-reference/runtime-pallets/erc20peg ## Calls ### activateDeposits Activate/deactivate deposits (root only) **Namespace** ``` api.tx.erc20Peg.activateDeposits ``` **Type** ``` function activateDeposits( activate: bool ) ``` ### activateWithdrawals Activate/deactivate withdrawals (root only) **Namespace** ``` api.tx.erc20Peg.activateWithdrawals ``` **Type** ``` function activateWithdrawals( activate: bool ) ``` ### setErc20AssetMap **Namespace** ``` api.tx.erc20Peg.setErc20AssetMap ``` **Type** ``` function setErc20AssetMap( asset_id: u32, eth_address: H160 ) ``` ### setErc20Meta **Namespace** ``` api.tx.erc20Peg.setErc20Meta ``` **Type** ``` function setErc20Meta( details: Vec<(H160,Bytes,u8)> ) ``` ### setErc20PegAddress **Namespace** ``` api.tx.erc20Peg.setErc20PegAddress ``` **Type** ``` function setErc20PegAddress( eth_address: H160 ) ``` ### setPaymentDelay **Namespace** ``` api.tx.erc20Peg.setPaymentDelay ``` **Type** ``` function setPaymentDelay( asset_id: u32, min_balance: u128, delay: u32 ) ``` ### setRootPegAddress **Namespace** ``` api.tx.erc20Peg.setRootPegAddress ``` **Type** ``` function setRootPegAddress( eth_address: H160 ) ``` ### withdraw **Namespace** ``` api.tx.erc20Peg.withdraw ``` **Type** ``` function withdraw( asset_id: u32, amount: u128, beneficiary: H160 ) ``` ## Storage ### assetIdToErc20 Map GA asset Id to ERC20 address **Namespace** ``` api.query.erc20Peg.assetIdToErc20 ``` **Type** ``` function assetIdToErc20( u32 ): Option ``` ### contractAddress The peg contract address on Ethereum **Namespace** ``` api.query.erc20Peg.contractAddress ``` **Type** ``` function contractAddress( ): H160 ``` ### delayedPayments Map from DelayedPaymentId to PendingPayment **Namespace** ``` api.query.erc20Peg.delayedPayments ``` **Type** ``` function delayedPayments( u64 ): Option ``` ### delayedPaymentSchedule Map from block number to DelayedPaymentIds scheduled for that block **Namespace** ``` api.query.erc20Peg.delayedPaymentSchedule ``` **Type** ``` function delayedPaymentSchedule( u32 ): Vec ``` ### depositsActive Whether deposit are active **Namespace** ``` api.query.erc20Peg.depositsActive ``` **Type** ``` function depositsActive( ): bool ``` ### erc20Meta Metadata for well-known erc20 tokens (symbol, decimals) **Namespace** ``` api.query.erc20Peg.erc20Meta ``` **Type** ``` function erc20Meta( H160 ): Option<(Bytes,u8)> ``` ### erc20ToAssetId Map ERC20 address to GA asset Id **Namespace** ``` api.query.erc20Peg.erc20ToAssetId ``` **Type** ``` function erc20ToAssetId( H160 ): Option ``` ### nextDelayedPaymentId The next available payment id for withdrawals and deposits **Namespace** ``` api.query.erc20Peg.nextDelayedPaymentId ``` **Type** ``` function nextDelayedPaymentId( ): u64 ``` ### paymentDelay Map from asset\_id to minimum amount and delay **Namespace** ``` api.query.erc20Peg.paymentDelay ``` **Type** ``` function paymentDelay( u32 ): Option<(u128,u32)> ``` ### readyBlocks The blocks with payments that are ready to be processed **Namespace** ``` api.query.erc20Peg.readyBlocks ``` **Type** ``` function readyBlocks( ): Vec ``` ### rootPegContractAddress The ROOT peg contract address on Ethereum **Namespace** ``` api.query.erc20Peg.rootPegContractAddress ``` **Type** ``` function rootPegContractAddress( ): H160 ``` ### withdrawalsActive Whether withdrawals are active **Namespace** ``` api.query.erc20Peg.withdrawalsActive ``` **Type** ``` function withdrawalsActive( ): bool ``` ## Events ### DelayedErc20DepositFailed A delayed erc20 deposit has failed (payment\_id, beneficiary) **Namespace** ``` api.events.erc20Peg.DelayedErc20DepositFailed ``` **Type** ``` type DelayedErc20DepositFailed = { param0: u64, param1: SeedPrimitivesSignatureAccountId20 } ``` ### DelayedErc20WithdrawalFailed A delayed erc20 withdrawal has failed (asset\_id, beneficiary) **Namespace** ``` api.events.erc20Peg.DelayedErc20WithdrawalFailed ``` **Type** ``` type DelayedErc20WithdrawalFailed = { param0: u32, param1: H160 } ``` ### Erc20Deposit A bridged erc20 deposit succeeded. (asset, amount, beneficiary) **Namespace** ``` api.events.erc20Peg.Erc20Deposit ``` **Type** ``` type Erc20Deposit = { param0: u32, param1: u128, param2: SeedPrimitivesSignatureAccountId20 } ``` ### Erc20DepositDelayed An erc20 deposit has been delayed.(payment\_id, scheduled block, amount, beneficiary) **Namespace** ``` api.events.erc20Peg.Erc20DepositDelayed ``` **Type** ``` type Erc20DepositDelayed = { param0: u64, param1: u32, param2: u128, param3: SeedPrimitivesSignatureAccountId20 } ``` ### Erc20DepositFail A bridged erc20 deposit failed. (source address, abi data) **Namespace** ``` api.events.erc20Peg.Erc20DepositFail ``` **Type** ``` type Erc20DepositFail = { param0: H160, param1: Bytes } ``` ### Erc20Withdraw Tokens were burnt for withdrawal on Ethereum as ERC20s (asset, amount, beneficiary) **Namespace** ``` api.events.erc20Peg.Erc20Withdraw ``` **Type** ``` type Erc20Withdraw = { param0: u32, param1: u128, param2: H160 } ``` ### Erc20WithdrawalDelayed A withdrawal has been delayed.(payment\_id, scheduled block, amount, beneficiary) **Namespace** ``` api.events.erc20Peg.Erc20WithdrawalDelayed ``` **Type** ``` type Erc20WithdrawalDelayed = { param0: u64, param1: u32, param2: u128, param3: H160 } ``` ### NoAvailableDelayedPaymentIds There are no more payment ids available, they've been exhausted **Namespace** ``` api.events.erc20Peg.NoAvailableDelayedPaymentIds ``` **Type** ``` type NoAvailableDelayedPaymentIds = { } ``` ### PaymentDelaySet A delay was added for an asset\_id (asset\_id, min\_balance, delay) **Namespace** ``` api.events.erc20Peg.PaymentDelaySet ``` **Type** ``` type PaymentDelaySet = { param0: u32, param1: u128, param2: u32 } ``` ### SetContractAddress The peg contract address has been set **Namespace** ``` api.events.erc20Peg.SetContractAddress ``` **Type** ``` type SetContractAddress = { param0: H160 } ``` ### SetRootPegContract The ROOT peg contract address has been set **Namespace** ``` api.events.erc20Peg.SetRootPegContract ``` **Type** ``` type SetRootPegContract = { param0: H160 } ``` ## Errors ### CreateAssetFailed Could not create the bridged asset **Namespace** ``` api.errors.erc20Peg.CreateAssetFailed ``` ### DepositsPaused Deposits are inactive **Namespace** ``` api.errors.erc20Peg.DepositsPaused ``` ### EvmWithdrawalFailed Withdrawals over the set payment delay for EVM calls are disabled **Namespace** ``` api.errors.erc20Peg.EvmWithdrawalFailed ``` ### InvalidAbiEncoding The abi received does not match the encoding scheme **Namespace** ``` api.errors.erc20Peg.InvalidAbiEncoding ``` ### InvalidAmount Deposit has bad amount **Namespace** ``` api.errors.erc20Peg.InvalidAmount ``` ### InvalidPalletId Could not convert pallet id to account **Namespace** ``` api.errors.erc20Peg.InvalidPalletId ``` ### InvalidSourceAddress The peg source address is incorrect for the token being bridged **Namespace** ``` api.errors.erc20Peg.InvalidSourceAddress ``` ### UnsupportedAsset Withdrawals of this asset are not supported **Namespace** ``` api.errors.erc20Peg.UnsupportedAsset ``` ### WithdrawalsPaused Withdrawals are inactive **Namespace** ``` api.errors.erc20Peg.WithdrawalsPaused ``` undefined # EthBridge Source: https://docs.therootnetwork.com/build/substrate/api-reference/runtime-pallets/ethbridge ## Calls ## depositRelayerBond **Namespace** ``` api.tx.ethBridge.depositRelayerBond ``` **Type** ``` function depositRelayerBond( ) ``` ## finaliseAuthoritiesChange **Namespace** ``` api.tx.ethBridge.finaliseAuthoritiesChange ``` **Type** ``` function finaliseAuthoritiesChange( next_notary_keys: Vec ) ``` ## setBridgePaused **Namespace** ``` api.tx.ethBridge.setBridgePaused ``` **Type** ``` function setBridgePaused( paused: bool ) ``` ## setChallengePeriod **Namespace** ``` api.tx.ethBridge.setChallengePeriod ``` **Type** ``` function setChallengePeriod( blocks: u32 ) ``` ## setContractAddress **Namespace** ``` api.tx.ethBridge.setContractAddress ``` **Type** ``` function setContractAddress( contract_address: H160 ) ``` ## setDelayedEventProofsPerBlock **Namespace** ``` api.tx.ethBridge.setDelayedEventProofsPerBlock ``` **Type** ``` function setDelayedEventProofsPerBlock( count: u8 ) ``` ## setEventBlockConfirmations **Namespace** ``` api.tx.ethBridge.setEventBlockConfirmations ``` **Type** ``` function setEventBlockConfirmations( confirmations: u64 ) ``` ## setRelayer **Namespace** ``` api.tx.ethBridge.setRelayer ``` **Type** ``` function setRelayer( relayer: SeedPrimitivesSignatureAccountId20 ) ``` ## setXrplDoorSigners **Namespace** ``` api.tx.ethBridge.setXrplDoorSigners ``` **Type** ``` function setXrplDoorSigners( new_signers: Vec<(SeedPrimitivesEthyCryptoAppCryptoPublic,bool)> ) ``` ## submitChallenge **Namespace** ``` api.tx.ethBridge.submitChallenge ``` **Type** ``` function submitChallenge( event_claim_id: u64 ) ``` ## submitEvent **Namespace** ``` api.tx.ethBridge.submitEvent ``` **Type** ``` function submitEvent( tx_hash: H256, event: Bytes ) ``` ## submitNotarization **Namespace** ``` api.tx.ethBridge.submitNotarization ``` **Type** ``` function submitNotarization( payload: PalletEthyNotarizationPayload, _signature: SeedPrimitivesEthyCryptoAppCryptoSignature ) ``` ## withdrawRelayerBond **Namespace** ``` api.tx.ethBridge.withdrawRelayerBond ``` **Type** ``` function withdrawRelayerBond( ) ``` ## Storage ## authoritiesChangedThisEra Flag to indicate whether authorities have been changed during the current era **Namespace** ``` api.query.ethBridge.authoritiesChangedThisEra ``` **Type** ``` function authoritiesChangedThisEra( ): bool ``` ## bridgePaused Whether the bridge is paused (e.g. during validator transitions or by governance) **Namespace** ``` api.query.ethBridge.bridgePaused ``` **Type** ``` function bridgePaused( ): bool ``` ## challengePeriod The (optimistic) challenge period after which a submitted event is considered valid **Namespace** ``` api.query.ethBridge.challengePeriod ``` **Type** ``` function challengePeriod( ): u32 ``` ## challengerAccount Maps from event claim id to challenger and bond amount paid **Namespace** ``` api.query.ethBridge.challengerAccount ``` **Type** ``` function challengerAccount( u64 ): Option<(SeedPrimitivesSignatureAccountId20,u128)> ``` ## contractAddress The bridge contract address on Ethereum **Namespace** ``` api.query.ethBridge.contractAddress ``` **Type** ``` function contractAddress( ): H160 ``` ## delayedEventProofsPerBlock The maximum number of delayed events that can be processed in on\_initialize() **Namespace** ``` api.query.ethBridge.delayedEventProofsPerBlock ``` **Type** ``` function delayedEventProofsPerBlock( ): u8 ``` ## ethCallNotarizations EthCallOracle notarizations keyed by (Id, Notary) **Namespace** ``` api.query.ethBridge.ethCallNotarizations ``` **Type** ``` function ethCallNotarizations( u64, SeedPrimitivesEthyCryptoAppCryptoPublic ): Option ``` ## ethCallNotarizationsAggregated map from EthCallOracle notarizations to an aggregated count **Namespace** ``` api.query.ethBridge.ethCallNotarizationsAggregated ``` **Type** ``` function ethCallNotarizationsAggregated( u64 ): Option> ``` ## ethCallRequestInfo EthCallOracle request info **Namespace** ``` api.query.ethBridge.ethCallRequestInfo ``` **Type** ``` function ethCallRequestInfo( u64 ): Option ``` ## ethCallRequests Queue of pending EthCallOracle requests **Namespace** ``` api.query.ethBridge.ethCallRequests ``` **Type** ``` function ethCallRequests( ): Vec ``` ## eventBlockConfirmations The minimum number of block confirmations needed to notarize an Ethereum event **Namespace** ``` api.query.ethBridge.eventBlockConfirmations ``` **Type** ``` function eventBlockConfirmations( ): u64 ``` ## eventNotarizations Notarizations for queued events Either: None = no notarization exists OR Some(yay/nay) **Namespace** ``` api.query.ethBridge.eventNotarizations ``` **Type** ``` function eventNotarizations( u64, SeedPrimitivesEthyCryptoAppCryptoPublic ): Option ``` ## messagesValidAt Map from block number to list of EventClaims that will be considered valid and should be forwarded to handlers (i.e after the optimistic challenge period has passed without issue) **Namespace** ``` api.query.ethBridge.messagesValidAt ``` **Type** ``` function messagesValidAt( u32 ): Vec ``` ## nextAuthorityChange The block in which we process the next authority change **Namespace** ``` api.query.ethBridge.nextAuthorityChange ``` **Type** ``` function nextAuthorityChange( ): Option ``` ## nextEthCallId Subscription Id for EthCall requests **Namespace** ``` api.query.ethBridge.nextEthCallId ``` **Type** ``` function nextEthCallId( ): u64 ``` ## nextEventProofId Id of the next event proof **Namespace** ``` api.query.ethBridge.nextEventProofId ``` **Type** ``` function nextEventProofId( ): u64 ``` ## nextNotaryKeys Scheduled notary (validator) public keys for the next session **Namespace** ``` api.query.ethBridge.nextNotaryKeys ``` **Type** ``` function nextNotaryKeys( ): Vec ``` ## notaryKeys Active notary (validator) public keys **Namespace** ``` api.query.ethBridge.notaryKeys ``` **Type** ``` function notaryKeys( ): Vec ``` ## notarySetId The current validator set id **Namespace** ``` api.query.ethBridge.notarySetId ``` **Type** ``` function notarySetId( ): u64 ``` ## notarySetProofId The event proof Id generated by the previous validator set to notarize the current set. Useful for syncing the latest proof to Ethereum **Namespace** ``` api.query.ethBridge.notarySetProofId ``` **Type** ``` function notarySetProofId( ): u64 ``` ## notaryXrplKeys Active xrpl notary (validator) public keys **Namespace** ``` api.query.ethBridge.notaryXrplKeys ``` **Type** ``` function notaryXrplKeys( ): Vec ``` ## pendingClaimChallenges List of all event ids that are currently being challenged **Namespace** ``` api.query.ethBridge.pendingClaimChallenges ``` **Type** ``` function pendingClaimChallenges( ): Vec ``` ## pendingClaimStatus Status of pending event claims **Namespace** ``` api.query.ethBridge.pendingClaimStatus ``` **Type** ``` function pendingClaimStatus( u64 ): Option ``` ## pendingEventClaims Queued event claims, can be challenged within challenge period **Namespace** ``` api.query.ethBridge.pendingEventClaims ``` **Type** ``` function pendingEventClaims( u64 ): Option ``` ## pendingEventProofs Queued event proofs to be processed once bridge has been re-enabled **Namespace** ``` api.query.ethBridge.pendingEventProofs ``` **Type** ``` function pendingEventProofs( u64 ): Option ``` ## processedMessageIds Tracks processed message Ids (prevent replay) **Namespace** ``` api.query.ethBridge.processedMessageIds ``` **Type** ``` function processedMessageIds( ): Vec ``` ## relayer The permissioned relayer **Namespace** ``` api.query.ethBridge.relayer ``` **Type** ``` function relayer( ): Option ``` ## relayerPaidBond Maps from relayer account to their paid bond amount **Namespace** ``` api.query.ethBridge.relayerPaidBond ``` **Type** ``` function relayerPaidBond( SeedPrimitivesSignatureAccountId20 ): u128 ``` ## xrplDoorSigners Door Signers set by sudo (white list) **Namespace** ``` api.query.ethBridge.xrplDoorSigners ``` **Type** ``` function xrplDoorSigners( SeedPrimitivesEthyCryptoAppCryptoPublic ): bool ``` ## xrplNotarySetProofId The event proof Id generated by the previous validator set to notarize the current set. Useful for syncing the latest proof to Xrpl **Namespace** ``` api.query.ethBridge.xrplNotarySetProofId ``` **Type** ``` function xrplNotarySetProofId( ): u64 ``` ## Events ## AuthoritySetChange A notary (validator) set change is in motion (event\_id, new\_validator\_set\_id) A proof for the change will be generated with the given `event_id` **Namespace** ``` api.events.ethBridge.AuthoritySetChange ``` **Type** ``` type AuthoritySetChange = { param0: u64, param1: u64 } ``` ## Challenged An event has been challenged (claim\_id, challenger) **Namespace** ``` api.events.ethBridge.Challenged ``` **Type** ``` type Challenged = { param0: u64, param1: SeedPrimitivesSignatureAccountId20 } ``` ## EventSend An event proof has been sent for signing by ethy-gadget **Namespace** ``` api.events.ethBridge.EventSend ``` **Type** ``` type EventSend = { event_proof_id: u64, signing_request: PalletEthyEthySigningRequest } ``` ## EventSubmit An event has been submitted from Ethereum (event\_claim\_id, event\_claim, process\_at) **Namespace** ``` api.events.ethBridge.EventSubmit ``` **Type** ``` type EventSubmit = { param0: u64, param1: PalletEthyEventClaim, param2: u32 } ``` ## FinaliseScheduleFail The schedule to unpause the bridge has failed (scheduled\_block) **Namespace** ``` api.events.ethBridge.FinaliseScheduleFail ``` **Type** ``` type FinaliseScheduleFail = { param0: u32 } ``` ## Invalid Verifying an event failed **Namespace** ``` api.events.ethBridge.Invalid ``` **Type** ``` type Invalid = { param0: u64 } ``` ## ProcessAtExtended The event is still awaiting consensus. Process block pushed out (claim\_id, process\_at) **Namespace** ``` api.events.ethBridge.ProcessAtExtended ``` **Type** ``` type ProcessAtExtended = { param0: u64, param1: u32 } ``` ## ProcessingFailed Processing an event failed **Namespace** ``` api.events.ethBridge.ProcessingFailed ``` **Type** ``` type ProcessingFailed = { param0: u64, param1: SeedPalletCommonEventRouterError } ``` ## ProcessingOk Processing an event succeeded **Namespace** ``` api.events.ethBridge.ProcessingOk ``` **Type** ``` type ProcessingOk = { param0: u64 } ``` ## ProofDelayed Generating event proof delayed as bridge is paused **Namespace** ``` api.events.ethBridge.ProofDelayed ``` **Type** ``` type ProofDelayed = { param0: u64 } ``` ## RelayerBondDeposit An account has deposited a relayer bond **Namespace** ``` api.events.ethBridge.RelayerBondDeposit ``` **Type** ``` type RelayerBondDeposit = { param0: SeedPrimitivesSignatureAccountId20, param1: u128 } ``` ## RelayerBondWithdraw An account has withdrawn a relayer bond **Namespace** ``` api.events.ethBridge.RelayerBondWithdraw ``` **Type** ``` type RelayerBondWithdraw = { param0: SeedPrimitivesSignatureAccountId20, param1: u128 } ``` ## RelayerSet A new relayer has been set **Namespace** ``` api.events.ethBridge.RelayerSet ``` **Type** ``` type RelayerSet = { param0: Option } ``` ## SetContractAddress The bridge contract address has been set **Namespace** ``` api.events.ethBridge.SetContractAddress ``` **Type** ``` type SetContractAddress = { param0: H160 } ``` ## Verified Verifying an event succeeded **Namespace** ``` api.events.ethBridge.Verified ``` **Type** ``` type Verified = { param0: u64 } ``` ## XrplAuthoritySetChange A notary (validator) set change for Xrpl is in motion (event\_id, new\_validator\_set\_id) A proof for the change will be generated with the given `event_id` **Namespace** ``` api.events.ethBridge.XrplAuthoritySetChange ``` **Type** ``` type XrplAuthoritySetChange = { param0: u64, param1: u64 } ``` ## XrplAuthoritySetChangeRequestFailed Xrpl authority set change request failed **Namespace** ``` api.events.ethBridge.XrplAuthoritySetChangeRequestFailed ``` **Type** ``` type XrplAuthoritySetChangeRequestFailed = { } ``` ## XrplDoorSignersSet Xrpl Door signers are set **Namespace** ``` api.events.ethBridge.XrplDoorSignersSet ``` **Type** ``` type XrplDoorSignersSet = { } ``` ## Errors ## BridgePaused The bridge is paused pending validator set changes (once every era / 24 hours) It will reactive after \~10 minutes **Namespace** ``` api.errors.ethBridge.BridgePaused ``` ## CantBondRelayer The relayer already has a bonded amount **Namespace** ``` api.errors.ethBridge.CantBondRelayer ``` ## CantUnbondRelayer The relayer is active and cant unbond the specified amount **Namespace** ``` api.errors.ethBridge.CantUnbondRelayer ``` ## ClaimAlreadyChallenged There is already a challenge for this claim **Namespace** ``` api.errors.ethBridge.ClaimAlreadyChallenged ``` ## EventReplayPending Event was already submitted and is pending **Namespace** ``` api.errors.ethBridge.EventReplayPending ``` ## EventReplayProcessed Event was already submitted and is complete **Namespace** ``` api.errors.ethBridge.EventReplayProcessed ``` ## HttpFetch **Namespace** ``` api.errors.ethBridge.HttpFetch ``` ## Internal Some internal operation failed **Namespace** ``` api.errors.ethBridge.Internal ``` ## InvalidClaim Claim was invalid e.g. not properly ABI encoded **Namespace** ``` api.errors.ethBridge.InvalidClaim ``` ## InvalidNotarization A notarization was invalid **Namespace** ``` api.errors.ethBridge.InvalidNotarization ``` ## MaxNewSignersExceeded Someone tried to set a greater amount of validators than allowed **Namespace** ``` api.errors.ethBridge.MaxNewSignersExceeded ``` ## NoBondPaid The relayer hasn't paid the relayer bond so can't be set as the active relayer **Namespace** ``` api.errors.ethBridge.NoBondPaid ``` ## NoClaim There is no event claim associated with the supplied claim\_id **Namespace** ``` api.errors.ethBridge.NoClaim ``` ## NoLocalSigningAccount **Namespace** ``` api.errors.ethBridge.NoLocalSigningAccount ``` ## NoPermission Caller does not have permission for that action **Namespace** ``` api.errors.ethBridge.NoPermission ``` ## OcwConfig offchain worker not configured properly **Namespace** ``` api.errors.ethBridge.OcwConfig ``` ## OffchainUnsignedTxSignedPayload **Namespace** ``` api.errors.ethBridge.OffchainUnsignedTxSignedPayload ``` undefined # Ethereum Source: https://docs.therootnetwork.com/build/substrate/api-reference/runtime-pallets/ethereum ## Calls ### transact Transact an Ethereum transaction. **Namespace** ``` api.tx.ethereum.transact ``` **Type** ``` function transact( transaction: EthereumTransactionTransactionV2 ) ``` ## Storage ### blockHash **Namespace** ``` api.query.ethereum.blockHash ``` **Type** ``` function blockHash( U256 ): H256 ``` ### currentBlock The current Ethereum block. **Namespace** ``` api.query.ethereum.currentBlock ``` **Type** ``` function currentBlock( ): Option ``` ### currentReceipts The current Ethereum receipts. **Namespace** ``` api.query.ethereum.currentReceipts ``` **Type** ``` function currentReceipts( ): Option> ``` ### currentTransactionStatuses The current transaction statuses. **Namespace** ``` api.query.ethereum.currentTransactionStatuses ``` **Type** ``` function currentTransactionStatuses( ): Option> ``` ### pending Current building block's transactions and receipts. **Namespace** ``` api.query.ethereum.pending ``` **Type** ``` function pending( ): Vec<(EthereumTransactionTransactionV2,FpRpcTransactionStatus,EthereumReceiptReceiptV3)> ``` ## Events ### Executed An ethereum transaction was successfully executed. **Namespace** ``` api.events.ethereum.Executed ``` **Type** ``` type Executed = { from: H160, to: H160, transaction_hash: H256, exit_reason: EvmCoreErrorExitReason } ``` ## Errors ### BalanceLow **Namespace** ``` api.errors.ethereum.BalanceLow ``` ### GasLimitTooHigh **Namespace** ``` api.errors.ethereum.GasLimitTooHigh ``` ### GasLimitTooLow **Namespace** ``` api.errors.ethereum.GasLimitTooLow ``` ### GasPriceTooLow **Namespace** ``` api.errors.ethereum.GasPriceTooLow ``` ### InvalidNonce **Namespace** ``` api.errors.ethereum.InvalidNonce ``` ### InvalidSignature Signature is invalid. **Namespace** ``` api.errors.ethereum.InvalidSignature ``` ### PreLogExists Pre-log is present, therefore transact is not allowed. **Namespace** ``` api.errors.ethereum.PreLogExists ``` ### Undefined **Namespace** ``` api.errors.ethereum.Undefined ``` undefined # Evm Source: https://docs.therootnetwork.com/build/substrate/api-reference/runtime-pallets/evm ## Calls ### call Issue an EVM call operation. This is similar to a message call transaction in Ethereum. **Namespace** ``` api.tx.evm.call ``` **Type** ``` function call( source: H160, target: H160, input: Bytes, value: U256, gas_limit: u64, max_fee_per_gas: U256, max_priority_fee_per_gas: Option, nonce: Option, access_list: Vec<(H160,Vec)> ) ``` ### create Issue an EVM create operation. This is similar to a contract creation transaction in Ethereum. **Namespace** ``` api.tx.evm.create ``` **Type** ``` function create( source: H160, init: Bytes, value: U256, gas_limit: u64, max_fee_per_gas: U256, max_priority_fee_per_gas: Option, nonce: Option, access_list: Vec<(H160,Vec)> ) ``` ### create2 Issue an EVM create2 operation. **Namespace** ``` api.tx.evm.create2 ``` **Type** ``` function create2( source: H160, init: Bytes, salt: H256, value: U256, gas_limit: u64, max_fee_per_gas: U256, max_priority_fee_per_gas: Option, nonce: Option, access_list: Vec<(H160,Vec)> ) ``` ### withdraw Withdraw balance from EVM into currency/balances pallet. **Namespace** ``` api.tx.evm.withdraw ``` **Type** ``` function withdraw( address: H160, value: u128 ) ``` ## Storage ### accountCodes **Namespace** ``` api.query.evm.accountCodes ``` **Type** ``` function accountCodes( H160 ): Bytes ``` ### accountStorages **Namespace** ``` api.query.evm.accountStorages ``` **Type** ``` function accountStorages( H160, H256 ): H256 ``` ## Events ### Created A contract has been created at given address. **Namespace** ``` api.events.evm.Created ``` **Type** ``` type Created = { address: H160 } ``` ### CreatedFailed A contract was attempted to be created, but the execution failed. **Namespace** ``` api.events.evm.CreatedFailed ``` **Type** ``` type CreatedFailed = { address: H160 } ``` ### Executed A contract has been executed successfully with states applied. **Namespace** ``` api.events.evm.Executed ``` **Type** ``` type Executed = { address: H160 } ``` ### ExecutedFailed A contract has been executed with errors. States are reverted with only gas fees applied. **Namespace** ``` api.events.evm.ExecutedFailed ``` **Type** ``` type ExecutedFailed = { address: H160 } ``` ### Log Ethereum events from contracts. **Namespace** ``` api.events.evm.Log ``` **Type** ``` type Log = { log: EthereumLog } ``` ## Errors ### BalanceLow Not enough balance to perform action **Namespace** ``` api.errors.evm.BalanceLow ``` ### FeeOverflow Calculating total fee overflowed **Namespace** ``` api.errors.evm.FeeOverflow ``` ### GasLimitTooHigh Gas limit is too high. **Namespace** ``` api.errors.evm.GasLimitTooHigh ``` ### GasLimitTooLow Gas limit is too low. **Namespace** ``` api.errors.evm.GasLimitTooLow ``` ### GasPriceTooLow Gas price is too low. **Namespace** ``` api.errors.evm.GasPriceTooLow ``` ### InvalidNonce Nonce is invalid **Namespace** ``` api.errors.evm.InvalidNonce ``` ### PaymentOverflow Calculating total payment overflowed **Namespace** ``` api.errors.evm.PaymentOverflow ``` ### Reentrancy EVM reentrancy **Namespace** ``` api.errors.evm.Reentrancy ``` ### Undefined Undefined error. **Namespace** ``` api.errors.evm.Undefined ``` ### WithdrawFailed Withdraw fee failed **Namespace** ``` api.errors.evm.WithdrawFailed ``` undefined # EvmChainId Source: https://docs.therootnetwork.com/build/substrate/api-reference/runtime-pallets/evmchainid ## Calls ### setChainId **Namespace** ``` api.tx.evmChainId.setChainId ``` **Type** ``` function setChainId( chain_id: Compact ) ``` ## Storage ### chainId The EVM chain ID. **Namespace** ``` api.query.evmChainId.chainId ``` **Type** ``` function chainId( ): u64 ``` ## Events ### ChainIdSet **Namespace** ``` api.events.evmChainId.ChainIdSet ``` **Type** ``` type ChainIdSet = { param0: u64 } ``` undefinedundefined # FeeControl Source: https://docs.therootnetwork.com/build/substrate/api-reference/runtime-pallets/feecontrol ## Calls ### setEvmBaseFee **Namespace** ``` api.tx.feeControl.setEvmBaseFee ``` **Type** ``` function setEvmBaseFee( value: U256 ) ``` ### setLengthMultiplier **Namespace** ``` api.tx.feeControl.setLengthMultiplier ``` **Type** ``` function setLengthMultiplier( value: u128 ) ``` ### setWeightMultiplier **Namespace** ``` api.tx.feeControl.setWeightMultiplier ``` **Type** ``` function setWeightMultiplier( value: Perbill ) ``` ## Storage ### data **Namespace** ``` api.query.feeControl.data ``` **Type** ``` function data( ): PalletFeeControlFeeControlFeeConfig ``` ## Events ### EvmBaseFeeSet The EVM base fee has been set to `base_fee` **Namespace** ``` api.events.feeControl.EvmBaseFeeSet ``` **Type** ``` type EvmBaseFeeSet = { base_fee: U256 } ``` ### LengthMultiplierSet The length multiplier has been set to `length_multiplier` **Namespace** ``` api.events.feeControl.LengthMultiplierSet ``` **Type** ``` type LengthMultiplierSet = { length_multiplier: u128 } ``` ### WeightMultiplierSet The weight multiplier has been set to `weight_multiplier` **Namespace** ``` api.events.feeControl.WeightMultiplierSet ``` **Type** ``` type WeightMultiplierSet = { weight_multiplier: Perbill } ``` undefined # FeeProxy Source: https://docs.therootnetwork.com/build/substrate/api-reference/runtime-pallets/feeproxy ## Calls ### callWithFeePreferences Call an internal call with specified gas token payment\_asset: The token to be used for paying gas fees. This is exchanged in OnChargeTransaction::withdraw\_fee() max\_payment: The limit of how many tokens will be used to perform the exchange call: The inner call to be performed after the exchange **Namespace** ``` api.tx.feeProxy.callWithFeePreferences ``` **Type** ``` function callWithFeePreferences( payment_asset: u32, max_payment: u128, call: Call ) ``` undefined## Events ### CallWithFeePreferences A call was made with specified payment asset **Namespace** ``` api.events.feeProxy.CallWithFeePreferences ``` **Type** ``` type CallWithFeePreferences = { who: SeedPrimitivesSignatureAccountId20, payment_asset: u32, max_payment: u128 } ``` ## Errors ### FeeTokenIsGasToken The selected fee token is equal to the native gas token **Namespace** ``` api.errors.feeProxy.FeeTokenIsGasToken ``` ### NestedFeePreferenceCall The inner call is a fee preference call **Namespace** ``` api.errors.feeProxy.NestedFeePreferenceCall ``` ## Constants ### feeAssetId The native token asset Id (managed by pallet-balances) **Namespace** ``` api.consts.feeProxy.feeAssetId ``` **Type** ``` type feeAssetId = u32 ``` # FuturePass Source: https://docs.therootnetwork.com/build/substrate/api-reference/runtime-pallets/futurepass ## Calls ### create Create a \[FuturePass]learn/glossary) account for the delegator who is able to make calls on behalf of FuturePass. The dispatch origin for this call must be *Signed*. Parameters: * `account`: The delegated account for the FuturePass. **Namespace** ``` api.tx.futurepass.create ``` **Type** ``` function create( account: SeedPrimitivesSignatureAccountId20 ) ``` ### migrateEvmFuturepass This extrinsic migrates EVM-based FuturePass assets to the Substrate-based FuturePass (native). Parameters: * `owner` - The account ID of the owner of the EVM-based FuturePass. * `evm_futurepass` - The account ID of the EVM-based FuturePass. * `asset_ids` - A vector of asset IDs representing the assets to be migrated. * `collection_ids` - A vector of collection IDs representing the NFTs collections to be migrated. **Namespace** ``` api.tx.futurepass.migrateEvmFuturepass ``` **Type** ``` function migrateEvmFuturepass( owner: SeedPrimitivesSignatureAccountId20, evm_futurepass: SeedPrimitivesSignatureAccountId20, asset_ids: Vec, collection_ids: Vec ) ``` ### proxyExtrinsic Dispatch the given call through FuturePass account. Transaction fees will be paid by the FuturePass. The dispatch origin for this call must be *Signed* Parameters: * `futurepass`: The FuturePass account through which the call is dispatched * `call`: The Call that needs to be dispatched through the FuturePass account **Namespace** ``` api.tx.futurepass.proxyExtrinsic ``` **Type** ``` function proxyExtrinsic( futurepass: SeedPrimitivesSignatureAccountId20, call: Call ) ``` ### registerDelegateWithSignature Register a delegator to an existing FuturePass account given message parameters for a respective signature. **Note**: * Only FuturePass owner account can add more delegates. * The signer is recovered from the signature given the message parameters (which are used to reconstruct the message). You can assume the message is constructed like so: \--- `solidity bytes32 message = keccak256(abi.encodePacked(futurepass, delegate, proxyType, deadline)); ethSignedMessage = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", message));` *** The dispatch origin for this call must be *Signed*. Parameters: * `futurepass`: FuturePass account to register the account as delegate; 20 bytes. * `delegate`: The delegated account for the futurepass; 20 bytes. * `proxy_type`: Delegate permission level; 1 byte. * `deadline`: Deadline for the signature; 4 bytes. * `signature`: Signature of the message parameters. **Namespace** ``` api.tx.futurepass.registerDelegateWithSignature ``` **Type** ``` function registerDelegateWithSignature( futurepass: SeedPrimitivesSignatureAccountId20, delegate: SeedPrimitivesSignatureAccountId20, proxy_type: SeedRuntimeImplsProxyType, deadline: u32, signature: [u8;65] ) ``` ### setFuturepassMigrator Update FuturePass native assets migrator admin account. The dispatch origin for this call must be sudo/root origin. Parameters: * `migrator`: The new account that will become the FuturePass asset migrator. **Namespace** ``` api.tx.futurepass.setFuturepassMigrator ``` **Type** ``` function setFuturepassMigrator( migrator: SeedPrimitivesSignatureAccountId20 ) ``` ### transferFuturepass Transfer ownership of a FuturePass to a new account. The new owner must not already own a FuturePass. This removes all delegates from the FuturePass. The new owner will be the only delegate; they can add more delegates. The dispatch origin for this call must be *Signed* and must be the current owner of the FuturePass. Parameters: * `current_owner`: The current owner of the FuturePass. * `new_owner`: The new account that will become the owner of the FuturePass. **Namespace** ``` api.tx.futurepass.transferFuturepass ``` **Type** ``` function transferFuturepass( current_owner: SeedPrimitivesSignatureAccountId20, new_owner: Option ) ``` ### unregisterDelegate Unregister a delegate from a FuturePass account. The dispatch origin for this call must be *Signed*. Parameters: * `futurepass`: FuturePass account to unregister the delegate from. * `delegate`: The delegated account for the FuturePass. **Note**: If the caller is the FuturePass holder (owner), they can remove any delegate, including themselves. However, if the caller is not the owner, they must be the delegate and can only remove themselves. **Namespace** ``` api.tx.futurepass.unregisterDelegate ``` **Type** ``` function unregisterDelegate( futurepass: SeedPrimitivesSignatureAccountId20, delegate: SeedPrimitivesSignatureAccountId20 ) ``` ## Storage ### defaultProxy Accounts which have set FuturePass as default proxied on-chain account (delegate -> FuturePass) **Namespace** ``` api.query.futurepass.defaultProxy ``` **Type** ``` function defaultProxy( SeedPrimitivesSignatureAccountId20 ): Option ``` ### holders FuturePass holders (account -> futurepass) **Namespace** ``` api.query.futurepass.holders ``` **Type** ``` function holders( SeedPrimitivesSignatureAccountId20 ): Option ``` ### migrationAdmin Migration data for the user (root) and collections they can migrate **Namespace** ``` api.query.futurepass.migrationAdmin ``` **Type** ``` function migrationAdmin( ): Option ``` ### nextFuturepassId The next available incrementing futurepass id **Namespace** ``` api.query.futurepass.nextFuturepassId ``` **Type** ``` function nextFuturepassId( ): u128 ``` ## Events ### DefaultFuturepassSet FuturePass set as default proxy **Namespace** ``` api.events.futurepass.DefaultFuturepassSet ``` **Type** ``` type DefaultFuturepassSet = { delegate: SeedPrimitivesSignatureAccountId20, futurepass: Option } ``` ### DelegateRegistered Delegate registration to FuturePass account **Namespace** ``` api.events.futurepass.DelegateRegistered ``` **Type** ``` type DelegateRegistered = { futurepass: SeedPrimitivesSignatureAccountId20, delegate: SeedPrimitivesSignatureAccountId20, proxy_type: SeedRuntimeImplsProxyType } ``` ### DelegateUnregistered Delegate unregistration from FuturePass account **Namespace** ``` api.events.futurepass.DelegateUnregistered ``` **Type** ``` type DelegateUnregistered = { futurepass: SeedPrimitivesSignatureAccountId20, delegate: SeedPrimitivesSignatureAccountId20 } ``` ### FuturepassAssetsMigrated Migration of FuturePass assets **Namespace** ``` api.events.futurepass.FuturepassAssetsMigrated ``` **Type** ``` type FuturepassAssetsMigrated = { evm_futurepass: SeedPrimitivesSignatureAccountId20, futurepass: SeedPrimitivesSignatureAccountId20, assets: Vec, collections: Vec } ``` ### FuturepassCreated FuturePass creation **Namespace** ``` api.events.futurepass.FuturepassCreated ``` **Type** ``` type FuturepassCreated = { futurepass: SeedPrimitivesSignatureAccountId20, delegate: SeedPrimitivesSignatureAccountId20 } ``` ### FuturepassMigratorSet Updating FuturePass migrator account **Namespace** ``` api.events.futurepass.FuturepassMigratorSet ``` **Type** ``` type FuturepassMigratorSet = { migrator: SeedPrimitivesSignatureAccountId20 } ``` ### FuturepassTransferred FuturePass transfer **Namespace** ``` api.events.futurepass.FuturepassTransferred ``` **Type** ``` type FuturepassTransferred = { old_owner: SeedPrimitivesSignatureAccountId20, new_owner: Option, futurepass: SeedPrimitivesSignatureAccountId20 } ``` ### ProxyExecuted A proxy call was executed with the given call **Namespace** ``` api.events.futurepass.ProxyExecuted ``` **Type** ``` type ProxyExecuted = { delegate: SeedPrimitivesSignatureAccountId20, result: Result } ``` ## Errors ### AccountAlreadyRegistered Account is already FuturePass holder **Namespace** ``` api.errors.futurepass.AccountAlreadyRegistered ``` ### AccountParsingFailure AccountParsingFailure **Namespace** ``` api.errors.futurepass.AccountParsingFailure ``` ### DelegateAlreadyExists Account already exists as a delegate **Namespace** ``` api.errors.futurepass.DelegateAlreadyExists ``` ### DelegateNotRegistered Account is not FuturePass delegate **Namespace** ``` api.errors.futurepass.DelegateNotRegistered ``` ### ExpiredDeadline ExpiredDeadline **Namespace** ``` api.errors.futurepass.ExpiredDeadline ``` ### InvalidDeadline Invalid deadline **Namespace** ``` api.errors.futurepass.InvalidDeadline ``` ### InvalidProxyType Invalid proxy type **Namespace** ``` api.errors.futurepass.InvalidProxyType ``` ### InvalidSignature Invalid signature **Namespace** ``` api.errors.futurepass.InvalidSignature ``` ### MigratorNotSet FuturePass migrator admin account is not set **Namespace** ``` api.errors.futurepass.MigratorNotSet ``` ### NotFuturepassOwner Account is not FuturePass owner **Namespace** ``` api.errors.futurepass.NotFuturepassOwner ``` ### OwnerCannotUnregister FuturePass owner cannot remove themselves **Namespace** ``` api.errors.futurepass.OwnerCannotUnregister ``` ### PermissionDenied Account does not have permission to call this function **Namespace** ``` api.errors.futurepass.PermissionDenied ``` ### RegisterDelegateSignerMismatch RegisterDelegateSignerMismatch **Namespace** ``` api.errors.futurepass.RegisterDelegateSignerMismatch ``` undefined # Grandpa Source: https://docs.therootnetwork.com/build/substrate/api-reference/runtime-pallets/grandpa ## Calls ### noteStalled Note that the current authority set of the GRANDPA finality gadget has stalled. This will trigger a forced authority set change at the beginning of the next session, to be enacted `delay` blocks after that. The `delay` should be high enough to safely assume that the block signalling the forced change will not be re-orged e.g. 1000 blocks. The block production rate (which may be slowed down because of finality lagging) should be taken into account when choosing the `delay`. The GRANDPA voters based on the new authority will start voting on top of `best_finalized_block_number` for new finalized blocks. `best_finalized_block_number` should be the highest of the latest finalized block of all validators of the new authority set. **Note**: Only callable by root. **Namespace** ``` api.tx.grandpa.noteStalled ``` **Type** ``` function noteStalled( delay: u32, best_finalized_block_number: u32 ) ``` ### reportEquivocation Report voter equivocation/misbehavior. This method will verify the equivocation proof and validate the given key ownership proof against the extracted offender. If both are valid, the offence will be reported. **Namespace** ``` api.tx.grandpa.reportEquivocation ``` **Type** ``` function reportEquivocation( equivocation_proof: SpFinalityGrandpaEquivocationProof, key_owner_proof: SpCoreVoid ) ``` ### reportEquivocationUnsigned Report voter equivocation/misbehavior. This method will verify the equivocation proof and validate the given key ownership proof against the extracted offender. If both are valid, the offence will be reported. This extrinsic must be called unsigned and it is expected that only block authors will call it (validated in `ValidateUnsigned`), as such if the block author is defined it will be defined as the equivocation reporter. **Namespace** ``` api.tx.grandpa.reportEquivocationUnsigned ``` **Type** ``` function reportEquivocationUnsigned( equivocation_proof: SpFinalityGrandpaEquivocationProof, key_owner_proof: SpCoreVoid ) ``` ## Storage ### currentSetId The number of changes (both in terms of keys and underlying economic responsibilities) in the "set" of Grandpa validators from genesis. **Namespace** ``` api.query.grandpa.currentSetId ``` **Type** ``` function currentSetId( ): u64 ``` ### nextForced next block number where we can force a change. **Namespace** ``` api.query.grandpa.nextForced ``` **Type** ``` function nextForced( ): Option ``` ### pendingChange Pending change: (signaled at, scheduled change). **Namespace** ``` api.query.grandpa.pendingChange ``` **Type** ``` function pendingChange( ): Option ``` ### setIdSession A mapping from grandpa set ID to the index of the *most recent* session for which its members were responsible. TWOX-NOTE: `SetId` is not under user control. **Namespace** ``` api.query.grandpa.setIdSession ``` **Type** ``` function setIdSession( u64 ): Option ``` ### stalled `true` if we are currently stalled. **Namespace** ``` api.query.grandpa.stalled ``` **Type** ``` function stalled( ): Option<(u32,u32)> ``` ### state State of the current authority set. **Namespace** ``` api.query.grandpa.state ``` **Type** ``` function state( ): PalletGrandpaStoredState ``` ## Events ### NewAuthorities New authority set has been applied. **Namespace** ``` api.events.grandpa.NewAuthorities ``` **Type** ``` type NewAuthorities = { authority_set: Vec<(SpFinalityGrandpaAppPublic,u64)> } ``` ### Paused Current authority set has been paused. **Namespace** ``` api.events.grandpa.Paused ``` **Type** ``` type Paused = { } ``` ### Resumed Current authority set has been resumed. **Namespace** ``` api.events.grandpa.Resumed ``` **Type** ``` type Resumed = { } ``` ## Errors ### ChangePending Attempt to signal GRANDPA change with one already pending. **Namespace** ``` api.errors.grandpa.ChangePending ``` ### DuplicateOffenceReport A given equivocation report is valid but already previously reported. **Namespace** ``` api.errors.grandpa.DuplicateOffenceReport ``` ### InvalidEquivocationProof An equivocation proof provided as part of an equivocation report is invalid. **Namespace** ``` api.errors.grandpa.InvalidEquivocationProof ``` ### InvalidKeyOwnershipProof A key ownership proof provided as part of an equivocation report is invalid. **Namespace** ``` api.errors.grandpa.InvalidKeyOwnershipProof ``` ### PauseFailed Attempt to signal GRANDPA pause when the authority set isn't live (either paused or already pending pause). **Namespace** ``` api.errors.grandpa.PauseFailed ``` ### ResumeFailed Attempt to signal GRANDPA resume when the authority set isn't paused (either live or already pending resume). **Namespace** ``` api.errors.grandpa.ResumeFailed ``` ### TooSoon Cannot signal forced change so soon after last. **Namespace** ``` api.errors.grandpa.TooSoon ``` ## Constants ### maxAuthorities Max Authorities in use **Namespace** ``` api.consts.grandpa.maxAuthorities ``` **Type** ``` type maxAuthorities = u32 ``` ## JSON-RPC Methods ### `proveFinality` Prove finality for the given block number, returning the Justification for the last block in the set. **Interface** ``` api.rpc.grandpa.proveFinality(blockNumber: BlockNumber): Option ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"grandpa_proveFinality", "params":[blockNumber: BlockNumber] } ``` ### `roundState` Returns the state of the current best round state as well as the ongoing background rounds **Interface** ``` api.rpc.grandpa.roundState(): ReportedRoundStates ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"grandpa_roundState", "params":[] } ``` ### `subscribeJustifications` Subscribes to grandpa justifications **Interface** ``` api.rpc.grandpa.subscribeJustifications(): JustificationNotification ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"grandpa_subscribeJustifications", "params":[] } ``` # Historical Source: https://docs.therootnetwork.com/build/substrate/api-reference/runtime-pallets/historical ## Storage ### historicalSessions Mapping from historical session indices to session-data root hash and validator count. **Namespace** ``` api.query.historical.historicalSessions ``` **Type** ``` function historicalSessions( u32 ): Option<(H256,u32)> ``` ### storedRange The range of historical sessions we store. \[first, last) **Namespace** ``` api.query.historical.storedRange ``` **Type** ``` function storedRange( ): Option<(u32,u32)> ``` # ImOnline Source: https://docs.therootnetwork.com/build/substrate/api-reference/runtime-pallets/imonline ## Calls ### heartbeat **Namespace** ``` api.tx.imOnline.heartbeat ``` **Type** ``` function heartbeat( heartbeat: PalletImOnlineHeartbeat, signature: PalletImOnlineSr25519AppSr25519Signature ) ``` ## Storage ### authoredBlocks For each session index, we keep a mapping of `ValidatorId` to the number of blocks authored by the given authority. **Namespace** ``` api.query.imOnline.authoredBlocks ``` **Type** ``` function authoredBlocks( u32, SeedPrimitivesSignatureAccountId20 ): u32 ``` ### heartbeatAfter The block number after which it's ok to send heartbeats in the current session. At the beginning of each session we set this to a value that should fall roughly in the middle of the session duration. The idea is to first wait for the validators to produce a block in the current session, so that the heartbeat later on will not be necessary. This value will only be used as a fallback if we fail to get a proper session progress estimate from `NextSessionRotation`, as those estimates should be more accurate then the value we calculate for `HeartbeatAfter`. **Namespace** ``` api.query.imOnline.heartbeatAfter ``` **Type** ``` function heartbeatAfter( ): u32 ``` ### keys The current set of keys that may issue a heartbeat. **Namespace** ``` api.query.imOnline.keys ``` **Type** ``` function keys( ): Vec ``` ### receivedHeartbeats For each session index, we keep a mapping of `SessionIndex` and `AuthIndex` to `WrapperOpaque`. **Namespace** ``` api.query.imOnline.receivedHeartbeats ``` **Type** ``` function receivedHeartbeats( u32, u32 ): Option> ``` ## Events ### AllGood At the end of the session, no offence was committed. **Namespace** ``` api.events.imOnline.AllGood ``` **Type** ``` type AllGood = { } ``` ### HeartbeatReceived A new heartbeat was received from `AuthorityId`. **Namespace** ``` api.events.imOnline.HeartbeatReceived ``` **Type** ``` type HeartbeatReceived = { authority_id: PalletImOnlineSr25519AppSr25519Public } ``` ### SomeOffline At the end of the session, at least one validator was found to be offline. **Namespace** ``` api.events.imOnline.SomeOffline ``` **Type** ``` type SomeOffline = { offline: Vec<(SeedPrimitivesSignatureAccountId20,PalletStakingExposure)> } ``` ## Errors ### DuplicatedHeartbeat Duplicated heartbeat. **Namespace** ``` api.errors.imOnline.DuplicatedHeartbeat ``` ### InvalidKey Non existent public key. **Namespace** ``` api.errors.imOnline.InvalidKey ``` ## Constants ### unsignedPriority A configuration for base priority of unsigned transactions. This is exposed so that it can be tuned for particular runtime, when multiple pallets send unsigned transactions. **Namespace** ``` api.consts.imOnline.unsignedPriority ``` **Type** ``` type unsignedPriority = u64 ``` # LiquidityPools Source: https://docs.therootnetwork.com/build/substrate/api-reference/runtime-pallets/liquiditypool The Liquidity Pools pallet is a fully permissionless Substrate pallet that enables the creation and management of liquidity pools for any asset pair. It provides a flexible framework for users to stake their assets in pools and earn rewards, with automatic rollover capabilities to maintain continuous participation across successive pools. ## Calls ### create\_pool Creates a new liquidity pool specifying reward and staked asset IDs, interest rate, maximum token limit, and lock period (start and end blocks). Anyone can create a pool without special permissions. **Namespace** ``` api.tx.liquidityPools.createPool ``` **Type** ``` function create_pool(reward_asset_id: u32, staked_asset_id: u32, interest_rate: u32, max_tokens: u128, lock_start_block: u32, lock_end_block: u32) ``` ### set\_pool\_succession Links a predecessor pool to a successor pool, enabling automatic rollover of user stakes when the predecessor pool completes its cycle. **Namespace** ``` api.tx.liquidityPools.setPoolSuccession ``` **Type** ``` function set_pool_succession(predecessor_pool_id: u32, successor_pool_id: u32) ``` ### set\_pool\_rollover Lets users opt in or out of automatic rollover to the successor pool when the current pool matures. **Namespace** ``` api.tx.liquidityPools.setPoolRollover ``` **Type** ``` function set_pool_rollover(id: u32, should_rollover: bool) ``` ### close\_pool Allows a pool creator to close their pool. Upon closing, only unclaimed reward tokens are returned to the creator. Staked tokens remain in the pool for users to withdraw. The pool remains in the Closed state until all user funds are withdrawn. **Namespace** ``` api.tx.liquidityPools.closePool ``` **Type** ``` function close_pool(id: u32) ``` ### enter\_pool Enables users to join an open pool by staking their assets up to the pool's maximum capacity. **Namespace** ``` api.tx.liquidityPools.enterPool ``` **Type** ``` function enter_pool(pool_id: u32, amount: u128) ``` ### exit\_pool Permits users to withdraw their staked assets from an Open pool before the lock period begins, and also from a Closed pool after the pool has been manually closed by the creator. **Namespace** ``` api.tx.liquidityPools.exitPool ``` **Type** ``` function exit_pool(id: u32) ``` ### claim\_reward Allows users to claim their earned rewards after a pool matures. If the user opted out of rollover, their principle is also returned. **Namespace** ``` api.tx.liquidityPools.claimReward ``` **Type** ``` function claim_reward(id: u32) ``` ### rollover\_unsigned An internal extrinsic executed by the offchain worker to process the automatic rollover of user stakes. **Namespace** ``` api.tx.liquidityPools.rolloverUnsigned ``` **Type** ``` function rollover_unsigned(id: u32, current_block: u32) ``` ## Storage ### Pools Stores information about each liquidity pool **Namespace** ``` api.query.liquidityPools.pools ``` **Type** ``` function pools(pool_id: u32) -> Option ``` ### PoolUsers Tracks user participation in pools **Namespace** ``` api.query.liquidityPools.poolUsers ``` **Type** ``` function poolUsers(pool_id: u32, account_id: AccountId) -> Option ``` ### PoolRelationships Maps predecessor pools to successor pools **Namespace** ``` api.query.liquidityPools.poolRelationships ``` **Type** ``` function poolRelationships(pool_id: u32) -> Option ``` ### NextPoolId Increment-only unique pool id **Namespace** ``` api.query.liquidityPools.nextPoolId ``` **Type** ``` function nextPoolId() -> u32 ``` ### NextRolloverUnsignedAt Tracks when next rollover should occur **Namespace** ``` api.query.liquidityPools.nextRolloverUnsignedAt ``` **Type** ``` function nextRolloverUnsignedAt() -> u32 ``` ### RolloverPivot Tracks progress during batch rollover operations **Namespace** ``` api.query.liquidityPools.rolloverPivot ``` **Type** ``` function rolloverPivot(pool_id: u32) -> BoundedVec ``` ### ProcessedPoolPivot Tracks the next pool id pivot used for batched processing during on\_idle. **Namespace** ``` api.query.liquidityPools.processedPoolPivot ``` **Type** ``` function processedPoolPivot() -> u32 ``` ## Events ### PoolOpen When a new pool is created **Namespace** ``` api.events.liquidityPools.PoolOpen ``` **Type** ``` struct PoolOpen { pool_id: u32, reward_asset_id: u32, staked_asset_id: u32, interest_rate: u32, max_tokens: u128, lock_start_block: u32, lock_end_block: u32 } ``` ### PoolStarted When a pool enters lock period **Namespace** ``` api.events.liquidityPools.PoolStarted ``` **Type** ``` struct PoolStarted { pool_id: u32 } ``` ### PoolRenewing When a pool starts rollover process **Namespace** ``` api.events.liquidityPools.PoolRenewing ``` **Type** ``` struct PoolRenewing { pool_id: u32 } ``` ### PoolMatured When a pool is ready for rewards claiming **Namespace** ``` api.events.liquidityPools.PoolMatured ``` **Type** ``` struct PoolMatured { pool_id: u32 } ``` ### PoolClosed When a pool is closed **Namespace** ``` api.events.liquidityPools.PoolClosed ``` **Type** ``` struct PoolClosed { pool_id: u32, reward_asset_amount: u128, staked_asset_amount: u128, receiver: AccountId } ``` Note: On close, only reward tokens are transferred to the creator; users must exit to withdraw staked tokens. ### SetSuccession When pools are linked for rollover **Namespace** ``` api.events.liquidityPools.SetSuccession ``` **Type** ``` struct SetSuccession { predecessor_pool_id: u32, successor_pool_id: u32 } ``` ### UserInfoUpdated When user rollover preference is updated **Namespace** ``` api.events.liquidityPools.UserInfoUpdated ``` **Type** ``` struct UserInfoUpdated { pool_id: u32, account_id: AccountId, should_rollover: bool } ``` ### UserJoined When user joins a pool **Namespace** ``` api.events.liquidityPools.UserJoined ``` **Type** ``` struct UserJoined { account_id: AccountId, pool_id: u32, amount: u128 } ``` ### UserExited When user exits a pool **Namespace** ``` api.events.liquidityPools.UserExited ``` **Type** ``` struct UserExited { account_id: AccountId, pool_id: u32, amount: u128 } ``` ### UserRolledOver When user is rolled over to successor pool **Namespace** ``` api.events.liquidityPools.UserRolledOver ``` **Type** ``` struct UserRolledOver { account_id: AccountId, pool_id: u32, rolled_to_pool_id: u32, amount: u128 } ``` ### RewardsClaimed When rewards are claimed **Namespace** ``` api.events.liquidityPools.RewardsClaimed ``` **Type** ``` struct RewardsClaimed { account_id: AccountId, pool_id: u32, amount: u128 } ``` ## Errors ### NotPoolCreator Caller is not the pool creator **Namespace** ``` api.errors.liquidityPools.NotPoolCreator ``` ### InvalidBlockRange Invalid block range for pool **Namespace** ``` api.errors.liquidityPools.InvalidBlockRange ``` ### PoolAlreadyExists Pool already exists **Namespace** ``` api.errors.liquidityPools.PoolAlreadyExists ``` ### PoolDoesNotExist Pool does not exist **Namespace** ``` api.errors.liquidityPools.PoolDoesNotExist ``` ### SuccessorPoolDoesNotExist Successor pool does not exist **Namespace** ``` api.errors.liquidityPools.SuccessorPoolDoesNotExist ``` ### PredecessorPoolDoesNotExist Predecessor pool does not exist **Namespace** ``` api.errors.liquidityPools.PredecessorPoolDoesNotExist ``` ### SuccessorPoolSizeShouldBeGreaterThanPredecessor Successor pool too small **Namespace** ``` api.errors.liquidityPools.SuccessorPoolSizeShouldBeGreaterThanPredecessor ``` ### SuccessorPoolSizeShouldBeLockedAfterPredecessor Invalid successor timing **Namespace** ``` api.errors.liquidityPools.SuccessorPoolSizeShouldBeLockedAfterPredecessor ``` ### RolloverPoolsShouldBeTheSameAsset Asset mismatch between pools **Namespace** ``` api.errors.liquidityPools.RolloverPoolsShouldBeTheSameAsset ``` ### NoTokensStaked No tokens staked for operation **Namespace** ``` api.errors.liquidityPools.NoTokensStaked ``` ### PoolNotOpen Pool not in open state **Namespace** ``` api.errors.liquidityPools.PoolNotOpen ``` ### NotReadyForClaimingReward Pool not mature for claiming **Namespace** ``` api.errors.liquidityPools.NotReadyForClaimingReward ``` ### NoAvailablePoolId Exceeds maximum pool ID **Namespace** ``` api.errors.liquidityPools.NoAvailablePoolId ``` ### StakingLimitExceeded Pool capacity limit reached **Namespace** ``` api.errors.liquidityPools.StakingLimitExceeded ``` ### OffchainErrNotValidator Offchain worker not validator **Namespace** ``` api.errors.liquidityPools.OffchainErrNotValidator ``` ### OffchainErrTooEarly Offchain worker called too early **Namespace** ``` api.errors.liquidityPools.OffchainErrTooEarly ``` ### OffchainErrSubmitTransaction Offchain transaction submission error **Namespace** ``` api.errors.liquidityPools.OffchainErrSubmitTransaction ``` ### OffchainErrWrongTransactionSource Offchain transaction source error **Namespace** ``` api.errors.liquidityPools.OffchainErrWrongTransactionSource ``` ### PivotStringTooLong Pivot string exceeds maximum length **Namespace** ``` api.errors.liquidityPools.PivotStringTooLong ``` ### PoolAlreadyClosed Pool is already in the Closed state **Namespace** ``` api.errors.liquidityPools.PoolAlreadyClosed ``` ### CannotExitPool Cannot exit the pool in the current state or conditions **Namespace** ``` api.errors.liquidityPools.CannotExitPool ``` ### RewardCalculationOverflow Overflow occurred during reward calculation **Namespace** ``` api.errors.liquidityPools.RewardCalculationOverflow ``` # MaintenanceMode Source: https://docs.therootnetwork.com/build/substrate/api-reference/runtime-pallets/maintenancemode ## Calls ### blockAccount Blocks an account from transacting on the network **Namespace** ``` api.tx.maintenanceMode.blockAccount ``` **Type** ``` function blockAccount( account: SeedPrimitivesSignatureAccountId20, blocked: bool ) ``` ### blockCall Blocks a call from being executed pallet\_name: The name of the pallet as per the runtime file. i.e. FeeProxy call\_name: The snake\_case name for the call. i.e. set\_fee Both pallet and call names are not case sensitive **Namespace** ``` api.tx.maintenanceMode.blockCall ``` **Type** ``` function blockCall( pallet_name: Bytes, call_name: Bytes, blocked: bool ) ``` ### blockEvmTarget Blocks an account from transacting on the network Can be used to block individual precompile addresses or contracts **Namespace** ``` api.tx.maintenanceMode.blockEvmTarget ``` **Type** ``` function blockEvmTarget( target_address: H160, blocked: bool ) ``` ### blockPallet Blocks an entire pallets calls from being executed pallet\_name: The name of the pallet as per the runtime file. i.e. FeeProxy Pallet names are not case sensitive **Namespace** ``` api.tx.maintenanceMode.blockPallet ``` **Type** ``` function blockPallet( pallet_name: Bytes, blocked: bool ) ``` ### enableMaintenanceMode Enable maintenance mode which prevents all non sudo calls **Namespace** ``` api.tx.maintenanceMode.enableMaintenanceMode ``` **Type** ``` function enableMaintenanceMode( enabled: bool ) ``` ## Storage ### blockedAccounts Map from account to blocked status **Namespace** ``` api.query.maintenanceMode.blockedAccounts ``` **Type** ``` function blockedAccounts( SeedPrimitivesSignatureAccountId20 ): bool ``` ### blockedCalls Map from call to blocked status map (PalletNameBytes, FunctionNameBytes) => bool **Namespace** ``` api.query.maintenanceMode.blockedCalls ``` **Type** ``` function blockedCalls( (Bytes,Bytes) ): bool ``` ### blockedEVMAddresses Map from EVM target address to blocked status **Namespace** ``` api.query.maintenanceMode.blockedEVMAddresses ``` **Type** ``` function blockedEVMAddresses( H160 ): bool ``` ### blockedPallets Map from pallet to blocked status map PalletNameBytes => bool **Namespace** ``` api.query.maintenanceMode.blockedPallets ``` **Type** ``` function blockedPallets( Bytes ): bool ``` ### maintenanceModeActive Determines whether maintenance mode is currently active **Namespace** ``` api.query.maintenanceMode.maintenanceModeActive ``` **Type** ``` function maintenanceModeActive( ): bool ``` ## Events ### AccountBlocked An account was blocked **Namespace** ``` api.events.maintenanceMode.AccountBlocked ``` **Type** ``` type AccountBlocked = { account: SeedPrimitivesSignatureAccountId20, blocked: bool } ``` ### CallBlocked An account was blocked **Namespace** ``` api.events.maintenanceMode.CallBlocked ``` **Type** ``` type CallBlocked = { pallet_name: Bytes, call_name: Bytes, blocked: bool } ``` ### EVMTargetBlocked An account was blocked **Namespace** ``` api.events.maintenanceMode.EVMTargetBlocked ``` **Type** ``` type EVMTargetBlocked = { target_address: H160, blocked: bool } ``` ### MaintenanceModeActivated Maintenance mode was activated **Namespace** ``` api.events.maintenanceMode.MaintenanceModeActivated ``` **Type** ``` type MaintenanceModeActivated = { enabled: bool } ``` ### PalletBlocked An account was blocked **Namespace** ``` api.events.maintenanceMode.PalletBlocked ``` **Type** ``` type PalletBlocked = { pallet_name: Bytes, blocked: bool } ``` ## Errors ### AccountBlocked This account is not authorized to execute this transaction **Namespace** ``` api.errors.maintenanceMode.AccountBlocked ``` ### CannotBlock This pallet or call cannot be blocked **Namespace** ``` api.errors.maintenanceMode.CannotBlock ``` ### InvalidCallName The call name is not valid utf-8 characters **Namespace** ``` api.errors.maintenanceMode.InvalidCallName ``` ### InvalidPalletName The pallet name is not valid utf-8 characters **Namespace** ``` api.errors.maintenanceMode.InvalidPalletName ``` ### MaintenanceModeActive This call is disabled as the chain is in maintenance mode **Namespace** ``` api.errors.maintenanceMode.MaintenanceModeActive ``` ## Constants ### stringLimit The maximum length of a pallet or call name, stored on-chain **Namespace** ``` api.consts.maintenanceMode.stringLimit ``` **Type** ``` type stringLimit = u32 ``` # Marketplace Source: https://docs.therootnetwork.com/build/substrate/api-reference/runtime-pallets/marketplace ## Calls ### acceptOffer Accepts an offer on a token Caller must be token owner **Namespace** ``` api.tx.marketplace.acceptOffer ``` **Type** ``` function acceptOffer( offer_id: u64 ) ``` ### auctionNft Auction a bundle of tokens on the open market to the highest bidder * Tokens must be from the same collection * Tokens with individual royalties schedules cannot be sold in bundles Caller must be the token owner * `payment_asset` fungible asset Id to receive payment with * `reserve_price` winning bid must be over this threshold * `duration` length of the auction (in blocks), uses default duration if unspecified **Namespace** ``` api.tx.marketplace.auctionNft ``` **Type** ``` function auctionNft( collection_id: u32, serial_numbers: Vec, payment_asset: u32, reserve_price: u128, duration: Option, marketplace_id: Option ) ``` ### bid Place a bid on an open auction * `amount` to bid (in the seller's requested payment asset) **Namespace** ``` api.tx.marketplace.bid ``` **Type** ``` function bid( listing_id: u128, amount: u128 ) ``` ### buy Buy a token listing for its specified price **Namespace** ``` api.tx.marketplace.buy ``` **Type** ``` function buy( listing_id: u128 ) ``` ### cancelOffer Cancels an offer on a token Caller must be the offer buyer **Namespace** ``` api.tx.marketplace.cancelOffer ``` **Type** ``` function cancelOffer( offer_id: u64 ) ``` ### cancelSale Close a sale or auction returning tokens Requires no successful bids have been made for an auction. Caller must be the listed seller **Namespace** ``` api.tx.marketplace.cancelSale ``` **Type** ``` function cancelSale( listing_id: u128 ) ``` ### makeSimpleOffer Create an offer on a token Locks funds until offer is accepted, rejected or cancelled An offer can't be made on a token currently in an auction (This follows the behaviour of Opensea and forces the buyer to bid rather than create an offer) **Namespace** ``` api.tx.marketplace.makeSimpleOffer ``` **Type** ``` function makeSimpleOffer( token_id: (u32,u32), amount: u128, asset_id: u32, marketplace_id: Option ) ``` ### registerMarketplace Flag an account as a marketplace `marketplace_account` - if specified, this account will be registered `entitlement` - Permill, percentage of sales to go to the marketplace If no marketplace is specified the caller will be registered **Namespace** ``` api.tx.marketplace.registerMarketplace ``` **Type** ``` function registerMarketplace( marketplace_account: Option, entitlement: Permill ) ``` ### sellNft Sell a bundle of tokens at a fixed price * Tokens must be from the same collection * Tokens with individual royalties schedules cannot be sold with this method `buyer` optionally, the account to receive the NFT. If unspecified, then any account may purchase `asset_id` fungible asset Id to receive as payment for the NFT `fixed_price` ask price `duration` listing duration time in blocks from now Caller must be the token owner **Namespace** ``` api.tx.marketplace.sellNft ``` **Type** ``` function sellNft( collection_id: u32, serial_numbers: Vec, buyer: Option, payment_asset: u32, fixed_price: u128, duration: Option, marketplace_id: Option ) ``` ### setFeeTo Set the `FeeTo` account This operation requires root access **Namespace** ``` api.tx.marketplace.setFeeTo ``` **Type** ``` function setFeeTo( fee_to: Option ) ``` ### updateFixedPrice Update fixed price for a single token sale `listing_id` id of the fixed price listing `new_price` new fixed price Caller must be the token owner **Namespace** ``` api.tx.marketplace.updateFixedPrice ``` **Type** ``` function updateFixedPrice( listing_id: u128, new_price: u128 ) ``` ## Storage ### feeTo The pallet id for the tx fee pot **Namespace** ``` api.query.marketplace.feeTo ``` **Type** ``` function feeTo( ): Option ``` ### listingEndSchedule Block numbers where listings will close. Value is `true` if at block number `listing_id` is scheduled to close. **Namespace** ``` api.query.marketplace.listingEndSchedule ``` **Type** ``` function listingEndSchedule( u32, u128 ): Option ``` ### listings NFT sale/auction listings keyed by listing id **Namespace** ``` api.query.marketplace.listings ``` **Type** ``` function listings( u128 ): Option ``` ### listingWinningBid Winning bids on open listings. **Namespace** ``` api.query.marketplace.listingWinningBid ``` **Type** ``` function listingWinningBid( u128 ): Option<(SeedPrimitivesSignatureAccountId20,u128)> ``` ### nextListingId The next available listing Id **Namespace** ``` api.query.marketplace.nextListingId ``` **Type** ``` function nextListingId( ): u128 ``` ### nextMarketplaceId The next available marketplace id **Namespace** ``` api.query.marketplace.nextMarketplaceId ``` **Type** ``` function nextMarketplaceId( ): u32 ``` ### nextOfferId The next available offer\_id **Namespace** ``` api.query.marketplace.nextOfferId ``` **Type** ``` function nextOfferId( ): u64 ``` ### offers Map from offer\_id to the information related to the offer **Namespace** ``` api.query.marketplace.offers ``` **Type** ``` function offers( u64 ): Option ``` ### openCollectionListings Map from collection to any open listings **Namespace** ``` api.query.marketplace.openCollectionListings ``` **Type** ``` function openCollectionListings( u32, u128 ): Option ``` ### registeredMarketplaces Map from marketplace account\_id to royalties schedule **Namespace** ``` api.query.marketplace.registeredMarketplaces ``` **Type** ``` function registeredMarketplaces( u32 ): Option ``` ### tokenOffers Maps from token\_id to a vector of offer\_ids on that token **Namespace** ``` api.query.marketplace.tokenOffers ``` **Type** ``` function tokenOffers( (u32,u32) ): Option> ``` ## Events ### AuctionClose An auction has closed without selling **Namespace** ``` api.events.marketplace.AuctionClose ``` **Type** ``` type AuctionClose = { collection_id: u32, listing_id: u128, reason: PalletMarketplaceAuctionClosureReason } ``` ### AuctionOpen An auction has opened **Namespace** ``` api.events.marketplace.AuctionOpen ``` **Type** ``` type AuctionOpen = { collection_id: u32, serial_numbers: Vec, payment_asset: u32, reserve_price: u128, listing_id: u128, marketplace_id: Option, seller: SeedPrimitivesSignatureAccountId20 } ``` ### AuctionSold An auction has sold **Namespace** ``` api.events.marketplace.AuctionSold ``` **Type** ``` type AuctionSold = { collection_id: u32, listing_id: u128, payment_asset: u32, hammer_price: u128, winner: SeedPrimitivesSignatureAccountId20 } ``` ### Bid A new highest bid was placed **Namespace** ``` api.events.marketplace.Bid ``` **Type** ``` type Bid = { collection_id: u32, serial_numbers: Vec, listing_id: u128, amount: u128, bidder: SeedPrimitivesSignatureAccountId20 } ``` ### FeeToSet The network fee receiver address has been updated **Namespace** ``` api.events.marketplace.FeeToSet ``` **Type** ``` type FeeToSet = { account: Option } ``` ### FixedPriceSaleClose A fixed price sale has closed without selling **Namespace** ``` api.events.marketplace.FixedPriceSaleClose ``` **Type** ``` type FixedPriceSaleClose = { collection_id: u32, serial_numbers: Vec, listing_id: u128, reason: PalletMarketplaceFixedPriceClosureReason } ``` ### FixedPriceSaleComplete A fixed price sale has completed **Namespace** ``` api.events.marketplace.FixedPriceSaleComplete ``` **Type** ``` type FixedPriceSaleComplete = { collection_id: u32, serial_numbers: Vec, listing_id: u128, price: u128, payment_asset: u32, buyer: SeedPrimitivesSignatureAccountId20, seller: SeedPrimitivesSignatureAccountId20 } ``` ### FixedPriceSaleList A fixed price sale has been listed **Namespace** ``` api.events.marketplace.FixedPriceSaleList ``` **Type** ``` type FixedPriceSaleList = { collection_id: u32, serial_numbers: Vec, listing_id: u128, marketplace_id: Option, price: u128, payment_asset: u32, seller: SeedPrimitivesSignatureAccountId20 } ``` ### FixedPriceSalePriceUpdate A fixed price sale has had its price updated **Namespace** ``` api.events.marketplace.FixedPriceSalePriceUpdate ``` **Type** ``` type FixedPriceSalePriceUpdate = { collection_id: u32, serial_numbers: Vec, listing_id: u128, new_price: u128 } ``` ### MarketplaceRegister An account has been registered as a marketplace **Namespace** ``` api.events.marketplace.MarketplaceRegister ``` **Type** ``` type MarketplaceRegister = { account: SeedPrimitivesSignatureAccountId20, entitlement: Permill, marketplace_id: u32 } ``` ### Offer An offer has been made on an NFT **Namespace** ``` api.events.marketplace.Offer ``` **Type** ``` type Offer = { offer_id: u64, amount: u128, asset_id: u32, marketplace_id: Option, buyer: SeedPrimitivesSignatureAccountId20 } ``` ### OfferAccept An offer has been accepted **Namespace** ``` api.events.marketplace.OfferAccept ``` **Type** ``` type OfferAccept = { offer_id: u64, token_id: (u32,u32), amount: u128, asset_id: u32 } ``` ### OfferCancel An offer has been cancelled **Namespace** ``` api.events.marketplace.OfferCancel ``` **Type** ``` type OfferCancel = { offer_id: u64, token_id: (u32,u32) } ``` ## Errors ### BidTooLow Auction bid was lower than reserve or current highest bid **Namespace** ``` api.errors.marketplace.BidTooLow ``` ### InvalidMetadataPath The metadata path is invalid (non-utf8 or empty) **Namespace** ``` api.errors.marketplace.InvalidMetadataPath ``` ### InvalidOffer No offer exists for the given OfferId **Namespace** ``` api.errors.marketplace.InvalidOffer ``` ### IsTokenOwner The caller owns the token and can't make an offer **Namespace** ``` api.errors.marketplace.IsTokenOwner ``` ### MarketplaceNotRegistered The account\_id hasn't been registered as a marketplace **Namespace** ``` api.errors.marketplace.MarketplaceNotRegistered ``` ### MaxOffersReached The maximum number of offers on this token has been reached **Namespace** ``` api.errors.marketplace.MaxOffersReached ``` ### MixedBundleSale Selling tokens from different collection is not allowed **Namespace** ``` api.errors.marketplace.MixedBundleSale ``` ### NoAvailableIds No more Ids are available, they've been exhausted **Namespace** ``` api.errors.marketplace.NoAvailableIds ``` ### NoCollectionFound The collection does not exist **Namespace** ``` api.errors.marketplace.NoCollectionFound ``` ### NotBuyer The caller is not the specified buyer **Namespace** ``` api.errors.marketplace.NotBuyer ``` ### NotCollectionOwner Origin is not the collection owner and is not permitted to perform the operation **Namespace** ``` api.errors.marketplace.NotCollectionOwner ``` ### NotForAuction The token is not listed for auction sale **Namespace** ``` api.errors.marketplace.NotForAuction ``` ### NotForFixedPriceSale The token is not listed for fixed price sale **Namespace** ``` api.errors.marketplace.NotForFixedPriceSale ``` ### NoToken The token does not exist **Namespace** ``` api.errors.marketplace.NoToken ``` ### NotSeller The caller is not the seller of the NFT **Namespace** ``` api.errors.marketplace.NotSeller ``` ### NotTokenOwner Origin does not own the NFT **Namespace** ``` api.errors.marketplace.NotTokenOwner ``` ### RoyaltiesInvalid Total royalties would exceed 100% of sale or an empty vec is supplied **Namespace** ``` api.errors.marketplace.RoyaltiesInvalid ``` ### TokenLocked Cannot operate on a listed NFT **Namespace** ``` api.errors.marketplace.TokenLocked ``` ### TokenNotListed The token is not listed for sale **Namespace** ``` api.errors.marketplace.TokenNotListed ``` ### TokenOnAuction Cannot make an offer on a token up for auction **Namespace** ``` api.errors.marketplace.TokenOnAuction ``` ### ZeroOffer Offer amount needs to be greater than 0 **Namespace** ``` api.errors.marketplace.ZeroOffer ``` ## Constants ### defaultFeeTo The default account which collects network fees from marketplace sales **Namespace** ``` api.consts.marketplace.defaultFeeTo ``` **Type** ``` type defaultFeeTo = Option ``` ### defaultListingDuration Default auction / sale length in blocks **Namespace** ``` api.consts.marketplace.defaultListingDuration ``` **Type** ``` type defaultListingDuration = u32 ``` ### palletId This pallet's Id, used for deriving a sovereign account ID **Namespace** ``` api.consts.marketplace.palletId ``` **Type** ``` type palletId = FrameSupportPalletId ``` # Multisig Source: https://docs.therootnetwork.com/build/substrate/api-reference/runtime-pallets/multisig ## Calls ### approveAsMulti Register approval for a dispatch to be made from a deterministic composite account if approved by a total of `threshold - 1` of `other_signatories`. Payment: `DepositBase` will be reserved if this is the first approval, plus `threshold` times `DepositFactor`. It is returned once this dispatch happens or is cancelled. The dispatch origin for this call must be *Signed*. * `threshold`: The total number of approvals for this dispatch before it is executed. * `other_signatories`: The accounts (other than the sender) who can approve this dispatch. May not be empty. * `maybe_timepoint`: If this is the first approval, then this must be `None`. If it is not the first approval, then it must be `Some`, with the timepoint (block number and transaction index) of the first approval transaction. * `call_hash`: The hash of the call to be executed. NOTE: If this is the final approval, you will want to use `as_multi` instead. **Namespace** ``` api.tx.multisig.approveAsMulti ``` **Type** ``` function approveAsMulti( threshold: u16, other_signatories: Vec, maybe_timepoint: Option, call_hash: [u8;32], max_weight: WeightV1 ) ``` ### asMulti Register approval for a dispatch to be made from a deterministic composite account if approved by a total of `threshold - 1` of `other_signatories`. If there are enough, then dispatch the call. Payment: `DepositBase` will be reserved if this is the first approval, plus `threshold` times `DepositFactor`. It is returned once this dispatch happens or is cancelled. The dispatch origin for this call must be *Signed*. * `threshold`: The total number of approvals for this dispatch before it is executed. * `other_signatories`: The accounts (other than the sender) who can approve this dispatch. May not be empty. * `maybe_timepoint`: If this is the first approval, then this must be `None`. If it is not the first approval, then it must be `Some`, with the timepoint (block number and transaction index) of the first approval transaction. * `call`: The call to be executed. NOTE: Unless this is the final approval, you will generally want to use `approve_as_multi` instead, since it only requires a hash of the call. Result is equivalent to the dispatched result if `threshold` is exactly `1`. Otherwise on success, result is `Ok` and the result from the interior call, if it was executed, may be found in the deposited `MultisigExecuted` event. **Namespace** ``` api.tx.multisig.asMulti ``` **Type** ``` function asMulti( threshold: u16, other_signatories: Vec, maybe_timepoint: Option, call: WrapperKeepOpaque, store_call: bool, max_weight: WeightV1 ) ``` ### asMultiThreshold1 Immediately dispatch a multi-signature call using a single approval from the caller. The dispatch origin for this call must be *Signed*. * `other_signatories`: The accounts (other than the sender) who are part of the multi-signature, but do not participate in the approval process. * `call`: The call to be executed. Result is equivalent to the dispatched result. **Namespace** ``` api.tx.multisig.asMultiThreshold1 ``` **Type** ``` function asMultiThreshold1( other_signatories: Vec, call: Call ) ``` ### cancelAsMulti Cancel a pre-existing, on-going multisig transaction. Any deposit reserved previously for this operation will be unreserved on success. The dispatch origin for this call must be *Signed*. * `threshold`: The total number of approvals for this dispatch before it is executed. * `other_signatories`: The accounts (other than the sender) who can approve this dispatch. May not be empty. * `timepoint`: The timepoint (block number and transaction index) of the first approval transaction for this dispatch. * `call_hash`: The hash of the call to be executed. **Namespace** ``` api.tx.multisig.cancelAsMulti ``` **Type** ``` function cancelAsMulti( threshold: u16, other_signatories: Vec, timepoint: PalletMultisigTimepoint, call_hash: [u8;32] ) ``` ## Storage ### calls **Namespace** ``` api.query.multisig.calls ``` **Type** ``` function calls( [u8;32] ): Option<(WrapperKeepOpaque,SeedPrimitivesSignatureAccountId20,u128)> ``` ### multisigs The set of open multisig operations. **Namespace** ``` api.query.multisig.multisigs ``` **Type** ``` function multisigs( SeedPrimitivesSignatureAccountId20, [u8;32] ): Option ``` ## Events ### MultisigApproval A multisig operation has been approved by someone. **Namespace** ``` api.events.multisig.MultisigApproval ``` **Type** ``` type MultisigApproval = { approving: SeedPrimitivesSignatureAccountId20, timepoint: PalletMultisigTimepoint, multisig: SeedPrimitivesSignatureAccountId20, call_hash: [u8;32] } ``` ### MultisigCancelled A multisig operation has been cancelled. **Namespace** ``` api.events.multisig.MultisigCancelled ``` **Type** ``` type MultisigCancelled = { cancelling: SeedPrimitivesSignatureAccountId20, timepoint: PalletMultisigTimepoint, multisig: SeedPrimitivesSignatureAccountId20, call_hash: [u8;32] } ``` ### MultisigExecuted A multisig operation has been executed. **Namespace** ``` api.events.multisig.MultisigExecuted ``` **Type** ``` type MultisigExecuted = { approving: SeedPrimitivesSignatureAccountId20, timepoint: PalletMultisigTimepoint, multisig: SeedPrimitivesSignatureAccountId20, call_hash: [u8;32], result: Result } ``` ### NewMultisig A new multisig operation has begun. **Namespace** ``` api.events.multisig.NewMultisig ``` **Type** ``` type NewMultisig = { approving: SeedPrimitivesSignatureAccountId20, multisig: SeedPrimitivesSignatureAccountId20, call_hash: [u8;32] } ``` ## Errors ### AlreadyApproved Call is already approved by this signatory. **Namespace** ``` api.errors.multisig.AlreadyApproved ``` ### AlreadyStored The data to be stored is already stored. **Namespace** ``` api.errors.multisig.AlreadyStored ``` ### MaxWeightTooLow The maximum weight information provided was too low. **Namespace** ``` api.errors.multisig.MaxWeightTooLow ``` ### MinimumThreshold Threshold must be 2 or greater. **Namespace** ``` api.errors.multisig.MinimumThreshold ``` ### NoApprovalsNeeded Call doesn't need any (more) approvals. **Namespace** ``` api.errors.multisig.NoApprovalsNeeded ``` ### NotFound Multisig operation not found when attempting to cancel. **Namespace** ``` api.errors.multisig.NotFound ``` ### NoTimepoint No timepoint was given, yet the multisig operation is already underway. **Namespace** ``` api.errors.multisig.NoTimepoint ``` ### NotOwner Only the account that originally created the multisig is able to cancel it. **Namespace** ``` api.errors.multisig.NotOwner ``` ### SenderInSignatories The sender was contained in the other signatories; it shouldn't be. **Namespace** ``` api.errors.multisig.SenderInSignatories ``` ### SignatoriesOutOfOrder The signatories were provided out of order; they should be ordered. **Namespace** ``` api.errors.multisig.SignatoriesOutOfOrder ``` ### TooFewSignatories There are too few signatories in the list. **Namespace** ``` api.errors.multisig.TooFewSignatories ``` ### TooManySignatories There are too many signatories in the list. **Namespace** ``` api.errors.multisig.TooManySignatories ``` ### UnexpectedTimepoint A timepoint was given, yet no multisig operation is underway. **Namespace** ``` api.errors.multisig.UnexpectedTimepoint ``` ### WrongTimepoint A different timepoint was given to the multisig operation that is underway. **Namespace** ``` api.errors.multisig.WrongTimepoint ``` ## Constants ### depositBase The base amount of currency needed to reserve for creating a multisig execution or to store a dispatch call for later. This is held for an additional storage item whose value size is `4 + sizeof((BlockNumber, Balance, AccountId))` bytes and whose key size is `32 + sizeof(AccountId)` bytes. **Namespace** ``` api.consts.multisig.depositBase ``` **Type** ``` type depositBase = u128 ``` ### depositFactor The amount of currency needed per unit threshold when creating a multisig execution. This is held for adding 32 bytes more into a pre-existing storage value. **Namespace** ``` api.consts.multisig.depositFactor ``` **Type** ``` type depositFactor = u128 ``` ### maxSignatories The maximum amount of signatories allowed in the multisig. **Namespace** ``` api.consts.multisig.maxSignatories ``` **Type** ``` type maxSignatories = u16 ``` # NFI Source: https://docs.therootnetwork.com/build/substrate/api-reference/runtime-pallets/nfi The NFI (Non-Fungible Intelligence) pallet allows for enabling NFI compatibility on new or existing collections. Once enabled, when an NFI-compatible NFT/SFT is minted, our trusted relayer will automatically generate the NFI data, storing the resulting NFIData on-chain. Note: There may be an additional charge for NFTs minted with NFI enabled. See the [**MintFee**](/build/substrate/api-reference/runtime-pallets/nfi#mint-fee) section below. 0.5% of the mint fee is sent to the Vortex for redistribution to network participants. *** ## Pallet Calls *** #### Enable NFI > Enables NFI compatibility on a collection. Caller must be the collection owner > > **Namespace:** > > ``` > api.tx.nfi.enableNfi > ``` > > **Type:** > > ``` > function enableNfi( > collection_id: u32, > sub_type: SeedPrimitivesNfiNFISubType > ) > ``` #### Manual Data Request > Users can manually request NFI data if it does not already exist on a token. This can be used to manually request data for pre-existing tokens in a collection that has had NFI enabled Caller must be either the token owner or the collection owner Note. the mint fee will need to be paid for any manual request > > **Namespace:** > > ``` > api.tx.nfi.manualDataRequest > ``` > > **Type:** > > ``` > function manualDataRequest( > token_id: (u32,u32), > sub_type: SeedPrimitivesNfiNFISubType > ) > ``` #### Submit NFI Data > Submit NFI data to the chain. Caller must be the registered relayer. NFI must be enabled for the collection > > **Namespace:** > > ``` > api.tx.nfi.submitNfiData > ``` > > **Type:** > > ``` > function submitNfiData( > token_id: (u32,u32), > data_item: SeedPrimitivesNfiNFIDataType > ) > ``` #### Set Fee Details (Sudo Only) > Set the NFI mint fee which is paid per token by the minter. Setting fee\_details to None removes the mint fee > > **Namespace:** > > ``` > api.tx.nfi.setFeeDetails > ``` > > **Type:** > > ``` > function setFeeDetails( > sub_type: SeedPrimitivesNfiNFISubType, > fee_details: Option > ) > ``` #### Set Relayer (Sudo Only) > Set the relayer address. This address is able to submit the NFI data back to the chain. Caller must be sudo > > **Namespace:** > > ``` > api.tx.nfi.setRelayer > ``` > > **Type:** > > ``` > function setRelayer( > relayer: SeedPrimitivesSignatureAccountId20, > ) > ``` #### Set Fee To (Sudo Only) > Set the 'FeeTo' account. Caller must be sudo > > **Namespace:** > > ``` > api.tx.nfi.setFeeTo > ``` > > **Type:** > > ``` > function setFeeTo( > fee_to: Option, > ) > ``` *** ## Pallet Storage *** #### Relayer > Stores the permission enabled relayer account > > **Namespace:** > > ``` > api.query.nfi.relayer > ``` > > **Type:** > > ``` > function relayer(): Option > ``` #### Mint Fee > Stores the extra mint fee that is charged for NFI enabled tokens > > **Namespace:** > > ``` > api.query.nfi.mintFee > ``` > > **Type:** > > ``` > function mintFee( > SeedPrimitivesNfiNFISubType > ): SeedPrimitivesNfiFeeDetails > ``` #### NFI Data > Stores the NFI Data linked to a token > > **Namespace:** > > ``` > api.query.nfi.nfiData > ``` > > **Type:** > > ``` > function nfiData( > (u32,u32), // token_id > SeedPrimitivesNfiNFISubType > ): SeedPrimitivesNfiDataType > ``` #### NFI Enabled > Whether or not NFI is enabled for a collection > > **Namespace:** > > ``` > api.query.nfi.nfiEnabled > ``` > > **Type:** > > ``` > function nfiEnabled( > u32, // collection_id > SeedPrimitivesNfiNFISubType > ): boolean > ``` #### Fee To > The Fee To address that collects network fees > > **Namespace:** > > ``` > api.query.nfi.feeTo > ``` > > **Type:** > > ``` > function feeTo(): Option > ``` *** ## Pallet Events *** #### Data Request > Request for new NFI data creation > > **Namespace:** > > ``` > api.events.nfi.DataRequest > ``` > > **Type:** > > ``` > type DataRequest = { > sub_type: SeedPrimitivesNfiNFISubType, > caller: SeedPrimitivesSignatureAccountId20, > collection_id: u32, > serial_numbers: Vec > } > ``` #### Data Set > A new NFI storage item has been set > > **Namespace:** > > ``` > api.events.nfi.DataSet > ``` > > **Type:** > > ``` > type DataSet = { > sub_type: SeedPrimitivesNfiNFISubType, > token_id: (u32,u32), > data_item: SeedPrimitivesNfiNFIDataType > } > ``` #### Data Removed > NFI storage has been removed for a token > > **Namespace:** > > ``` > api.events.nfi.DataRemoved > ``` > > **Type:** > > ``` > type DataRemoved = { > token_id: (u32,u32) > } > ``` #### Fee Details Set > New fee details have been set > > **Namespace:** > > ``` > api.events.nfi.FeeDetailsSet > ``` > > **Type:** > > ``` > type FeeDetailsSet = { > sub_type: SeedPrimitivesNfiNFISubType, > fee_details: SeedPrimitivesNfiFeeDetails > } > ``` #### Fee To Set > The network fee receiver address has been updated > > **Namespace:** > > ``` > api.events.nfi.FeeToSet > ``` > > **Type:** > > ``` > type FeeToSet = { > account: SeedPrimitivesSignatureAccountId20 > } > ``` #### Mint Fee Paid > Additional mint fee has been paid to the receiver address > > **Namespace:** > > ``` > api.events.nfi.MintFeePaid > ``` > > **Type:** > > ``` > type MintFeePaid = { > sub_type: SeedPrimitivesNfiNFISubType, > who: SeedPrimitivesSignatureAccountId20, > asset_id: u32, > total_fee: u128 > } > ``` #### NFI Enabled > NFI compatibility enabled for a collection > > **Namespace:** > > ``` > api.events.nfi.NfiEnabled > ``` > > **Type:** > > ``` > type NfiEnabled = { > sub_type: SeedPrimitivesNfiNFISubType, > collection_id: u32, > } > ``` #### Relayer Set > A new relayer has been set > > **Namespace:** > > ``` > api.events.nfi.RelayerSet > ``` > > **Type:** > > ``` > type RelayerSet = { > account: SeedPrimitivesSignatureAccountId20 > } > ``` *** ## Pallet Errors *** #### Invalid Mint Fee > The mint fee must be a valid integer above 0 > > **Namespace:** > > ``` > api.errors.nfi.InvalidMintFee > ``` #### Not Enabled > NFI storage is not enabled for this collection > > **Namespace:** > > ``` > api.errors.nfi.NotEnabled > ``` #### Not Relayer > The caller is not the relayer and does not have permission to perform this action > > **Namespace:** > > ``` > api.errors.nfi.NotRelayer > ``` #### Not Collection Owner > The caller is not the collection owner and does not have permission to perform this action > > **Namespace:** > > ``` > api.errors.nfi.NotCollectionOwner > ``` #### Not Token Owner > The caller is not the token owner and does not have permission to perform this action > > **Namespace:** > > ``` > api.errors.nfi.NotTokenOwner > ``` #### No Token > The token does not exist > > **Namespace:** > > ``` > api.errors.nfi.NoToken > ``` *** ## Pallet Constants *** #### Network Fee Percentage > Percentage of sale price to charge for network fees > > **Namespace:** > > ``` > api.consts.nfi.NetworkFeePercentage > ``` > > **Type:** > > ``` > type NetworkFeePercentage = Permill > ``` #### Max Data Length > Maximum length of data stored per token > > **Namespace:** > > ``` > api.consts.nfi.MaxDataLength > ``` > > **Type:** > > ``` > type MaxDataLength = u32 > ``` # NFT Source: https://docs.therootnetwork.com/build/substrate/api-reference/runtime-pallets/nft ## Calls ### burn Burn a token 🔥 Caller must be the token owner **Namespace** ``` api.tx.nft.burn ``` **Type** ``` function burn( token_id: (u32,u32) ) ``` ### claimUnownedCollection Bridged collections from Ethereum will initially lack an owner. These collections will be assigned to the pallet. This allows for claiming those collections assuming they were assigned to the pallet **Namespace** ``` api.tx.nft.claimUnownedCollection ``` **Type** ``` function claimUnownedCollection( collection_id: u32, new_owner: SeedPrimitivesSignatureAccountId20 ) ``` ### createCollection Create a new collection Additional tokens can be minted via `mint` * `name` - the name of the collection * `initial_issuance` - number of tokens to mint now * `max_issuance` - maximum number of tokens allowed in collection * `token_owner` - the token owner, defaults to the caller * `metadata_scheme` - The off-chain metadata referencing scheme for tokens in this * `royalties_schedule` - defacto royalties plan for secondary sales, this will apply to all tokens in the collection by default * `cross_chain_compatibility` - Is this collection XLS-20 compatible. Note, if enabled, the metadata\_scheme will be immutable **Namespace** ``` api.tx.nft.createCollection ``` **Type** ``` function createCollection( name: Bytes, initial_issuance: u32, max_issuance: Option, token_owner: Option, metadata_scheme: Bytes, royalties_schedule: Option, cross_chain_compatibility: PalletNftCrossChainCompatibility ) ``` ### mint Mint tokens for an existing collection * `collection_id` - the collection to mint tokens in * `quantity` - how many tokens to mint * `token_owner` - the token owner, defaults to the caller if unspecified Caller must be the collection owner **Namespace** ``` api.tx.nft.mint ``` **Type** ``` function mint( collection_id: u32, quantity: u32, token_owner: Option ) ``` ### setBaseUri Set the base URI of a collection Caller must be the current collection owner.\\ Cannot change if XLS20 compatibility is enabled. **Namespace** ``` api.tx.nft.setBaseUri ``` **Type** ``` function setBaseUri( collection_id: u32, base_uri: Bytes ) ``` ### setMaxIssuance Set the max issuance of a collection Caller must be the current collection owner **Namespace** ``` api.tx.nft.setMaxIssuance ``` **Type** ``` function setMaxIssuance( collection_id: u32, max_issuance: u32 ) ``` ### setMintFee **Namespace** ``` api.tx.nft.setMintFee ``` **Type** ``` function setMintFee( collection_id: u32, pricing_details: Option<(u32,u128)> ) ``` ### setName Set the name of a collection Caller must be the current collection owner **Namespace** ``` api.tx.nft.setName ``` **Type** ``` function setName( collection_id: u32, name: Bytes ) ``` ### setOwner Set the owner of a collection Caller must be the current collection owner **Namespace** ``` api.tx.nft.setOwner ``` **Type** ``` function setOwner( collection_id: u32, new_owner: SeedPrimitivesSignatureAccountId20 ) ``` ### setRoyaltiesSchedule Set the royalties schedule of a collection Caller must be the current collection owner **Namespace** ``` api.tx.nft.setRoyaltiesSchedule ``` **Type** ``` function setRoyaltiesSchedule( collection_id: u32, royalties_schedule: SeedPrimitivesNftRoyaltiesSchedule ) ``` ### togglePublicMint **Namespace** ``` api.tx.nft.togglePublicMint ``` **Type** ``` function togglePublicMint( collection_id: u32, enabled: bool ) ``` ### transfer Transfer ownership of an NFT Caller must be the token owner **Namespace** ``` api.tx.nft.transfer ``` **Type** ``` function transfer( collection_id: u32, serial_numbers: Vec, new_owner: SeedPrimitivesSignatureAccountId20 ) ``` ### setUtilityFlags Set utility flags of a collection. Allows the restriction of certain operations on a collection such as transfer, burn or mint. Flags apply to all tokens in the collection, but individual token flags take priority over collection flags. * `collection_id` - The collection to set the utility flags for * `utility_flags` - An object containing the utility flags. ``` CollectionUtilityFlags { transferable: bool, burnable: bool, mintable: bool, } ``` **Namespace** ``` api.tx.nft.setUtilityFlags ``` **Type** ``` function setUtilityFlags( collection_id: u32, utility_flags: CollectionUtilityFlags, ) ``` ### setTokenTransferableFlag Set transferable flag on a token, allowing or disallowing transfers. Token utility flags take priority over the collection utility flags, enabling fine-grained control over individual token transferability. **Priority Order:** 1. Token-level flags (highest priority) 2. Collection-level flags (fallback) * `token_id` - The token id (collection\_id, serial\_number) to set the flags for * `transferable` - Whether the token should be transferable **Note:** Soulbound tokens cannot have their utility flags modified after issuance. **Namespace** ``` api.tx.nft.setTokenTransferableFlag ``` **Type** ``` function setTokenTransferableFlag( token_id: (u32,u32), transferable: bool ) ``` ### issueSoulbound Issue soulbound tokens. The issuance will be pending until the designated token owner [accepts the issuance](./nft#acceptsoulboundissuance). Soulbound tokens will always be non-transferable. * `collection_id` - The collection id to create the issuance for * `quantity` - The number of tokens to issue * `token_owner` - Account id of the token owner * `burn_authority` - The token burn authority. This value will dictate which account is allowed to burn the token, and cannot be altered post-issuance. ``` TokenBurnAuthority { /// The token can be burned by the collection_owner CollectionOwner, /// The token can be burned by the token_owner TokenOwner, /// The token can be burned by either token or collection owner Both, /// The token cannot be burned by anyone Neither, } ``` **Namespace** ``` api.tx.nft.issueSoulbound ``` **Type** ``` function issueSoulbound( collection_id: u32, quantity: u32, token_owner: SeedPrimitivesSignatureAccountId20, burn_authority: TokenBurnAuthority ) ``` ### acceptSoulboundIssuance Accept the issuance of a soulbound token * `collection_id` - The collection id the issuance is for * `issuance_id` - The issuance id. An issuance id is created and emitted when a soulbound token is issued. All pending issuances for an account can be retrieved by querying the collection's [pending issuances](./nft#pendingissuances). **Namespace** ``` api.tx.nft.acceptSoulboundIssuance ``` **Type** ``` function acceptSoulboundIssuance( collection_id: u32, issuance_id: u32, ) ``` ### setAdditionalData Sets additional data for a token. This allows storing extra information for a token outside the collection metadata. * `token_id` - The token id (collection\_id, serial\_number) to set data for * `additional_data` - Optional additional data. Pass `None` to remove existing data **Namespace** ``` api.tx.nft.setAdditionalData ``` **Type** ``` function setAdditionalData( token_id: (u32,u32), additional_data: Option ) ``` ### mintWithAdditionalData Mint a single token alongside some additional data. This is equivalent to calling `mint` followed by `setAdditionalData`, but more efficient. * `collection_id` - The collection to mint the token in * `token_owner` - The token owner, defaults to the caller if unspecified * `additional_data` - Additional data to store with the token **Namespace** ``` api.tx.nft.mintWithAdditionalData ``` **Type** ``` function mintWithAdditionalData( collection_id: u32, token_owner: Option, additional_data: Bytes ) ``` ## Storage ### collectionInfo Map from collection to its information **Namespace** ``` api.query.nft.collectionInfo ``` **Type** ``` function collectionInfo( u32 ): Option ``` ### tokenInfo Map from a token to its information, including owner, lock status and utility flags **Namespace** ``` api.query.nft.tokenInfo ``` **Type** ``` type TokenInformation = { owner: SeedPrimitivesSignatureAccountId20, lock_status: Option, utility_flags: { transferable: bool, burn_authority: Option } } function tokenInfo( collection_id: u32, serial_number: u32 ): Option ``` ### ownedTokens All tokens owned by a single account, organized by collection **Namespace** ``` api.query.nft.ownedTokens ``` **Type** ``` function ownedTokens( account_id: SeedPrimitivesSignatureAccountId20, collection_id: u32 ): Vec ``` ### nextCollectionId The next available incrementing collection id **Namespace** ``` api.query.nft.nextCollectionId ``` **Type** ``` function nextCollectionId( ): u32 ``` ### publicMintInfo Map from collection to its public minting information **Namespace** ``` api.query.nft.publicMintInfo ``` **Type** ``` function publicMintInfo( u32 ): Option ``` ### utilityFlags Map from a collection id to its utility flags. These flags control operations at the collection level and apply to all tokens unless overridden by token-specific flags. **Namespace** ``` api.query.nft.utilityFlags ``` **Type** ``` type CollectionUtilityFlags = { transferable: bool, burnable: bool, mintable: bool, } function utilityFlags(u32): CollectionUtilityFlags ``` ### additionalTokenData Map from a token\_id to additional token data. Useful for assigning extra information to a token outside the collection metadata. **Namespace** ``` api.query.nft.additionalTokenData ``` **Type** ``` function additionalTokenData( (u32, u32) ): Bytes ``` ### tokenUtilityFlags Map from a token id to its utility flags. Token-level flags take priority over collection-level flags, allowing fine-grained control over individual tokens. **Namespace** ``` api.query.nft.tokenUtilityFlags ``` **Type** ``` type TokenUtilityFlags = { transferable: bool, burnAuthority: Option, } function tokenUtilityFlags( (u32, u32) ): TokenUtilityFlags ``` ### pendingIssuances Map from a collection id to the collection's pending issuances **Namespace** ``` api.query.nft.pendingIssuances ``` **Type** ``` type PendingIssuance = { issuanceId: u32; quantity: u32; burnAuthority: TokenBurnAuthority; } type CollectionPendingIssuances = { nextIssuanceId: u32; pendingIssuances: Vec<(AccountId, PendingIssuance)>; } function pendingIssuances( u32 ): CollectionPendingIssuances ``` Can be used to retrieve pending issuances for a particular account. ``` const collectionIssuances = await api.query.nft.pendingIssuances(collectionId); const pendingIssuances = collectionIssuances. pendingIssuances. toJSON(). find((p) => p[0] === accountId); ``` ## Events ### BaseUriSet Base URI was set **Namespace** ``` api.events.nft.BaseUriSet ``` **Type** ``` type BaseUriSet = { collection_id: u32, base_uri: Bytes } ``` ### BridgedMint Token(s) were bridged **Namespace** ``` api.events.nft.BridgedMint ``` **Type** ``` type BridgedMint = { collection_id: u32, serial_numbers: Vec, owner: SeedPrimitivesSignatureAccountId20 } ``` ### Burn A token was burned **Namespace** ``` api.events.nft.Burn ``` **Type** ``` type Burn = { token_owner: SeedPrimitivesSignatureAccountId20, collection_id: u32, serial_number: u32 } ``` ### CollectionClaimed Collection has been claimed **Namespace** ``` api.events.nft.CollectionClaimed ``` **Type** ``` type CollectionClaimed = { account: SeedPrimitivesSignatureAccountId20, collection_id: u32 } ``` ### CollectionCreate A new collection of tokens was created **Namespace** ``` api.events.nft.CollectionCreate ``` **Type** ``` type CollectionCreate = { collection_uuid: u32, initial_issuance: u32, max_issuance: Option, collection_owner: SeedPrimitivesSignatureAccountId20, metadata_scheme: Bytes, name: Bytes, royalties_schedule: Option, origin_chain: SeedPrimitivesNftOriginChain, compatibility: PalletNftCrossChainCompatibility } ``` ### MaxIssuanceSet Max issuance was set **Namespace** ``` api.events.nft.MaxIssuanceSet ``` **Type** ``` type MaxIssuanceSet = { collection_id: u32, max_issuance: u32 } ``` ### Mint Token(s) were minted **Namespace** ``` api.events.nft.Mint ``` **Type** ``` type Mint = { collection_id: u32, start: u32, end: u32, owner: SeedPrimitivesSignatureAccountId20 } ``` ### MintFeePaid Payment was made to cover a public mint **Namespace** ``` api.events.nft.MintFeePaid ``` **Type** ``` type MintFeePaid = { who: SeedPrimitivesSignatureAccountId20, collection_id: u32, payment_asset: u32, payment_amount: u128, token_count: u32 } ``` ### MintPriceSet A mint price was set for a collection **Namespace** ``` api.events.nft.MintPriceSet ``` **Type** ``` type MintPriceSet = { collection_id: u32, payment_asset: Option, mint_price: Option } ``` ### NameSet Name was set **Namespace** ``` api.events.nft.NameSet ``` **Type** ``` type NameSet = { collection_id: u32, name: Bytes } ``` ### OwnerSet A new owner was set **Namespace** ``` api.events.nft.OwnerSet ``` **Type** ``` type OwnerSet = { collection_id: u32, new_owner: SeedPrimitivesSignatureAccountId20 } ``` ### PublicMintToggle Public minting was enabled/disabled for a collection **Namespace** ``` api.events.nft.PublicMintToggle ``` **Type** ``` type PublicMintToggle = { collection_id: u32, enabled: bool } ``` ### RoyaltiesScheduleSet Royalties schedule was set **Namespace** ``` api.events.nft.RoyaltiesScheduleSet ``` **Type** ``` type RoyaltiesScheduleSet = { collection_id: u32, royalties_schedule: SeedPrimitivesNftRoyaltiesSchedule } ``` ### Transfer A token was transferred **Namespace** ``` api.events.nft.Transfer ``` **Type** ``` type Transfer = { previous_owner: SeedPrimitivesSignatureAccountId20, collection_id: u32, serial_numbers: Vec, new_owner: SeedPrimitivesSignatureAccountId20 } ``` ### UtilityFlagsSet Utility flags were set for a collection **Namespace** ``` api.events.nft.UtilityFlagsSet ``` **Type** ``` type UtilityFlagsSet = { collection_id: u32, utility_flags: CollectionUtilityFlags } ``` ### TokenTransferableFlagSet Token transferable flag was set **Namespace** ``` api.events.nft.TokenTransferableFlagSet ``` **Type** ``` type TokenTransferableFlagSet = { token_id: (u32, u32), transferable: bool } ``` ### PendingIssuanceCreated A pending issuance for a soulbound token was created **Namespace** ``` api.events.nft.PendingIssuanceCreated ``` **Type** ``` type PendingIssuanceCreated = { collection_id: u32, issuance_id: u32, token_owner: SeedPrimitivesSignatureAccountId20, quantity: u32, burn_authority: TokenBurnAuthority, } ``` ### Issued Soulbound tokens were successfully issued **Namespace** ``` api.events.nft.Issued ``` **Type** ``` type Issued = { token_owner: SeedPrimitivesSignatureAccountId20, start: u32, end: u32, burn_authority: TokenBurnAuthority, } ``` ### AdditionalDataSet Some additional data has been set for a token **Namespace** ``` api.events.nft.AdditionalDataSet ``` **Type** ``` type AdditionalDataSet = { token_id: (u32, u32), additional_data: Option, } ``` ## Errors ### AttemptedMintOnBridgedToken Attemped to mint a token that was bridged from a different chain **Namespace** ``` api.errors.nft.AttemptedMintOnBridgedToken ``` ### BlockedMint Token(s) blocked from minting during the bridging process **Namespace** ``` api.errors.nft.BlockedMint ``` ### CannotClaimNonClaimableCollections Cannot claim already claimed collections **Namespace** ``` api.errors.nft.CannotClaimNonClaimableCollections ``` ### CannotUpdateMetadata Only Root originated NFTs that are not XLS-20 compatible can have their metadata updated **Namespace** ``` api.errors.nft.CannotUpdateMetadata ``` ### CollectionIssuanceNotZero Total issuance of collection must be zero to add xls20 compatibility **Namespace** ``` api.errors.nft.CollectionIssuanceNotZero ``` ### MintUtilityBlocked Minting has been disabled for tokens within this collection **Namespace** ``` api.errors.nft.MintUtilityBlocked ``` ### CollectionNameInvalid Given collection name is invalid (invalid utf-8, too long, empty) **Namespace** ``` api.errors.nft.CollectionNameInvalid ``` ### InitialIssuanceNotZero Initial issuance on XLS-20 compatible collections must be zero **Namespace** ``` api.errors.nft.InitialIssuanceNotZero ``` ### InvalidMaxIssuance Max issuance needs to be greater than 0 and initial\_issuance Cannot exceed MaxTokensPerCollection **Namespace** ``` api.errors.nft.InvalidMaxIssuance ``` ### InvalidMetadataPath The metadata path is invalid (non-utf8 or empty) **Namespace** ``` api.errors.nft.InvalidMetadataPath ``` ### InvalidNewOwner The caller can not be the new owner **Namespace** ``` api.errors.nft.InvalidNewOwner ``` ### InvalidAdditionalData The additional data cannot be an empty vec **Namespace** ``` api.errors.nft.InvalidAdditionalData ``` ### MaxIssuanceAlreadySet The max issuance has already been set and can't be changed **Namespace** ``` api.errors.nft.MaxIssuanceAlreadySet ``` ### MaxIssuanceReached The collection max issuance has been reached and no more tokens can be minted **Namespace** ``` api.errors.nft.MaxIssuanceReached ``` ### MintLimitExceeded The quantity exceeds the max tokens per mint limit **Namespace** ``` api.errors.nft.MintLimitExceeded ``` ### NoAvailableIds No more Ids are available, they've been exhausted **Namespace** ``` api.errors.nft.NoAvailableIds ``` ### NoCollectionFound The collection does not exist **Namespace** ``` api.errors.nft.NoCollectionFound ``` ### NotCollectionOwner Origin is not the collection owner and is not permitted to perform the operation **Namespace** ``` api.errors.nft.NotCollectionOwner ``` ### NoToken The token does not exist **Namespace** ``` api.errors.nft.NoToken ``` ### NotTokenOwner Origin does not own the NFT **Namespace** ``` api.errors.nft.NotTokenOwner ``` ### PublicMintDisabled This collection has not allowed public minting **Namespace** ``` api.errors.nft.PublicMintDisabled ``` ### RoyaltiesInvalid Total royalties would exceed 100% of sale or an empty vec is supplied **Namespace** ``` api.errors.nft.RoyaltiesInvalid ``` ### TokenLimitExceeded The number of tokens have exceeded the max tokens allowed **Namespace** ``` api.errors.nft.TokenLimitExceeded ``` ### TokenLocked Cannot operate on a listed NFT **Namespace** ``` api.errors.nft.TokenLocked ``` ### TransferUtilityBlocked Transfer has been disabled for tokens within this collection **Namespace** ``` api.errors.nft.TransferUtilityBlocked ``` ### BurnUtilityBlocked Burning has been disabled for tokens within this collection **Namespace** ``` api.errors.nft.BurnUtilityBlocked ``` ### PendingIssuanceLimitExceeded The number of pending issuances has exceeded the max for a collection **Namespace** ``` api.errors.nft.PendingIssuanceLimitExceeded ``` ### InvalidPendingIssuance Attempted to accept an issuance that does not exist, or is not set for the caller **Namespace** ``` api.errors.nft.InvalidPendingIssuance ``` ### CannotUpdateTokenUtility Attempted to update the token utility flags for a soulbound token **Namespace** ``` api.errors.nft.CannotUpdateTokenUtility ``` ### InvalidBurnAuthority Attempted to burn a token from an account that does not adhere to the token's burn authority **Namespace** ``` api.errors.nft.InvalidBurnAuthority ``` ### SerialNumbersNotUnique The SerialNumbers attempting to be transferred are not unique **Namespace** ``` api.errors.nft.SerialNumbersNotUnique ``` ## Constants ### palletId This pallet's Id, used for deriving a sovereign account ID **Namespace** ``` api.consts.nft.palletId ``` **Type** ``` type palletId = FrameSupportPalletId ``` ### stringLimit The maximum length of a collection name, stored on-chain **Namespace** ``` api.consts.nft.stringLimit ``` **Type** ``` type stringLimit = u32 ``` ## JSON-RPC Methods ### `ownedTokens` Get all NFTs owned by an account **Interface** ``` api.rpc.nft.ownedTokens(collectionId: CollectionUuid, who: AccountId, cursor: SerialNumber, limit: u16): Json ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"nft_ownedTokens", "params":[collectionId: CollectionUuid, who: AccountId, cursor: SerialNumber, limit: u16] } ``` ### `tokenUri` Get the URI of a token **Interface** ``` api.rpc.nft.tokenUri(tokenId: TokenId): Json ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"nft_tokenUri", "params":[tokenId: TokenId] } ``` ### `collectionDetails` Get information related to a collection such as name, owner and max issuance **Interface** ``` api.rpc.nft.collectionDetails(collectionId: CollectionUuid): Json ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"nft_collectionDetails", "params":[collectionId: CollectionUuid] } ``` # NftPeg Source: https://docs.therootnetwork.com/build/substrate/api-reference/runtime-pallets/nftpeg ## Calls ### reclaimBlockedNfts Withdraw blocked tokens, must be called by the destination defined in `BlockedTokens` **Namespace** ``` api.tx.nftPeg.reclaimBlockedNfts ``` **Type** ``` function reclaimBlockedNfts( blocked_mint_id: u32, destination: H160 ) ``` ### setContractAddress **Namespace** ``` api.tx.nftPeg.setContractAddress ``` **Type** ``` function setContractAddress( contract: H160 ) ``` ### withdraw **Namespace** ``` api.tx.nftPeg.withdraw ``` **Type** ``` function withdraw( collection_ids: Vec, serial_numbers: Vec>, destination: H160 ) ``` ## Storage ### blockedTokens **Namespace** ``` api.query.nftPeg.blockedTokens ``` **Type** ``` function blockedTokens( u32 ): Option ``` ### contractAddress **Namespace** ``` api.query.nftPeg.contractAddress ``` **Type** ``` function contractAddress( ): H160 ``` ### ethToRootNft **Namespace** ``` api.query.nftPeg.ethToRootNft ``` **Type** ``` function ethToRootNft( H160 ): Option ``` ### nextBlockedMintId The next available BlockedMintId **Namespace** ``` api.query.nftPeg.nextBlockedMintId ``` **Type** ``` function nextBlockedMintId( ): u32 ``` ### rootNftToErc721 **Namespace** ``` api.query.nftPeg.rootNftToErc721 ``` **Type** ``` function rootNftToErc721( u32 ): Option ``` ## Events ### ContractAddressSet The NFT-peg contract address was set **Namespace** ``` api.events.nftPeg.ContractAddressSet ``` **Type** ``` type ContractAddressSet = { contract: H160 } ``` ### ERC721Blocked Bridged ERC721 tokens were unable to be minted due to collection limit being reached **Namespace** ``` api.events.nftPeg.ERC721Blocked ``` **Type** ``` type ERC721Blocked = { blocked_mint_id: u32, destination_address: SeedPrimitivesSignatureAccountId20, collection_id: u32, serial_numbers: Vec } ``` ### Erc721Deposit An ERC721 deposit was made **Namespace** ``` api.events.nftPeg.Erc721Deposit ``` **Type** ``` type Erc721Deposit = { destination: SeedPrimitivesSignatureAccountId20 } ``` ### Erc721Mint Bridged ERC721 tokens were minted **Namespace** ``` api.events.nftPeg.Erc721Mint ``` **Type** ``` type Erc721Mint = { collection_id: u32, serial_numbers: Vec, owner: SeedPrimitivesSignatureAccountId20 } ``` ### Erc721Withdraw An ERC721 withdraw was made **Namespace** ``` api.events.nftPeg.Erc721Withdraw ``` **Type** ``` type Erc721Withdraw = { origin: SeedPrimitivesSignatureAccountId20, collection_ids: Vec, serial_numbers: Vec>, destination: H160 } ``` ## Errors ### ExceedsMaxAddresses Send more addresses than are allowed **Namespace** ``` api.errors.nftPeg.ExceedsMaxAddresses ``` ### ExceedsMaxTokens Sent more tokens than are allowed **Namespace** ``` api.errors.nftPeg.ExceedsMaxTokens ``` ### ExceedsMaxVecLength The length of the given vec exceeds the maximal allowed length limit **Namespace** ``` api.errors.nftPeg.ExceedsMaxVecLength ``` ### InvalidAbiEncoding The abi data passed in could not be decoded **Namespace** ``` api.errors.nftPeg.InvalidAbiEncoding ``` ### InvalidAbiPrefix The prefix uint in the abi encoded data was invalid **Namespace** ``` api.errors.nftPeg.InvalidAbiPrefix ``` ### NoBlockedTokensFound No blocked tokens for the given id **Namespace** ``` api.errors.nftPeg.NoBlockedTokensFound ``` ### NoCollectionFound No collection info exists **Namespace** ``` api.errors.nftPeg.NoCollectionFound ``` ### NoMappedTokenExists No mapped token was stored for bridging the token back to the bridged chain **Namespace** ``` api.errors.nftPeg.NoMappedTokenExists ``` ### NoPermissionToBridge Tried to bridge a token that originates from Root, which is not yet supported **Namespace** ``` api.errors.nftPeg.NoPermissionToBridge ``` ### NotBlockedTokenDestination Blocked tokens can only be reclaimed by the destination address **Namespace** ``` api.errors.nftPeg.NotBlockedTokenDestination ``` ### StateSyncDisabled The state sync decoding feature is not implemented **Namespace** ``` api.errors.nftPeg.StateSyncDisabled ``` ### TokenListLengthMismatch Multiple tokens were passed from contract, but amounts were unqeual per each array **Namespace** ``` api.errors.nftPeg.TokenListLengthMismatch ``` ## Constants ### delayLength **Namespace** ``` api.consts.nftPeg.delayLength ``` **Type** ``` type delayLength = u32 ``` # Offences Source: https://docs.therootnetwork.com/build/substrate/api-reference/runtime-pallets/offences ## Storage ### concurrentReportsIndex A vector of reports of the same kind that happened at the same time slot. **Namespace** ``` api.query.offences.concurrentReportsIndex ``` **Type** ``` function concurrentReportsIndex( [u8;16], Bytes ): Vec ``` ### reports The primary structure that holds all offence records keyed by report identifiers. **Namespace** ``` api.query.offences.reports ``` **Type** ``` function reports( H256 ): Option ``` ### reportsByKindIndex Enumerates all reports of a kind along with the time they happened. All reports are sorted by the time of offence. Note that the actual type of this mapping is `Vec`, this is because values of different types are not supported at the moment so we are doing the manual serialization. **Namespace** ``` api.query.offences.reportsByKindIndex ``` **Type** ``` function reportsByKindIndex( [u8;16] ): Bytes ``` ## Events ### Offence There is an offence reported of the given `kind` happened at the `session_index` and (kind-specific) time slot. This event is not deposited for duplicate slashes. \[kind, timeslot]. **Namespace** ``` api.events.offences.Offence ``` **Type** ``` type Offence = { kind: [u8;16], timeslot: Bytes } ``` # Preimage Source: https://docs.therootnetwork.com/build/substrate/api-reference/runtime-pallets/preimage ## Calls ### notePreimage Register a preimage on-chain. If the preimage was previously requested, no fees or deposits are taken for providing the preimage. Otherwise, a deposit is taken proportional to the size of the preimage. **Namespace** ``` api.tx.preimage.notePreimage ``` **Type** ``` function notePreimage( bytes: Bytes ) ``` ### requestPreimage Request a preimage be uploaded to the chain without paying any fees or deposits. If the preimage requests has already been provided on-chain, we unreserve any deposit a user may have paid, and take the control of the preimage out of their hands. **Namespace** ``` api.tx.preimage.requestPreimage ``` **Type** ``` function requestPreimage( hash: H256 ) ``` ### unnotePreimage Clear an unrequested preimage from the runtime storage. **Namespace** ``` api.tx.preimage.unnotePreimage ``` **Type** ``` function unnotePreimage( hash: H256 ) ``` ### unrequestPreimage Clear a previously made request for a preimage. IMPORTANT: This must not be called on`hash`more times than`request_preimage`. **Namespace** ``` api.tx.preimage.unrequestPreimage ``` **Type** ``` function unrequestPreimage( hash: H256 ) ``` ## Storage ### preimageFor The preimages stored by this pallet. **Namespace** ``` api.query.preimage.preimageFor ``` **Type** ``` function preimageFor( H256 ): Option ``` ### statusFor The request status of a given hash. **Namespace** ``` api.query.preimage.statusFor ``` **Type** ``` function statusFor( H256 ): Option ``` ## Events ### Cleared A preimage has ben cleared. **Namespace** ``` api.events.preimage.Cleared ``` **Type** ``` type Cleared = { hash: H256 } ``` ### Noted A preimage has been noted. **Namespace** ``` api.events.preimage.Noted ``` **Type** ``` type Noted = { hash: H256 } ``` ### Requested A preimage has been requested. **Namespace** ``` api.events.preimage.Requested ``` **Type** ``` type Requested = { hash: H256 } ``` ## Errors ### AlreadyNoted Preimage has already been noted on-chain. **Namespace** ``` api.errors.preimage.AlreadyNoted ``` ### NotAuthorized The user is not authorized to perform this action. **Namespace** ``` api.errors.preimage.NotAuthorized ``` ### NotNoted The preimage cannot be removed since it has not yet been noted. **Namespace** ``` api.errors.preimage.NotNoted ``` ### NotRequested The preimage request cannot be removed since no outstanding requests exist. **Namespace** ``` api.errors.preimage.NotRequested ``` ### Requested A preimage may not be removed when there are outstanding requests. **Namespace** ``` api.errors.preimage.Requested ``` ### TooLarge Preimage is too large to store on-chain. **Namespace** ``` api.errors.preimage.TooLarge ``` undefined # Proxy Source: https://docs.therootnetwork.com/build/substrate/api-reference/runtime-pallets/proxy ## Calls ### addProxy Register a proxy account for the sender that is able to make calls on its behalf. The dispatch origin for this call must be *Signed*. Parameters: * `proxy`: The account that the `caller` would like to make a proxy. * `proxy_type`: The permissions allowed for this proxy account. * `delay`: The announcement period required of the initial proxy. Will generally be zero. **Namespace** ``` api.tx.proxy.addProxy ``` **Type** ``` function addProxy( delegate: SeedPrimitivesSignatureAccountId20, proxy_type: SeedRuntimeImplsProxyType, delay: u32 ) ``` ### announce Publish the hash of a proxy-call that will be made in the future. This must be called some number of blocks before the corresponding `proxy` is attempted if the delay associated with the proxy relationship is greater than zero. No more than `MaxPending` announcements may be made at any one time. This will take a deposit of `AnnouncementDepositFactor` as well as `AnnouncementDepositBase` if there are no other pending announcements. The dispatch origin for this call must be *Signed* and a proxy of `real`. Parameters: * `real`: The account that the proxy will make a call on behalf of. * `call_hash`: The hash of the call to be made by the `real` account. **Namespace** ``` api.tx.proxy.announce ``` **Type** ``` function announce( real: SeedPrimitivesSignatureAccountId20, call_hash: H256 ) ``` ### createPure Spawn a fresh new account that is guaranteed to be otherwise inaccessible, and initialize it with a proxy of `proxy_type` for `origin` sender. Requires a `Signed` origin. * `proxy_type`: The type of the proxy that the sender will be registered as over the new account. This will almost always be the most permissive `ProxyType` possible to allow for maximum flexibility. * `index`: A disambiguation index, in case this is called multiple times in the same transaction (e.g. with `utility::batch`). Unless you're using `batch` you probably just want to use `0`. * `delay`: The announcement period required of the initial proxy. Will generally be zero. Fails with `Duplicate` if this has already been called in this transaction, from the same sender, with the same parameters. Fails if there are insufficient funds to pay for deposit. **Namespace** ``` api.tx.proxy.createPure ``` **Type** ``` function createPure( proxy_type: SeedRuntimeImplsProxyType, delay: u32, index: u16 ) ``` ### killPure Removes a previously spawned pure proxy. WARNING: **All access to this account will be lost.** Any funds held in it will be inaccessible. Requires a `Signed` origin and the sender account must have been created by a call to `pure` with corresponding parameters. * `spawner`: The account that was originally called `pure` to create this account. * `index`: The disambiguation index originally passed to `pure`. Probably `0`. * `proxy_type`: The proxy type originally passed to `pure`. * `height`: The height of the chain when the call to `pure` was processed. * `ext_index`: The extrinsic index in which the call to `pure` was processed. Fails with `NoPermission` in case the caller is not a previously created pure account whose `pure` call has corresponding parameters. **Namespace** ``` api.tx.proxy.killPure ``` **Type** ``` function killPure( spawner: SeedPrimitivesSignatureAccountId20, proxy_type: SeedRuntimeImplsProxyType, index: u16, height: Compact, ext_index: Compact ) ``` ### proxy Dispatch the given `call` from an account that the sender is authorised for through `add_proxy`. Removes any corresponding announcement(s). The dispatch origin for this call must be *Signed*. Parameters: * `real`: The account that the proxy will make a call on behalf of. * `force_proxy_type`: Specify the exact proxy type to be used and checked for this call. * `call`: The call to be made by the `real` account. **Namespace** ``` api.tx.proxy.proxy ``` **Type** ``` function proxy( real: SeedPrimitivesSignatureAccountId20, force_proxy_type: Option, call: Call ) ``` ### proxyAnnounced Dispatch the given `call` from an account that the sender is authorized for through `add_proxy`. Removes any corresponding announcement(s). The dispatch origin for this call must be *Signed*. Parameters: * `real`: The account that the proxy will make a call on behalf of. * `force_proxy_type`: Specify the exact proxy type to be used and checked for this call. * `call`: The call to be made by the `real` account. **Namespace** ``` api.tx.proxy.proxyAnnounced ``` **Type** ``` function proxyAnnounced( delegate: SeedPrimitivesSignatureAccountId20, real: SeedPrimitivesSignatureAccountId20, force_proxy_type: Option, call: Call ) ``` ### rejectAnnouncement Remove the given announcement of a delegate. May be called by a target (proxied) account to remove a call that one of their delegates (`delegate`) has announced they want to execute. The deposit is returned. The dispatch origin for this call must be *Signed*. Parameters: * `delegate`: The account that previously announced the call. * `call_hash`: The hash of the call to be made. **Namespace** ``` api.tx.proxy.rejectAnnouncement ``` **Type** ``` function rejectAnnouncement( delegate: SeedPrimitivesSignatureAccountId20, call_hash: H256 ) ``` ### removeAnnouncement Remove a given announcement. May be called by a proxy account to remove a call they previously announced and return the deposit. The dispatch origin for this call must be *Signed*. Parameters: * `real`: The account that the proxy will make a call on behalf of. * `call_hash`: The hash of the call to be made by the `real` account. **Namespace** ``` api.tx.proxy.removeAnnouncement ``` **Type** ``` function removeAnnouncement( real: SeedPrimitivesSignatureAccountId20, call_hash: H256 ) ``` ### removeProxies Unregister all proxy accounts for the sender. The dispatch origin for this call must be *Signed*. WARNING: This may be called on accounts created by `pure`, however, if done, then the unreserved fees will be inaccessible. **All access to this account will be lost.** **Namespace** ``` api.tx.proxy.removeProxies ``` **Type** ``` function removeProxies( ) ``` ### removeProxy Unregister a proxy account for the sender. The dispatch origin for this call must be *Signed*. Parameters: * `proxy`: The account that the `caller` would like to remove as a proxy. * `proxy_type`: The permissions currently enabled for the removed proxy account. **Namespace** ``` api.tx.proxy.removeProxy ``` **Type** ``` function removeProxy( delegate: SeedPrimitivesSignatureAccountId20, proxy_type: SeedRuntimeImplsProxyType, delay: u32 ) ``` ## Storage ### announcements The announcements made by the proxy (key). **Namespace** ``` api.query.proxy.announcements ``` **Type** ``` function announcements( SeedPrimitivesSignatureAccountId20 ): (Vec,u128) ``` ### proxies The set of account proxies. Maps the account which has delegated to the accounts which are being delegated to, together with the amount held on deposit. **Namespace** ``` api.query.proxy.proxies ``` **Type** ``` function proxies( SeedPrimitivesSignatureAccountId20 ): (Vec,u128) ``` ## Events ### Announced An announcement was placed to make a call in the future. **Namespace** ``` api.events.proxy.Announced ``` **Type** ``` type Announced = { real: SeedPrimitivesSignatureAccountId20, proxy: SeedPrimitivesSignatureAccountId20, call_hash: H256 } ``` ### ProxyAdded A proxy was added. **Namespace** ``` api.events.proxy.ProxyAdded ``` **Type** ``` type ProxyAdded = { delegator: SeedPrimitivesSignatureAccountId20, delegatee: SeedPrimitivesSignatureAccountId20, proxy_type: SeedRuntimeImplsProxyType, delay: u32 } ``` ### ProxyExecuted A proxy was executed correctly, with the given. **Namespace** ``` api.events.proxy.ProxyExecuted ``` **Type** ``` type ProxyExecuted = { result: Result } ``` ### ProxyRemoved A proxy was removed. **Namespace** ``` api.events.proxy.ProxyRemoved ``` **Type** ``` type ProxyRemoved = { delegator: SeedPrimitivesSignatureAccountId20, delegatee: SeedPrimitivesSignatureAccountId20, proxy_type: SeedRuntimeImplsProxyType, delay: u32 } ``` ### PureCreated A pure account has been created by new proxy with given disambiguation index and proxy type. **Namespace** ``` api.events.proxy.PureCreated ``` **Type** ``` type PureCreated = { pure: SeedPrimitivesSignatureAccountId20, who: SeedPrimitivesSignatureAccountId20, proxy_type: SeedRuntimeImplsProxyType, disambiguation_index: u16 } ``` ## Errors ### Duplicate Account is already a proxy. **Namespace** ``` api.errors.proxy.Duplicate ``` ### NoPermission Call may not be made by proxy because it may escalate its privileges. **Namespace** ``` api.errors.proxy.NoPermission ``` ### NoSelfProxy Cannot add self as proxy. **Namespace** ``` api.errors.proxy.NoSelfProxy ``` ### NotFound Proxy registration not found. **Namespace** ``` api.errors.proxy.NotFound ``` ### NotProxy Sender is not a proxy of the account to be proxied. **Namespace** ``` api.errors.proxy.NotProxy ``` ### TooMany There are too many proxies registered or too many announcements pending. **Namespace** ``` api.errors.proxy.TooMany ``` ### Unannounced Announcement, if made at all, was made too recently. **Namespace** ``` api.errors.proxy.Unannounced ``` ### Unproxyable A call which is incompatible with the proxy type's filter was attempted. **Namespace** ``` api.errors.proxy.Unproxyable ``` ## Constants ### announcementDepositBase The base amount of currency needed to reserve for creating an announcement. This is held when a new storage item holding a `Balance` is created (typically 16 bytes). **Namespace** ``` api.consts.proxy.announcementDepositBase ``` **Type** ``` type announcementDepositBase = u128 ``` ### announcementDepositFactor The amount of currency needed per announcement made. This is held for adding an `AccountId`, `Hash` and `BlockNumber` (typically 68 bytes) into a pre-existing storage value. **Namespace** ``` api.consts.proxy.announcementDepositFactor ``` **Type** ``` type announcementDepositFactor = u128 ``` ### maxPending The maximum amount of time-delayed announcements that are allowed to be pending. **Namespace** ``` api.consts.proxy.maxPending ``` **Type** ``` type maxPending = u32 ``` ### maxProxies The maximum amount of proxies allowed for a single account. **Namespace** ``` api.consts.proxy.maxProxies ``` **Type** ``` type maxProxies = u32 ``` ### proxyDepositBase The base amount of currency needed to reserve for creating a proxy. This is held for an additional storage item whose value size is `sizeof(Balance)` bytes and whose key size is `sizeof(AccountId)` bytes. **Namespace** ``` api.consts.proxy.proxyDepositBase ``` **Type** ``` type proxyDepositBase = u128 ``` ### proxyDepositFactor The amount of currency needed per proxy added. This is held for adding 32 bytes plus an instance of `ProxyType` more into a pre-existing storage value. Thus, when configuring `ProxyDepositFactor` one should take into account `32 + proxy_type.encode().len()` bytes of data. **Namespace** ``` api.consts.proxy.proxyDepositFactor ``` **Type** ``` type proxyDepositFactor = u128 ``` # Recovery Source: https://docs.therootnetwork.com/build/substrate/api-reference/runtime-pallets/recovery ## Calls ### asRecovered Send a call through a recovered account. The dispatch origin for this call must be *Signed* and registered to be able to make calls on behalf of the recovered account. Parameters: * `account`: The recovered account you want to make a call on-behalf-of. * `call`: The call you want to make with the recovered account. **Namespace** ``` api.tx.recovery.asRecovered ``` **Type** ``` function asRecovered( account: SeedPrimitivesSignatureAccountId20, call: Call ) ``` ### cancelRecovered Cancel the ability to use `as_recovered` for `account`. The dispatch origin for this call must be *Signed* and registered to be able to make calls on behalf of the recovered account. Parameters: * `account`: The recovered account you are able to call on-behalf-of. **Namespace** ``` api.tx.recovery.cancelRecovered ``` **Type** ``` function cancelRecovered( account: SeedPrimitivesSignatureAccountId20 ) ``` ### claimRecovery Allow a successful rescuer to claim their recovered account. The dispatch origin for this call must be *Signed* and must be a "rescuer" who has successfully completed the account recovery process: collected `threshold` or more vouches, waited `delay_period` blocks since initiation. Parameters: * `account`: The lost account that you want to claim has been successfully recovered by you. **Namespace** ``` api.tx.recovery.claimRecovery ``` **Type** ``` function claimRecovery( account: SeedPrimitivesSignatureAccountId20 ) ``` ### closeRecovery As the controller of a recoverable account, close an active recovery process for your account. Payment: By calling this function, the recoverable account will receive the recovery deposit `RecoveryDeposit` placed by the rescuer. The dispatch origin for this call must be *Signed* and must be a recoverable account with an active recovery process for it. Parameters: * `rescuer`: The account trying to rescue this recoverable account. **Namespace** ``` api.tx.recovery.closeRecovery ``` **Type** ``` function closeRecovery( rescuer: SeedPrimitivesSignatureAccountId20 ) ``` ### createRecovery Create a recovery configuration for your account. This makes your account recoverable. Payment: `ConfigDepositBase` + `FriendDepositFactor` \* #\_of\_friends balance will be reserved for storing the recovery configuration. This deposit is returned in full when the user calls `remove_recovery`. The dispatch origin for this call must be *Signed*. Parameters: * `friends`: A list of friends you trust to vouch for recovery attempts. Should be ordered and contain no duplicate values. * `threshold`: The number of friends that must vouch for a recovery attempt before the account can be recovered. Should be less than or equal to the length of the list of friends. * `delay_period`: The number of blocks after a recovery attempt is initialized that needs to pass before the account can be recovered. **Namespace** ``` api.tx.recovery.createRecovery ``` **Type** ``` function createRecovery( friends: Vec, threshold: u16, delay_period: u32 ) ``` ### initiateRecovery Initiate the process for recovering a recoverable account. Payment: `RecoveryDeposit` balance will be reserved for initiating the recovery process. This deposit will always be repatriated to the account trying to be recovered. See `close_recovery`. The dispatch origin for this call must be *Signed*. Parameters: * `account`: The lost account that you want to recover. This account needs to be recoverable (i.e. have a recovery configuration). **Namespace** ``` api.tx.recovery.initiateRecovery ``` **Type** ``` function initiateRecovery( account: SeedPrimitivesSignatureAccountId20 ) ``` ### removeRecovery Remove the recovery process for your account. Recovered accounts are still accessible. **Note**: The user must make sure to call `close_recovery` on all active recovery attempts before calling this function else it will fail. Payment: By calling this function the recoverable account will unreserve their recovery configuration deposit. (`ConfigDepositBase` + `FriendDepositFactor` \* #\_of\_friends) The dispatch origin for this call must be *Signed* and must be a recoverable account (i.e. has a recovery configuration). **Namespace** ``` api.tx.recovery.removeRecovery ``` **Type** ``` function removeRecovery( ) ``` ### setRecovered Allow ROOT to bypass the recovery process and set an a rescuer account for a lost account directly. The dispatch origin for this call must be *ROOT*. Parameters: * `lost`: The "lost account" to be recovered. * `rescuer`: The "rescuer account" which can call as the lost account. **Namespace** ``` api.tx.recovery.setRecovered ``` **Type** ``` function setRecovered( lost: SeedPrimitivesSignatureAccountId20, rescuer: SeedPrimitivesSignatureAccountId20 ) ``` ### vouchRecovery Allow a "friend" of a recoverable account to vouch for an active recovery process for that account. The dispatch origin for this call must be *Signed* and must be a "friend" for the recoverable account. Parameters: * `lost`: The lost account that you want to recover. * `rescuer`: The account trying to rescue the lost account that you want to vouch for. The combination of these two parameters must point to an active recovery process. **Namespace** ``` api.tx.recovery.vouchRecovery ``` **Type** ``` function vouchRecovery( lost: SeedPrimitivesSignatureAccountId20, rescuer: SeedPrimitivesSignatureAccountId20 ) ``` ## Storage ### activeRecoveries Active recovery attempts. First account is the account to be recovered, and the second account is the user trying to recover the account. **Namespace** ``` api.query.recovery.activeRecoveries ``` **Type** ``` function activeRecoveries( SeedPrimitivesSignatureAccountId20, SeedPrimitivesSignatureAccountId20 ): Option ``` ### proxy The list of allowed proxy accounts. Map from the user who can access it to the recovered account. **Namespace** ``` api.query.recovery.proxy ``` **Type** ``` function proxy( SeedPrimitivesSignatureAccountId20 ): Option ``` ### recoverable The set of recoverable accounts and their recovery configuration. **Namespace** ``` api.query.recovery.recoverable ``` **Type** ``` function recoverable( SeedPrimitivesSignatureAccountId20 ): Option ``` ## Events ### AccountRecovered Lost account has been successfully recovered by the rescuer account. **Namespace** ``` api.events.recovery.AccountRecovered ``` **Type** ``` type AccountRecovered = { lost_account: SeedPrimitivesSignatureAccountId20, rescuer_account: SeedPrimitivesSignatureAccountId20 } ``` ### RecoveryClosed A recovery process for lost account by rescuer account has been closed. **Namespace** ``` api.events.recovery.RecoveryClosed ``` **Type** ``` type RecoveryClosed = { lost_account: SeedPrimitivesSignatureAccountId20, rescuer_account: SeedPrimitivesSignatureAccountId20 } ``` ### RecoveryCreated A recovery process has been set up for an account. **Namespace** ``` api.events.recovery.RecoveryCreated ``` **Type** ``` type RecoveryCreated = { account: SeedPrimitivesSignatureAccountId20 } ``` ### RecoveryInitiated A recovery process has been initiated for lost account by rescuer account. **Namespace** ``` api.events.recovery.RecoveryInitiated ``` **Type** ``` type RecoveryInitiated = { lost_account: SeedPrimitivesSignatureAccountId20, rescuer_account: SeedPrimitivesSignatureAccountId20 } ``` ### RecoveryRemoved A recovery process has been removed for an account. **Namespace** ``` api.events.recovery.RecoveryRemoved ``` **Type** ``` type RecoveryRemoved = { lost_account: SeedPrimitivesSignatureAccountId20 } ``` ### RecoveryVouched A recovery process for a lost account by rescuer account has been vouched for by the sender. **Namespace** ``` api.events.recovery.RecoveryVouched ``` **Type** ``` type RecoveryVouched = { lost_account: SeedPrimitivesSignatureAccountId20, rescuer_account: SeedPrimitivesSignatureAccountId20, sender: SeedPrimitivesSignatureAccountId20 } ``` ## Errors ### AlreadyProxy This account is already set up for recovery **Namespace** ``` api.errors.recovery.AlreadyProxy ``` ### AlreadyRecoverable This account is already set up for recovery **Namespace** ``` api.errors.recovery.AlreadyRecoverable ``` ### AlreadyStarted A recovery process has already started for this account **Namespace** ``` api.errors.recovery.AlreadyStarted ``` ### AlreadyVouched This user has already vouched for this recovery **Namespace** ``` api.errors.recovery.AlreadyVouched ``` ### BadState Some internal state is broken. **Namespace** ``` api.errors.recovery.BadState ``` ### DelayPeriod The friend must wait until the delay period to vouch for this recovery **Namespace** ``` api.errors.recovery.DelayPeriod ``` ### MaxFriends Friends list must be less than max friends **Namespace** ``` api.errors.recovery.MaxFriends ``` ### NotAllowed User is not allowed to make a call on behalf of this account **Namespace** ``` api.errors.recovery.NotAllowed ``` ### NotEnoughFriends Friends list must be greater than zero and threshold **Namespace** ``` api.errors.recovery.NotEnoughFriends ``` ### NotFriend This account is not a friend who can vouch **Namespace** ``` api.errors.recovery.NotFriend ``` ### NotRecoverable This account is not set up for recovery **Namespace** ``` api.errors.recovery.NotRecoverable ``` ### NotSorted Friends list must be sorted and free of duplicates **Namespace** ``` api.errors.recovery.NotSorted ``` ### NotStarted A recovery process has not started for this rescuer **Namespace** ``` api.errors.recovery.NotStarted ``` ### StillActive There are still active recovery attempts that need to be closed **Namespace** ``` api.errors.recovery.StillActive ``` ### Threshold The threshold for recovering this account has not been met **Namespace** ``` api.errors.recovery.Threshold ``` ### ZeroThreshold Threshold must be greater than zero **Namespace** ``` api.errors.recovery.ZeroThreshold ``` ## Constants ### configDepositBase The base amount of currency needed to reserve for creating a recovery configuration. This is held for an additional storage item whose value size is `2 + sizeof(BlockNumber, Balance)` bytes. **Namespace** ``` api.consts.recovery.configDepositBase ``` **Type** ``` type configDepositBase = u128 ``` ### friendDepositFactor The amount of currency needed per additional user when creating a recovery configuration. This is held for adding `sizeof(AccountId)` bytes more into a pre-existing storage value. **Namespace** ``` api.consts.recovery.friendDepositFactor ``` **Type** ``` type friendDepositFactor = u128 ``` ### maxFriends The maximum amount of friends allowed in a recovery configuration. **NOTE**: The threshold programmed in this Pallet uses u16, so it does not make sense to have a limit here greater than u16::MAX. But also, that is a lot more than you should probably set this value to anyway. **Namespace** ``` api.consts.recovery.maxFriends ``` **Type** ``` type maxFriends = u32 ``` ### recoveryDeposit The base amount of currency needed to reserve for starting a recovery. This is primarily held for deterring malicious recovery attempts, and should have a value large enough that a bad actor would choose not to place this deposit. It also acts to fund additional storage item whose value size is `sizeof(BlockNumber, Balance + T * AccountId)` bytes. Where T is a configurable threshold. **Namespace** ``` api.consts.recovery.recoveryDeposit ``` **Type** ``` type recoveryDeposit = u128 ``` # Scheduler Source: https://docs.therootnetwork.com/build/substrate/api-reference/runtime-pallets/scheduler ## Calls ### cancel Cancel an anonymously scheduled task. **Namespace** ``` api.tx.scheduler.cancel ``` **Type** ``` function cancel( when: u32, index: u32 ) ``` ### cancelNamed Cancel a named scheduled task. **Namespace** ``` api.tx.scheduler.cancelNamed ``` **Type** ``` function cancelNamed( id: Bytes ) ``` ### schedule Anonymously schedule a task. **Namespace** ``` api.tx.scheduler.schedule ``` **Type** ``` function schedule( when: u32, maybe_periodic: Option<(u32,u32)>, priority: u8, call: FrameSupportScheduleMaybeHashed ) ``` ### scheduleAfter Anonymously schedule a task after a delay. **Namespace** ``` api.tx.scheduler.scheduleAfter ``` **Type** ``` function scheduleAfter( after: u32, maybe_periodic: Option<(u32,u32)>, priority: u8, call: FrameSupportScheduleMaybeHashed ) ``` ### scheduleNamed Schedule a named task. **Namespace** ``` api.tx.scheduler.scheduleNamed ``` **Type** ``` function scheduleNamed( id: Bytes, when: u32, maybe_periodic: Option<(u32,u32)>, priority: u8, call: FrameSupportScheduleMaybeHashed ) ``` ### scheduleNamedAfter Schedule a named task after a delay. **Namespace** ``` api.tx.scheduler.scheduleNamedAfter ``` **Type** ``` function scheduleNamedAfter( id: Bytes, after: u32, maybe_periodic: Option<(u32,u32)>, priority: u8, call: FrameSupportScheduleMaybeHashed ) ``` ## Storage ### agenda Items to be executed, indexed by the block number that they should be executed on. **Namespace** ``` api.query.scheduler.agenda ``` **Type** ``` function agenda( u32 ): Vec> ``` ### lookup Lookup from identity to the block number and index of the task. **Namespace** ``` api.query.scheduler.lookup ``` **Type** ``` function lookup( Bytes ): Option<(u32,u32)> ``` ## Events ### CallLookupFailed The call for the provided hash was not found so the task has been aborted. **Namespace** ``` api.events.scheduler.CallLookupFailed ``` **Type** ``` type CallLookupFailed = { task: (u32,u32), id: Option, error: FrameSupportScheduleLookupError } ``` ### Canceled Canceled some task. **Namespace** ``` api.events.scheduler.Canceled ``` **Type** ``` type Canceled = { when: u32, index: u32 } ``` ### Dispatched Dispatched some task. **Namespace** ``` api.events.scheduler.Dispatched ``` **Type** ``` type Dispatched = { task: (u32,u32), id: Option, result: Result } ``` ### Scheduled Scheduled some task. **Namespace** ``` api.events.scheduler.Scheduled ``` **Type** ``` type Scheduled = { when: u32, index: u32 } ``` ## Errors ### FailedToSchedule Failed to schedule a call **Namespace** ``` api.errors.scheduler.FailedToSchedule ``` ### NotFound Cannot find the scheduled call. **Namespace** ``` api.errors.scheduler.NotFound ``` ### RescheduleNoChange Reschedule failed because it does not change scheduled time. **Namespace** ``` api.errors.scheduler.RescheduleNoChange ``` ### TargetBlockNumberInPast Given target block number is in the past. **Namespace** ``` api.errors.scheduler.TargetBlockNumberInPast ``` ## Constants ### maximumWeight The maximum weight that may be scheduled per block for any dispatchables of less priority than `schedule::HARD_DEADLINE`. **Namespace** ``` api.consts.scheduler.maximumWeight ``` **Type** ``` type maximumWeight = WeightV1 ``` ### maxScheduledPerBlock The maximum number of scheduled calls in the queue for a single block. Not strictly enforced, but used for weight estimation. **Namespace** ``` api.consts.scheduler.maxScheduledPerBlock ``` **Type** ``` type maxScheduledPerBlock = u32 ``` # Session Source: https://docs.therootnetwork.com/build/substrate/api-reference/runtime-pallets/session ## Calls ### purgeKeys Removes any session key(s) of the function caller. This doesn't take effect until the next session. The dispatch origin of this function must be Signed and the account must be either be convertible to a validator ID using the chain's typical addressing system (this usually means being a controller account) or directly convertible into a validator ID (which usually means being a stash account). **Namespace** ``` api.tx.session.purgeKeys ``` **Type** ``` function purgeKeys( ) ``` ### setKeys Sets the session key(s) of the function caller to `keys`. Allows an account to set its session key prior to becoming a validator. This doesn't take effect until the next session. The dispatch origin of this function must be signed. **Namespace** ``` api.tx.session.setKeys ``` **Type** ``` function setKeys( keys: SeedRuntimeSessionKeys, proof: Bytes ) ``` ## Storage ### currentIndex Current index of the session. **Namespace** ``` api.query.session.currentIndex ``` **Type** ``` function currentIndex( ): u32 ``` ### disabledValidators Indices of disabled validators. The vec is always kept sorted so that we can find whether a given validator is disabled using binary search. It gets cleared when `on_session_ending` returns a new set of identities. **Namespace** ``` api.query.session.disabledValidators ``` **Type** ``` function disabledValidators( ): Vec ``` ### keyOwner The owner of a key. The key is the `KeyTypeId` + the encoded key. **Namespace** ``` api.query.session.keyOwner ``` **Type** ``` function keyOwner( (SpCoreCryptoKeyTypeId,Bytes) ): Option ``` ### nextKeys The next session keys for a validator. **Namespace** ``` api.query.session.nextKeys ``` **Type** ``` function nextKeys( SeedPrimitivesSignatureAccountId20 ): Option ``` ### queuedChanged True if the underlying economic identities or weighting behind the validators has changed in the queued validator set. **Namespace** ``` api.query.session.queuedChanged ``` **Type** ``` function queuedChanged( ): bool ``` ### queuedKeys The queued keys for the next session. When the next session begins, these keys will be used to determine the validator's session keys. **Namespace** ``` api.query.session.queuedKeys ``` **Type** ``` function queuedKeys( ): Vec<(SeedPrimitivesSignatureAccountId20,SeedRuntimeSessionKeys)> ``` ### validators The current set of validators. **Namespace** ``` api.query.session.validators ``` **Type** ``` function validators( ): Vec ``` ## Events ### NewSession New session has happened. Note that the argument is the session index, not the block number as the type might suggest. **Namespace** ``` api.events.session.NewSession ``` **Type** ``` type NewSession = { session_index: u32 } ``` ## Errors ### DuplicatedKey Registered duplicate key. **Namespace** ``` api.errors.session.DuplicatedKey ``` ### InvalidProof Invalid ownership proof. **Namespace** ``` api.errors.session.InvalidProof ``` ### NoAccount Key setting account is not live, so it's impossible to associate keys. **Namespace** ``` api.errors.session.NoAccount ``` ### NoAssociatedValidatorId No associated validator ID for account. **Namespace** ``` api.errors.session.NoAssociatedValidatorId ``` ### NoKeys No keys are associated with this account. **Namespace** ``` api.errors.session.NoKeys ``` undefined # Sft Source: https://docs.therootnetwork.com/build/substrate/api-reference/runtime-pallets/sft ## Calls ### burn Burn a token 🔥 Caller must be the token owner **Namespace** ``` api.tx.sft.burn ``` **Type** ``` function burn( collection_id: u32, serial_numbers: Vec<(u32,u128)> ) ``` ### createCollection Create a new collection to group multiple semi-fungible tokens Tokens can be created within the collection by calling create\_token `collection_name` - the name of the collection `collection_owner` - the collection owner, defaults to the caller `metadata_scheme` - The off-chain metadata referencing scheme for tokens in this `royalties_schedule` - defacto royalties plan for secondary sales, this will apply to all tokens in the collection by default. The collectionUuid used to store the SFT CollectionInfo is retrieved from the NFT pallet. This is so that CollectionUuids are unique across all collections, regardless of if they are SFT or NFT collections. **Namespace** ``` api.tx.sft.createCollection ``` **Type** ``` function createCollection( collection_name: Bytes, collection_owner: Option, metadata_scheme: Bytes, royalties_schedule: Option ) ``` ### createToken Create additional tokens for an existing collection These tokens act similar to tokens within an ERC1155 contract Each token has individual issuance, max\_issuance, **Namespace** ``` api.tx.sft.createToken ``` **Type** ``` function createToken( collection_id: u32, token_name: Bytes, initial_issuance: u128, max_issuance: Option, token_owner: Option ) ``` ### createTokenWithAdditionalData Create additional tokens for an existing collection with additional data. These tokens act similar to tokens within an ERC1155 contract. Each token has individual issuance, max\_issuance, and additional data. **Namespace** ``` api.tx.sft.createTokenWithAdditionalData ``` **Type** ``` function createTokenWithAdditionalData( collection_id: u32, token_name: Bytes, initial_issuance: u128, max_issuance: Option, token_owner: Option, additional_data: Bytes ) ``` ### mint Mints some balances into some serial numbers for an account This acts as a batch mint function and allows for multiple serial numbers and quantities to be passed in simultaneously. Must be called by the collection owner `collection_id` - the SFT collection to mint into `serial_numbers` - A list of serial numbers to mint into `quantities` - A list of quantities to mint into each serial number `token_owner` - The owner of the tokens, defaults to the caller **Namespace** ``` api.tx.sft.mint ``` **Type** ``` function mint( collection_id: u32, serial_numbers: Vec<(u32,u128)>, token_owner: Option ) ``` ### setBaseUri Set the base URI of a collection (MetadataScheme) Caller must be the current collection owner **Namespace** ``` api.tx.sft.setBaseUri ``` **Type** ``` function setBaseUri( collection_id: u32, metadata_scheme: Bytes ) ``` ### setMaxIssuance Set the max issuance of a collection Caller must be the current collection owner **Namespace** ``` api.tx.sft.setMaxIssuance ``` **Type** ``` function setMaxIssuance( token_id: (u32,u32), max_issuance: u128 ) ``` ### setMintFee **Namespace** ``` api.tx.sft.setMintFee ``` **Type** ``` function setMintFee( token_id: (u32,u32), pricing_details: Option<(u32,u128)> ) ``` ### setName Set the name of a collection Caller must be the current collection owner **Namespace** ``` api.tx.sft.setName ``` **Type** ``` function setName( collection_id: u32, collection_name: Bytes ) ``` ### setOwner Set the owner of a collection Caller must be the current collection owner **Namespace** ``` api.tx.sft.setOwner ``` **Type** ``` function setOwner( collection_id: u32, new_owner: SeedPrimitivesSignatureAccountId20 ) ``` ### setRoyaltiesSchedule Set the royalties schedule of a collection Caller must be the current collection owner **Namespace** ``` api.tx.sft.setRoyaltiesSchedule ``` **Type** ``` function setRoyaltiesSchedule( collection_id: u32, royalties_schedule: SeedPrimitivesNftRoyaltiesSchedule ) ``` ### togglePublicMint **Namespace** ``` api.tx.sft.togglePublicMint ``` **Type** ``` function togglePublicMint( token_id: (u32,u32), enabled: bool ) ``` ### setTokenName **Namespace** ``` api.tx.sft.setTokenName ``` **Type** ``` function setTokenName( token_id: (u32, u32), token_name: Bytes ) ``` ### transfer Transfer ownership of an SFT Caller must be the token owner **Namespace** ``` api.tx.sft.transfer ``` **Type** ``` function transfer( collection_id: u32, serial_numbers: Vec<(u32,u128)>, new_owner: SeedPrimitivesSignatureAccountId20 ) ``` ### setUtilityFlags Set utility flags of a collection. This allows restricting certain operations on a collection such as transfer, burn or mint. Caller must be the collection owner. * *collection\_id* - The id of the collection * *utility\_flags* - An object containing the utility flags. ``` CollectionUtilityFlags { transferable: bool, burnable: bool, mintable: bool, } ``` **Namespace** ``` api.tx.sft.setUtilityFlags ``` **Type** ``` function setUtilityFlags( collection_id: u32, utility_flags: CollectionUtilityFlags, ) ``` ### setTokenTransferableFlag Set transferable flag on a token, allowing or disallowing transfers. Caller must be the collection owner. **Namespace** ``` api.tx.sft.setTokenTransferableFlag ``` **Type** ``` function setTokenTransferableFlag( token_id: (u32, u32), transferable: bool, ) ``` ### setTokenBurnAuthority Set burn authority on a token. This value will be immutable once set. Caller must be the collection owner. * *token\_id* -. The token id * *burn\_authority* - The token burn authority. This value will dictate which account is allowed to burn the token. ``` TokenBurnAuthority { /// The token can be burned by the collection_owner CollectionOwner, /// The token can be burned by the token_owner TokenOwner, /// The token can be burned by either token or collection owner Both, /// The token cannot be burned by anyone Neither, } ``` **Namespace** `api.tx.sft.setTokenBurnAuthority` **Type** ``` function setTokenBurnAuthority( token_id: (u32, u32), burn_authority: TokenBurnAuthority ) ``` ### setAdditionalData Set additional data for a token. This allows collection owners or token owners to store custom data associated with specific tokens. * `token_id` - The token id to set additional data for * `additional_data` - Custom data to associate with the token **Namespace** ``` api.tx.sft.setAdditionalData ``` **Type** ``` function setAdditionalData( token_id: (u32,u32), additional_data: Bytes ) ``` ### burnAsCollectionOwner Burn a token as the collection owner. The burn authority must have already been set and set to either the collection owner or both. * *token\_owner* - The account id of the token owner * *collection\_id* - The collection id * *serial\_numbers* - Array of serial number and the amount of tokens to burn **Namespace** ``` api.tx.sft.burnAsCollectionOwner ``` **Type** ``` function burnAsCollectionOwner( token_owner: SeedPrimitivesSignatureAccountId20, collection_id: u32, serial_numbers: Vec ) ``` ### issueSoulbound Issue soulbound tokens. The issuance will be pending until the token owner accepts the issuance. The burn authority for the specified tokens must already have been set prior to attempting to issue the tokens. * *token\_owner* - Account id of the token owner. The tokens will be burned for this account. * *collection\_id* - The collection id to issue the tokens for * *serial\_numbers* - List of token ids and the amount to issue **Namespace** ``` api.tx.sft.issueSoulbound ``` **Type** ``` function issueSoulbound( colelction_id: u32, serial_numbers: Vec<(u32, u32)>, token_owner: ) ``` ### acceptSoulboundIssuance Accept the issuance of a soulbound tokens * *collection\_id* - The collection id * *issuance\_id* - The issuance id. An issuance id is created and emitted on issuance. All pending issuances for an account can be retrieved by querying the collection's [pending issuances](./sft#pendingissuances). **Namespace** ``` api.tx.sft.acceptSoulboundIssuance ``` **Type** ``` function acceptSoulboundIssuance( collection_id: u32, issuance_idL u32 ) ``` ## Storage ### publicMintInfo Map from collection to its public minting information **Namespace** ``` api.query.sft.publicMintInfo ``` **Type** ``` function publicMintInfo( (u32,u32) ): Option ``` ### sftCollectionInfo Map from collection to its information **Namespace** ``` api.query.sft.sftCollectionInfo ``` **Type** ``` function sftCollectionInfo( u32 ): Option ``` ### tokenInfo Map from token to its token information, including ownership information **Namespace** ``` api.query.sft.tokenInfo ``` **Type** ``` function tokenInfo( (u32,u32) ): Option ``` ### utilityFlags Map from a collection id to it's utility flags **Namespace** ``` api.query.sft.utilityFlags ``` **Type** ``` function utilityFlags(u32): CollectionUtilityFlags ``` ### tokenUtilityFlags Map from a token id to its utility flags **Namespace** ``` api.query.sft.tokenUtilityFlags ``` **Type** ``` type TokenUtilityFlags = { transferable: bool, burnAuthority: Option, } function tokenUtilityFlags( (u32, u32) ): TokenUtilityFlags ``` ### additionalData Map from a token id to its additional data **Namespace** ``` api.query.sft.additionalData ``` **Type** ``` function additionalData( (u32, u32) ): Option ``` ### pendingIssuances Map from a collection id to the collection's pending issuances **Namespace** ``` api.query.sft.pendingIssuances ``` **Type** ``` type SftPendingIssuance = { issuanceId: u32; serial_numbers: Vec<(u32, u32)> } type CollectionPendingIssuances = { nextIssuanceId: u32; pendingIssuances: Vec(AccountId, PendingIssuance) } function pendingIssuances( u32 ): CollectionPendingIssuances ``` Can be used to retrieve pending issuances for a particular account. ``` const collectionIssuances = await api.query.sft.pendingIssuances(collectionId); const pendingIssuances = collectionIssuances. pendingIssuances. toJSON(). find((p) => p[0] === accountId); ``` ## Events ### BaseUriSet Base URI was set **Namespace** ``` api.events.sft.BaseUriSet ``` **Type** ``` type BaseUriSet = { collection_id: u32, metadata_scheme: Bytes } ``` ### Burn A token was burned **Namespace** ``` api.events.sft.Burn ``` **Type** ``` type Burn = { collection_id: u32, serial_numbers: Vec, balances: Vec, owner: SeedPrimitivesSignatureAccountId20 } ``` ### CollectionCreate A new collection of tokens was created **Namespace** ``` api.events.sft.CollectionCreate ``` **Type** ``` type CollectionCreate = { collection_id: u32, collection_owner: SeedPrimitivesSignatureAccountId20, metadata_scheme: Bytes, name: Bytes, royalties_schedule: Option, origin_chain: SeedPrimitivesNftOriginChain } ``` ### MaxIssuanceSet Max issuance was set **Namespace** ``` api.events.sft.MaxIssuanceSet ``` **Type** ``` type MaxIssuanceSet = { token_id: (u32,u32), max_issuance: u128 } ``` ### Mint Token(s) were minted **Namespace** ``` api.events.sft.Mint ``` **Type** ``` type Mint = { collection_id: u32, serial_numbers: Vec, balances: Vec, owner: SeedPrimitivesSignatureAccountId20 } ``` ### MintFeePaid Payment was made to cover a public mint **Namespace** ``` api.events.sft.MintFeePaid ``` **Type** ``` type MintFeePaid = { who: SeedPrimitivesSignatureAccountId20, token_id: (u32,u32), payment_asset: u32, payment_amount: u128, token_count: u128 } ``` ### MintPriceSet A mint price was set for a collection **Namespace** ``` api.events.sft.MintPriceSet ``` **Type** ``` type MintPriceSet = { token_id: (u32,u32), payment_asset: Option, mint_price: Option } ``` ### NameSet Name was set **Namespace** ``` api.events.sft.NameSet ``` **Type** ``` type NameSet = { collection_id: u32, collection_name: Bytes } ``` ### OwnerSet A new owner was set **Namespace** ``` api.events.sft.OwnerSet ``` **Type** ``` type OwnerSet = { collection_id: u32, new_owner: SeedPrimitivesSignatureAccountId20 } ``` ### PublicMintToggle Public minting was enabled/disabled for a collection **Namespace** ``` api.events.sft.PublicMintToggle ``` **Type** ``` type PublicMintToggle = { token_id: (u32,u32), enabled: bool } ``` ### RoyaltiesScheduleSet Royalties schedule was set **Namespace** ``` api.events.sft.RoyaltiesScheduleSet ``` **Type** ``` type RoyaltiesScheduleSet = { collection_id: u32, royalties_schedule: SeedPrimitivesNftRoyaltiesSchedule } ``` ### TokenCreate A new token was created within a collection **Namespace** ``` api.events.sft.TokenCreate ``` **Type** ``` type TokenCreate = { token_id: (u32,u32), initial_issuance: u128, max_issuance: Option, token_name: Bytes, token_owner: SeedPrimitivesSignatureAccountId20 } ``` ### Transfer A token was transferred **Namespace** ``` api.events.sft.Transfer ``` **Type** ``` type Transfer = { previous_owner: SeedPrimitivesSignatureAccountId20, collection_id: u32, serial_numbers: Vec, balances: Vec, new_owner: SeedPrimitivesSignatureAccountId20 } ``` ### UtilityFlagsSet Utility flags were set for a collection **Namespace** ``` api.events.sft.UtilityFlagsSet ``` **Type** ``` type UtilityFlagsSet = { collection_id: u32, utility_flags: CollectionUtilityFlags, } ``` ### TokenTransferableFlagSet Token transferable flag was set **Namespace** ``` api.events.sft.TokenTransferableFlagSet ``` **Type** ``` type TokenTransferableFlagSet = { token_id: (u32, u32), transferable: bool, } ``` ### AdditionalDataSet Additional data was set for a token **Namespace** ``` api.events.sft.AdditionalDataSet ``` **Type** ``` type AdditionalDataSet = { token_id: (u32, u32), additional_data: Bytes } ``` ### PendingIssuanceCreated A pending issuance for a soulbound token has been created **Namespace** ``` api.events.sft.PendingIssuanceCreated ``` **Type** ``` PendingIssuanceCreated = { collection_id: u32, issuance_id: u32, serial_numbers: Vec, balances: Vec, token_owner: SeedPrimitivesSignatureAccountId20, } ``` ### Issued Soulbound tokens were successfully issued **Namespace** ``` api.events.sft.Issued ``` **Type** ``` type Issued = { token_owner: SeedPrimitivesSignatureAccountId20, serial_numbers: Vec, balances: Vec, } ``` ## Errors ### InsufficientBalance The user does not own enough of this token to perform the operation **Namespace** ``` api.errors.sft.InsufficientBalance ``` ### InvalidMaxIssuance Max issuance needs to be greater than 0 and initial\_issuance Cannot exceed MaxTokensPerCollection **Namespace** ``` api.errors.sft.InvalidMaxIssuance ``` ### InvalidNewOwner Caller can not be the new owner **Namespace** ``` api.errors.sft.InvalidNewOwner ``` ### InvalidQuantity The specified quantity must be greater than 0 **Namespace** ``` api.errors.sft.InvalidQuantity ``` ### MaxIssuanceAlreadySet The max issuance has already been set and can't be changed **Namespace** ``` api.errors.sft.MaxIssuanceAlreadySet ``` ### MaxIssuanceReached The collection max issuance has been reached and no more tokens can be minted **Namespace** ``` api.errors.sft.MaxIssuanceReached ``` ### MaxOwnersReached The max amount of owners per token has been reached **Namespace** ``` api.errors.sft.MaxOwnersReached ``` ### NameInvalid Given collection or token name is invalid (invalid utf-8, empty) **Namespace** ``` api.errors.sft.NameInvalid ``` ### NoCollectionFound The collection does not exist **Namespace** ``` api.errors.sft.NoCollectionFound ``` ### NotCollectionOwner Origin is not the collection owner and is not permitted to perform the operation **Namespace** ``` api.errors.sft.NotCollectionOwner ``` ### NoToken The token does not exist **Namespace** ``` api.errors.sft.NoToken ``` ### Overflow The operation would cause a numeric overflow **Namespace** ``` api.errors.sft.Overflow ``` ### PublicMintDisabled This collection has not allowed public minting **Namespace** ``` api.errors.sft.PublicMintDisabled ``` ### RoyaltiesInvalid Total royalties would exceed 100% of sale or an empty vec is supplied **Namespace** ``` api.errors.sft.RoyaltiesInvalid ``` ### InvalidAdditionalData The additional data provided is invalid or exceeds the maximum allowed size **Namespace** ``` api.errors.sft.InvalidAdditionalData ``` ## Constants ### maxOwnersPerSftToken Max unique owners that can own an SFT token **Namespace** ``` api.consts.sft.maxOwnersPerSftToken ``` **Type** ``` type maxOwnersPerSftToken = u32 ``` ### maxSerialsPerMint Max tokens that can be minted in one transaction **Namespace** ``` api.consts.sft.maxSerialsPerMint ``` **Type** ``` type maxSerialsPerMint = u32 ``` ### maxTokensPerSftCollection Max tokens that a collection can contain **Namespace** ``` api.consts.sft.maxTokensPerSftCollection ``` **Type** ``` type maxTokensPerSftCollection = u32 ``` ### palletId This pallet's Id, used for deriving a sovereign account ID **Namespace** ``` api.consts.sft.palletId ``` **Type** ``` type palletId = FrameSupportPalletId ``` ### stringLimit The maximum length of a collection or token name, stored on-chain **Namespace** ``` api.consts.sft.stringLimit ``` **Type** ``` type stringLimit = u32 ``` # Staking Source: https://docs.therootnetwork.com/build/substrate/api-reference/runtime-pallets/staking ## Calls ### bond Take the origin account as a stash and lock up `value` of its balance. `controller` will be the account that controls it. `value` must be more than the `minimum_balance` specified by `T::Currency`. The dispatch origin for this call must be *Signed* by the stash account. Emits `Bonded`. **Namespace** ``` api.tx.staking.bond ``` **Type** ``` function bond( controller: SeedPrimitivesSignatureAccountId20, value: Compact, payee: PalletStakingRewardDestination ) ``` ### bondExtra Add some extra amount that have appeared in the stash `free_balance` into the balance up for staking. The dispatch origin for this call must be *Signed* by the stash, not the controller. Use this if there are additional funds in your stash account that you wish to bond. Unlike [`bond`](Self::bond) or [`unbond`](Self::unbond) this function does not impose any limitation on the amount that can be added. Emits `Bonded`. **Namespace** ``` api.tx.staking.bondExtra ``` **Type** ``` function bondExtra( max_additional: Compact ) ``` ### cancelDeferredSlash Cancel enactment of a deferred slash. Can be called by the `T::SlashCancelOrigin`. Parameters: era and indices of the slashes for that era to kill. **Namespace** ``` api.tx.staking.cancelDeferredSlash ``` **Type** ``` function cancelDeferredSlash( era: u32, slash_indices: Vec ) ``` ### chill Declare no desire to either validate or nominate. Effects will be felt at the beginning of the next era. The dispatch origin for this call must be *Signed* by the controller, not the stash. **Namespace** ``` api.tx.staking.chill ``` **Type** ``` function chill( ) ``` ### chillOther Declare a `controller` to stop participating as either a validator or nominator. Effects will be felt at the beginning of the next era. The dispatch origin for this call must be *Signed*, but can be called by anyone. If the caller is the same as the controller being targeted, then no further checks are enforced, and this function behaves just like `chill`. If the caller is different than the controller being targeted, the following conditions must be met: * `controller` must belong to a nominator who has become non-decodable, Or: * A `ChillThreshold` must be set and checked which defines how close to the max nominators or validators we must reach before users can start chilling one-another. * A `MaxNominatorCount` and `MaxValidatorCount` must be set which is used to determine how close we are to the threshold. * A `MinNominatorBond` and `MinValidatorBond` must be set and checked, which determines if this is a person that should be chilled because they have not met the threshold bond required. This can be helpful if bond requirements are updated, and we need to remove old users who do not satisfy these requirements. **Namespace** ``` api.tx.staking.chillOther ``` **Type** ``` function chillOther( controller: SeedPrimitivesSignatureAccountId20 ) ``` ### forceApplyMinCommission Force a validator to have at least the minimum commission. This will not affect a validator who already has a commission greater than or equal to the minimum. Any account can call this. **Namespace** ``` api.tx.staking.forceApplyMinCommission ``` **Type** ``` function forceApplyMinCommission( validator_stash: SeedPrimitivesSignatureAccountId20 ) ``` ### forceNewEra Force there to be a new era at the end of the next session. After this, it will be reset to normal (non-forced) behaviour. The dispatch origin must be Root. **Warning:** The election process starts multiple blocks before the end of the era. If this is called just before a new era is triggered, the election process may not have enough blocks to get a result. **Namespace** ``` api.tx.staking.forceNewEra ``` **Type** ``` function forceNewEra( ) ``` ### forceNewEraAlways Force there to be a new era at the end of sessions indefinitely. The dispatch origin must be Root. **Warning:** The election process starts multiple blocks before the end of the era. If this is called just before a new era is triggered, the election process may not have enough blocks to get a result. **Namespace** ``` api.tx.staking.forceNewEraAlways ``` **Type** ``` function forceNewEraAlways( ) ``` ### forceNoEras Force there to be no new eras indefinitely. The dispatch origin must be Root. **Warning:** The election process starts multiple blocks before the end of the era. Thus the election process may be ongoing when this is called. In this case, the election will continue until the next era is triggered. **Namespace** ``` api.tx.staking.forceNoEras ``` **Type** ``` function forceNoEras( ) ``` ### forceUnstake Force a current staker to become completely unstaked, immediately. The dispatch origin must be Root. **Namespace** ``` api.tx.staking.forceUnstake ``` **Type** ``` function forceUnstake( stash: SeedPrimitivesSignatureAccountId20, num_slashing_spans: u32 ) ``` ### increaseValidatorCount Increments the ideal number of validators. The dispatch origin must be Root. **Namespace** ``` api.tx.staking.increaseValidatorCount ``` **Type** ``` function increaseValidatorCount( additional: Compact ) ``` ### kick Remove the given nominations from the calling validator. Effects will be felt at the beginning of the next era. The dispatch origin for this call must be *Signed* by the controller, not the stash. * `who`: A list of nominator stash accounts who are nominating this validator which should no longer be nominating this validator. **Note**: Making this call only makes sense if you first set the validator preferences to block any further nominations. **Namespace** ``` api.tx.staking.kick ``` **Type** ``` function kick( who: Vec ) ``` ### nominate Declare the desire to nominate `targets` for the origin controller. Effects will be felt at the beginning of the next era. The dispatch origin for this call must be *Signed* by the controller, not the stash. **Namespace** ``` api.tx.staking.nominate ``` **Type** ``` function nominate( targets: Vec ) ``` ### payoutStakers Currently disabled on TRN in favour of the [Vortex Distribution System](../../../../learn/tokenomics) Pay out all the stakers behind a single validator for a single era. * `validator_stash` is the stash account of the validator. Their nominators, up to `T::MaxNominatorRewardedPerValidator`, will also receive their rewards. * `era` may be any era between `[current_era - history_depth; current_era]`. The origin of this call must be *Signed*. Any account can call this function, even if it is not one of the stakers. **Namespace** ``` api.tx.staking.payoutStakers ``` **Type** ``` function payoutStakers( validator_stash: SeedPrimitivesSignatureAccountId20, era: u32 ) ``` ### reapStash Remove all data structures concerning a staker/stash once it is at a state where it can be considered `dust` in the staking system. The requirements are: 1. the `total_balance` of the stash is below existential deposit. 2. or, the `ledger.total` of the stash is below existential deposit. The former can happen in cases like a slash; the latter when a fully unbonded account is still receiving staking rewards in `RewardDestination::Staked`. It can be called by anyone, as long as `stash` meets the above requirements. Refunds the transaction fees upon successful execution. **Namespace** ``` api.tx.staking.reapStash ``` **Type** ``` function reapStash( stash: SeedPrimitivesSignatureAccountId20, num_slashing_spans: u32 ) ``` ### rebond Rebond a portion of the stash scheduled to be unlocked. The dispatch origin must be signed by the controller. **Namespace** ``` api.tx.staking.rebond ``` **Type** ``` function rebond( value: Compact ) ``` ### scaleValidatorCount Scale up the ideal number of validators by a factor. The dispatch origin must be Root. **Namespace** ``` api.tx.staking.scaleValidatorCount ``` **Type** ``` function scaleValidatorCount( factor: Percent ) ``` ### setController (Re-)set the controller of a stash. Effects will be felt instantly (as soon as this function is completed successfully). The dispatch origin for this call must be *Signed* by the stash, not the controller. **Namespace** ``` api.tx.staking.setController ``` **Type** ``` function setController( controller: SeedPrimitivesSignatureAccountId20 ) ``` ### setInvulnerables Set the validators who cannot be slashed (if any). The dispatch origin must be Root. **Namespace** ``` api.tx.staking.setInvulnerables ``` **Type** ``` function setInvulnerables( invulnerables: Vec ) ``` ### setPayee (Re-)set the payment target for a controller. Effects will be felt instantly (as soon as this function is completed successfully). The dispatch origin for this call must be *Signed* by the controller, not the stash. **Namespace** ``` api.tx.staking.setPayee ``` **Type** ``` function setPayee( payee: PalletStakingRewardDestination ) ``` ### setStakingConfigs Update the various staking configurations . * `min_nominator_bond`: The minimum active bond needed to be a nominator. * `min_validator_bond`: The minimum active bond needed to be a validator. * `max_nominator_count`: The max number of users who can be a nominator at once. When set to `None`, no limit is enforced. * `max_validator_count`: The max number of users who can be a validator at once. When set to `None`, no limit is enforced. * `chill_threshold`: The ratio of `max_nominator_count` or `max_validator_count` which should be filled in order for the `chill_other` transaction to work. * `min_commission`: The minimum amount of commission that each validators must maintain. This is checked only upon calling `validate`. Existing validators are not affected. RuntimeOrigin must be Root to call this function. **NOTE**: Existing nominators and validators will not be affected by this update. to kick people under the new limits, `chill_other` should be called. **Namespace** ``` api.tx.staking.setStakingConfigs ``` **Type** ``` function setStakingConfigs( min_nominator_bond: PalletStakingPalletConfigOpU128, min_validator_bond: PalletStakingPalletConfigOpU128, max_nominator_count: PalletStakingPalletConfigOpU32, max_validator_count: PalletStakingPalletConfigOpU32, chill_threshold: PalletStakingPalletConfigOpPercent, min_commission: PalletStakingPalletConfigOpPerbill ) ``` ### setValidatorCount Sets the ideal number of validators. The dispatch origin must be Root. **Namespace** ``` api.tx.staking.setValidatorCount ``` **Type** ``` function setValidatorCount( new: Compact ) ``` ### unbond Schedule a portion of the stash to be unlocked ready for transfer out after the bond period ends. If this leaves an amount actively bonded less than T::Currency::minimum\_balance(), then it is increased to the full amount. The dispatch origin for this call must be *Signed* by the controller, not the stash. Once the unlock period is done, you can call `withdraw_unbonded` to actually move the funds out of management ready for transfer. No more than a limited number of unlocking chunks (see `MaxUnlockingChunks`) can co-exists at the same time. In that case, \[`Call::withdraw_unbonded`] need to be called first to remove some of the chunks (if possible). If a user encounters the `InsufficientBond` error when calling this extrinsic, they should call `chill` first in order to free up their bonded funds. Emits `Unbonded`. See also \[`Call::withdraw_unbonded`]. **Namespace** ``` api.tx.staking.unbond ``` **Type** ``` function unbond( value: Compact ) ``` ### validate Declare the desire to validate for the origin controller. Effects will be felt at the beginning of the next era. The dispatch origin for this call must be *Signed* by the controller, not the stash. preferences contain the **Validator Commission** which is a **Perbill** value **Namespace** ``` api.tx.staking.validate ``` **Type** ``` function validate( prefs: PalletStakingValidatorPrefs ) ``` ### withdrawUnbonded Remove any unlocked chunks from the `unlocking` queue from our management. This essentially frees up that balance to be used by the stash account to do whatever it wants. The dispatch origin for this call must be *Signed* by the controller. Emits `Withdrawn`. See also \[`Call::unbond`]. **Namespace** ``` api.tx.staking.withdrawUnbonded ``` **Type** ``` function withdrawUnbonded( num_slashing_spans: u32 ) ``` ## Storage ### activeEra The active era information, it holds index and start. The active era is the era being currently rewarded. Validator set of this era must be equal to \[`SessionInterface::validators`]. **Namespace** ``` api.query.staking.activeEra ``` **Type** ``` function activeEra( ): Option ``` ### bonded Map from all locked "stash" accounts to the controller account. **Namespace** ``` api.query.staking.bonded ``` **Type** ``` function bonded( SeedPrimitivesSignatureAccountId20 ): Option ``` ### bondedEras A mapping from still-bonded eras to the first session index of that era. Must contains information for eras for the range: `[active_era - bounding_duration; active_era]` **Namespace** ``` api.query.staking.bondedEras ``` **Type** ``` function bondedEras( ): Vec<(u32,u32)> ``` ### canceledSlashPayout The amount of currency given to reporters of a slash event which was canceled by extraordinary circumstances (e.g. governance). **Namespace** ``` api.query.staking.canceledSlashPayout ``` **Type** ``` function canceledSlashPayout( ): u128 ``` ### chillThreshold The threshold for when users can start calling `chill_other` for other validators / nominators. The threshold is compared to the actual number of validators / nominators (`CountFor*`) in the system compared to the configured max (`Max*Count`). **Namespace** ``` api.query.staking.chillThreshold ``` **Type** ``` function chillThreshold( ): Option ``` ### counterForNominators Counter for the related counted storage map **Namespace** ``` api.query.staking.counterForNominators ``` **Type** ``` function counterForNominators( ): u32 ``` ### counterForValidators Counter for the related counted storage map **Namespace** ``` api.query.staking.counterForValidators ``` **Type** ``` function counterForValidators( ): u32 ``` ### currentEra The current era index. This is the latest planned era, depending on how the Session pallet queues the validator set, it might be active or not. **Namespace** ``` api.query.staking.currentEra ``` **Type** ``` function currentEra( ): Option ``` ### currentPlannedSession The last planned session scheduled by the session pallet. This is basically in sync with the call to \[`pallet_session::SessionManager::new_session`]. **Namespace** ``` api.query.staking.currentPlannedSession ``` **Type** ``` function currentPlannedSession( ): u32 ``` ### erasRewardPoints Rewards for the last `HISTORY_DEPTH` eras. If reward hasn't been set or has been removed then 0 reward is returned. **Namespace** ``` api.query.staking.erasRewardPoints ``` **Type** ``` function erasRewardPoints( u32 ): PalletStakingEraRewardPoints ``` ### erasStakers Exposure of validator at era. This is keyed first by the era index to allow bulk deletion and then the stash account. Is it removed after `HISTORY_DEPTH` eras. If stakers hasn't been set or has been removed then empty exposure is returned. **Namespace** ``` api.query.staking.erasStakers ``` **Type** ``` function erasStakers( u32, SeedPrimitivesSignatureAccountId20 ): PalletStakingExposure ``` ### erasStakersClipped Clipped Exposure of validator at era. This is similar to \[`ErasStakers`] but number of nominators exposed is reduced to the `T::MaxNominatorRewardedPerValidator` biggest stakers. Note: The field `total` and `own` of the exposure remains unchanged. This is used to limit the i/o cost for the nominator payout. This is keyed fist by the era index to allow bulk deletion and then the stash account. Is it removed after `HISTORY_DEPTH` eras. If stakers hasn't been set or has been removed then empty exposure is returned. **Namespace** ``` api.query.staking.erasStakersClipped ``` **Type** ``` function erasStakersClipped( u32, SeedPrimitivesSignatureAccountId20 ): PalletStakingExposure ``` ### erasStartSessionIndex The session index at which the era start for the last `HISTORY_DEPTH` eras. Note: This tracks the starting session (i.e. session index when era start being active) for the eras in `[CurrentEra - HISTORY_DEPTH, CurrentEra]`. **Namespace** ``` api.query.staking.erasStartSessionIndex ``` **Type** ``` function erasStartSessionIndex( u32 ): Option ``` ### erasTotalStake The total amount staked for the last `HISTORY_DEPTH` eras. If total hasn't been set or has been removed then 0 stake is returned. **Namespace** ``` api.query.staking.erasTotalStake ``` **Type** ``` function erasTotalStake( u32 ): u128 ``` ### erasValidatorPrefs Similar to `ErasStakers`, this holds the preferences of validators. This is keyed first by the era index to allow bulk deletion and then the stash account. Is it removed after `HISTORY_DEPTH` eras. **Namespace** ``` api.query.staking.erasValidatorPrefs ``` **Type** ``` function erasValidatorPrefs( u32, SeedPrimitivesSignatureAccountId20 ): PalletStakingValidatorPrefs ``` ### erasValidatorReward The total validator era payout for the last `HISTORY_DEPTH` eras. Eras that haven't finished yet or has been removed doesn't have reward. **Namespace** ``` api.query.staking.erasValidatorReward ``` **Type** ``` function erasValidatorReward( u32 ): Option ``` ### forceEra Mode of era forcing. **Namespace** ``` api.query.staking.forceEra ``` **Type** ``` function forceEra( ): PalletStakingForcing ``` ### invulnerables Any validators that may never be slashed or forcibly kicked. It's a Vec since they're easy to initialize and the performance hit is minimal (we expect no more than four invulnerables) and restricted to testnets. **Namespace** ``` api.query.staking.invulnerables ``` **Type** ``` function invulnerables( ): Vec ``` ### ledger Map from all (unlocked) "controller" accounts to the info regarding the staking. **Namespace** ``` api.query.staking.ledger ``` **Type** ``` function ledger( SeedPrimitivesSignatureAccountId20 ): Option ``` ### maxNominatorsCount The maximum nominator count before we stop allowing new validators to join. When this value is not set, no limits are enforced. **Namespace** ``` api.query.staking.maxNominatorsCount ``` **Type** ``` function maxNominatorsCount( ): Option ``` ### maxValidatorsCount The maximum validator count before we stop allowing new validators to join. When this value is not set, no limits are enforced. **Namespace** ``` api.query.staking.maxValidatorsCount ``` **Type** ``` function maxValidatorsCount( ): Option ``` ### minCommission The minimum amount of commission that validators can set. If set to `0`, no limit exists. **Namespace** ``` api.query.staking.minCommission ``` **Type** ``` function minCommission( ): Perbill ``` ### minimumValidatorCount Minimum number of staking participants before emergency conditions are imposed. **Namespace** ``` api.query.staking.minimumValidatorCount ``` **Type** ``` function minimumValidatorCount( ): u32 ``` ### minNominatorBond The minimum active bond to become and maintain the role of a nominator. **Namespace** ``` api.query.staking.minNominatorBond ``` **Type** ``` function minNominatorBond( ): u128 ``` ### minValidatorBond The minimum active bond to become and maintain the role of a validator. **Namespace** ``` api.query.staking.minValidatorBond ``` **Type** ``` function minValidatorBond( ): u128 ``` ### nominators The map from nominator stash key to their nomination preferences, namely the validators that they wish to support. Note that the keys of this storage map might become non-decodable in case the \[`Config::MaxNominations`] configuration is decreased. In this rare case, these nominators are still existent in storage, their key is correct and retrievable (i.e. `contains_key` indicates that they exist), but their value cannot be decoded. Therefore, the non-decodable nominators will effectively not-exist, until they re-submit their preferences such that it is within the bounds of the newly set `Config::MaxNominations`. This implies that `::iter_keys().count()` and `::iter().count()` might return different values for this map. Moreover, the main `::count()` is aligned with the former, namely the number of keys that exist. Lastly, if any of the nominators become non-decodable, they can be chilled immediately via \[`Call::chill_other`] dispatchable by anyone. **Namespace** ``` api.query.staking.nominators ``` **Type** ``` function nominators( SeedPrimitivesSignatureAccountId20 ): Option ``` ### nominatorSlashInEra All slashing events on nominators, mapped by era to the highest slash value of the era. **Namespace** ``` api.query.staking.nominatorSlashInEra ``` **Type** ``` function nominatorSlashInEra( u32, SeedPrimitivesSignatureAccountId20 ): Option ``` ### offendingValidators Indices of validators that have offended in the active era and whether they are currently disabled. This value should be a superset of disabled validators since not all offences lead to the validator being disabled (if there was no slash). This is needed to track the percentage of validators that have offended in the current era, ensuring a new era is forced if `OffendingValidatorsThreshold` is reached. The vec is always kept sorted so that we can find whether a given validator has previously offended using binary search. It gets cleared when the era ends. **Namespace** ``` api.query.staking.offendingValidators ``` **Type** ``` function offendingValidators( ): Vec<(u32,bool)> ``` ### payee Where the reward payment should be made. Keyed by stash. **Namespace** ``` api.query.staking.payee ``` **Type** ``` function payee( SeedPrimitivesSignatureAccountId20 ): PalletStakingRewardDestination ``` ### slashingSpans Slashing spans for stash accounts. **Namespace** ``` api.query.staking.slashingSpans ``` **Type** ``` function slashingSpans( SeedPrimitivesSignatureAccountId20 ): Option ``` ### slashRewardFraction The percentage of the slash that is distributed to reporters. The rest of the slashed value is handled by the `Slash`. **Namespace** ``` api.query.staking.slashRewardFraction ``` **Type** ``` function slashRewardFraction( ): Perbill ``` ### spanSlash Records information about the maximum slash of a stash within a slashing span, as well as how much reward has been paid out. **Namespace** ``` api.query.staking.spanSlash ``` **Type** ``` function spanSlash( (SeedPrimitivesSignatureAccountId20,u32) ): PalletStakingSlashingSpanRecord ``` ### storageVersion True if network has been upgraded to this version. Storage version of the pallet. This is set to v7.0.0 for new networks. **Namespace** ``` api.query.staking.storageVersion ``` **Type** ``` function storageVersion( ): PalletStakingReleases ``` ### unappliedSlashes All unapplied slashes that are queued for later. **Namespace** ``` api.query.staking.unappliedSlashes ``` **Type** ``` function unappliedSlashes( u32 ): Vec ``` ### validatorCount The ideal number of staking participants. **Namespace** ``` api.query.staking.validatorCount ``` **Type** ``` function validatorCount( ): u32 ``` ### validators The map from (wannabe) validator stash key to the preferences of that validator. **Namespace** ``` api.query.staking.validators ``` **Type** ``` function validators( SeedPrimitivesSignatureAccountId20 ): PalletStakingValidatorPrefs ``` ### validatorSlashInEra All slashing events on validators, mapped by era to the highest slash proportion and slash value of the era. **Namespace** ``` api.query.staking.validatorSlashInEra ``` **Type** ``` function validatorSlashInEra( u32, SeedPrimitivesSignatureAccountId20 ): Option<(Perbill,u128)> ``` ## Events ### Bonded An account has bonded this amount. \[stash, amount] NOTE: This event is only emitted when funds are bonded via a dispatchable. Notably, it will not be emitted for staking rewards when they are added to stake. **Namespace** ``` api.events.staking.Bonded ``` **Type** ``` type Bonded = { stash: SeedPrimitivesSignatureAccountId20, amount: u128 } ``` ### Chilled An account has stopped participating as either a validator or nominator. **Namespace** ``` api.events.staking.Chilled ``` **Type** ``` type Chilled = { stash: SeedPrimitivesSignatureAccountId20 } ``` ### EraPaid The era payout has been set; the first balance is the validator-payout; the second is the remainder from the maximum amount of reward. **Namespace** ``` api.events.staking.EraPaid ``` **Type** ``` type EraPaid = { era_index: u32, validator_payout: u128, remainder: u128 } ``` ### Kicked A nominator has been kicked from a validator. **Namespace** ``` api.events.staking.Kicked ``` **Type** ``` type Kicked = { nominator: SeedPrimitivesSignatureAccountId20, stash: SeedPrimitivesSignatureAccountId20 } ``` ### OldSlashingReportDiscarded An old slashing report from a prior era was discarded because it could not be processed. **Namespace** ``` api.events.staking.OldSlashingReportDiscarded ``` **Type** ``` type OldSlashingReportDiscarded = { session_index: u32 } ``` ### PayoutStarted The stakers' rewards are getting paid. **Namespace** ``` api.events.staking.PayoutStarted ``` **Type** ``` type PayoutStarted = { era_index: u32, validator_stash: SeedPrimitivesSignatureAccountId20 } ``` ### Rewarded The nominator has been rewarded by this amount. **Namespace** ``` api.events.staking.Rewarded ``` **Type** ``` type Rewarded = { stash: SeedPrimitivesSignatureAccountId20, amount: u128 } ``` ### Slashed One staker (and potentially its nominators) has been slashed by the given amount. **Namespace** ``` api.events.staking.Slashed ``` **Type** ``` type Slashed = { staker: SeedPrimitivesSignatureAccountId20, amount: u128 } ``` ### StakersElected A new set of stakers was elected. **Namespace** ``` api.events.staking.StakersElected ``` **Type** ``` type StakersElected = { } ``` ### StakingElectionFailed The election failed. No new era is planned. **Namespace** ``` api.events.staking.StakingElectionFailed ``` **Type** ``` type StakingElectionFailed = { } ``` ### Unbonded An account has unbonded this amount. **Namespace** ``` api.events.staking.Unbonded ``` **Type** ``` type Unbonded = { stash: SeedPrimitivesSignatureAccountId20, amount: u128 } ``` ### ValidatorPrefsSet A validator has set their preferences. **Namespace** ``` api.events.staking.ValidatorPrefsSet ``` **Type** ``` type ValidatorPrefsSet = { stash: SeedPrimitivesSignatureAccountId20, prefs: PalletStakingValidatorPrefs } ``` ### Withdrawn An account has called `withdraw_unbonded` and removed unbonding chunks worth `Balance` from the unlocking queue. **Namespace** ``` api.events.staking.Withdrawn ``` **Type** ``` type Withdrawn = { stash: SeedPrimitivesSignatureAccountId20, amount: u128 } ``` ## Errors ### AlreadyBonded Stash is already bonded. **Namespace** ``` api.errors.staking.AlreadyBonded ``` ### AlreadyClaimed Rewards for this era have already been claimed for this validator. **Namespace** ``` api.errors.staking.AlreadyClaimed ``` ### AlreadyPaired Controller is already paired. **Namespace** ``` api.errors.staking.AlreadyPaired ``` ### BadState Internal state has become somehow corrupted and the operation cannot continue. **Namespace** ``` api.errors.staking.BadState ``` ### BadTarget A nomination target was supplied that was blocked or otherwise not a validator. **Namespace** ``` api.errors.staking.BadTarget ``` ### BoundNotMet Some bound is not met. **Namespace** ``` api.errors.staking.BoundNotMet ``` ### CannotChillOther The user has enough bond and thus cannot be chilled forcefully by an external person. **Namespace** ``` api.errors.staking.CannotChillOther ``` ### CommissionTooLow Commission is too low. Must be at least `MinCommission`. **Namespace** ``` api.errors.staking.CommissionTooLow ``` ### DuplicateIndex Duplicate index. **Namespace** ``` api.errors.staking.DuplicateIndex ``` ### EmptyTargets Targets cannot be empty. **Namespace** ``` api.errors.staking.EmptyTargets ``` ### FundedTarget Attempting to target a stash that still has funds. **Namespace** ``` api.errors.staking.FundedTarget ``` ### IncorrectHistoryDepth Incorrect previous history depth input provided. **Namespace** ``` api.errors.staking.IncorrectHistoryDepth ``` ### IncorrectSlashingSpans Incorrect number of slashing spans provided. **Namespace** ``` api.errors.staking.IncorrectSlashingSpans ``` ### InsufficientBond Cannot have a validator or nominator role, with value less than the minimum defined by governance (see `MinValidatorBond` and `MinNominatorBond`). If unbonding is the intention, `chill` first to remove one's role as validator/nominator. **Namespace** ``` api.errors.staking.InsufficientBond ``` ### InvalidEraToReward Invalid era to reward. **Namespace** ``` api.errors.staking.InvalidEraToReward ``` ### InvalidNumberOfNominations Invalid number of nominations. **Namespace** ``` api.errors.staking.InvalidNumberOfNominations ``` ### InvalidSlashIndex Slash record index out of bounds. **Namespace** ``` api.errors.staking.InvalidSlashIndex ``` ### NoMoreChunks Can not schedule more unlock chunks. **Namespace** ``` api.errors.staking.NoMoreChunks ``` ### NotController Not a controller account. **Namespace** ``` api.errors.staking.NotController ``` ### NotSortedAndUnique Items are not sorted and unique. **Namespace** ``` api.errors.staking.NotSortedAndUnique ``` ### NotStash Not a stash account. **Namespace** ``` api.errors.staking.NotStash ``` ### NoUnlockChunk Can not rebond without unlocking chunks. **Namespace** ``` api.errors.staking.NoUnlockChunk ``` ### TooManyNominators There are too many nominators in the system. Governance needs to adjust the staking settings to keep things safe for the runtime. **Namespace** ``` api.errors.staking.TooManyNominators ``` ### TooManyTargets Too many nomination targets supplied. **Namespace** ``` api.errors.staking.TooManyTargets ``` ### TooManyValidators There are too many validators in the system. Governance needs to adjust the staking settings to keep things safe for the runtime. **Namespace** ``` api.errors.staking.TooManyValidators ``` ## Constants ### bondingDuration Number of eras that staked funds must remain bonded for. **Namespace** ``` api.consts.staking.bondingDuration ``` **Type** ``` type bondingDuration = u32 ``` ### historyDepth Number of eras to keep in history. Following information is kept for eras in `[current_era - HistoryDepth, current_era]`: `ErasStakers`, `ErasStakersClipped`, `ErasValidatorPrefs`, `ErasValidatorReward`, `ErasRewardPoints`, `ErasTotalStake`, `ErasStartSessionIndex`, `StakingLedger.claimed_rewards`. Must be more than the number of eras delayed by session. I.e. active era must always be in history. I.e. `active_era > current_era - history_depth` must be guaranteed. If migrating an existing pallet from storage value to config value, this should be set to same value or greater as in storage. Note: `HistoryDepth` is used as the upper bound for the `BoundedVec` item `StakingLedger.claimed_rewards`. Setting this value lower than the existing value can lead to inconsistencies in the `StakingLedger` and will need to be handled properly in a migration. The test `reducing_history_depth_abrupt` shows this effect. **Namespace** ``` api.consts.staking.historyDepth ``` **Type** ``` type historyDepth = u32 ``` ### maxNominations Maximum number of nominations per nominator. **Namespace** ``` api.consts.staking.maxNominations ``` **Type** ``` type maxNominations = u32 ``` ### maxNominatorRewardedPerValidator The maximum number of nominators rewarded for each validator. For each validator only the `$MaxNominatorRewardedPerValidator` biggest stakers can claim their reward. This used to limit the i/o cost for the nominator payout. **Namespace** ``` api.consts.staking.maxNominatorRewardedPerValidator ``` **Type** ``` type maxNominatorRewardedPerValidator = u32 ``` ### maxUnlockingChunks The maximum number of `unlocking` chunks a \[`StakingLedger`] can have. Effectively determines how many unique eras a staker may be unbonding in. Note: `MaxUnlockingChunks` is used as the upper bound for the `BoundedVec` item `StakingLedger.unlocking`. Setting this value lower than the existing value can lead to inconsistencies in the `StakingLedger` and will need to be handled properly in a runtime migration. The test `reducing_max_unlocking_chunks_abrupt` shows this effect. **Namespace** ``` api.consts.staking.maxUnlockingChunks ``` **Type** ``` type maxUnlockingChunks = u32 ``` ### sessionsPerEra Number of sessions per era. **Namespace** ``` api.consts.staking.sessionsPerEra ``` **Type** ``` type sessionsPerEra = u32 ``` ### slashDeferDuration Number of eras that slashes are deferred by, after computation. This should be less than the bonding duration. Set to 0 if slashes should be applied immediately, without opportunity for intervention. **Namespace** ``` api.consts.staking.slashDeferDuration ``` **Type** ``` type slashDeferDuration = u32 ``` # Sudo Source: https://docs.therootnetwork.com/build/substrate/api-reference/runtime-pallets/sudo ## Calls ### setKey Authenticates the current sudo key and sets the given AccountId (`new`) as the new sudo key. The dispatch origin for this call must be *Signed*. **Namespace** ``` api.tx.sudo.setKey ``` **Type** ``` function setKey( new: SeedPrimitivesSignatureAccountId20 ) ``` ### sudo Authenticates the sudo key and dispatches a function call with `Root` origin. The dispatch origin for this call must be *Signed*. **Namespace** ``` api.tx.sudo.sudo ``` **Type** ``` function sudo( call: Call ) ``` ### sudoAs Authenticates the sudo key and dispatches a function call with `Signed` origin from a given account. The dispatch origin for this call must be *Signed*. **Namespace** ``` api.tx.sudo.sudoAs ``` **Type** ``` function sudoAs( who: SeedPrimitivesSignatureAccountId20, call: Call ) ``` ### sudoUncheckedWeight Authenticates the sudo key and dispatches a function call with `Root` origin. This function does not check the weight of the call, and instead allows the Sudo user to specify the weight of the call. The dispatch origin for this call must be *Signed*. **Namespace** ``` api.tx.sudo.sudoUncheckedWeight ``` **Type** ``` function sudoUncheckedWeight( call: Call, weight: WeightV1 ) ``` ## Storage ### key The `AccountId` of the sudo key. **Namespace** ``` api.query.sudo.key ``` **Type** ``` function key( ): Option ``` ## Events ### KeyChanged The \[sudoer] just switched identity; the old key is supplied if one existed. **Namespace** ``` api.events.sudo.KeyChanged ``` **Type** ``` type KeyChanged = { old_sudoer: Option } ``` ### Sudid A sudo just took place. \[result] **Namespace** ``` api.events.sudo.Sudid ``` **Type** ``` type Sudid = { sudo_result: Result } ``` ### SudoAsDone A sudo just took place. \[result] **Namespace** ``` api.events.sudo.SudoAsDone ``` **Type** ``` type SudoAsDone = { sudo_result: Result } ``` ## Errors ### RequireSudo Sender must be the Sudo account **Namespace** ``` api.errors.sudo.RequireSudo ``` undefined # SyloActionPermissions Source: https://docs.therootnetwork.com/build/substrate/api-reference/runtime-pallets/sylo-action-permissions The Sylo Action Permissions pallet allows accounts to manage transact permissions. A transact permission enables the grantee to execute extrinsics on behalf of the grantor. ## Transact Permission A transact permission record is stored on-chain, keyed by the account id of the grantor, and the account id of the grantee. It allows the grantee to call the `transact` extrinsic, which execute the underlying extrinsic on behalf of the grantor. The record contains the following fields: * **spender**: The account that is pays for the extrinsic fees when `transact` is called. This is either the `GRANTOR` or the `GRANTEE`. * **spending\_balance**: When the spender is the `GRANTOR`, the grantor can specify a spending balance. This acts as a limit on the maximum amount of funds that the grantee can use to call `transact` on behalf of the grantor. This value is deducted by the extrinsic fee when `transact` is called. * **allowed\_calls**: A list of `CallId` that the grantee can use in `transact`. This value must be specified for all of the extrinsics that the grantor wishes to permit. A call id is a tuple of the pallet name and the extrinsic name. Example: `("nft", "transfer")`. Wildcard values can be used for both the pallet and extrinsic names, e.g. `("*", "*")` will allow all extrinsics to be called. A set of pallets are blacklisted from being used in `transact`. This includes the following pallets: * `Sudo` * `Proxy` * `Futurepass` * `SyloActionPermissions` (prevents grantee from modifying the permission record itself) * **expiry**: An optional expiry block for the permission. ## Payment The extrinsics for managing the transact permissions (grant, revoke, update, accept) are paid using the SYLO token (asset id `2148`). It is not possible to use the fee proxy to modify the fee token for these extrinsics. The `transact` extrinsic itself is paid using the regular fee payment mechanism. ## Calls ### grantTransactPermission Grant a transact permission to another account. **Namespace** ``` api.tx.syloActionPermissions.grantTransactPermission ``` **Type** ``` function grantTransactPermission( /// The account to grant the permission to grantee: AccountId, /// The account that will pay for the extrinsic fees spender: Spender, /// The maximum amount of funds that the grantee can use when calling `transact` spending_balance: Option, /// The list of allowed calls, allowed_calls: Vec<(Vec, Vec)>, /// An optional expiry block for the permission expiry: Option ) ``` ### updateTransactPermission Update an existing transact permission record. This takes in a set of optional values, which will update the existing record if the value is `Some`. **Namespace** ``` api.tx.syloActionPermissions.updateTransactPermission ``` **Type** ``` function updateTransactPermission( /// The grantee to update the permission for grantee: AccountId, /// The account that will pay for the extrinsic fees spender: Option(Spender), /// The maximum amount of funds that the grantee can use when calling `transact` spending_balance: Option>, /// The list of allowed calls, allowed_calls: Option, Vec)>>, /// An optional expiry block for the permission expiry: Option> ) ``` ### revokeTransactPermission Revoke a previously granted transact permission. **Namespace** ``` api.tx.syloActionPermissions.revokeTransactPermission ``` **Type** ``` function revokeTransactPermission( /// The grantee to revoke the permission for grantee: AccountId ) ``` ### acceptTransactPermission Accept a transact permission that has been granted to the caller. Unlike `grantTransactPermission`, this call is intended to be used by the grantee. This call is primarily for the use case where the grantor has generated a new account, but does not have the means to execute the `grantTransactPermission` themselves. For example, not having any funds associated with the account. The grantor can instead sign a token that includes the permission details, as well as the grantee's account id. The grantee can then supply the token and token signature to this call to create the accompanying permission record. Updating the on-chain permission record can be done by calling this extrinsic again with the updated values and a new token signature. **Token Signature** The grantor must sign an encoded transact permission token. The token structure includes the following fields: ``` type TransactPermissionToken = { // Account id of the grantee grantee: AccountId, // Indicates that the futurepass account of the permission grantor // should be used, instead of the account recovered from the signature. use_futurepass: Option, // The account that will pay for the extrinsic fees spender: Spender, // The maximum amount of funds that the grantee can use when calling `transact` spending_balance: Option, // The list of allowed calls, allowed_calls: Vec<(Vec, Vec)>, // An optional expiry block for the permission expiry: Option, // A randomly generated 32 byte nonce used to prevent replays nonce: Bytes } ``` The type registry for `PalletSyloActionPermissionsTransactPermissionToken` can be used to encode the token. ```typescript import { u8aToHex } from "@polkadot/util"; import { utils as ethersUtils } from "ethers"; const SPENDER_TYPE = { Grantor: "GRANTOR", Grantee: "GRANTEE", }; const permissionToken = { grantee: grantee.address, use_futurepass: false, spender: SPENDER_TYPE.Grantee, spending_balance: null, allowed_calls: [["*", "*"]], expiry: null, nonce: u8aToHex(ethersUtils.randomBytes(32)), }; const serializedToken = api.registry .createType( "PalletSyloActionPermissionsTransactPermissionToken", permissionToken ) .toU8a(); ``` **Signing** A signature can either be in the form of an EIP191 signature, or an XRPL signature. ```typescript import { KeyringPair } from "@polkadot/keyring/types"; import { hexToU8a } from "@polkadot/util"; const grantor = keyring.addFromSeed(hexToU8a(`0xPrivateKey`)); // Sign the serialized token using EIP191 const signature = await grantor.signMessage(serializedToken); const eip191Sig = { EIP191: signature }; ``` ```typescript import { encode, encodeForSigning } from "ripple-binary-codec"; import { computePublicKey } from "ethers/lib/utils"; import { KeyringPair } from "@polkadot/keyring/types"; import { hexToU8a } from "@polkadot/util"; const GRANTOR_PRIVATE_KEY = "0xPrivateKey"; const grantor = keyring.addFromSeed(hexToU8a(GRANTOR_PRIVATE_KEY)); // compute ecdsa public key const publicKey = computePublicKey(grantor.publicKey, true); // create xaman tx object const xamanJsonTx = { AccountTxnID: "16969036626990000000000000000000F236FD752B5E4C84810AB3D41A3C2580", SigningPubKey: publicKey.slice(2), Account: deriveAddress(publicKey.slice(2)), Memos: [ { Memo: { MemoType: stringToHex("extrinsic"), MemoData: u8aToHex(serializedToken).substring(2), }, }, ], }; // Sign XRPL transaction const encodedSigningMessage = encodeForSigning(xamanJsonTx); const signature = sign(encodedSigningMessage, GRANTOR_PRIVATE_KEY.slice(2)); const xrplSig = { XRPL: { encodedMsg: `0x${encode(xamanJsonTx)}`, signature: `0x${signature}`, }, }; ``` **Namespace** ```api.tx.syloActionPermissions.acceptTransactPermission ``` **Type** ```function acceptTransactPermission( /// The token that contains the permission details token: TransactPermissionToken, /// The signature of the token, either EIP191 or XRPL signature: TransactPermissionTokenSignature ); ``` ## Storage ### TransactPermissions Map from grantor and grantee to a transact permission record. **Namespace** ``` api.query.syloActionPermissions.transactPermissions ``` **Type** ``` type TransactPermission = { spender: GRANTOR | GRANTEE, spending_balance: Option, allowed_calls: Vec<(CallId)>, block: BlockNumber, expiry: Option } function TransactPermissions( grantor: AccountId, grantee: AccountId ): Option ``` ## Events ### TransactPermissionGranted An account has been granted a transact permission. **Namespace** ``` api.events.syloActionPermissions.TransactPermissionGranted ``` **Type** ``` type TransactPermissionGranted = { grantor: AccountId, grantee: AccountId, spender: Spender, spending_balance: Option, allowed_calls: Vec, expiry: Option, } ``` ### TransactPermissionUpdated An account has updated a transact permission. **Namespace** ``` api.events.syloActionPermissions.TransactPermissionUpdated ``` **Type** ``` type TransactPermissionUpdated = { grantor: AccountId, grantee: AccountId, spender: Spender, spending_balance: Option, allowed_calls: Vec, expiry: Option, } ``` ### TransactPermissionRevoked An account has revoked a transact permission. **Namespace** ``` api.events.syloActionPermissions.TransactPermissionRevoked ``` **Type** ``` type TransactPermissionRevoked = { grantor: AccountId, grantee: AccountId, } ``` ### TransactPermissionAccepted An account has accepted a transact permission. **Namespace** ``` api.events.syloActionPermissions.TransactPermissionAccepted ``` **Type** ``` type TransactPermissionAccepted = { grantor: AccountId, grantee: AccountId, } ``` ### TransactPermissionExecuted An account has executed an extrinsic on behalf of another account using a transact permission. **Namespace** ``` api.events.syloActionPermissions.TransactPermissionExecuted ``` **Type** ``` type TransactPermissionExecuted = { grantor: AccountId, grantee: AccountId, } ``` ## Errors ### PermissionNotGranted The permission does not exist or has not been granted. **Namespace** ``` api.errors.syloActionPermissions.PermissionNotGranted ``` ### NotAuthorizedCall The call is not authorized under the granted permission. **Namespace** ``` api.errors.syloActionPermissions.NotAuthorizedCall ``` ### PermissionExpired The permission has expired and is no longer valid. **Namespace** ``` api.errors.syloActionPermissions.PermissionExpired ``` ### InvalidExpiry The provided expiry block is in the past. **Namespace** ``` api.errors.syloActionPermissions.InvalidExpiry ``` ### PermissionAlreadyExists A permission already exists and has not yet expired. **Namespace** ``` api.errors.syloActionPermissions.PermissionAlreadyExists ``` ### InvalidSpendingBalance The specified spending balance is not allowed. **Namespace** ``` api.errors.syloActionPermissions.InvalidSpendingBalance ``` ### InvalidTokenSignature The provided token signature is invalid or cannot be verified. **Namespace** ``` api.errors.syloActionPermissions.InvalidTokenSignature ``` ### GranteeDoesNotMatch The grantee in the token does not match the caller. **Namespace** ``` api.errors.syloActionPermissions.GranteeDoesNotMatch ``` ### NonceAlreadyUsed The nonce provided in the token has already been used. **Namespace** ``` api.errors.syloActionPermissions.NonceAlreadyUsed ``` ### InvalidFuturepassInToken The futurepass in the token is not owned by the grantor. **Namespace** ``` api.errors.syloActionPermissions.InvalidFuturepassInToken ``` ### InsufficientSpendingBalance The spending balance is insufficient to cover the transaction fee. **Namespace** ``` api.errors.syloActionPermissions.InsufficientSpendingBalance ``` # SyloDataPermissions Source: https://docs.therootnetwork.com/build/substrate/api-reference/runtime-pallets/sylo-data-permissions The Sylo Data Permissions allows data authors to grant, update, and revoke data permissions. It integrates with the Sylo Data Verification pallet to allow authors to manage fine-grained access control over their data. ## Permission Levels There are three types of permissions that can be associated with data items: * **VIEW**: Allows the grantee to view the data when fetching the item from a storage sylo. * **MODIFY**: Allows the grantee to modify the data. This includes the onchain validation record and also the data itself that is held by storage sylos. * **DISTRIBUTE**: Allows the grantee to distribute the data. The MODIFY and DISTRIBUTE permissions imply the VIEW permission. ``` enum DataPermission { VIEW, MODIFY, DISTRIBUTE, } ``` ## Record Types Data permissions are stored as records in the Sylo Data Permissions pallet. There are three differing forms of records to satisfy various use cases: * **Data Permission Record**: This is the simplest form of record and applies to a single data item. * **Tagged Permission Record**: A tagged record will hold a set of data tags. The permission applies to any data items that share at least of the tags in the record. This allows an author to easily grant a permission to a group of related data items. * **Permission Reference Record**: This record type indicates that there exists another permission record that is stored offchain on a storage sylo. The offchain permission record itself requires that a on-chain validation record for it exists and stores the actual permissions. This type of record is suitable when an author whishes to grant permissions over many data items that may not share any tags. ## Calls ### grantDataPermissions Grants another account access permissions for a set of data items. The caller must be the author or have been granted the DISTRIBUTE permission by the author. **Namespace** ``` api.tx.syloDataPermissions.grantDataPermissions ``` **Type** ``` function grantDataPermissions( /// The account that owns the data. When this differs from the caller, the caller /// must be a distributor. data_author: AccountId, /// The account to grant permissions to grantee: AccountId, /// List of data ids data_ids: Vec>, /// The permission level permission: DataPermission, /// An optional blocknumber for the expiry expiry: Option, /// Whether the permission is irrevocable irrevocable: bool, ) ``` Data permission records are stored as a list of record under the key of (grantor, grantee). A `u32` value will be assigned to each record to identify it. ### revokeDataPermission Revokes a previously granted data permission. The caller must be the author or the original grantor of the permission. **Namespace** ``` api.tx.syloDataPermissions.revokeDataPermission ``` **Type** ``` function revokeDataPermission( /// The account that owns the data. When this differs from the caller, the caller /// must be a distributor. data_author: AccountId, /// The id of the permission record. permission_id: u32, /// The account that was granted the permission grantee: AccountId, /// The data id of the item to revoke the permission for data_id: Vec>, ) ``` ### grantTaggedPermissions Grants a tagged permission record. The caller must be the original data author. Distributors are not allowed to grant tagged permissions. **Namespace** ``` api.tx.syloDataPermissions.grantTaggedPermissions ``` **Type** ``` function grantTaggedPermissions( /// The account that was granted the permission grantee: AccountId, /// The permission level permission: DataPermission, /// List of data tags tags: Vec>, /// An optional blocknumber for the expiry expiry: Option, /// Whether the permission is irrevocable irrevocable: bool, ) ``` ### revokeTaggedPermission Revokes a previously granted tagged permission. The caller must be the author or the original grantor of the permission. **Namespace** ``` api.tx.syloDataPermissions.revokeTaggedPermission ``` **Type** ``` function revokeTaggedPermission( /// The id of the permission record. permission_id: u32, /// The account that was granted the permission grantee: AccountId, ) ``` ### grantPermissionReference Creates a permission reference record. The caller must be the author. **Namespace** ``` api.tx.syloDataPermissions.grantPermissionReference ``` **Type** ``` function grantPermissionReference( /// The account to grant permissions to grantee: AccountId, /// The data id of the offchain permission record. This data item // must have an accompanying on-chain validation record. permission_record_id: Vec, ) ``` ### revokePermissionReference Revokes a previously granted permission reference. The caller must be the author. **Namespace** ``` api.tx.syloDataPermissions.revokePermissionReference ``` **Type** ``` function revokePermissionReference( /// The account that was granted the permission grantee: AccountId, ) ``` ## Storage ### PermissionRecords Maps from grantor and grantee to a permission record id and the permission record itself. **Namespace** ``` api.query.syloDataPermissions.PermissionRecords ``` **Type** ``` type PermissionRecord { grantor: AccountId, permission: DataPermission, block: BlockNumber, expiry: Option, irrevocable: bool, } function PermissionRecords( data_author: AccountId, grantee: AccountId, data_id: Bytes ): Vec<(u32, PermissionRecord)> ``` ### TaggedPermissionRecords Maps from grantor and grantee to a permission record id and the tagged permission record. **Namespace** ``` api.query.syloDataPermissions.TaggedPermissionRecords ``` **Type** ``` type TaggedPermissionRecord { permission: DataPermission, tags: Vec>, block: BlockNumber, expiry: Option, irrevocable: bool, } function TaggedPermissionRecords( data_author: AccountId, grantee: AccountId ): Vec<(u32, TaggedPermissionRecord)> ``` ### PermissionReferences Stores permission references for off-chain records. **Namespace** ``` api.query.syloDataPermissions.PermissionReferences ``` **Type** ``` type PermissionReference { permission_record_id: Vec, } function PermissionReferences( data_author: AccountId, grantee: AccountId ): Option ``` ## Events ### DataPermissionGranted An account has been granted permission for a specific data record. **Namespace** ``` api.events.syloDataPermissions.DataPermissionGranted ``` **Type** ``` type DataPermissionGranted = { data_author: AccountId, grantor: AccountId, grantee: AccountId, data_id: Bytes, permission: DataPermission, expiry: Option, irrevocable: bool, } ``` ### DataPermissionRevoked An account's permission has been revoked for a specific data record. **Namespace** ``` api.events.syloDataPermissions.DataPermissionRevoked ``` **Type** ``` type DataPermissionRevoked = { revoker: AccountId, grantee: AccountId, permission: DataPermission, data_id: Bytes, } ``` ### ExpiredDataPermissionRemoved An expired data permission has been automatically removed. **Namespace** ``` api.events.syloDataPermissions.ExpiredDataPermissionRemoved ``` **Type** ``` type ExpiredDataPermissionRemoved = { data_author: AccountId, grantee: AccountId, data_id: Bytes, permission_id: u32, } ``` ### TaggedDataPermissionsGranted An account has been granted tagged permissions. **Namespace** ``` api.events.syloDataPermissions.TaggedDataPermissionsGranted ``` **Type** ``` type TaggedDataPermissionsGranted = { grantor: AccountId, grantee: AccountId, permission: DataPermission, tags: Vec, expiry: Option, irrevocable: bool, } ``` ### TaggedDataPermissionsRevoked A tagged permission for an account has been revoked. **Namespace** ``` api.events.syloDataPermissions.TaggedDataPermissionsRevoked ``` **Type** ``` type TaggedDataPermissionsRevoked = { revoker: AccountId, grantee: AccountId, permission: DataPermission, tags: Vec, } ``` ### PermissionReferenceGranted An account has been granted a permission reference. **Namespace** ``` api.events.syloDataPermissions.PermissionReferenceGranted ``` **Type** ``` type PermissionReferenceGranted = { grantor: AccountId, grantee: AccountId, permission_record_id: Bytes, } ``` ### PermissionReferenceRevoked An account's permission reference has been revoked. **Namespace** ``` api.events.syloDataPermissions.PermissionReferenceRevoked ``` **Type** ``` type PermissionReferenceRevoked = { grantor: AccountId, grantee: AccountId, permission_record_id: Bytes, } ``` ## Errors ### DataRecordDoesNotExist Attempted to grant permissions for a data record that does not exist. **Namespace** ``` api.errors.syloDataPermissions.DataRecordDoesNotExist ``` ### IrrevocableCannotBeExpirable A permission that is set to irrevocable cannot also be set to have an expiry. **Namespace** ``` api.errors.syloDataPermissions.IrrevocableCannotBeExpirable ``` ### InvalidExpiry Expiry value for permission record is invalid. **Namespace** ``` api.errors.syloDataPermissions.InvalidExpiry ``` ### ExceededMaxPermissions Exceeded the maximum number of record permissions granted to a given account. **Namespace** ``` api.errors.syloDataPermissions.ExceededMaxPermissions ``` ### MissingDistributePermission Attempted to grant a permission as a delegate without the required DISTRIBUTE permission. **Namespace** ``` api.errors.syloDataPermissions.MissingDistributePermission ``` ### CannotGrantDistributePermission Distribute permissions can only be granted by the data author. **Namespace** ``` api.errors.syloDataPermissions.CannotGrantDistributePermission ``` ### PermissionIrrevocable An irrevocable permission cannot be revoked. **Namespace** ``` api.errors.syloDataPermissions.PermissionIrrevocable ``` ### NotPermissionGrantor Only the account that granted a permission or the data author can revoke a permission. **Namespace** ``` api.errors.syloDataPermissions.NotPermissionGrantor ``` ### PermissionNotFound Cannot revoke a permission that does not exist. **Namespace** ``` api.errors.syloDataPermissions.PermissionNotFound ``` ### MissingValidationRecord An accompanying verification record for the off-chain permission does not exist. **Namespace** ``` api.errors.syloDataPermissions.MissingValidationRecord ``` ### PermissionReferenceAlreadyExists An existing permission reference has already been granted. **Namespace** ``` api.errors.syloDataPermissions.PermissionReferenceAlreadyExists ``` ### ExceededMaxExpiringPermissions Exceeded the maximum number of permissions that can expire on the same block. **Namespace** ``` api.errors.syloDataPermissions.ExceededMaxExpiringPermissions ``` ### InvalidString String values in an RPC call, in either the inputs or outputs, are invalid. **Namespace** ``` api.errors.syloDataPermissions.InvalidString ``` # SyloDataVerification Source: https://docs.therootnetwork.com/build/substrate/api-reference/runtime-pallets/sylo-data-verification The Sylo Data Verification pallet provides functionality for registering resolvers and verifying data through validation records. It allows users to create, update, and delete validation records that can be used to verify the authenticity and integrity of data. ## Calls ### setPaymentAsset Set the asset used to pay for sylo extrinsics. This operation requires root access. **Namespace** ``` api.tx.syloDataVerification.setPaymentAsset ``` **Type** ``` function setPaymentAsset( payment_asset: u32 ) ``` ### setSyloResolverMethod Set the string used as the reserved sylo resolver method. This operation requires root access. **Namespace** ``` api.tx.syloDataVerification.setSyloResolverMethod ``` **Type** ``` function setSyloResolverMethod( resolver_method: Bytes ) ``` ### registerResolver Register a new resolver. The caller will be set as the controller of the resolver. **Namespace** ``` api.tx.syloDataVerification.registerResolver ``` **Type** ``` function registerResolver( identifier: Bytes, service_endpoints: Vec ) ``` ### updateResolver Update the service endpoints of an existing resolver. Caller must be the controller of the resolver. **Namespace** ``` api.tx.syloDataVerification.updateResolver ``` **Type** ``` function updateResolver( identifier: Bytes, service_endpoints: Vec ) ``` ### deregisterResolver Deregister an existing resolver. Caller must be the controller of the resolver. **Namespace** ``` api.tx.syloDataVerification.deregisterResolver ``` **Type** ``` function deregisterResolver( identifier: Bytes ) ``` ### createValidationRecord Create a new validation record. The caller will be set as the record's author. For any specified resolvers which use the reserved sylo resolver method, those resolvers must already be registered and exist in storage. The initial record entry will use the current system block for the block value. **Namespace** ``` api.tx.syloDataVerification.createValidationRecord ``` **Type** ``` function createValidationRecord( data_id: Bytes, resolvers: Vec<{method: Bytes, identifier: Bytes}>, data_type: Bytes, tags: Vec, checksum: H256 ) ``` ### addValidationRecordEntry Add a new entry to an existing validation record. The current block will be used as the entry's block number. Caller must be the author of the record. **Namespace** ``` api.tx.syloDataVerification.addValidationRecordEntry ``` **Type** ``` function addValidationRecordEntry( data_id: Bytes, checksum: H256 ) ``` ### updateValidationRecord Update a validation record's fields. The call takes in an Option value for the fields: resolvers, data\_type, and tags. Setting those fields to Some value will update the field in storage, whilst setting to None will be a no-op. Caller must be the author of the record. **Namespace** ``` api.tx.syloDataVerification.updateValidationRecord ``` **Type** ``` function updateValidationRecord( data_id: Bytes, resolvers: Option>, data_type: Option, tags: Option> ) ``` ### deleteValidationRecord Delete an existing validation record. Caller must be the author of the record. **Namespace** ``` api.tx.syloDataVerification.deleteValidationRecord ``` **Type** ``` function deleteValidationRecord( data_id: Bytes ) ``` ## Storage ### SyloAssetId The asset used to pay for sylo extrinsics. **Namespace** ``` api.query.syloDataVerification.syloAssetId ``` **Type** ``` function syloAssetId(): Option ``` ### SyloResolverMethod The string reserved for the method used by sylo resolvers. **Namespace** ``` api.query.syloDataVerification.syloResolverMethod ``` **Type** ``` function syloResolverMethod(): Bytes ``` ### Resolvers Map from resolver identifier to resolver information. **Namespace** ``` api.query.syloDataVerification.resolvers ``` **Type** ``` function resolvers( Bytes ): Option<{ controller: AccountId, service_endpoints: Vec }> ``` ### ValidationRecords Map from account and data identifier to validation record information. **Namespace** ``` api.query.syloDataVerification.validationRecords ``` **Type** ``` function validationRecords( AccountId, Bytes ): Option<{ author: AccountId, resolvers: Vec<{method: Bytes, identifier: Bytes}>, data_type: Bytes, tags: Vec, entries: Vec<{checksum: H256, block: BlockNumber}> }> ``` ## Events ### PaymentAssetSet The asset used for extrinsics has been set. **Namespace** ``` api.events.syloDataVerification.PaymentAssetSet ``` **Type** ``` type PaymentAssetSet = { asset_id: u32 } ``` ### SyloResolverMethodSet The string reserved for the method used by sylo resolvers has been set. **Namespace** ``` api.events.syloDataVerification.SyloResolverMethodSet ``` **Type** ``` type SyloResolverMethodSet = { method: Vec } ``` ### ResolverRegistered A new resolver has been registered and set in storage. **Namespace** ``` api.events.syloDataVerification.ResolverRegistered ``` **Type** ``` type ResolverRegistered = { id: Vec, controller: AccountId, service_endpoints: Vec> } ``` ### ResolverUpdated An existing resolver has had its service endpoints updated. **Namespace** ``` api.events.syloDataVerification.ResolverUpdated ``` **Type** ``` type ResolverUpdated = { id: Vec, controller: AccountId, service_endpoints: Vec> } ``` ### ResolverDeregistered An existing resolver has been deregistered and removed from storage. **Namespace** ``` api.events.syloDataVerification.ResolverDeregistered ``` **Type** ``` type ResolverDeregistered = { id: Vec } ``` ### ValidationRecordCreated A new validation record has been created and set in storage. **Namespace** ``` api.events.syloDataVerification.ValidationRecordCreated ``` **Type** ``` type ValidationRecordCreated = { author: AccountId, id: Vec } ``` ### ValidationEntryAdded An entry of an existing validation record has been added. **Namespace** ``` api.events.syloDataVerification.ValidationEntryAdded ``` **Type** ``` type ValidationEntryAdded = { author: AccountId, id: Vec, checksum: H256 } ``` ### ValidationRecordUpdated An existing validation record has had its fields updated. **Namespace** ``` api.events.syloDataVerification.ValidationRecordUpdated ``` **Type** ``` type ValidationRecordUpdated = { author: AccountId, id: Vec, resolvers: Option>>, data_type: Option>, tags: Option>> } ``` ### ValidationRecordDeleted An existing validation record has been deleted and removed from storage. **Namespace** ``` api.events.syloDataVerification.ValidationRecordDeleted ``` **Type** ``` type ValidationRecordDeleted = { author: AccountId, id: Vec } ``` ## Errors ### ResolverAlreadyRegistered The Resolver identifier is already in use. **Namespace** ``` api.errors.syloDataVerification.ResolverAlreadyRegistered ``` ### ResolverNotRegistered The Resolver has not been registered. **Namespace** ``` api.errors.syloDataVerification.ResolverNotRegistered ``` ### NotController Account is not controller of resolver. **Namespace** ``` api.errors.syloDataVerification.NotController ``` ### RecordAlreadyCreated A validation record with the given data id has already been created. **Namespace** ``` api.errors.syloDataVerification.RecordAlreadyCreated ``` ### NoValidationRecord The validation record to be updated has not been created. **Namespace** ``` api.errors.syloDataVerification.NoValidationRecord ``` ## Constants ### MaxResolvers The maximum number of resolvers in a validation record. **Namespace** ``` api.consts.syloDataVerification.MaxResolvers ``` **Type** ``` type MaxResolvers = u32 ``` ### MaxTags The maximum number of tags in a validation record. **Namespace** ``` api.consts.syloDataVerification.MaxTags ``` **Type** ``` type MaxTags = u32 ``` ### MaxEntries The maximum number of validation entries in a record. **Namespace** ``` api.consts.syloDataVerification.MaxEntries ``` **Type** ``` type MaxEntries = u32 ``` ### MaxServiceEndpoints The maximum number of service endpoints for a registered resolver. **Namespace** ``` api.consts.syloDataVerification.MaxServiceEndpoints ``` **Type** ``` type MaxServiceEndpoints = u32 ``` ### StringLimit The max length of strings used within the Sylo Pallet. **Namespace** ``` api.consts.syloDataVerification.StringLimit ``` **Type** ``` type StringLimit = u32 ``` # System Source: https://docs.therootnetwork.com/build/substrate/api-reference/runtime-pallets/system ## Calls ### fillBlock A dispatch that will fill the block weight up to the given ratio. **Namespace** ``` api.tx.system.fillBlock ``` **Type** ``` function fillBlock( ratio: Perbill ) ``` ### killPrefix Kill all storage items with a key that starts with the given prefix. **NOTE:** We rely on the Root origin to provide us the number of subkeys under the prefix we are removing to accurately calculate the weight of this function. **Namespace** ``` api.tx.system.killPrefix ``` **Type** ``` function killPrefix( prefix: Bytes, subkeys: u32 ) ``` ### killStorage Kill some items from storage. **Namespace** ``` api.tx.system.killStorage ``` **Type** ``` function killStorage( keys: Vec ) ``` ### remark Make some on-chain remark. **Namespace** ``` api.tx.system.remark ``` **Type** ``` function remark( remark: Bytes ) ``` ### remarkWithEvent Make some on-chain remark and emit event. **Namespace** ``` api.tx.system.remarkWithEvent ``` **Type** ``` function remarkWithEvent( remark: Bytes ) ``` **Usage** system.remarkWithEvent along with utitity.batch call can be used to track an extrinsic. ``` const rootWSEndpoint = "wss://porcini.rootnet.app/ws"; const provider = new WsProvider(rootWSEndpoint); const api = await ApiPromise.create({ noInitWarn: true, provider, types: { AccountId: "EthereumAccountId", AccountId20: "EthereumAccountId", AccountId32: "EthereumAccountId", Address: "AccountId", LookupSource: "AccountId", Lookup0: "AccountId" } }); // Transfer xrp and system remark const calls = [ api.tx.assets.transfer(assetId, destination, amount), api.tx.system.remarkWithEvent('Project id 1234') ]; logger.info( { parameters: [...calls], }, `create a "utility.batch" extrinsic` ); const extrinsic = api.tx.utility.batch(calls); // Sign and Send the transaction await extrinsic.signAndSend(ALICE, {nonce}, ({ events = [], status }) => { if (status.isInBlock) { console.log('Successful transfer of ' + randomAmount + ' with hash ' + status.asInBlock.toHex()); } else { console.log('Status of transfer: ' + status.type); } // This should emit 'system.Remarked' event with the event data hashed. // To check the hashed value, can go to https://portal.rootnet.live/?rpc=wss%3A%2F%2Froot.rootnet.live%2Farchive%2Fws#/signing and add the event data events.forEach(({ phase, event: { data, method, section } }) => { console.log(phase.toString() + ' : ' + section + '.' + method + ' ' + data.toString()); }); }); ``` ### setCode Set the new runtime code. **Namespace** ``` api.tx.system.setCode ``` **Type** ``` function setCode( code: Bytes ) ``` ### setCodeWithoutChecks Set the new runtime code without doing any checks of the given `code`. **Namespace** ``` api.tx.system.setCodeWithoutChecks ``` **Type** ``` function setCodeWithoutChecks( code: Bytes ) ``` ### setHeapPages Set the number of pages in the WebAssembly environment's heap. **Namespace** ``` api.tx.system.setHeapPages ``` **Type** ``` function setHeapPages( pages: u64 ) ``` ### setStorage Set some items of storage. **Namespace** ``` api.tx.system.setStorage ``` **Type** ``` function setStorage( items: Vec<(Bytes,Bytes)> ) ``` ## Storage ### account The full account information for a particular account ID. **Namespace** ``` api.query.system.account ``` **Type** ``` function account( SeedPrimitivesSignatureAccountId20 ): FrameSystemAccountInfo ``` ### allExtrinsicsLen Total length (in bytes) for all extrinsics put together, for the current block. **Namespace** ``` api.query.system.allExtrinsicsLen ``` **Type** ``` function allExtrinsicsLen( ): Option ``` ### blockHash Map of block numbers to block hashes. **Namespace** ``` api.query.system.blockHash ``` **Type** ``` function blockHash( u32 ): H256 ``` ### blockWeight The current weight for the block. **Namespace** ``` api.query.system.blockWeight ``` **Type** ``` function blockWeight( ): FrameSupportDispatchPerDispatchClassWeight ``` ### digest Digest of the current block, also part of the block header. **Namespace** ``` api.query.system.digest ``` **Type** ``` function digest( ): SpRuntimeDigest ``` ### eventCount The number of events in the `Events` list. **Namespace** ``` api.query.system.eventCount ``` **Type** ``` function eventCount( ): u32 ``` ### events Events deposited for the current block. NOTE: The item is unbound and should therefore never be read on chain. It could otherwise inflate the PoV size of a block. Events have a large in-memory size. Box the events to not go out-of-memory just in case someone still reads them from within the runtime. **Namespace** ``` api.query.system.events ``` **Type** ``` function events( ): Vec ``` ### eventTopics Mapping between a topic (represented by T::Hash) and a vector of indexes of events in the `>` list. All topic vectors have deterministic storage locations depending on the topic. This allows light-clients to leverage the changes trie storage tracking mechanism and in case of changes fetch the list of events of interest. The value has the type `(T::BlockNumber, EventIndex)` because if we used only just the `EventIndex` then in case if the topic has the same contents on the next block no notification will be triggered thus the event might be lost. **Namespace** ``` api.query.system.eventTopics ``` **Type** ``` function eventTopics( H256 ): Vec<(u32,u32)> ``` ### executionPhase The execution phase of the block. **Namespace** ``` api.query.system.executionPhase ``` **Type** ``` function executionPhase( ): Option ``` ### extrinsicCount Total extrinsics count for the current block. **Namespace** ``` api.query.system.extrinsicCount ``` **Type** ``` function extrinsicCount( ): Option ``` ### extrinsicData Extrinsics data for the current block (maps an extrinsic's index to its data). **Namespace** ``` api.query.system.extrinsicData ``` **Type** ``` function extrinsicData( u32 ): Bytes ``` ### lastRuntimeUpgrade Stores the `spec_version` and `spec_name` of when the last runtime upgrade happened. **Namespace** ``` api.query.system.lastRuntimeUpgrade ``` **Type** ``` function lastRuntimeUpgrade( ): Option ``` ### number The current block number being processed. Set by `execute_block`. **Namespace** ``` api.query.system.number ``` **Type** ``` function number( ): u32 ``` ### parentHash Hash of the previous block. **Namespace** ``` api.query.system.parentHash ``` **Type** ``` function parentHash( ): H256 ``` ### upgradedToTripleRefCount True if we have upgraded so that AccountInfo contains three types of `RefCount`. False (default) if not. **Namespace** ``` api.query.system.upgradedToTripleRefCount ``` **Type** ``` function upgradedToTripleRefCount( ): bool ``` ### upgradedToU32RefCount True if we have upgraded so that `type RefCount` is `u32`. False (default) if not. **Namespace** ``` api.query.system.upgradedToU32RefCount ``` **Type** ``` function upgradedToU32RefCount( ): bool ``` ## Events ### CodeUpdated `:code` was updated. **Namespace** ``` api.events.system.CodeUpdated ``` **Type** ``` type CodeUpdated = { } ``` ### ExtrinsicFailed An extrinsic failed. **Namespace** ``` api.events.system.ExtrinsicFailed ``` **Type** ``` type ExtrinsicFailed = { dispatch_error: SpRuntimeDispatchError, dispatch_info: FrameSupportDispatchDispatchInfo } ``` ### ExtrinsicSuccess An extrinsic completed successfully. **Namespace** ``` api.events.system.ExtrinsicSuccess ``` **Type** ``` type ExtrinsicSuccess = { dispatch_info: FrameSupportDispatchDispatchInfo } ``` ### KilledAccount An account was reaped. **Namespace** ``` api.events.system.KilledAccount ``` **Type** ``` type KilledAccount = { account: SeedPrimitivesSignatureAccountId20 } ``` ### NewAccount A new account was created. **Namespace** ``` api.events.system.NewAccount ``` **Type** ``` type NewAccount = { account: SeedPrimitivesSignatureAccountId20 } ``` ### Remarked On on-chain remark happened. **Namespace** ``` api.events.system.Remarked ``` **Type** ``` type Remarked = { sender: SeedPrimitivesSignatureAccountId20, hash: H256 } ``` ## Errors ### CallFiltered The origin filter prevent the call to be dispatched. **Namespace** ``` api.errors.system.CallFiltered ``` ### FailedToExtractRuntimeVersion Failed to extract the runtime version from the new runtime. Either calling `Core_version` or decoding `RuntimeVersion` failed. **Namespace** ``` api.errors.system.FailedToExtractRuntimeVersion ``` ### InvalidSpecName The name of specification does not match between the current runtime and the new runtime. **Namespace** ``` api.errors.system.InvalidSpecName ``` ### NonDefaultComposite Suicide called when the account has non-default composite data. **Namespace** ``` api.errors.system.NonDefaultComposite ``` ### NonZeroRefCount There is a non-zero reference count preventing the account from being purged. **Namespace** ``` api.errors.system.NonZeroRefCount ``` ### SpecVersionNeedsToIncrease The specification version is not allowed to decrease between the current runtime and the new runtime. **Namespace** ``` api.errors.system.SpecVersionNeedsToIncrease ``` ## Constants ### blockHashCount Maximum number of block number to block hash mappings to keep (oldest pruned first). **Namespace** ``` api.consts.system.blockHashCount ``` **Type** ``` type blockHashCount = u32 ``` ### blockLength The maximum length of a block (in bytes). **Namespace** ``` api.consts.system.blockLength ``` **Type** ``` type blockLength = FrameSystemLimitsBlockLength ``` ### blockWeights Block & extrinsics weights: base values and limits. **Namespace** ``` api.consts.system.blockWeights ``` **Type** ``` type blockWeights = FrameSystemLimitsBlockWeights ``` ### dbWeight The weight of runtime database operations the runtime can invoke. **Namespace** ``` api.consts.system.dbWeight ``` **Type** ``` type dbWeight = SpWeightsRuntimeDbWeight ``` ### ss58Prefix The designated SS58 prefix of this chain. This replaces the "ss58Format" property declared in the chain spec. Reason is that the runtime should know about the prefix in order to make use of it as an identifier of the chain. **Namespace** ``` api.consts.system.ss58Prefix ``` **Type** ``` type ss58Prefix = u16 ``` ### version Get the chain's current version. **Namespace** ``` api.consts.system.version ``` **Type** ``` type version = SpVersionRuntimeVersion ``` ## JSON-RPC Methods ### `accountNextIndex` Retrieves the next accountIndex as available on the node **Interface** ``` api.rpc.system.accountNextIndex(accountId: AccountId): Index ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"system_accountNextIndex", "params":[accountId: AccountId] } ``` ### `addLogFilter` Adds the supplied directives to the current log filter This method is only active with appropriate flags **Interface** ``` api.rpc.system.addLogFilter(directives: Text): Null ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"system_addLogFilter", "params":[directives: Text] } ``` ### `addReservedPeer` Adds a reserved peer This method is only active with appropriate flags **Interface** ``` api.rpc.system.addReservedPeer(peer: Text): Text ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"system_addReservedPeer", "params":[peer: Text] } ``` ### `chain` Retrieves the chain **Interface** ``` api.rpc.system.chain(): Text ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"system_chain", "params":[] } ``` ### `chainType` Retrieves the chain type **Interface** ``` api.rpc.system.chainType(): ChainType ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"system_chainType", "params":[] } ``` ### `dryRun` Dry run an extrinsic at a given block This method is only active with appropriate flags **Interface** ``` api.rpc.system.dryRun(extrinsic: Bytes, at?: BlockHash): ApplyExtrinsicResult ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"system_dryRun", "params":[extrinsic: Bytes, at?: BlockHash] } ``` ### `health` Return health status of the node **Interface** ``` api.rpc.system.health(): Health ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"system_health", "params":[] } ``` ### `localListenAddresses` The addresses include a trailing /p2p/ with the local PeerId, and are thus suitable to be passed to addReservedPeer or as a bootnode address for example **Interface** ``` api.rpc.system.localListenAddresses(): Vec ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"system_localListenAddresses", "params":[] } ``` ### `localPeerId` Returns the base58-encoded PeerId of the node **Interface** ``` api.rpc.system.localPeerId(): Text ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"system_localPeerId", "params":[] } ``` ### `name` Retrieves the node name **Interface** ``` api.rpc.system.name(): Text ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"system_name", "params":[] } ``` ### `nodeRoles` Returns the roles the node is running as **Interface** ``` api.rpc.system.nodeRoles(): Vec ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"system_nodeRoles", "params":[] } ``` ### `peers` Returns the currently connected peers This method is only active with appropriate flags **Interface** ``` api.rpc.system.peers(): Vec ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"system_peers", "params":[] } ``` ### `properties` Get a custom set of properties as a JSON object, defined in the chain spec **Interface** ``` api.rpc.system.properties(): ChainProperties ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"system_properties", "params":[] } ``` ### `removeReservedPeer` Remove a reserved peer This method is only active with appropriate flags **Interface** ``` api.rpc.system.removeReservedPeer(peerId: Text): Text ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"system_removeReservedPeer", "params":[peerId: Text] } ``` ### `reservedPeers` Returns the list of reserved peers **Interface** ``` api.rpc.system.reservedPeers(): Vec ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"system_reservedPeers", "params":[] } ``` ### `resetLogFilter` Resets the log filter to Substrate defaults This method is only active with appropriate flags **Interface** ``` api.rpc.system.resetLogFilter(): Null ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"system_resetLogFilter", "params":[] } ``` ### `syncState` Returns the state of the syncing of the node **Interface** ``` api.rpc.system.syncState(): SyncState ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"system_syncState", "params":[] } ``` ### `version` Retrieves the version of the node **Interface** ``` api.rpc.system.version(): Text ``` **JSON** ``` { "id":1, "jsonrpc":"2.0", "method":"system_version", "params":[] } ``` # Timestamp Source: https://docs.therootnetwork.com/build/substrate/api-reference/runtime-pallets/timestamp ## Calls ### set Set the current time. This call should be invoked exactly once per block. It will panic at the finalization phase, if this call hasn't been invoked by that time. The timestamp should be greater than the previous one by the amount specified by `MinimumPeriod`. The dispatch origin for this call must be `Inherent`. **Namespace** ``` api.tx.timestamp.set ``` **Type** ``` function set( now: Compact ) ``` ## Storage ### didUpdate Did the timestamp get updated in this block? **Namespace** ``` api.query.timestamp.didUpdate ``` **Type** ``` function didUpdate( ): bool ``` ### now Current time for the current block. **Namespace** ``` api.query.timestamp.now ``` **Type** ``` function now( ): u64 ``` undefinedundefined## Constants ### minimumPeriod The minimum period between blocks. Beware that this is different to the *expected* period that the block production apparatus provides. Your chosen consensus system will generally work with this to determine a sensible block time. e.g. For Aura, it will be double this period on default settings. **Namespace** ``` api.consts.timestamp.minimumPeriod ``` **Type** ``` type minimumPeriod = u64 ``` # TokenApprovals Source: https://docs.therootnetwork.com/build/substrate/api-reference/runtime-pallets/tokenapprovals ## Pallet Calls #### erc1155ApprovalForAll ***Only accessible through the EVM.*** > Set approval for an account (or contract) to transfer any tokens from an SFT collection mapping(address => mapping(address => bool)) private \_operatorApprovals; > > **Namespace:** > > ``` > api.tx.tokenApprovals.erc1155ApprovalForAll > ``` > > **Type:** > > ``` > function erc1155ApprovalForAll( > caller: SeedPrimitivesSignatureAccountId20, > operator_account: SeedPrimitivesSignatureAccountId20, > collection_uuid: u32, > approved: bool > ) > ``` #### erc20Approval ***Only accessible through the EVM.*** > Set approval for an account to transfer an amount of tokens on behalf of the caller Mapping from caller to spender and amount mapping(address => mapping(address => uint256)) private \_allowances; > > **Namespace:** > > ``` > api.tx.tokenApprovals.erc20Approval > ``` > > **Type:** > > ``` > function erc20Approval( > caller: SeedPrimitivesSignatureAccountId20, > spender: SeedPrimitivesSignatureAccountId20, > asset_id: u32, > amount: u128 > ) > ``` #### erc20UpdateApproval ***Only accessible through the EVM.*** > Removes an approval over an account and asset\_id mapping(address => mapping(address => uint256)) private \_allowances; > > **Namespace:** > > ``` > api.tx.tokenApprovals.erc20UpdateApproval > ``` > > **Type:** > > ``` > function erc20UpdateApproval( > caller: SeedPrimitivesSignatureAccountId20, > spender: SeedPrimitivesSignatureAccountId20, > asset_id: u32, > amount: u128 > ) > ``` #### erc721Approval ***Only accessible through the EVM.*** > Set approval for a single NFT Mapping from token\_id to operator clears approval on transfer mapping(uint256 => address) private \_tokenApprovals; > > **Namespace:** > > ``` > api.tx.tokenApprovals.erc721Approval > ``` > > **Type:** > > ``` > function erc721Approval( > caller: SeedPrimitivesSignatureAccountId20, > operator_account: SeedPrimitivesSignatureAccountId20, > token_id: (u32,u32) > ) > ``` #### erc721ApprovalForAll ***Only accessible through the EVM.*** > Set approval for an account (or contract) to transfer any tokens from a collection mapping(address => mapping(address => bool)) private \_operatorApprovals; > > **Namespace:** > > ``` > api.tx.tokenApprovals.erc721ApprovalForAll > ``` > > **Type:** > > ``` > function erc721ApprovalForAll( > caller: SeedPrimitivesSignatureAccountId20, > operator_account: SeedPrimitivesSignatureAccountId20, > collection_uuid: u32, > approved: bool > ) > ``` #### erc721RemoveApproval > Public method which allows users to remove approvals on a token they own. Can be called outside of the EVM as a Substrate extrinsic. > > **Namespace:** > > ``` > api.tx.tokenApprovals.erc721RemoveApproval > ``` > > **Type:** > > ``` > function erc721RemoveApproval( > token_id: (u32,u32) > ) > ``` ## Pallet Storage #### eRC1155ApprovalsForAll > **Namespace:** > > ``` > api.query.tokenApprovals.eRC1155ApprovalsForAll > ``` > > **Type:** > > ``` > function eRC1155ApprovalsForAll( > SeedPrimitivesSignatureAccountId20, > (u32,SeedPrimitivesSignatureAccountId20) > ): Option > ``` #### eRC20Approvals > **Namespace:** > > ``` > api.query.tokenApprovals.eRC20Approvals > ``` > > **Type:** > > ``` > function eRC20Approvals( > (SeedPrimitivesSignatureAccountId20,u32), > SeedPrimitivesSignatureAccountId20 > ): Option > ``` #### eRC721Approvals > **Namespace:** > > ``` > api.query.tokenApprovals.eRC721Approvals > ``` > > **Type:** > > ``` > function eRC721Approvals( > (u32,u32) > ): Option > ``` #### eRC721ApprovalsForAll **Namespace:** > ``` > api.query.tokenApprovals.eRC721ApprovalsForAll > ``` > > **Type:** > > ``` > function eRC721ApprovalsForAll( > SeedPrimitivesSignatureAccountId20, > (u32,SeedPrimitivesSignatureAccountId20) > ): Option > ``` ## Pallet Errors #### AlreadyApproved > Address is already approved > > **Namespace:** > > ``` > api.errors.tokenApprovals.AlreadyApproved > ``` #### ApprovalDoesntExist > There is no approval set for this token > > **Namespace:** > > ``` > api.errors.tokenApprovals.ApprovalDoesntExist > ``` #### ApprovedAmountTooLow > The caller is not approved for the requested amount > > **Namespace:** > > ``` > api.errors.tokenApprovals.ApprovedAmountTooLow > ``` #### CallerNotApproved > The caller isn't approved for any amount > > **Namespace:** > > ``` > api.errors.tokenApprovals.CallerNotApproved > ``` #### CallerNotOperator > The caller account can't be the same as the operator account > > **Namespace:** > > ``` > api.errors.tokenApprovals.CallerNotOperator > ``` #### NoToken > The token doesn't exist > > **Namespace:** > > ``` > api.errors.tokenApprovals.NoToken > ``` #### NotTokenOwner > The account is not the owner of the token > > **Namespace:** > > ``` > api.errors.tokenApprovals.NotTokenOwner > ``` #### NotTokenOwnerOrApproved > The account is not the owner of the token or an approved account > > **Namespace:** > > ``` > api.errors.tokenApprovals.NotTokenOwnerOrApproved > ``` # TransactionPayment Source: https://docs.therootnetwork.com/build/substrate/api-reference/runtime-pallets/transactionpayment ## Storage ### nextFeeMultiplier **Namespace** ``` api.query.transactionPayment.nextFeeMultiplier ``` **Type** ``` function nextFeeMultiplier( ): u128 ``` ### storageVersion **Namespace** ``` api.query.transactionPayment.storageVersion ``` **Type** ``` function storageVersion( ): PalletTransactionPaymentReleases ``` ## Events ### TransactionFeePaid A transaction fee `actual_fee`, of which `tip` was added to the minimum inclusion fee, has been paid by `who`. **Namespace** ``` api.events.transactionPayment.TransactionFeePaid ``` **Type** ``` type TransactionFeePaid = { who: SeedPrimitivesSignatureAccountId20, actual_fee: u128, tip: u128 } ``` undefined## Constants ### operationalFeeMultiplier A fee multiplier for `Operational` extrinsics to compute "virtual tip" to boost their `priority` This value is multiplied by the `final_fee` to obtain a "virtual tip" that is later added to a tip component in regular `priority` calculations. It means that a `Normal` transaction can front-run a similarly sized `Operational` extrinsic (with no tip), by including a tip value greater than the virtual tip. \`\`\`rust,ignore // For `Normal` let priority = priority\_calc(tip); // For `Operational` let virtual\_tip = (inclusion\_fee + tip) \* OperationalFeeMultiplier; let priority = priority\_calc(tip + virtual\_tip); \`\`\` Note: Since we use `final_fee` the multiplier applies also to the regular `tip` sent with the transaction. So, not only does the transaction get a priority bump based on the `inclusion_fee`, but we also amplify the impact of tips applied to `Operational` transactions. **Namespace** ``` api.consts.transactionPayment.operationalFeeMultiplier ``` **Type** ``` type operationalFeeMultiplier = u8 ``` # TxFeePot Source: https://docs.therootnetwork.com/build/substrate/api-reference/runtime-pallets/txfeepot ## Storage ### eraTxFees Accrued transaction fees in the current staking Era **Namespace** ``` api.query.txFeePot.eraTxFees ``` **Type** ``` function eraTxFees( ): u128 ``` undefinedundefined## Constants ### txFeePotId **Namespace** ``` api.consts.txFeePot.txFeePotId ``` **Type** ``` type txFeePotId = FrameSupportPalletId ``` # Utility Source: https://docs.therootnetwork.com/build/substrate/api-reference/runtime-pallets/utility ## Calls ### asDerivative Send a call through an indexed pseudonym of the sender. Filter from origin are passed along. The call will be dispatched with an origin which use the same filter as the origin of this call. **NOTE**: * If you need to ensure that any account-based filtering is not honored (i.e. because you expect `proxy` to have been used prior in the call stack and you do not want the call restrictions to apply to any sub-accounts), then use `as_multi_threshold_1` in the Multisig pallet instead. * Prior to version \*12, this was called `as_limited_sub`. The dispatch origin for this call must be *Signed*. **Namespace** ``` api.tx.utility.asDerivative ``` **Type** ``` function asDerivative( index: u16, call: Call ) ``` ### batch Send a batch of dispatch calls. May be called from any origin. * `calls`: The calls to be dispatched from the same origin. The number of call must not exceed the constant: `batched_calls_limit` (available in constant metadata). If origin is root then call are dispatch without checking origin filter. (This includes bypassing `frame_system::Config::BaseCallFilter`). This will return `Ok` in all circumstances. To determine the success of the batch, an event is deposited. If a call failed and the batch was interrupted, then the `BatchInterrupted` event is deposited, along with the number of successful calls made and the error of the failed call. If all were successful, then the `BatchCompleted` event is deposited. **Namespace** ``` api.tx.utility.batch ``` **Type** ``` function batch( calls: Vec ) ``` ### batchAll Send a batch of dispatch calls and atomically execute them. The whole transaction will rollback and fail if any of the calls failed. May be called from any origin. * `calls`: The calls to be dispatched from the same origin. The number of call must not exceed the constant: `batched_calls_limit` (available in constant metadata). If origin is root then call are dispatch without checking origin filter. (This includes bypassing `frame_system::Config::BaseCallFilter`). **Namespace** ``` api.tx.utility.batchAll ``` **Type** ``` function batchAll( calls: Vec ) ``` ### dispatchAs Dispatches a function call with a provided origin. The dispatch origin for this call must be *Root*. **Namespace** ``` api.tx.utility.dispatchAs ``` **Type** ``` function dispatchAs( as_origin: SeedRuntimeOriginCaller, call: Call ) ``` ### forceBatch Send a batch of dispatch calls. Unlike `batch`, it allows errors and won't interrupt. May be called from any origin. * `calls`: The calls to be dispatched from the same origin. The number of call must not exceed the constant: `batched_calls_limit` (available in constant metadata). If origin is root then call are dispatch without checking origin filter. (This includes bypassing `frame_system::Config::BaseCallFilter`). **Namespace** ``` api.tx.utility.forceBatch ``` **Type** ``` function forceBatch( calls: Vec ) ``` undefined## Events ### BatchCompleted Batch of dispatches completed fully with no error. **Namespace** ``` api.events.utility.BatchCompleted ``` **Type** ``` type BatchCompleted = { } ``` ### BatchCompletedWithErrors Batch of dispatches completed but has errors. **Namespace** ``` api.events.utility.BatchCompletedWithErrors ``` **Type** ``` type BatchCompletedWithErrors = { } ``` ### BatchInterrupted Batch of dispatches did not complete fully. Index of first failing dispatch given, as well as the error. **Namespace** ``` api.events.utility.BatchInterrupted ``` **Type** ``` type BatchInterrupted = { index: u32, error: SpRuntimeDispatchError } ``` ### DispatchedAs A call was dispatched. **Namespace** ``` api.events.utility.DispatchedAs ``` **Type** ``` type DispatchedAs = { result: Result } ``` ### ItemCompleted A single item within a Batch of dispatches has completed with no error. **Namespace** ``` api.events.utility.ItemCompleted ``` **Type** ``` type ItemCompleted = { } ``` ### ItemFailed A single item within a Batch of dispatches has been completed with error. **Namespace** ``` api.events.utility.ItemFailed ``` **Type** ``` type ItemFailed = { error: SpRuntimeDispatchError } ``` ## Errors ### TooManyCalls Too many calls batched. **Namespace** ``` api.errors.utility.TooManyCalls ``` ## Constants ### batchedCallsLimit The limit on the number of batched calls. **Namespace** ``` api.consts.utility.batchedCallsLimit ``` **Type** ``` type batchedCallsLimit = u32 ``` # VortexDistribution Source: https://docs.therootnetwork.com/build/substrate/api-reference/runtime-pallets/vortexdistribution ## Calls ### setAdmin Set a new admin account that can perform privileged operations. The dispatch origin for this call must be *Root*. Parameters: * `new`: The new admin account. **Namespace** ``` api.tx.vortexDistribution.setAdmin ``` **Type** ``` function setAdmin( new: AccountId ) ``` ### createVtxDist Create a new Vortex distribution. The dispatch origin for this call must be *Root* or *Admin*. **Namespace** ``` api.tx.vortexDistribution.createVtxDist ``` **Type** ``` function createVtxDist() ``` ### disableVtxDist Disable a Vortex distribution. The dispatch origin for this call must be *Root* or *Admin*. Parameters: * `id`: The ID of the distribution to disable. **Namespace** ``` api.tx.vortexDistribution.disableVtxDist ``` **Type** ``` function disableVtxDist( id: VtxDistIdentifier ) ``` ### setConsiderCurrentBalance Set whether to consider current balances for reward calculations. The dispatch origin for this call must be *Root* or *Admin*. Parameters: * `value`: Boolean indicating whether to consider current balances. **Namespace** ``` api.tx.vortexDistribution.setConsiderCurrentBalance ``` **Type** ``` function setConsiderCurrentBalance( value: boolean ) ``` ### setDisableRedeem Enable or disable token redemption functionality. The dispatch origin for this call must be *Root* or *Admin*. Parameters: * `value`: Boolean indicating whether to disable redemption. **Namespace** ``` api.tx.vortexDistribution.setDisableRedeem ``` **Type** ``` function setDisableRedeem( value: boolean ) ``` ### setEnableManualRewardInput Enable or disable manual reward input. The dispatch origin for this call must be *Root* or *Admin*. Parameters: * `value`: Boolean indicating whether to enable manual reward input. **Namespace** ``` api.tx.vortexDistribution.setEnableManualRewardInput ``` **Type** ``` function setEnableManualRewardInput( value: boolean ) ``` ### setFeePotAssetBalances Set fee pot asset balances. The dispatch origin for this call must be *Root* or *Admin*. Parameters: * `id`: The distribution ID. * `assets_balances`: List of asset balances. **Namespace** ``` api.tx.vortexDistribution.setFeePotAssetBalances ``` **Type** ``` function setFeePotAssetBalances( id: VtxDistIdentifier, assets_balances: Vec<(AssetId, Balance)> ) ``` ### setVtxVaultAssetBalances Set Vortex vault asset balances. The dispatch origin for this call must be *Root* or *Admin*. Parameters: * `id`: The distribution ID. * `assets_balances`: List of asset balances. **Namespace** ``` api.tx.vortexDistribution.setVtxVaultAssetBalances ``` **Type** ``` function setVtxVaultAssetBalances( id: VtxDistIdentifier, assets_balances: Vec<(AssetId, Balance)> ) ``` ### setVtxTotalSupply Set Vortex total supply. The dispatch origin for this call must be *Root* or *Admin*. Parameters: * `id`: The distribution ID. * `supply`: Total supply amount. **Namespace** ``` api.tx.vortexDistribution.setVtxTotalSupply ``` **Type** ``` function setVtxTotalSupply( id: VtxDistIdentifier, supply: Balance ) ``` ### setAssetPrices Set asset prices. The dispatch origin for this call must be *Root* or *Admin*. Parameters: * `id`: The distribution ID. * `asset_prices`: List of asset prices. **Namespace** ``` api.tx.vortexDistribution.setAssetPrices ``` **Type** ``` function setAssetPrices( id: VtxDistIdentifier, asset_prices: Vec<(AssetId, Balance)> ) ``` ### registerRewardPoints Register reward points. The dispatch origin for this call must be *Root* or *Admin*. Parameters: * `id`: The distribution ID. * `reward_points`: List of reward points. **Namespace** ``` api.tx.vortexDistribution.registerRewardPoints ``` **Type** ``` function registerRewardPoints( id: VtxDistIdentifier, reward_points: Vec<(AccountId, Balance)> ) ``` ### registerWorkPoints Register work points. The dispatch origin for this call must be *Root* or *Admin*. Parameters: * `id`: The distribution ID. * `work_points`: List of work points. **Namespace** ``` api.tx.vortexDistribution.registerWorkPoints ``` **Type** ``` function registerWorkPoints( id: VtxDistIdentifier, work_points: Vec<(AccountId, Balance)> ) ``` ### triggerVtxDistribution Trigger a Vortex distribution. The dispatch origin for this call must be *Root* or *Admin*. Parameters: * `id`: The distribution ID. **Namespace** ``` api.tx.vortexDistribution.triggerVtxDistribution ``` **Type** ``` function triggerVtxDistribution( id: VtxDistIdentifier ) ``` ### startVtxDist Start a Vortex distribution. The dispatch origin for this call must be *Root* or *Admin*. Parameters: * `id`: The distribution ID. **Namespace** ``` api.tx.vortexDistribution.startVtxDist ``` **Type** ``` function startVtxDist( id: VtxDistIdentifier ) ``` ### payUnsigned Process unsigned payouts. The dispatch origin for this call must be *None*. Parameters: * `id`: The distribution ID. * `current_block`: Current block number. **Namespace** ``` api.tx.vortexDistribution.payUnsigned ``` **Type** ``` function payUnsigned( id: VtxDistIdentifier, current_block: BlockNumber ) ``` ### setVtxVaultRedeemAssetList Set redeemable assets list. The dispatch origin for this call must be *Root* or *Admin*. Parameters: * `assets_list`: List of redeemable assets. **Namespace** ``` api.tx.vortexDistribution.setVtxVaultRedeemAssetList ``` **Type** ``` function setVtxVaultRedeemAssetList( assets_list: Vec ) ``` ### registerRewards Register rewards manually. The dispatch origin for this call must be *Root* or *Admin*. Parameters: * `id`: The distribution ID. * `rewards`: List of rewards. **Namespace** ``` api.tx.vortexDistribution.registerRewards ``` **Type** ``` function registerRewards( id: VtxDistIdentifier, rewards: Vec<(AccountId, Balance)> ) ``` ### redeemTokensFromVault Redeem tokens from the Vortex vault. The dispatch origin for this call must be *Signed*. Parameters: * `vortex_token_amount`: Amount of Vortex tokens to redeem. **Namespace** ``` api.tx.vortexDistribution.redeemTokensFromVault ``` **Type** ``` function redeemTokensFromVault( vortex_token_amount: Balance ) ``` ## Storage ### adminAccount The admin account that can perform privileged operations. **Namespace** ``` api.query.vortexDistribution.adminAccount ``` **Type** ``` function adminAccount(): Option ``` ### nextVortexId The next available Vortex distribution ID. **Namespace** ``` api.query.vortexDistribution.nextVortexId ``` **Type** ``` function nextVortexId(): VtxDistIdentifier ``` ### considerCurrentBalance Flag indicating whether to consider current balances for reward calculations. **Namespace** ``` api.query.vortexDistribution.considerCurrentBalance ``` **Type** ``` function considerCurrentBalance(): boolean ``` ### disableRedeem Flag to disable token redemption functionality. **Namespace** ``` api.query.vortexDistribution.disableRedeem ``` **Type** ``` function disableRedeem(): boolean ``` ### enableManualRewardInput Flag to enable manual reward input. **Namespace** ``` api.query.vortexDistribution.enableManualRewardInput ``` **Type** ``` function enableManualRewardInput(): boolean ``` ### vtxVaultRedeemAssetList List of assets available for redemption. **Namespace** ``` api.query.vortexDistribution.vtxVaultRedeemAssetList ``` **Type** ``` function vtxVaultRedeemAssetList(): Vec ``` ### totalRewardPoints Total reward points for each distribution cycle. **Namespace** ``` api.query.vortexDistribution.totalRewardPoints ``` **Type** ``` function totalRewardPoints( id: VtxDistIdentifier ): Balance ``` ### totalWorkPoints Total work points for each distribution cycle. **Namespace** ``` api.query.vortexDistribution.totalWorkPoints ``` **Type** ``` function totalWorkPoints( id: VtxDistIdentifier ): Balance ``` ### vtxDistStatuses Status of each Vortex distribution. **Namespace** ``` api.query.vortexDistribution.vtxDistStatuses ``` **Type** ``` function vtxDistStatuses( id: VtxDistIdentifier ): VtxDistStatus ``` ### vtxTotalSupply Total supply of Vortex tokens for each distribution. **Namespace** ``` api.query.vortexDistribution.vtxTotalSupply ``` **Type** ``` function vtxTotalSupply( id: VtxDistIdentifier ): Balance ``` ### vtxPrice Vortex token price for each distribution. **Namespace** ``` api.query.vortexDistribution.vtxPrice ``` **Type** ``` function vtxPrice( id: VtxDistIdentifier ): Balance ``` ### vtxDistOrderbook Order book for each Vortex distribution. **Namespace** ``` api.query.vortexDistribution.vtxDistOrderbook ``` **Type** ``` function vtxDistOrderbook( id: VtxDistIdentifier, account: AccountId ): (Balance, boolean) ``` ### rewardPoints Reward points for each account in each distribution. **Namespace** ``` api.query.vortexDistribution.rewardPoints ``` **Type** ``` function rewardPoints( id: VtxDistIdentifier, account: AccountId ): Balance ``` ### workPoints Work points for each account in each distribution. **Namespace** ``` api.query.vortexDistribution.workPoints ``` **Type** ``` function workPoints( id: VtxDistIdentifier, account: AccountId ): Balance ``` ### feePotAssetsList Fee pot asset list for each distribution. **Namespace** ``` api.query.vortexDistribution.feePotAssetsList ``` **Type** ``` function feePotAssetsList( id: VtxDistIdentifier ): Vec<(AssetId, Balance)> ``` ### vtxVaultAssetsList Vortex vault asset list for each distribution. **Namespace** ``` api.query.vortexDistribution.vtxVaultAssetsList ``` **Type** ``` function vtxVaultAssetsList( id: VtxDistIdentifier ): Vec<(AssetId, Balance)> ``` ### assetPrices Asset prices for each distribution. **Namespace** ``` api.query.vortexDistribution.assetPrices ``` **Type** ``` function assetPrices( id: VtxDistIdentifier, asset: AssetId ): Balance ``` ### totalNetworkReward Total network reward for each distribution. **Namespace** ``` api.query.vortexDistribution.totalNetworkReward ``` **Type** ``` function totalNetworkReward( id: VtxDistIdentifier ): Balance ``` ### totalBootstrapReward Total bootstrap reward for each distribution. **Namespace** ``` api.query.vortexDistribution.totalBootstrapReward ``` **Type** ``` function totalBootstrapReward( id: VtxDistIdentifier ): Balance ``` ### totalVortex Total Vortex amount for each distribution. **Namespace** ``` api.query.vortexDistribution.totalVortex ``` **Type** ``` function totalVortex( id: VtxDistIdentifier ): Balance ``` ### nextUnsignedAt Next unsigned transaction block number. **Namespace** ``` api.query.vortexDistribution.nextUnsignedAt ``` **Type** ``` function nextUnsignedAt(): BlockNumber ``` ### vtxDistPayoutPivot Payout pivot block for each distribution. **Namespace** ``` api.query.vortexDistribution.vtxDistPayoutPivot ``` **Type** ``` function vtxDistPayoutPivot( id: VtxDistIdentifier ): Vec ``` ### vtxRewardCalculationPivot Reward calculation pivot block for each distribution. **Namespace** ``` api.query.vortexDistribution.vtxRewardCalculationPivot ``` **Type** ``` function vtxRewardCalculationPivot( id: VtxDistIdentifier ): Vec ``` ## Constants ### VTX\_DIST\_UNSIGNED\_PRIORITY Priority for unsigned transactions. **Type** ``` TransactionPriority ``` ### PRECISION\_MULTIPLIER Precision multiplier for integer math (10^6). **Type** ``` u128 ``` ### PRICE\_MULTIPLIER Asset price multiplier (10^6). **Type** ``` u128 ``` ## Errors ### RequireAdmin When admin privileges are required. ### VtxDistIdNotAvailable When no distribution ID is available. ### VtxDistAlreadyEnabled When distribution is already enabled. ### VtxDistDisabled When distribution is disabled. ### NoVtxAssetMinted When no Vortex assets are minted. ### InvalidAmount When an invalid amount is provided. ### VtxDistIdInUse When distribution ID is already in use. ### NotAValidator When caller is not a validator. ### VortexPeriodNotSet When Vortex period is not set. ### PivotStringTooLong When pivot string is too long. ### AssetsShouldNotIncludeVtxAsset When assets include Vortex asset. ### CannotTrigger When distribution cannot be triggered. ### CannotRedeem When distribution cannot be redeemed. ### NotTriggered When distribution is not triggered. ### ExceededMaxRewards When rewards exceed maximum limit. ### VortexPriceIsZero When Vortex price is zero. ### RootPriceIsZero When root price is zero. ### VtxRedeemDisabled When Vortex redemption is disabled. ### ManualRewardInputDisabled When manual reward input is disabled. ### VtxRewardPayoutFailed When reward payout fails. ### RewardPointsNotRegistered When reward points are not registered. # VoterList Source: https://docs.therootnetwork.com/build/substrate/api-reference/runtime-pallets/voterlist ## Calls ### putInFrontOf Move the caller's Id directly in front of `lighter`. The dispatch origin for this call must be *Signed* and can only be called by the Id of the account going in front of `lighter`. Only works if * both nodes are within the same bag, * and `origin` has a greater `Score` than `lighter`. **Namespace** ``` api.tx.voterList.putInFrontOf ``` **Type** ``` function putInFrontOf( lighter: SeedPrimitivesSignatureAccountId20 ) ``` ### rebag Declare that some `dislocated` account has, through rewards or penalties, sufficiently changed its score that it should properly fall into a different bag than its current one. Anyone can call this function about any potentially dislocated account. Will always update the stored score of `dislocated` to the correct score, based on `ScoreProvider`. If `dislocated` does not exists, it returns an error. **Namespace** ``` api.tx.voterList.rebag ``` **Type** ``` function rebag( dislocated: SeedPrimitivesSignatureAccountId20 ) ``` ## Storage ### counterForListNodes Counter for the related counted storage map **Namespace** ``` api.query.voterList.counterForListNodes ``` **Type** ``` function counterForListNodes( ): u32 ``` ### listBags A bag stored in storage. Stores a `Bag` struct, which stores head and tail pointers to itself. **Namespace** ``` api.query.voterList.listBags ``` **Type** ``` function listBags( u64 ): Option ``` ### listNodes A single node, within some bag. Nodes store links forward and back within their respective bags. **Namespace** ``` api.query.voterList.listNodes ``` **Type** ``` function listNodes( SeedPrimitivesSignatureAccountId20 ): Option ``` ## Events ### Rebagged Moved an account from one bag to another. **Namespace** ``` api.events.voterList.Rebagged ``` **Type** ``` type Rebagged = { who: SeedPrimitivesSignatureAccountId20, from: u64, to: u64 } ``` ### ScoreUpdated Updated the score of some account to the given amount. **Namespace** ``` api.events.voterList.ScoreUpdated ``` **Type** ``` type ScoreUpdated = { who: SeedPrimitivesSignatureAccountId20, new_score: u64 } ``` ## Errors ### List A error in the list interface implementation. **Namespace** ``` api.errors.voterList.List ``` ## Constants ### bagThresholds The list of thresholds separating the various bags. Ids are separated into unsorted bags according to their score. This specifies the thresholds separating the bags. An id's bag is the largest bag for which the id's score is less than or equal to its upper threshold. When ids are iterated, higher bags are iterated completely before lower bags. This means that iteration is *semi-sorted*: ids of higher score tend to come before ids of lower score, but peer ids within a particular bag are sorted in insertion order. **Expressing the constant** This constant must be sorted in strictly increasing order. Duplicate items are not permitted. There is an implied upper limit of `Score::MAX`; that value does not need to be specified within the bag. For any two threshold lists, if one ends with `Score::MAX`, the other one does not, and they are otherwise equal, the two lists will behave identically. **Calculation** It is recommended to generate the set of thresholds in a geometric series, such that there exists some constant ratio such that `threshold[k + 1] == (threshold[k] * constant_ratio).max(threshold[k] + 1)` for all `k`. The helpers in the `/utils/frame/generate-bags` module can simplify this calculation. **Examples** * If `BagThresholds::get().is_empty()`, then all ids are put into the same bag, and iteration is strictly in insertion order. * If `BagThresholds::get().len() == 64`, and the thresholds are determined according to the procedure given above, then the constant ratio is equal to 2. * If `BagThresholds::get().len() == 200`, and the thresholds are determined according to the procedure given above, then the constant ratio is approximately equal to 1.248. * If the threshold list begins `[1, 2, 3, ...]`, then an id with score 0 or 1 will fall into bag 0, an id with score 2 will fall into bag 1, etc. **Migration** In the event that this list ever changes, a copy of the old bags list must be retained. With that `List::migrate` can be called, which will perform the appropriate migration. **Namespace** ``` api.consts.voterList.bagThresholds ``` **Type** ``` type bagThresholds = Vec ``` # Xls20 Source: https://docs.therootnetwork.com/build/substrate/api-reference/runtime-pallets/xls20 ## Calls ### enableXls20Compatibility Enables XLS-20 compatibility on a collection. However, this will remove the ability to change the collection metadata. * Collection must not have any tokens minted * Caller must be collection owner **Namespace** ``` api.tx.xls20.enableXls20Compatibility ``` **Type** ``` function enableXls20Compatibility( collection_id: u32 ) ``` ### fulfillXls20Mint Submit XLS-20 token ids to The Root Network Only callable by the trusted relayer account Can apply multiple mappings from the same collection in one transaction **Namespace** ``` api.tx.xls20.fulfillXls20Mint ``` **Type** ``` function fulfillXls20Mint( collection_id: u32, token_mappings: Vec<(u32,[u8;64])> ) ``` ### reRequestXls20Mint **Namespace** ``` api.tx.xls20.reRequestXls20Mint ``` **Type** ``` function reRequestXls20Mint( collection_id: u32, serial_numbers: Vec ) ``` ### setRelayer Set the relayer address **Namespace** ``` api.tx.xls20.setRelayer ``` **Type** ``` function setRelayer( relayer: SeedPrimitivesSignatureAccountId20 ) ``` ### setXls20Fee Set the xls20 mint fee which is paid per token by the collection owner This covers the additional costs incurred by the relayer for the following: * Minting the token on XRPL * Calling fulfill\_xls20\_mint on The Root Network **Namespace** ``` api.tx.xls20.setXls20Fee ``` **Type** ``` function setXls20Fee( new_fee: u128 ) ``` ## Storage ### relayer The permissioned relayer **Namespace** ``` api.query.xls20.relayer ``` **Type** ``` function relayer( ): Option ``` ### xls20MintFee The extra cost of minting an XLS-20 compatible NFT **Namespace** ``` api.query.xls20.xls20MintFee ``` **Type** ``` function xls20MintFee( ): u128 ``` ### xls20TokenMap Maps from TRN native token\_id to XLS-20 TokenId **Namespace** ``` api.query.xls20.xls20TokenMap ``` **Type** ``` function xls20TokenMap( u32, u32 ): Option<[u8;64]> ``` ## Events ### RelayerSet A new relayer has been set **Namespace** ``` api.events.xls20.RelayerSet ``` **Type** ``` type RelayerSet = { account: SeedPrimitivesSignatureAccountId20 } ``` ### Xls20CompatibilityEnabled A collection has had XLS-20 compatibility enabled **Namespace** ``` api.events.xls20.Xls20CompatibilityEnabled ``` **Type** ``` type Xls20CompatibilityEnabled = { collection_id: u32 } ``` ### Xls20MappingSet A new XLS20 mapping has been set **Namespace** ``` api.events.xls20.Xls20MappingSet ``` **Type** ``` type Xls20MappingSet = { collection_id: u32, mappings: Vec<(u32,[u8;64])> } ``` ### Xls20MintFeePaid Additional mint fee for XLS-20 mint has been paid to relayer **Namespace** ``` api.events.xls20.Xls20MintFeePaid ``` **Type** ``` type Xls20MintFeePaid = { collection_owner: SeedPrimitivesSignatureAccountId20, total_fee: u128 } ``` ### Xls20MintFeeSet A new Xls20 Mint Fee has been set **Namespace** ``` api.events.xls20.Xls20MintFeeSet ``` **Type** ``` type Xls20MintFeeSet = { new_fee: u128 } ``` ### Xls20MintRequest Request sent to XLS20 Relayer **Namespace** ``` api.events.xls20.Xls20MintRequest ``` **Type** ``` type Xls20MintRequest = { collection_id: u32, serial_numbers: Vec, token_uris: Vec } ``` ## Errors ### MappingAlreadyExists There is already a Root native -> XLS-20 mapping for this token **Namespace** ``` api.errors.xls20.MappingAlreadyExists ``` ### NotCollectionOwner No the owner of the collection **Namespace** ``` api.errors.xls20.NotCollectionOwner ``` ### NoToken The NFT does not exist **Namespace** ``` api.errors.xls20.NoToken ``` ### NotRelayer The caller is not the relayer and does not have permission to perform this action **Namespace** ``` api.errors.xls20.NotRelayer ``` ### NotXLS20Compatible The collection is not compatible with XLS-20 **Namespace** ``` api.errors.xls20.NotXLS20Compatible ``` ### Xls20MintFeeTooLow The supplied fee for minting XLS-20 tokens is too low **Namespace** ``` api.errors.xls20.Xls20MintFeeTooLow ``` undefined # XrplBridge Source: https://docs.therootnetwork.com/build/substrate/api-reference/runtime-pallets/xrplbridge *** ## Pallet Calls *** ### Add Relayer > add a relayer > > **Namespace:** > > ``` > api.tx.xrplBridge.addRelayer > ``` > > **Type:** > > ``` > function addRelayer( > relayer: SeedPrimitivesSignatureAccountId20 > ) > ``` ### Prune Settled Ledger Index (Sudo Only) > **Namespace:** > > ``` > api.tx.xrplBridge.pruneSettledLedgerIndex > ``` > > **Type:** > > ``` > function pruneSettledLedgerIndex( > ledger_index: u32 > ) > ``` ### Remove Relayer > remove a relayer > > **Namespace:** > > ``` > api.tx.xrplBridge.removeRelayer > ``` > > **Type:** > > ``` > function removeRelayer( > relayer: SeedPrimitivesSignatureAccountId20 > ) > ``` ### Reset Settled Xrpl Tx Data (Sudo Only) > **Namespace:** > > ``` > api.tx.xrplBridge.resetSettledXrplTxData > ``` > > **Type:** > > ``` > function resetSettledXrplTxData( > highest_settled_ledger_index: u32, > submission_window_width: u32, > highest_pruned_ledger_index: Option, > settled_tx_data: Option> > ) > ``` ### Set Door Address (Sudo Only) > Set XRPL door address managed by this pallet > > **Namespace:** > > ``` > api.tx.xrplBridge.setDoorAddress > ``` > > **Type:** > > ``` > function setDoorAddress( > door_address: H160 > ) > ``` ### Set Door Tx Fee (Sudo Only) > Set the door tx fee amount > > **Namespace:** > > ``` > api.tx.xrplBridge.setDoorTxFee > ``` > > **Type:** > > ``` > function setDoorTxFee( > fee: u64 > ) > ``` ### Set Payment Delay (Sudo Only) > Sets the payment delay payment\_delay is a tuple of payment\_threshold and delay in blocks > > **Namespace:** > > ``` > api.tx.xrplBridge.setPaymentDelay > ``` > > **Type:** > > ``` > function setPaymentDelay( > asset_id: u32, > payment_delay: Option<(u128,u32)> > ) > ``` ### Set Ticket Sequence Current Allocation (Sudo Only) > Set the door account current ticket sequence params for current allocation - force set > > **Namespace:** > > ``` > api.tx.xrplBridge.setTicketSequenceCurrentAllocation > ``` > > **Type:** > > ``` > function setTicketSequenceCurrentAllocation( > ticket_sequence: u32, > start_ticket_sequence: u32, > ticket_bucket_size: u32 > ) > ``` ### Set Ticket Sequence Next Allocation > Set the door account ticket sequence params for the next allocation > > **Namespace:** > > ``` > api.tx.xrplBridge.setTicketSequenceNextAllocation > ``` > > **Type:** > > ``` > function setTicketSequenceNextAllocation( > start_ticket_sequence: u32, > ticket_bucket_size: u32 > ) > ``` ### Set Xrp Source Tag (Sudo Only) > Set the xrp source tag > > **Namespace:** > > ``` > api.tx.xrplBridge.setXrpSourceTag > ``` > > **Type:** > > ``` > function setXrpSourceTag( > source_tag: u32 > ) > ``` ### Submit Challenge > Submit xrp transaction challenge > > **Namespace:** > > ``` > api.tx.xrplBridge.submitChallenge > ``` > > **Type:** > > ``` > function submitChallenge( > transaction_hash: H512 > ) > ``` ### Submit Transaction > Submit xrp transaction > > **Namespace:** > > ``` > api.tx.xrplBridge.submitTransaction > ``` > > **Type:** > > ``` > function submitTransaction( > ledger_index: u64, > transaction_hash: H512, > transaction: PalletXrplBridgeXrplTxData, > timestamp: u64 > ) > ``` ### Withdraw Xrp > Note. Use withdraw instead Withdraw xrp transaction > > **Namespace:** > > ``` > api.tx.xrplBridge.withdrawXrp > ``` > > **Type:** > > ``` > function withdrawXrp( > amount: u128, > destination: H160 > ) > ``` ### Withdraw Xrp With Destination Tag > Note. Use withdraw instead Withdraw xrp transaction > > **Namespace:** > > ``` > api.tx.xrplBridge.withdrawXrpWithDestinationTag > ``` > > **Type:** > > ``` > function withdrawXrpWithDestinationTag( > amount: u128, > destination: H160, > destination_tag: u32 > ) > ``` ### Withdraw > Withdraw asset specified by asset\_id. This extrinsic replaces withdrawXrp and withdrawXrpWithDestinationTag > > **Namespace:** > > ``` > api.tx.xrplBridge.withdraw > ``` > > **Type:** > > ``` > function withdraw( > asset_id: u32, > amount: u128, > destination: H160, > destination_tag: Option > ) > ``` ### Set Xrpl Asset Map (Sudo Only) > Sets the mapping for an asset to an xrpl symbol Sets both XRPLToAssetId and AssetIdToXRPL > > **Namespace:** > > ``` > api.tx.xrplBridge.setXrplAssetMap > ``` > > **Type:** > > ``` > function setXrplAssetMap( > asset_id: u32, > xrpl_currency: PalletXrplBridgeXRPLCurrency, > ) > ``` *** ## Pallet Storage *** ### Challenge XRP Transaction List > Challenge received for a transaction mapped by hash, will be cleared when validator validates > > **Namespace:** > > ``` > api.query.xrplBridge.challengeXRPTransactionList > ``` > > **Type:** > > ``` > function challengeXRPTransactionList( > H512 > ): Option > ``` ### Delayed Payments > Map from DelayedPaymentId to (sender, WithdrawTx) > > **Namespace:** > > ``` > api.query.xrplBridge.delayedPayments > ``` > > **Type:** > > ``` > function delayedPayments( > u64 > ): Option > ``` ### Delayed Payment Schedule > Map from block number to DelayedPatmentIds scheduled for that block > > **Namespace:** > > ``` > api.query.xrplBridge.delayedPaymentSchedule > ``` > > **Type:** > > ``` > function delayedPaymentSchedule( > u32 > ): Option> > ``` ### Door Address > The door address on XRPL > > **Namespace:** > > ``` > api.query.xrplBridge.doorAddress > ``` > > **Type:** > > ``` > function doorAddress( > > ): Option > ``` ### Door Ticket Sequence > The current ticket sequence of the XRPL door account > > **Namespace:** > > ``` > api.query.xrplBridge.doorTicketSequence > ``` > > **Type:** > > ``` > function doorTicketSequence( > > ): u32 > ``` ### Door Ticket Sequence Params > The Ticket sequence params of the XRPL door account for the current allocation > > **Namespace:** > > ``` > api.query.xrplBridge.doorTicketSequenceParams > ``` > > **Type:** > > ``` > function doorTicketSequenceParams( > > ): PalletXrplBridgeXrplTicketSequenceParams > ``` ### Door Ticket Sequence Params Next > The Ticket sequence params of the XRPL door account for the next allocation > > **Namespace:** > > ``` > api.query.xrplBridge.doorTicketSequenceParamsNext > ``` > > **Type:** > > ``` > function doorTicketSequenceParamsNext( > > ): PalletXrplBridgeXrplTicketSequenceParams > ``` ### Door Tx Fee > The flat fee for XRPL door txs > > **Namespace:** > > ``` > api.query.xrplBridge.doorTxFee > ``` > > **Type:** > > ``` > function doorTxFee( > > ): u64 > ``` ### Highest Pruned Ledger Index > Highest pruned XRPL ledger index > > **Namespace:** > > ``` > api.query.xrplBridge.highestPrunedLedgerIndex > ``` > > **Type:** > > ``` > function highestPrunedLedgerIndex( > > ): u32 > ``` ### Highest Settled Ledger Index > Highest settled XRPL ledger index > > **Namespace:** > > ``` > api.query.xrplBridge.highestSettledLedgerIndex > ``` > > **Type:** > > ``` > function highestSettledLedgerIndex( > > ): u32 > ``` ### Next Delayed Payment Id > The next available delayedPaymentId > > **Namespace:** > > ``` > api.query.xrplBridge.nextDelayedPaymentId > ``` > > **Type:** > > ``` > function nextDelayedPaymentId( > > ): u64 > ``` ### Next Delay Process Block > The highest block number that has had all delayed payments processed > > **Namespace:** > > ``` > api.query.xrplBridge.nextDelayProcessBlock > ``` > > **Type:** > > ``` > function nextDelayProcessBlock( > > ): u32 > ``` ### Payment Delay > Payment delay for any withdraw over the specified Balance threshold > > **Namespace:** > > ``` > api.query.xrplBridge.paymentDelay > ``` > > **Type:** > > ``` > function paymentDelay( > u32 > ): Option<(u128,u32)> > ``` ### Process XRP Transaction > Temporary storage to set the transactions ready to be processed at specified block number > > **Namespace:** > > ``` > api.query.xrplBridge.processXRPTransaction > ``` > > **Type:** > > ``` > function processXRPTransaction( > u32 > ): Option> > ``` ### Process XRP Transaction Details > Stores submitted transactions from XRPL waiting to be processed Transactions will be cleared according to the submission window after processing > > **Namespace:** > > ``` > api.query.xrplBridge.processXRPTransactionDetails > ``` > > **Type:** > > ``` > function processXRPTransactionDetails( > H512 > ): Option<(u64,PalletXrplBridgeXrpTransaction,SeedPrimitivesSignatureAccountId20)> > ``` ### Relayer > List of all XRP transaction relayers > > **Namespace:** > > ``` > api.query.xrplBridge.relayer > ``` > > **Type:** > > ``` > function relayer( > SeedPrimitivesSignatureAccountId20 > ): Option > ``` ### Settled XRP Transaction Details > Settled xrp transactions stored against XRPL ledger index > > **Namespace:** > > ``` > api.query.xrplBridge.settledXRPTransactionDetails > ``` > > **Type:** > > ``` > function settledXRPTransactionDetails( > u32 > ): Option> > ``` ### Asset Id To XRPL > Map TRN asset Id to XRPL symbol, storage to keep mapping between TRN -> XRPL tokens/assets > > **Namespace:** > > ``` > api.query.xrplBridge.assetIdToXRPL > ``` > > **Type:** > > ``` > function assetIdToXRPL( > u32 > ): Option > ``` ### XRPL To Asset Id > Map XRPL symbol to TRN asset Id, storage to keep mapping between XRPL -> TRN tokens/assets > > **Namespace:** > > ``` > api.query.xrplBridge.xrplToAssetId > ``` > > **Type:** > > ``` > function xrplToAssetId( > PalletXrplBridgeXRPLCurrency > ): Option > ``` ### Source Tag > Source tag to be used to indicate the transaction is happening from futureverse > > **Namespace:** > > ``` > api.query.xrplBridge.sourceTag > ``` > > **Type:** > > ``` > function sourceTag( > > ): u32 > ``` ### Submission Window Width > XRPL transactions submission window width in ledger indexes > > **Namespace:** > > ``` > api.query.xrplBridge.submissionWindowWidth > ``` > > **Type:** > > ``` > function submissionWindowWidth( > > ): u32 > ``` ### Ticket Sequence Threshold Reached Emitted > Keeps track whether the TicketSequenceThresholdReached event is emitted > > **Namespace:** > > ``` > api.query.xrplBridge.ticketSequenceThresholdReachedEmitted > ``` > > **Type:** > > ``` > function ticketSequenceThresholdReachedEmitted( > > ): bool > ``` *** ## Pallet Events *** ### Door Address Set > **Namespace:** > > ``` > api.events.xrplBridge.DoorAddressSet > ``` > > **Type:** > > ``` > type DoorAddressSet = { > param0: H160 > } > ``` ### Door Next Ticket Sequence Param Set > **Namespace:** > > ``` > api.events.xrplBridge.DoorNextTicketSequenceParamSet > ``` > > **Type:** > > ``` > type DoorNextTicketSequenceParamSet = { > ticket_sequence_start_next: u32, > ticket_bucket_size_next: u32 > } > ``` ### Door Ticket Sequence Param Set > **Namespace:** > > ``` > api.events.xrplBridge.DoorTicketSequenceParamSet > ``` > > **Type:** > > ``` > type DoorTicketSequenceParamSet = { > ticket_sequence: u32, > ticket_sequence_start: u32, > ticket_bucket_size: u32 > } > ``` ### Ledger Index Manual Prune > **Namespace:** > > ``` > api.events.xrplBridge.LedgerIndexManualPrune > ``` > > **Type:** > > ``` > type LedgerIndexManualPrune = { > ledger_index: u32, > total_cleared: u32 > } > ``` ### Not Supported Transaction > Transaction not supported > > **Namespace:** > > ``` > api.events.xrplBridge.NotSupportedTransaction > ``` > > **Type:** > > ``` > type NotSupportedTransaction = { > > } > ``` ### Payment Delay Removed > The payment delay was removed > > **Namespace:** > > ``` > api.events.xrplBridge.PaymentDelayRemoved > ``` > > **Type:** > > ``` > type PaymentDelayRemoved = { > asset_id: u32, > } > ``` ### Payment Delay Set > The payment delay was set > > **Namespace:** > > ``` > api.events.xrplBridge.PaymentDelaySet > ``` > > **Type:** > > ``` > type PaymentDelaySet = { > asset_id: u32, > payment_threshold: u128, > delay: u32 > } > ``` ### Processing Failed > Processing an event failed > > **Namespace:** > > ``` > api.events.xrplBridge.ProcessingFailed > ``` > > **Type:** > > ``` > type ProcessingFailed = { > param0: u64, > param1: H512, > param2: SpRuntimeDispatchError > } > ``` ### Processing Ok > Processing an event succeeded > > **Namespace:** > > ``` > api.events.xrplBridge.ProcessingOk > ``` > > **Type:** > > ``` > type ProcessingOk = { > param0: u64, > param1: H512 > } > ``` ### Relayer Added > **Namespace:** > > ``` > api.events.xrplBridge.RelayerAdded > ``` > > **Type:** > > ``` > type RelayerAdded = { > param0: SeedPrimitivesSignatureAccountId20 > } > ``` ### Relayer Removed > **Namespace:** > > ``` > api.events.xrplBridge.RelayerRemoved > ``` > > **Type:** > > ``` > type RelayerRemoved = { > param0: SeedPrimitivesSignatureAccountId20 > } > ``` ### Ticket Sequence Threshold Reached > **Namespace:** > > ``` > api.events.xrplBridge.TicketSequenceThresholdReached > ``` > > **Type:** > > ``` > type TicketSequenceThresholdReached = { > param0: u32 > } > ``` ### Transaction Added > **Namespace:** > > ``` > api.events.xrplBridge.TransactionAdded > ``` > > **Type:** > > ``` > type TransactionAdded = { > param0: u64, > param1: H512 > } > ``` ### Transaction Challenge > **Namespace:** > > ``` > api.events.xrplBridge.TransactionChallenge > ``` > > **Type:** > > ``` > type TransactionChallenge = { > param0: u64, > param1: H512 > } > ``` ### Withdraw Delayed > A withdrawal was delayed as it was above the min\_payment threshold > > **Namespace:** > > ``` > api.events.xrplBridge.WithdrawDelayed > ``` > > **Type:** > > ``` > type WithdrawDelayed = { > sender: SeedPrimitivesSignatureAccountId20, > asset_id: u32, > amount: u128, > destination: H160, > delayed_payment_id: u64 > } > ``` ### Withdraw Request > Request to withdraw some XRP amount to XRPL > > **Namespace:** > > ``` > api.events.xrplBridge.WithdrawRequest > ``` > > **Type:** > > ``` > type WithdrawRequest = { > proof_id: u64, > sender: SeedPrimitivesSignatureAccountId20, > asset_id: u32, > amount: u128, > destination: H160 > } > ``` ### Xrpl Asset Map Set > A new mapping between asset\_id and XRPL currency was set > > **Namespace:** > > ``` > api.events.xrplBridge.xrplAssetMapSet > ``` > > **Type:** > > ``` > type XrplAssetMapSet = { > asset_id: u32, > xrpl_currency: PalletXrplBridgeXRPLCurrency > } > ``` *** ## Pallet Errors *** ### Asset Not Supported > This asset is not supported by the bridge > > **Namespace:** > > ``` > api.errors.xrplBridge.assetNotSupported > ``` ### Cannot Process More Transactions At That Block > Cannot process more transactions at that block > > **Namespace:** > > ``` > api.errors.xrplBridge.CannotProcessMoreTransactionsAtThatBlock > ``` ### Cannot Prune Active Ledger Index > This ledger index is within the submission window and can't be pruned > > **Namespace:** > > ``` > api.errors.xrplBridge.CannotPruneActiveLedgerIndex > ``` ### Delay Schedule At Capacity > The scheduled block cannot hold any more delayed payments > > **Namespace:** > > ``` > api.errors.xrplBridge.DelayScheduleAtCapacity > ``` ### Door Address Not Set > The door address has not been configured > > **Namespace:** > > ``` > api.errors.xrplBridge.DoorAddressNotSet > ``` ### Invalid Highest Pruned Index > highest\_pruned\_ledger\_index must be less than highest\_settled\_ledger\_index - submission\_window\_width > > **Namespace:** > > ``` > api.errors.xrplBridge.InvalidHighestPrunedIndex > ``` ### Invalid Signers > The signers are not known by ethy > > **Namespace:** > > ``` > api.errors.xrplBridge.InvalidSigners > ``` ### Next Ticket Sequence Params Invalid > The NextTicketSequenceParams is invalid > > **Namespace:** > > ``` > api.errors.xrplBridge.NextTicketSequenceParamsInvalid > ``` ### Next Ticket Sequence Params Not Set > The NextTicketSequenceParams has not been set > > **Namespace:** > > ``` > api.errors.xrplBridge.NextTicketSequenceParamsNotSet > ``` ### No Available Payment Ids > The paymentIds have been exhausted > > **Namespace:** > > ``` > api.errors.xrplBridge.NoAvailablePaymentIds > ``` ### Not Permitted > **Namespace:** > > ``` > api.errors.xrplBridge.NotPermitted > ``` ### No Transaction Details > There is no settledXRPTransactionDetails for this ledger index > > **Namespace:** > > ``` > api.errors.xrplBridge.NoTransactionDetails > ``` ### Outside Submission Window > Transaction submitted is outside the submission window > > **Namespace:** > > ``` > api.errors.xrplBridge.OutSideSubmissionWindow > ``` ### Relayer Does Not Exists > **Namespace:** > > ``` > api.errors.xrplBridge.RelayerDoesNotExists > ``` ### Ticket Sequence Params Invalid > The TicketSequenceParams is invalid > > **Namespace:** > > ``` > api.errors.xrplBridge.TicketSequenceParamsInvalid > ``` ### Too Many Signers > XRPL does not allow more than 8 signers for door address > > **Namespace:** > > ``` > api.errors.xrplBridge.TooManySigners > ``` ### Invalid Asset Decimals > The asset decimals are too high to bridge to XRPL > > **Namespace:** > > ``` > api.errors.xrplBridge.InvalidAssetDecimals > ``` ### Invalid Currency Code > The issued amount currency code is invalid > > **Namespace:** > > ``` > api.errors.xrplBridge.InvalidCurrencyCode > ``` ### Invalid Mantissa Exponent Conversion > Could not convert Balance to Mantissa Exponent > > **Namespace:** > > ``` > api.errors.xrplBridge.InvalidMantissaExponentConversion > ``` ### Invalid Symbol Mapping > XRPL symbol to TRN asset id mapping is invalid > > **Namespace:** > > ``` > api.errors.xrplBridge.InvalidSymbolMapping > ``` ### Asset Rounding Too High > The asset rounding due to saturation is too high, reduce the significant digits > > **Namespace:** > > ``` > api.errors.xrplBridge.AssetRoundingTooHigh > ``` ### Too Many Transactions Per Ledger > Too Many transactions per ledger > > **Namespace:** > > ``` > api.errors.xrplBridge.TooManyTransactionsPerLedger > ``` ### Tx Replay > Submitted a duplicate transaction hash > > **Namespace:** > > ``` > api.errors.xrplBridge.TxReplay > ``` ### Withdraw Invalid Amount > Withdraw amount must be non-zero and \< = u64 > > **Namespace:** > > ``` > api.errors.xrplBridge.WithdrawInvalidAmount > ``` *** ## Constants *** ### Challenge Period > Challenge Period to wait for a challenge before processing the transaction > > **Namespace:** > > ``` > api.consts.xrplBridge.challengePeriod > ``` > > **Type:** > > ``` > type challengePeriod = u32 > ``` ### Delayed Payment Block Limit > Upper limit to the number of blocks we can check per block for delayed payments > > **Namespace:** > > ``` > api.consts.xrplBridge.delayedPaymentBlockLimit > ``` > > **Type:** > > ``` > type delayedPaymentBlockLimit = u32 > ``` ### Max Delayed Payments Per Block > Maximum number of delayed transactions that can be processed in a single block > > **Namespace:** > > ``` > api.consts.xrplBridge.maxDelayedPaymentsPerBlock > ``` > > **Type:** > > ``` > type maxDelayedPaymentsPerBlock = u32 > ``` ### Max Pruned Transactions Per Block > Maximum number of transactions that can be pruned in on\_idle > > **Namespace:** > > ``` > api.consts.xrplBridge.maxPrunedTransactionsPerBlock > ``` > > **Type:** > > ``` > type maxPrunedTransactionsPerBlock = u32 > ``` ### Xrp Asset Id > XRP Asset Id set at runtime > > **Namespace:** > > ``` > api.consts.xrplBridge.xrpAssetId > ``` > > **Type:** > > ``` > type xrpAssetId = u32 > ``` ### Native Asset Id > ROOT Asset Id set at runtime > > **Namespace:** > > ``` > api.consts.xrplBridge.nativeAssetId > ``` > > **Type:** > > ``` > type nativeAssetId = u32 > ``` ### Pallet Id > This pallet's Id, used for deriving a sovereign account ID > > **Namespace:** > > ``` > api.consts.xrplBridge.palletId > ``` > > **Type:** > > ``` > type palletId = u32 > ``` # Primitives Source: https://docs.therootnetwork.com/build/substrate/cookbook/primitives ## Block ### How do I listen to new blocks? The example below shows how to subscribe to new blocks. It displays the block number every time a new block is seen by the node you are connected to. ```ts // Import the API async function main() { // Instantiate the API ... // We only display a couple, then unsubscribe let count = 0; // Subscribe to the new headers on-chain. The callback is fired when new headers // are found, the call itself returns a promise with a subscription that can be // used to unsubscribe from the newHead subscription const unsubscribe = await api.rpc.chain.subscribeNewHeads((header) => { console.log(`Chain is at block: #${header.number}`); if (++count === 256) { unsubscribe(); process.exit(0); } }); } main().catch(console.error); ``` ### How do I retrieve the header/extrinsic hash from blocks? A block hash refers to the hash over the header, the extrinsic hash refers to the hash of the encoded extrinsic. Since all objects returned by the API implement the `.hash => Hash` getter, we can simply use this to view the actual hash. ```ts // returns Hash const blockHash = await api.rpc.chain.getBlockHash(blockNumber); // returns SignedBlock const signedBlock = await api.rpc.chain.getBlock(blockHash); // the hash for the block, always via header (Hash -> toHex()) - will be // the same as blockHash above (also available on any header retrieved, // subscription or once-off) console.log(signedBlock.block.header.hash.toHex()); // the hash for each extrinsic in the block signedBlock.block.extrinsics.forEach((ex, index) => { console.log(index, ex.hash.toHex()); }); ``` ### How do I extract the block author? The block author is encoded inside the consensus logs for the block. To extract it, you need to decode the log (which the API does do) and then map the index of the validator to the list of session validators. This extraction is however available on the API derive for new head subscriptions, which returns an extended header with the author populated (assuming that the digest logs are known). ```ts // subscribe to all new headers (with extended info) api.derive.chain.subscribeNewHeads((header) => { console.log(`#${header.number}: ${header.author}`); }); ``` For a single header only, the derives also contain a `getHeader`, which once again returns a header extended with the author: ```ts // retrieve the last header (hash optional) const header = await api.derive.chain.getHeader(); console.log(`#${header.number}: ${header.author}`); ``` ### How do I view extrinsic information? The transactions are included in a signed block as part of the extrinsics - some of these will be unsigned and generated by the block author and some of these may be submitted from external sources and be signed (some palettes use unsigned transactions, so signed/unsigned is not an indication of origin). To retrieve the block and display the transaction information, we can do the following: ```ts // no blockHash is specified, so we retrieve the latest const signedBlock = await api.rpc.chain.getBlock(); // the information for each of the contained extrinsics signedBlock.block.extrinsics.forEach((ex, index) => { // the extrinsics are decoded by the API, human-like view console.log(index, ex.toHuman()); const { isSigned, meta, method: { args, method, section }, } = ex; // explicit display of name, args & documentation console.log(`${section}.${method}(${args.map((a) => a.toString()).join(", ")})`); console.log(meta.documentation.map((d) => d.toString()).join("\n")); // signer/nonce info if (isSigned) { console.log(`signer=${ex.signer.toString()}, nonce=${ex.nonce.toString()}`); } }); ``` In the above example, `.toHuman()` is used to format the extrinsic into a human-readable representation. You can inspect/extract specific fields from the decoded extrinsic as required. For instance `ex.method.section` would return the pallet that executed this transaction. ### How do I map extrinsics to their events? While the blocks contain the extrinsics, the system event storage will include the events and the details needed to allow for a mapping between them. For events, the `phase` is an enum that would be `isApplyExtrinsic` with the index in the cases where it refers to an extrinsic in a block. This index maps through the order of the extrinsics as found. To perform a mapping between the two, we need information from from both sources, as per the example below. ```ts // no blockHash is specified, so we retrieve the latest const signedBlock = await api.rpc.chain.getBlock(); const apiAt = await api.at(signedBlock.block.header.hash); const allRecords = await apiAt.query.system.events(); // map between the extrinsics and events signedBlock.block.extrinsics.forEach(({ method: { method, section } }, index) => { // filter the specific events based on the phase and then the // index of our extrinsic in the block const events = allRecords .filter(({ phase }) => phase.isApplyExtrinsic && phase.asApplyExtrinsic.eq(index)) .map(({ event }) => `${event.section}.${event.method}`); console.log(`${section}.${method}:: ${events.join(", ") || "no events"}`); }); ``` ### How do I determine if an extrinsic succeeded/failed? The code below extends the above example, where extrinsics are mapped to their blocks. In this example, we will specifically look for specific extrinsic events—namely, the `system.ExtrinsicSuccess` and `system.ExtrinsicFailed` events. The same logic can be applied to inspect any other type of expected event. ```ts // no blockHash is specified, so we retrieve the latest const signedBlock = await api.rpc.chain.getBlock(); // get the api and events at a specific block const apiAt = await api.at(signedBlock.block.header.hash); const allRecords = await apiAt.query.system.events(); // map between the extrinsics and events signedBlock.block.extrinsics.forEach(({ method: { method, section } }, index) => { allRecords // filter the specific events based on the phase and then the // index of our extrinsic in the block .filter(({ phase }) => phase.isApplyExtrinsic && phase.asApplyExtrinsic.eq(index)) // test the events against the specific types we are looking for .forEach(({ event }) => { if (api.events.system.ExtrinsicSuccess.is(event)) { // extract the data for this event // (In TS, because of the guard above, these will be typed) const [dispatchInfo] = event.data; console.log( `${section}.${method}:: ExtrinsicSuccess:: ${JSON.stringify(dispatchInfo.toHuman())}` ); } else if (api.events.system.ExtrinsicFailed.is(event)) { // extract the data for this event const [dispatchError, dispatchInfo] = event.data; let errorInfo; // decode the error if (dispatchError.isModule) { // for module errors, we have the section indexed, lookup // (For specific known errors, we can also do a check against the // api.errors...is(dispatchError.asModule) guard) const decoded = api.registry.findMetaError(dispatchError.asModule); errorInfo = `${decoded.section}.${decoded.name}`; } else { // Other, CannotLookup, BadOrigin, no extra info errorInfo = dispatchError.toString(); } console.log(`${section}.${method}:: ExtrinsicFailed:: ${errorInfo}`); } }); }); ``` ## Event ### How do I subscribe to node events? Query the system events and extract information from them. ```ts async function main() { // Instantiate the API ... // Subscribe to system events via storage api.query.system.events((events) => { console.log(`\nReceived ${events.length} events:`); // Loop through the Vec events.forEach((record) => { // Extract the phase, event and the event types const { event, phase } = record; const types = event.typeDef; // Show what we are busy with console.log(`\t${event.section}:${event.method}:: (phase=${phase.toString()})`); console.log(`\t\t${event.meta.documentation.toString()}`); // Loop through each of the parameters, displaying the type and data event.data.forEach((data, index) => { console.log(`\t\t\t${types[index].type}: ${data.toString()}`); }); }); }); } main().catch((error) => { console.error(error); process.exit(1); }); ``` ### How do I traverse events while submitting extrinsic? ```ts // Import the test keyring (already has dev keys for Alice, Bob, Charlie, Eve & Ferdie) const testKeyring = require("@polkadot/keyring/testing"); // Utility function for random values const { randomAsU8a } = require("@polkadot/util-crypto"); // Some constants we are using in this sample const ALICE = "0xE04CC55ebEE1cBCE552f250e85c57B70B2E2625b"; const AMOUNT = 10000; async function main() { // Instantiate the API ... // Create an instance of our testing keyring // If you're using ES6 module imports instead of require, just change this line to: // const keyring = testKeyring(); const keyring = testKeyring.default(); // Get the nonce for the admin key const { nonce } = await api.query.system.account(ALICE); // Find the actual keypair in the keyring const alicePair = keyring.getPair(ALICE); // Create a new random recipient const recipient = keyring.addFromSeed(randomAsU8a(32)).address; console.log( "Sending", AMOUNT, "from", alicePair.address, "to", recipient, "with nonce", nonce.toString() ); // Do the transfer and track the actual status api.tx.balances .transfer(recipient, AMOUNT) .signAndSend(alicePair, { nonce }, ({ events = [], status }) => { console.log("Transaction status:", status.type); if (status.isInBlock) { console.log("Included at block hash", status.asInBlock.toHex()); console.log("Events:"); events.forEach(({ event: { data, method, section }, phase }) => { console.log("\t", phase.toString(), `: ${section}.${method}`, data.toString()); }); } else if (status.isFinalized) { console.log("Finalized block hash", status.asFinalized.toHex()); process.exit(0); } }); } main().catch(console.error); ``` ## Storage ### How do I check for storage existence? In the metadata, a fallback is provided for each storage item. This means that when an entry does not exist, the fallback (which is the default value for the type) will be provided - querying for a non-existent key (unless an option) will yield a value: ```ts // retrieve Option const ledger = await api.query.staking.ledger("0x25451A4de12dcCc2D166922fA938E900fCc4ED24"); // retrieve ValidatorPrefs (will yield the default value) const prefs = await api.query.staking.validators("0x25451A4de12dcCc2D166922fA938E900fCc4ED24"); console.log(ledger.isNone, ledger.isSome); // true, false console.log(JSON.stringify(prefs.toHuman())); // {"commission":"0"} ``` In the second case, the non-existent prefs returns the default/fallback value for the storage item. So in this case, we don't know if the value is set to 0 or unset. Existence can be checked by using the storage size, which would be zero if nothing is stored. ```ts // exists const sizeY = await api.query.staking.validators.size("0x25451A4de12dcCc2D166922fA938E900fCc4ED24"); // non existent const sizeN = await api.query.staking.validators.size("0x5630a480727CD7799073b36472d9b1A6031F840b"); console.log(sizeY.isZero(), sizeY.toNumber()); // false 4 console.log(sizeN.isZero(), sizeY.toNumber()); // true 0 ``` ### How do I use `.entries()/.keys()` on double maps? As explained in the section [Building with Native API](/build/substrate/api-package) each map-type storage entry exposes the entries/keys helpers to retrieve the whole list. In the case of double maps, with the addition of a single argument, you can retrieve either all entries or a subset based on the first map key. In both these cases, entries/keys operate the same way, `.entries()` retrieving `(StorageKey, Codec)[]` and `.keys()` retrieving `StorageKey[]` ```ts // Retrieves the entries for all slashes, in all eras (no arg) const allEntries = await api.query.staking.nominatorSlashInEra.entries(); // nominatorSlashInEra(EraIndex, AccountId) for the types of the key args allEntries.forEach( ([ { args: [era, nominatorId], }, value, ]) => { console.log(`${era}: ${nominatorId} slashed ${value.toHuman()}`); } ); ``` While we can retrieve only the keys for a specific era, using an argument for the first part of the double map (as defined here, an `EraIndex`): ```ts // Retrieves the keys for the slashed validators in era 652 const slashedKeys = await api.query.staking.nominatorSlashInEra.keys(652); // key args still contains [EraIndex, AccountId] decoded console.log(`slashed: ${slashedKeys.map(({ args: [era, nominatorId] }) => nominatorId)`); ``` ### How do I read storage at specific blockhash? In addition to querying the latest storage, you can make storage queries at a specific blockhash. Be aware that the node applies a pruning strategy and typically only keeps the last 256 blocks, unless run in archive mode. ```ts const ALICE = "0xE04CC55ebEE1cBCE552f250e85c57B70B2E2625b"; const BOB = "0x25451A4de12dcCc2D166922fA938E900fCc4ED24"; async function main() { // Instantiate the API ... // Retrieve the last block header, extracting the hash and parentHash const { hash, parentHash } = await api.rpc.chain.getHeader(); console.log(`last header hash ${hash.toHex()}`); // Retrieve the balance at the preceding block for Alice using an at api const apiAt = await api.at(parentHash); const balance = await apiAt.query.system.account(ALICE); console.log(`Alice's balance at ${parentHash.toHex()} was ${balance.data.free}`); // Now perform a multi query, returning multiple balances at once const balances = await api.query.system.account.multi([ALICE, BOB]); console.log( `Current balances for Alice and Bob are ${balances[0].data.free} and ${balances[1].data.free}` ); } main() .catch(console.error) .finally(() => process.exit()); ``` ## Transaction ### How do I make a simple transfer? The example below shows how to create a transaction to make a transfer from one account to another. ```ts const { Keyring } = require("@polkadot/keyring"); import { hexToU8a } from "@polkadot/util"; const BOB = "0x25451A4de12dcCc2D166922fA938E900fCc4ED24"; async function main() { // Instantiate the API ... // Construct the keyring after the API (crypto has an async init) const keyring = new Keyring({ type: "ethereum" }); // Add Alice to our keyring const alice = keyring.addFromSeed(hexToU8a(ALICE_PRIVATE_KEY)); // Create a extrinsic, transferring 12345 units to Bob const transfer = api.tx.balances.transfer(BOB, 12345); // Sign and send the transaction using our account const hash = await transfer.signAndSend(alice); console.log("Transfer sent with hash", hash.toHex()); } main() .catch(console.error) .finally(() => process.exit()); ``` ### How do I estimate the transaction fees? In addition to the `signAndSend` helper on transactions, `.paymentInfo` (with the exact same parameters) are also exposed. Using the same sender, it applies a dummy signature to the transaction and then gets the fee estimation via RPC. ```ts // estimate the fees as RuntimeDispatchInfo, using the signer (either // address or locked/unlocked keypair) (When overrides are applied, e.g // nonce, the format would be `paymentInfo(sender, { nonce })`) const info = await api.tx.balances.transfer(recipient, 123).paymentInfo(sender); // log relevant info, partialFee is Balance, estimated for current console.log(` class=${info.class.toString()}, weight=${info.weight.toString()}, partialFee=${info.partialFee.toHuman()} `); ``` ### How do I get the decoded enum for an ExtrinsicFailed event? Assuming you are sending a tx via `.signAndSend`, the callback yields information around the tx pool status as well as any events when `isInBlock` or `isFinalized`. If an extrinsic fails via `system.ExtrinsicFailed` event, you can retrieve the error if defined as an enum on a module. ```ts api.tx.balances.transfer(recipient, 123).signAndSend(sender, ({ status, events }) => { if (status.isInBlock || status.isFinalized) { events // find/filter for failed events .filter(({ event }) => api.events.system.ExtrinsicFailed.is(event)) // we know that data for system.ExtrinsicFailed is // (DispatchError, DispatchInfo) .forEach( ({ event: { data: [error, info], }, }) => { if (error.isModule) { // for module errors, we have the section indexed, lookup const decoded = api.registry.findMetaError(error.asModule); const { docs, method, section } = decoded; console.log(`${section}.${method}: ${docs.join(" ")}`); } else { // Other, CannotLookup, BadOrigin, no extra info console.log(error.toString()); } } ); } }); ``` As of the `@polkadot/api` 2.3.1 additional result fields are exposed. Firstly there is `dispatchInfo: DispatchInfo` which occurs in both `ExtrinsicSuccess` & `ExtrinsicFailed` events. Additionally, on failures the `dispatchError: DispatchError` is exposed. With this in mind, the above example can be simplified to be: ```ts api.tx.balances .transfer(recipient, 123) .signAndSend(sender, ({ status, events, dispatchError }) => { // status would still be set, but in the case of error we can shortcut // to just check it (so an error would indicate InBlock or Finalized) if (dispatchError) { if (dispatchError.isModule) { // for module errors, we have the section indexed, lookup const decoded = api.registry.findMetaError(dispatchError.asModule); const { docs, name, section } = decoded; console.log(`${section}.${name}: ${docs.join(" ")}`); } else { // Other, CannotLookup, BadOrigin, no extra info console.log(dispatchError.toString()); } } }); ``` ### How do I get the Result of a Sudo event? The section above shows you how to listen for the result of a regular extrinsic. However, Sudo extrinsics do not directly report the success or failure of the underlying call. Instead, a Sudo transaction will return `Sudid(result)`, where `result` will be the information you are looking for. To properly parse this information, we will follow the steps above, but then specifically peek into the event data to find the final result: ```ts const unsub = await api.tx.sudo .sudo(api.tx.balances.forceTransfer(user1, user2, amount)) .signAndSend(sudoPair, ({ status, events }) => { if (status.isInBlock || status.isFinalized) { events // We know this tx should result in `Sudid` event. .filter(({ event }) => api.events.sudo.Sudid.is(event)) // We know that `Sudid` returns just a `Result` .forEach( ({ event: { data: [result], }, }) => { // Now we look to see if the extrinsic was actually successful or not... if (result.isError) { let error = result.asError; if (error.isModule) { // for module errors, we have the section indexed, lookup const decoded = api.registry.findMetaError(error.asModule); const { docs, name, section } = decoded; console.log(`${section}.${name}: ${docs.join(" ")}`); } else { // Other, CannotLookup, BadOrigin, no extra info console.log(error.toString()); } } } ); unsub(); } }); ``` ### How do I send an unsigned extrinsic? For most runtime modules, transactions need to be signed, and validation for this happens on the node side. There are, however, modules that accept unsigned extrinsics. An example would be the Polkadot/Kusama token claims (here, used as an example). ```ts // construct the transaction, exactly as per normal const utx = api.tx.claims.claim(beneficiary, ethSignature); // send it without calling sign, pass callback with status/events tx.send(({ status }) => { if (status.isInBlock) { console.log(`included in ${status.asInBlock}`); } }); ``` The signing is indicated by the first byte in the transaction, so in this case, we have called `.send` on it (no `.sign` or `.signAndSend`), so it will be sent using the unsigned state without the signature attached. **Note**: The status event is only available on providers that support subscriptions, such as `WSProvider` or `ScProvider`. On `HttpProvider`, which does not have bi-directional capabilities. There are no subscriptions, so it cannot listen to the events that are emitted by the transaction pool. In the case of `HttpProvider` the result, object returned will always be the non-unique transaction hash. ### How can I batch transactions? Polkadot/Substrate provides a `utility.batch` method that can be used to send a number of transactions at once. These are then executed from a single sender (single nonce specified) in sequence. This is very useful in many cases. For instance, if you wish to create a payout for a validator for multiple eras, you can use this method. Likewise, you can send several transfers at once or batch different types of transactions. ```ts // construct a list of transactions we want to batch const txs = [ api.tx.balances.transfer(addrBob, 12345), api.tx.balances.transfer(addrEve, 12345), api.tx.staking.unbond(12345), ]; // construct the batch and send the transactions api.tx.utility.batch(txs).signAndSend(sender, ({ status }) => { if (status.isInBlock) { console.log(`included in ${status.asInBlock}`); } }); ``` The fee for a batch transaction can be estimated similar to the fee for a single transaction using the exposed `.paymentInfo` helper method described earlier, and it is usually less than the sum of the fees for each transaction. ### How do I take the pending tx pool into account in my nonce? The `system.account` query will always contain the current state, i.e. it will reflect the nonce for the last known block. As such when sending multiple transactions in quick succession (see batching above), there may be transactions in the pool with the same nonce that `signAndSend` would apply - this call does not do any magic. It simply reads the state for the nonce. Since we can specify options for the `signAndSend` operation, we can override the nonce, either by manually incrementing it or querying it via `rpc.system.accountNextIndex`. ```ts for (let i = 0; i < 10; i++) { // retrieve sender's next index/nonce, taking txs in the pool into account const nonce = await api.rpc.system.accountNextIndex(sender); // send, just retrieving the hash, not waiting on status const txhash = await api.tx.balances.transfer(recipient, 123).signAndSend(sender, { nonce }); } ``` As a convenience function, the `accountNextIndex` can be omitted by specifying a nonce of `-1`, allowing the API to do the lookup. In this case, the above example can be simplified even further: ```ts for (let i = 0; i < 10; i++) { const txhash = await api.tx.balances.transfer(recipient, 123).signAndSend(sender, { nonce: -1 }); } ``` The latter form is preferred since it dispatches the RPC calls for nonce and blockHash (used for mortality) in parallel. This approach will yield a better throughput, especially with the above bulk example. # Tokens Source: https://docs.therootnetwork.com/build/substrate/cookbook/tokens ## Fungible Token ### How do I transfer `ROOT` token? Since ROOT token is a security token, it's managed by the `balances` pallet. To transfer ROOT tokens, use the following snippet: ```ts // transfer 1 ROOT to Alice await api.balances.transfer(1_000_000, "0xE04CC55ebEE1cBCE552f250e85c57B70B2E2625b").signAndSend(...); ``` ROOT token has 6 decimals. ### How do I transfer `XRP` or any other fungible tokens? XRP and any other non-default fungible tokens are managed by the [`assets`](/build/substrate/api-reference/runtime-pallets/assets) pallet, separate from the [`balances`](/build/substrate/api-reference/runtime-pallets/balances) pallet. That also means you need to provide the asset ID when you want to transfer any of these tokens. ```ts // get the `metadata` to determine the `decimals` const XRP_ID = 2; const metadata = (await api.query.assets.metadata(XRP_ID)).toJson(); const oneXRP = 1 * Math.pow(10, metadata.decimals); // transfer 1 XRP to Alice await api.assets.transfer(XRP_ID, "0xE04CC55ebEE1cBCE552f250e85c57B70B2E2625b", oneXRP).signAndSend(...); ``` To retrieve a list of available tokens and their asset IDs, checkout Tokens section in our [Rootscan Explorer](/build/connecting-to-the-root-network). ## NFT (Non-Fungible Token) ### How do I create and mint an NFT? To create your NFT collection, call the `nft.createCollection()` extrinsic with the following parameters: ```typescript await api.tx.nft.createCollection( collectionName, initialIssuance, maxIssuance, tokenOwner, metadataScheme, royaltiesSchedule, crossChainCompatibility ); ``` **Caution**: The `royaltiesSchedule` is in per mill (parts per million) scaling, so if you want a 10% royalty, that would be `100,000` (as `100_000 / 1_000_000 = 0.1`). Once your collection is created, the collection owner can call the `nft.mint()` method on the collection to start minting additional tokens so long as the max issuance has not been reached: ```typescript await api.tx.nft.mint(collectionId, quantity, beneficiary); ``` ## SFT (Semi-Fungible Token) ### How do I create and mint an SFT? SFTs are similar to NFTs however due to their similarity to ERC1155, there can be multiple tokens per SFT collection. Each SFT token has a unique ID, and the collection owner can mint multiple tokens with the same ID. To create your SFT collection, call the `sft.createCollection()` extrinsic with the following parameters: ```typescript await api.tx.sft.createCollection( collectionName, collectionOwner, metadataScheme, royaltiesSchedule ) ``` To create an SFT token within the collection, call the `sft.createToken()` extrinsic with the following parameters: ```typescript await api.tx.sft.createToken( collectionId, tokenName, initialIssuance, maxIssuance, tokenOwner ) ``` Once your token is created, the collection owner can call the `sft.mint()` method to start minting additional tokens so long as the max issuance for that token has not been reached. The owner can pass in a tuple of serialNumbers and quantities to mint multiple tokens at once. ```typescript await api.tx.sft.mint(collectionId, serialNumbers, tokenOwner); ``` # Building with Native API Source: https://docs.therootnetwork.com/build/substrate/core-concepts The most optimal way to interact with the Native API on The Root Network is via `@polkadot/api` package in combination with our package `@therootnetwork/api`. It provides web3 developers the ability to query and interact with The Root Network node using Javascript/Typescript. For installation instructions, see [Install Native API](/build/substrate/api-package). One of the most important things to understand about the `@polkadot/api` is that most interfaces are actually generated automatically when connected to a running node. This is quite a departure from other APIs in projects with static interfaces. While it may sound intimidating, this concept is actually a powerful feature present in any Substrate chain. It enables the API to be used in environments where the chain is customized. To unpack this, we will start with the metadata and explain what it actually provides, since it is critical to understand how to interact with the API and any underlying chain. ## Metadata When the API connects to a node, one of the first things it does is retrieve the metadata and decorate the API based on the metadata information. The metadata effectively provides data in the form of `api...
` that fits into one of the following categories: * `consts` - All runtime constants, e.g. `api.consts.balances.existentialDeposit`. These are not functions; rather, accessing the endpoint immediately yields the result as defined. * `query` - All chain state, e.g. `api.query.system.account()`. * `tx` - All extrinsics, e.g. `api.tx.balances.transfer(, )`. Additionally, the metadata also provides information on `events`. These are queryable via the `api.query.system.events()` interface and also appear on transactions. Both these cases are detailed later. None of the information contained within the `api.{consts, query, tx}..` endpoints are hardcoded in the API. Rather, everything is fully decorated by what the metadata exposes and is, therefore, completely dynamic. This means that when you connect to different chains, the metadata and API decoration will change and the API interfaces will reflect what is available on the chain you are connected to. ## Runtime Types Everything the API returns is a type with a consistent interface: `Codec`. This means that a `Vec` (an array of `u32` values), as well as a `Struct` (an object) or an `Enum`, has the same consistent base interface. Specific types will have values based on the type - decorated and available. As a minimum, anything returned by the API, be it a `Vec<...>`, `Option<...>`, `Struct` or any normal type will always have the following methods - as defined on the `Codec` interface: * `.eq()` - checks for equality against the other value. In all cases, it will accept "like" values, i.e. in the case of a number, you can pass a primitive (such as `1`), a hex value (such as `0x01`) or even a `Unit8Array` * `toHex()` - returns a hex-base representation of the value, always prefixed by `0x` * `toHuman()` - returns Human-parsable JSON structure with values formatted as per the settings * `toJSON()` - returns a JSON-like representation of the value. This is generally used when calling `JSON.stringify(...)` on the value * `toString()` - returns a string representation. In some cases, this performs additional encoding, i.e. for `Address`, `AccountId` and `AccountIndex`, it will encode to the ss58 address * `.toU8a()` - returns a `Uint8Array` representation of the encoded value (generally exactly as passed to the node, where values are SCALE encoded) Additionally, the following getters and utilities are available: * `.isEmpty` - `true` if the value is an all-empty value, i.e. `0` in for numbers, all-zero for Arrays (or anything `Uint8Array`), `false` is non-zero * `.hash` - a `Hash` (once again with all the methods above) that is a `blake2-256` representation of the contained value ## Chain Defaults In addition to the `api.[consts | query | tx]` detailed above, the API, upon connecting to a chain, fills in some information and makes it available directly on the API interface. These include - * `api.genesisHash` - The genesisHash of the connected chain * `api.runtimeMetadata` - The metadata as retrieved from the chain * `api.runtimeVersion` - The chain runtime version (including specification/implementation versions and types) ## Chain State The `api.rpc.
.` provides low-level interfaces to read the chain state that's not necessarily bound to the pallet storage. It's also the commonplace to add additional data query for the custom pallets, e.g. `api.rpc.tokenUri`. ```ts // Initialize the API as in previous sections ... // Retrieve the chain name const chain = await api.rpc.system.chain(); // Retrieve the latest header const lastHeader = await api.rpc.chain.getHeader(); // Log the information console.log(`${chain}: last block #${lastHeader.number} has hash ${lastHeader.hash}`); ``` It's possible to subscribe to RPC calls and receive up-to-date data. For instance, subscribe to a new block height change. ```ts ... let count = 0; // Subscribe to the new headers const unsubscribe = await api.rpc.chain.subscribeNewHeads((lastHeader) => { console.log(`${chain}: last block #${lastHeader.number} has hash ${lastHeader.hash}`); if (++count === 10) { unsubscribe(); } }); ``` Since we are dealing with a subscription, we now pass a callback into the `subscribeNewHeads` function, and this will be triggered on each header as they are imported. The same pattern applies to each of the `api.rpc.subscribe` functions. As the last parameter, a callback should be provided to stream the latest data as it becomes available. In general, whenever we create a subscription, we would like to clean up after ourselves and unsubscribe. Assuming we only want to log the first 10 headers, the above example demonstrates the use of the `unsubscribe()` function. ## Chain Storage The `api.query..` interfaces are used to read the public storage in each available pallet. Behind the scenes, the API uses the metadata information provided to construct queries based on the location and parameters provided to generate state keys and then queries these via RPC. ```ts // Initialize the API as in previous sections ... // The actual address that we will use const ADDR = '0xE04CC55ebEE1cBCE552f250e85c57B70B2E2625b'; const [now, { nonce, data: balance }] = await Promise.all([ api.query.timestamp.now(), api.query.system.account(ADDR) ]); console.log(`${now}: balance of ${balance.free} and a nonce of ${nonce}`); ``` Similar to RPC calls, sometimes it's necessary to subscribe to the chain state to handle your application logic. Fortunately, the API provides a straightforward way to do that. ```ts ... // Retrieve the current timestamp via subscription const unsubscribe = await api.query.timestamp.now((moment) => { console.log(`The last block has a timestamp of ${moment}`); // unsubscribe(); call to stop receiving updates }); ``` Instead of the `await` returning the actual one-time value, it returns a subscription `unsubscribe()` function. This function can be used to stop the subscription and clean up any underlying RPC connections. The supplied callback will contain the value streamed from the node as it changes. ## Transaction Transaction endpoints are exposed, as determined by the metadata, on the `api.tx..` endpoint. These allow you to submit transactions for inclusion in blocks, whether it's transfers, setting information or any other operation your chain supports. The Root Network supports the ECDSA key-pair standard. To submit a transaction, make sure you have a valid account with a small amount of `XRP` tokens to cover the transaction fee. Create a `keyring` instance as follows: ```ts import { Keyring } from "@polkadot/keyring"; import { stringToU8a, u8aToHex, hexToU8a } from "@polkadot/util"; // create a keyring with some non-default values specified const keyring = new Keyring({ type: "ethereum" }); const seedU8a = hexToU8a(ALICE_PRIVATE_KEY); const alice = keyring.addFromSeed(seedU8a); ``` Once that is done, to transfer a balance from Alice to Bob as per the example above, use the code below: ```ts ... // Sign and send a transfer from Alice to Bob const txHash = await api.tx.balances .transfer(BOB, 12345) .signAndSend(alice); // Show the hash console.log(`Submitted with hash ${txHash}`); ``` The result of this call is the transaction hash. This is a hash of the data; receiving it does not mean the transaction has been included. It only means that the hash has been accepted for propagation by the node. **Caution**: Transaction hash in Substrate-based blockchain is generally unique within a block but not across the chain. [Check out this article](https://wiki.polkadot.network/docs/build-protocol-info#unique-identifiers-for-extrinsics) for more details. Similar to `api.rpc` and `api.query` interfaces, it's possible to subscribe to the transaction state change to determine if it's been included in the block or not. ```ts ... // Make a transfer from Alice to Bob, waiting for inclusion const unsubscribe = await api.tx.balances .transfer(BOB, 12345) .signAndSend(alice, (result) => { console.log(`Current status is ${result.status.type}`); if (result.status.isInBlock) { console.log(`Transaction included at blockHash ${result.status.asInBlock}`); } else if (result.status.isFinalized) { console.log(`Transaction finalized at blockHash ${result.status.asFinalized}`); unsubscribe(); } }); ``` As per all previous subscriptions, the transaction subscription returns `unsubscribe()` and the actual method has a subscription callback. The `result` object has two parts: `events` (to be covered in the next section) and the `status` enum. When the `status` enum is in `Finalized` state (checked via `isFinalized`), the underlying value contains the block's hash where the transaction has been finalized. `Finalized` will follow `InBlock`, which is the block where the transaction has been included. `InBlock` does not mean the block is finalized, but rather applies to the transaction state, where `Finalized` means that the transaction cannot be forked off the chain. ## Transaction Events Any transaction will emit events. As a bare minimum, this will always be either a `system.ExtrinsicSuccess` or `system.ExtrinsicFailed` event for the specific transaction. These provide the overall execution result for the transaction, i.e. execution has succeeded or failed. Depending on the transaction sent, some other events may be emitted. For instance, for a `balances.transfer` this could include one or more of `Transfer`, `NewAccount` or `ReapedAccount`, as defined in the substrate `balances` event defaults. To display or act on these events, we can do the following: ```ts ... // Make a transfer from Alice to BOB, waiting for inclusion const unsubscribe = await api.tx.balances .transfer(BOB, 12345) .signAndSend(alice, ({ events = [], status, txHash }) => { console.log(`Current status is ${status.type}`); if (status.isFinalized) { console.log(`Transaction included at blockHash ${status.asFinalized}`); console.log(`Transaction hash ${txHash.toHex()}`); // Loop through Vec to display all events events.forEach(({ phase, event: { data, method, section } }) => { console.log(`\t' ${phase}: ${section}.${method}:: ${data}`); }); unsubscribe(); } }); ``` **Caution**: Be aware that when a transaction status is `isFinalized`, it means it is included, but it may still have failed - for instance, if you try to send a larger amount that you have free, the transaction is included in a block. However, from an end-user perspective, the transaction failed since the transfer did not occur. In these cases, a `system.ExtrinsicFailed` event will be available in the events array. ## Payment Information The RPC endpoints expose weight/payment information that takes an encoded extrinsic and calculates the on-chain weight fees for it. A wrapper for this is available on the tx itself, taking exactly the same parameters as you would pass to a normal `.signAndSend` operation, specifically `.paymentInfo(sender, )`. To expand on our previous example: ```ts // construct a transaction const transfer = api.tx.balances.transfer(BOB, 12345); // retrieve the payment info const { partialFee, weight } = await transfer.paymentInfo(alice); console.log(`transaction will have a weight of ${weight}, with ${partialFee.toHuman()} weight fees`); // send the tx transfer.signAndSend(alice, ({ events = [], status }) => { ... }); ``` # Test Faucet Source: https://docs.therootnetwork.com/build/test-faucet Access tokens for testing your dapps on The Root Network. # Testnet Rootscan Explorer Source: https://docs.therootnetwork.com/build/testnet-rootscan-explorer Monitor and debug your dapps on The Root Network testnet before deploying to production. # null Source: https://docs.therootnetwork.com/changelog Keep track of every change to The Root Network. This changelog lists all additions and updates to the The Root Network API, in chronological order. * Add variable benchmarks to NFT pallet * Updated the FeeProxy pallet to allow partners to accumulate fees via the PartnerAttribution pallet - if the partner has a fee percentage set (by an admin account). * Update the nft and sft pallets to support issuing of soulbound tokens, and update the ERC721 and ERC1155 precompiles to support the ERC5484 interface. * Removes the sort function from NFT.add\_user\_tokens * Use the Futurepass balance for the Proxy ROOT deposit when calling add\_delegate\_with\_signature * Updated Partner Attribution pallet * Add Partner Attribution Pallet * Dependency update for Grandpa fix Add nft\_collectionDetails RPC call * Add ERC-165 support ERC-20 and ERC-1155 EVM precompiles * Add ERC-165 support ERC-20 and ERC-1155 EVM precompiles * Add a check for NFI Data before emitting event on burn * Add set\_token\_name extrinsic to the SFT pallet * Introduce Sylo Data Verification Pallet * Update nft burn event to include a signer * Add nft\_collectionDetails RPC call * Add ERC-165 support ERC-20 and ERC-1155 EVM precompiles * Add ERC-165 support ERC-20 and ERC-1155 EVM precompiles * Add a check for NFI Data before emitting event on burn * Add set\_token\_name extrinsic to the SFT pallet * Introduce Sylo Data Verification Pallet * Update nft burn event to include a signer * Add multi-chain support to NFI pallet * Add ERC-165 support for the ERC-721 precompile * Remove unused dependencies * Remove storage getters from pallets in preparation for Substrate Upgrade * Add Destination tag to XRPL alt token bridge * Tidy up codebase to remove unwrap() and fix clippy warnings * XRPL NFT Bridging * Introduce pallet-migration for multiblock migrations. * Improve transact error handling * Add standard PR template * Fix for runtime migration to deploy EIP-2470 and Universal deployer via a runtime upgrade. A bugfix is included as a commit to remove additional checks which prevent internal migration code from executing; this also reduces migration weight * Adds SFT support to the marketplace precompile * Fixes bug that lets simple offers be made on non-existent tokens * Allows payment delay to be set on individual assets in XRPL bridge * Adds support for token bridging from XRPL to TRN * Adds NFI pallet which can be used to enable NFI compatibility for any NFT or SFT collection * Adds ECAdd, ECMul and ECPairing precompiles * Adds additional utility flags to NFT and SFT collections that allow the prevention of minting, transferring, and burning * Upgrade Substrate to v1.0.0 * Update MAXIMUM\_BLOCK\_WEIGHT to 1s * Update BLOCK\_GAS\_LIMIT to 15 Million * Update the build toolchain to `stable 1.80.0` * Fixes validator set issue on authorities change * Fixes eth paused on authorities set change bug * Optimises ethy on\_initialise functionality * Add benchmarks to Ethy pallet * Fixed a bug with XRPL transact mempool validation; incorrect tx origin may be used for FuturePass based extrinsics * Add a toggle to enable/disable the delay mechanism for either deposit or withdraw * Remove deprecated Futurepass Migration code * Adds XRPL transaction signing support for ed25519 * Fixes token lock bug for closed auctions * Update Ethy and ERC20-Peg to FrameV2 * Ethy gadget Witness message pruning based on the finalized block number * Redundant network gossip activity should be significantly reduced. * Should provide fixes for the current peer drop issue. * All the existing gossip Witness messages would be discarded due to the new format * There is a chance of discarding witnesses before they can form the proof if goes out of the live window. A separate mechanism to handle these scenarios will be introduced later. * Ensure at least 66% of the active validators are upgraded to the new image to avoid halting the proof formation. * Adds a total contributors parameter to the SaleInfo Struct within pallet-crowdsale that keeps track of total unique contributors * Adds fix that disallows public mint enabled collections to be crowdsale initialised * Adds `proxy_vault_call` extrinsic to crowdsale pallet which allows admin access to NFT collection info * Adds optional parameters to set custom name and symbol to voucher asset when initialising crowdsale * Added Crowdsale pallet (`pallet-crowdsale`) * Added SFT transfer event when a marketplace SFT listing is sold * Added cargo doc automation script * Prefix Futurepass precompile revert messages * Adds BlockNumber field to xrplBridge.WithdrawDelayed event * Adds pallet-xrpl which allows for the submission of signed XRPL transactions * Adds pallet-doughnut which adds support for permissioned doughnut based transaction execution * Adds SFT token support to the native marketplace pallet. * Introduced NFT marketplace precompile, enabling the trading of NFTs on the marketplace via Solidity interface at 0x00000000000000000000000000000000000006CD. * Unified RPC call to get balance for Root and other assets. * Added the ability to include `sourceTag` and `destinationTag` for XRPL withdraw (bridging TRN->XRPL). * Added ability to burn ERC721 assets via precompile. * Implemented fixes for tate fork script. * Updated self-contained call interfaces (future PR pre-req) * Fixed ERC20 precompile to validate maintenance mode restrictions. * Added a delay mechanism for large XRPL bridging transactions. * Updated bootnode list for Porcini and Root in the chainspec. * Optimized gas required for contract deployment by removing fees * Added a fix for ERC20 precompile asset existence verification. * Updated root\_human.json * Updated the bootnodes list for both Root and Porcini * Fixed a few bugs in the VortexDistribution pallet * Optimised XRPL pruning by moving pruning logic into on\_idle. * Reduced the collection royalty entitlements limit from 8 to 6. Caution: This change does not migrate any existing collections. However, if collections contain royalties with more than 6 entitlements, it is advised to reduce this number to avoid issues with marketplace support. * Added maintenance mode pallet which allows the sudo key to block calls, pallets, accounts, EVM addresses, or enter the whole chain into maintenance mode. * Added some helpful extrinsics to AssetsExt for mint, transfer and burn which route to the balances or assets pallet based on the AssetId. * Added the ability to set the asset deposit for creating a new asset at runtime. * Restricted Asset decimals to maximum 18 DP when creating a new asset. * Reverted dual staking functionality in favor of a more generic single-token staking mechanism. * Continuous improvements to our test environment, which should increase the speed at which we can write unit tests. * Changed pay\_unsigned to mint directly to the vault account. This simplification streamlines the distribution process by eliminating intermediate steps. * Removed the requirement to specify an amount when creating a new vortex distribution. The TotalVortex will now be utilized to manage the aggregated reward pool dynamically. * The price parameter has been temporarily deprecated as it is not currently utilized in the distribution logic. * Removed the vault parameter from the function signature. The vault will now be funded manually prior to reward distribution. * Removed the obsolete get\_vault\_account function, as account management will be handled more efficiently with the new logic. * Consolidated root and multisig operations, simplifying the administrative process. * Set root vault and fee vault addresses to fixed values to ensure consistency and security across transactions. * Fixed an issue in gas calculation of the ERC-20 precompile. It now charges the correct amount: * transfer should cost \~ 317,060 drops * transferFrom should cost \~ 358,396 drops * Added an admin extrinsic set\_length\_multiplier, allowing control of the gas scaling by the length of the transaction. * Introduced public mint functionalities for NFT and SFT pallets enabling any account to mint tokens from the enabled collections: * Disabled by default, it needs to be enabled with the toggle\_public\_mint extrinsic. * Mint fee can be set using the set\_mint\_fee extrinsic. * Added Vortex token distribution pallet, facilitating the distribution of Vortex tokens at the end of a 90 day cycle: * Asset prices are calculated off-chain and provided with the use of an admin function set\_asset\_prices. * Token distribution amounts can be specified per account using the admin function register\_rewards. * Vortex distribution is calculated, and tokens are minted through the admin function trigger\_vtx\_distribution. * Vortex payout is enabled through the use of an admin function start\_vtx\_dist. * Users can manually claim their tokens through the extrinsic, redeem\_tokens\_from\_vault. * Enabled bridging of ROOT token through existing ERC20-Peg. This differs from standard ERC20 bridging, as it transfers tokens to and from the erc20-peg pallet address rather than burning/minting on demand. * Disabled submit\_challenge extrinsic on the ETH bridge. # The Root Network Source: https://docs.therootnetwork.com/intro At the heart of the network infrastructure and protocols in the open metaverse is The Root Network (TRN). The Root Network is the core blockchain infrastructure designed with a strong emphasis on user onboarding, aiming to improve the web3 experience. While the initial onboarding process in web3 lacks user-friendliness and safety features compared to web2, once users are onboarded, web3 offers superior privacy and flexibility in handling assets and data. The Root Network has the following main elements: ## Substrate Core The Root Network uses [Substrate](https://substrate.io/) at its core. Substrate has two major advantages: a large, well-established developer community, and the technical capability to customize the chain runtimes to optimize for user experience. ## EVM Support for Smart Contracts Ethereum Virtual Machine (EVM) runs within The Root Network protocol and is able to read Solidity smart contracts and execute them. This gives The Root Network developers access to smart contract functionality and also means that any code previously written for Ethereum can now run natively on The Root Network. The EVM development ecosystem provides the broadest possible support for smart contracts and dapps, as well as compatibility with existing collections and collectibles in the NFT ecosystem. ## Custom Runtimes Our custom runtimes for Non-Fungible Assets, Gas Economy, Fungible Assets, Decentralized Exchange, Oracles and more, will provide the ingredients for creators to build applications and content without being a smart contract developer. They also provide a world-class onboarding experience. ## Non-Fungible Assets Runtime The Root Network NFT runtime provides a single unified network-wide experience for NFTs. In other networks, NFTs exist at the individual contract layer. In The Root Network, NFTs exist in a core network runtime. This provides a common standard to build interoperability. A uniform approach to minting, royalties and structuring, especially in the metadata and content formats, is essential for delivering the asset interoperability people imagine at the application layer. The NFT runtime also has unique features like: * Network-wide royalty enforcement * Native multi-wallet split and tiered royalties for creators * Native NFT to NFT swaps * Native Static and cold minting options * Build NFT dapps without needing to develop or deploy smart contracts * Fees from the NFT runtime are distributed to network stakers and validators The Root Network also integrates the XRPL XLS-20 NFT standard as a runtime, enabling compatibility with the XRPL NFT ecosystem and infrastructure. ## Multi-Token Economy The Root Network has a unique multi-token economy that enables the optimization of both gas and initial user onboarding. In traditional single-token networks, high or unpredictable gas fees create significant challenges for users, impacting their overall experience. Additionally, the need to understand and obtain gas for transactions poses a considerable barrier for new users entering decentralized applications within web3. The Root Network introduces a unique multi-token system where the primary network token, [ROOT](https://docs.therootnetwork.com/intro/learn/glossary), is separated from the gas token, XRP, sourced from a partnership with [Ripple](https://ripple.com/) and the [XRPL](https://xrpl.org/index.html). This separation enables efficient network operation and fosters liquidity for block rewards. The network addresses the user problem of complex gas acquisition by implementing an in-chain Gas fee exchange, allowing users to use the native token of the application or have developers pay fees on their behalf through liquidity pools. This innovative approach ensures smoother user onboarding without the necessity of comprehending the network's underlying economy or engaging with external exchanges. ## Fungible Assets Like the NFT runtime, users can create and launch standardized fungible tokens without having to deploy smart contract code, and compatible with XRPL fungible tokens. 1% of each new asset created in the Fungible Assets runtime is distributed to network node validators as a fee. ## Decentralized Exchange The network exchange runtime provides an in-chain decentralized exchange (DEX) with a rich set of features that enable users and developers to trade collectibles, build liquidity pools and launch token price discovery, without having to deploy smart contract code. Exchange fees are collected by node validators. The in-chain DEX will also be integrated into the XRPL DEX to draw liquidity from to bootstrap the network liquidity. ## Liquidity and Collectibles Bridges The Root Network natively supports collectibles bridges through its general purpose bridging runtime. This means, for example, [FLUF World](https://under.fluf.world/) assets on the ETH network or fungible and non-fungible assets on the XRPL can be bridged to The Root Network to gain additional utility. These two networks will be live at launch, but others can be added as the ecosystem grows. The Root Network can also act as a hub for other Substrate-based and XRPL-based networks. This would apply to people who want to build interoperable content in the ecosystem, but require their own MetaApp chain. # EVM Smart Contract Source: https://docs.therootnetwork.com/learn/features/EVM-smart-contract Utilizing the Ethereum Virtual Machine (EVM) Smart Contract module as well as our prebuilt core runtime modules, developers can build The Root Network dapps with smart contracts. The EVM integration ensures extensive support for smart contracts, dapps, and existing Ethereum asset collections, facilitating interoperable development and the effortless transition of Ethereum functionality to The Root Network with bidirectional communication. With the integrated EVM, developers can further enhance The Root Network's capabilities by deploying their own smart contracts, fostering deep connectivity to ROOT's native runtimes for an enriched developer and user experience. ## Smart Contract Module EVM is the mechanism developers must use to run smart contracts on the Ethereum blockchain. The EVM mechanism reads smart contracts written in Solidity. To integrate smart contracts into The Root Network blockchain, we built our very own EVM mechanism within our blockchain runtime. This EVM runs within The Root Network blockchain protocol and is able to read Solidity smart contracts and execute them on The Root Network. This gives The Root Network developers access to smart contract functionality and also means that any code previously written for Ethereum can now run on The Root Network blockchain natively. ## Benefits of Smart Contract Module The Root Network’s EVM support has a few important implications: * Access Ethereum code and infrastructure: The Root Network dapp developers can take advantage of the code and infrastructure built by the Ethereum ecosystem when building The Root Network dapps. * Easy dapp migration: Ethereum dapp developers can easily migrate their dapps to The Root Network for faster transaction speeds and lower transaction fees. * Speak your language: Solidity developers can keep using their favourite tools when developing on The Root Network. * Smart contracts on The Root Network: The EVM module allows you to call The Root Network modules from your smart contract code. This means you can create custom on-chain logic on top of The Root Network runtime modules. ## Choosing Between the EVM Module and Runtime Module The EVM module now gives dapp developers a choice of building methods. You can implement your dapp using smart contracts through the EVM module or runtime modules. Depending on what you are looking to build, choose one of the methods: * **The runtime modules** are the most efficient and cost-effective method of developing on The Root Network. All runtime modules are written in Rust, which makes them highly optimised on the blockchain’s protocol. The runtime modules also provide a selection of standard dapp functionalities made easily accessible through a simple JavaScript API. This helpful resource can save you a good amount of development time. We recommend developers explore the modules to check if the problem you are addressing has already been sorted by the provided functionalities before writing your custom smart contract. * **The EVM module** offers more flexibility. You can create your own custom logic to be deployed at any time. The EVM also allows you to use Solidity and tooling from Ethereum, which you may be more familiar with. You can also call The Root Network modules from your Smart Contracts to combine the power of The Root Network modules with existing Ethereum dapps. For more information, see [Building with EVM API](../../build/evm/evm-package). ## Next Steps To get building your dapp using the EVM module: * Check out the [EVM API section](../../build/evm/) * Check out the curated [EVM code examples](https://github.com/futureversecom/trn-examples/tree/main/examples/evm) # Any-token Gas Source: https://docs.therootnetwork.com/learn/features/any-token-gas Users can pay gas fees using any approved token or have them covered by developers. The Root Network introduces an innovative any-token economy, streamlining user onboarding and enhancing the gas fee system for both users and validators. This distinctive approach simplifies user onboarding by allowing users to utilize the native token of an application or enabling developers to manage fees on users' behalf. The Root Network seamlessly converts any configured token into the default gas token, ensuring user flexibility without the need to comprehend the network's intricate economy or engage with exchanges. Moreover, The Root Network distinguishes the staking token from the gas token, addressing challenges related to high or fluctuating network fees and resolving the issue of inadequate liquidity for incentivizing node operators. ### Next Steps The any-token gas protocol is encapsulated in the `feeProxy` pallet on-chain. To start utilizing this feature in your dapp, check out: * The pallet [Native API References](../../build/substrate/api-reference/runtime-pallets/feeproxy) and how it works with the [code examples](https://github.com/futureversecom/trn-examples/tree/main/examples/substrate/use-feeProxy). * The pallet [EVM API References](../../build/evm/runtime-precompiles/feeproxy) and how it works with the [code examples](https://github.com/futureversecom/trn-examples/tree/main/examples/evm/use-feeProxy). What's the difference between [Native API and EVM API](../../build/getting-started/)? # Decentralized Exchange Source: https://docs.therootnetwork.com/learn/features/decentralized-exchange The Root Network supports automated decentralized spot exchanges. It will allow users to: * Trade asset tokens instantly on The Root Network blockchain * Send exchanged tokens directly to a 3rd party account within a single exchange transaction The exchange will support all asset tokens active on The Root Network. This will include SYLO and ASTO tokens along with any generic assets created by new dapps on the network. ### Next Steps The decentralized exchange protocol is encapsulated in the `dex` pallet on-chain. To start utilizing this feature in your dapp, check out: * The pallet [Native API References](../../build/substrate/api-reference/runtime-pallets/dex) and how it works with the [code examples](https://github.com/futureversecom/trn-examples/tree/main/examples/substrate/use-dex). * The pallet [EVM API References](../../build/evm/runtime-precompiles/decentralized-exchange). What's the difference between [Native API and EVM API](../../build/getting-started/)? # null Source: https://docs.therootnetwork.com/learn/features/ethereum-bridge The Root Network Ethereum Bridge allows the secure transfer of tokens between The Root Network and Ethereum. It allows two-way transfers of ERC-20 tokens and native \$ETH. ### Benefits and Functions The Ethereum Bridge provides several key functions and benefits: * Secure transfer of tokens: Transferring tokens between The Root Network and Ethereum is seamless and secure. The bridge provides a decentralised and cryptographically secure way to move tokens and assets between the two chains. * Liquidity: Asset bridges unlock more liquidity for the network. Developers, metaverse projects and community members can utilise The Root Network for building while receiving payments in Ethereum-supported currency and ROOT. * Cross-chain functionality: Connecting blockchains means you can combine their strengths. This means collections already existing on the Ethereum network can be bridged to The Root Network to gain additional utility. * An open metaverse: Web3 infrastructure must be open and interoperable with portable collectibles. Bridges allow for this level of interoperability by connecting chains to create broader ecosystems of diverse utility. ### How does the Bridge work? The Ethereum Bridge uses The Root Network validators, chosen by the network-wide proof-of-stake mechanism. As well as being responsible for creating blocks on The Root Network, validators are now required to verify bridge transactions. They have the authority to act as notaries, verifying the authenticity of a deposit to a bridge contract when needed. The security of this system is based on threshold cryptography alongside a system of smart contracts. The process looks something like this: #### Ethereum → The Root Network 1. The user sends a deposit request to the Ethereum Bridge contract on Ethereum. This request contains: * The recipient address on The Root Network * The deposit amount * The token address (ERC-20 or native ETH) 2. The Ethereum Bridge relayer service waits for block confirmations on Ethereum and sends a deposit claim with relevant information to The Root Network. 3. A challenge period is initiated on The Root Network once the deposit claim is received. * If a challenge is submitted, validators will query the claim and check the transaction’s validity against Ethereum’s full node. The validators will determine who is correct (the challenger or the transaction requester) and slash the incorrect party. There will be some pay-out portion to the correct party. 4. Once the challenge period ends, the claim is considered valid. The token is minted and transferred to the intended recipient's address. #### The Root Network → Ethereum 1. The user sends a withdrawal request to the Ethereum Bridge module on The Root Network. This request contains: * The recipient address on Ethereum * The withdrawn amount * The token ID 2. Validators sign a message stating that The Root Network has burnt the requested token amount. The validators will also issue a withdrawal proof for the user. 3. The user submits the withdrawal proof to the Ethereum Bridge contract on Ethereum. 4. The Ethereum Bridge contract checks that the signatures are legitimate and then releases the tokens to the intended recipient address. # Identity and Smart Wallet Protocols Source: https://docs.therootnetwork.com/learn/features/identity-protocol Our native identity protocol allows users to establish a persistent and secure digital identity that can be used across multiple metaverse applications and experiences. Our smart wallet enables familiar web2 experiences within open metaverse applications. User-owned on-chain addresses, account abstraction and delegated payments allow users to manage their identity and assets through a single account, rather than having to manage multiple addresses and keys for different assets or applications across experiences. ### Next Steps The identity and smart wallet protocols are encapsulated in the `futurepass` pallet on-chain. To start utilizing this feature in your dapp, check out: * The pallet [Native API References](../../build/substrate/api-reference/runtime-pallets/futurepass) and how it works with the [code examples](https://github.com/futureversecom/trn-examples/tree/main/examples/substrate/use-futurepass). * The pallet [EVM API References](../../build/evm/runtime-precompiles/futurepass) and how it works with the [code examples](https://github.com/futureversecom/trn-examples/tree/main/examples/evm/use-futurepass). What's the difference between [Native API and EVM API](../../build/getting-started/)? # On-Chain Assets Source: https://docs.therootnetwork.com/learn/features/on-chain-assets The Root Network allows you to create digital assets and tokens that can be used and exchanged across different applications, experiences and destinations in the open metaverse. Our on-chain assets protocols support existing industry standards such as ERC-20, ERC-721, ERC-1155 and XLS-20, ensuring that digital assets remain compatible with a diverse range of metaverse applications and experiences. However, we provide additional functionality and enhanced user experience by connecting these to our in-chain runtimes. By leveraging these common standards, we promote seamless interoperability across the entire web3 ecosystem, providing users with a unified and frictionless experience. ### Next Steps To support on-chain assets protocol, we have several pallets that you can utilize in your dapp: **`assets` pallet (ERC-20 Standard)** * Pallet [Native API References](../../build/substrate/api-reference/runtime-pallets/assets) and [code examples](https://github.com/futureversecom/trn-examples/tree/main/examples/substrate/use-assets). * Pallet [EVM API References](../../build/evm/runtime-precompiles/assets-erc-20) and [code examples](https://github.com/futureversecom/trn-examples/tree/main/examples/evm/use-erc20). **`nft` pallet (ERC-721 Standard)** * Pallet [Native API References](../../build/substrate/api-reference/runtime-pallets/nft) and [code examples](https://github.com/futureversecom/trn-examples/tree/main/examples/substrate/use-nft). * Pallet [EVM API References](../../build/evm/runtime-precompiles/nft-erc-721) and [code examples](https://github.com/futureversecom/trn-examples/tree/main/examples/evm/use-erc721). **`sft` pallet (ERC-1155 Standard)** * Pallet [Native API References](../../build/substrate/api-reference/runtime-pallets/sft) and [code examples](https://github.com/futureversecom/trn-examples/tree/main/examples/substrate/use-sft). * Pallet [EVM API References](../../build/evm/runtime-precompiles/sft-erc-1155) and [code examples](https://github.com/futureversecom/trn-examples/tree/main/examples/evm/use-erc1155). What's the difference between [Native API and EVM API](../../build/getting-started/)? # On-Chain Collectibles Protocol Source: https://docs.therootnetwork.com/learn/features/on-chain-collectibles-protocol Using The Root Network’s NFT runtime module, you can mint and trade NFTs on The Root Network without ever needing to touch a smart contract. Instead, users can create custom NFTs using only a Javascript API or point-and-click with a user interface (UI). This not only simplifies the process of minting NFT assets for everyone but also ensures that creators are not restricted to a particular marketplace. The following features are designed to simplify the storage, sharing, and usage of NFTs: ## Create a token collection The first step to creating your NFTs on The Root Network is creating a specific collection to store groups of tokens. This makes it straightforward to organise your tokens by a common theme, such as an artistic feature, a timestamp or even a buyer. A collection can also contain just a single NFT if you would prefer individual groupings. To create an NFT collection, you must define a schema (arrangement) of attributes all tokens in the collection could contain. These could be characteristics such as: * General appearance (i.e. data represented within the NFT) * A specific timestamp * A specific creator * A naming system * A royalties scheme for secondary sales. This allows one or more creators to receive a set % of a sale price on all sales of your NFT Finally, you must give your collection a name. The more discoverable, the better! ## Create your individual tokens Once your collection has been created, you can start actually minting your NFTs. At this point, you can assign the token owner and individually determine a fixed price or royalty scheme. ## Next Steps To mint and trade NFTs on The Root Network, there are a couple of pallets you might want to check out: ### `nft` pallet (ERC-721 Standard) * Pallet [Native API References](../../build/substrate/api-reference/runtime-pallets/nft) and [code examples](https://github.com/futureversecom/trn-examples/tree/main/examples/substrate/use-nft). * Pallet [EVM API References](../../build/evm/runtime-precompiles/nft-erc-721) and [code examples](https://github.com/futureversecom/trn-examples/tree/main/examples/evm/use-erc721). ### `marketplace` pallet * Pallet [Native API References](../../build/substrate/api-reference/runtime-pallets/marketplace) and [code examples](https://github.com/futureversecom/trn-examples/tree/main/examples/substrate/use-marketplace). What's the difference between [Native API and EVM API](../../build/getting-started/)? # Staking Protocol Source: https://docs.therootnetwork.com/learn/features/staking-protocol There are three levels of participation with increasing responsibility and reward profiles. See the table below for a high-level explanation of the different levels, rewards and risks. For early backers, as outlined in [Tokenomics](../tokenomics), we are rewarding up to 10% of the total supply of ROOT tokens over 260 weeks as part of our Bootstrap Rewards. Please note tokenomics for The Root Network are subject to change in future. | Participation Level | Rewards | Risks | | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Staker** |

Earn rewards based on ROOT staked by the duration of the reward cycle.

Earn 0.0246 ROOT per ROOT staked for the reward cycle. This is rewarded in Vortex tokens at the end of the 90-day cycle.

|

Staked ROOT is locked. You can unstake at any time with a 28-day cool-down period.

Note: Withdrawing before the end of the reward cycle will result in the forfeiture of rewards from that cycle.

| | **Nominator** |

Earn based on ROOT staked by the duration of the reward cycle.

Earn 0.0492 ROOT per ROOT staked for the reward cycle. This is rewarded in Vortex tokens at the end of the 90-day cycle.

Also, earn based on work done by validators you nominated, based on commission percentage and amount of Work points accumulated during the reward cycle.

|

In addition to the notes from above, staked ROOT is exposed to slashing risk from the validators you nominate.

Being a nominator is not set and forget. Nominations should be periodically monitored.

| | **Validator** |

Earn based on ROOT staked by the duration of the reward cycle.

Earn 0.0739 ROOT per ROOT staked for the reward cycle. This is rewarded in Vortex tokens at the end of the 90-day cycle.

Earn based on work done as a validator, less commission you pay to nominators for selecting you.

|

Your staked ROOT is exposed to slashing risks.

Investment and skills required to set up, run and maintain a validator node.

| * All participants are rewarded at the end of the 90-day reward cycle, and you must still be staking in at the end of the 90-day reward cycle to receive your rewards. * Note that you can either stake or nominate from the same wallet. ## Staking * Stake your ROOT tokens for a reward cycle and choose not to nominate any validators. This is a low-risk method of participating. * By not taking on slashing risks for a nominator, your reduced risk is paired with a reward proportional to your risk. * You can stake at any point of the reward cycle. Your rewards are prorated by the duration you staked. * How to stake? Refer to [this section](../how-to/how-to-stake). ### Unstaking Withdrawing your funds from staking involves two steps in canceling a stake: * **Unstake**: This step schedules the unlocking and removal of some of the bond from the staking system. It's important to note that when you begin the unbonding process, you are still staked until you withdraw. * **Withdraw**: After the unstake process is complete, it returns the unstaked funds to your stash account. Withdrawal can only be performed once the unstake process has finished. Note that there is a time delay of 28 days for unstaking. You will not receive any rewards during the 28 day period, because the stake is in transit and cannot be used for any purposes. This 28-day waiting period is an industry-wide practice designed to prevent malicious actors from immediately exiting the system with their stake. ## Nominating This is the next level of participation. To become a nominator, you need to stake at least 25 ROOT. During the staking flow, you choose to nominate one or more validators. You can nominate at any point in the reward cycle. Your rewards are prorated by the duration you staked. In each Era (24 hours), the protocol elects validators to complete blocks and transactions, earning them Work points. When you nominate multiple validators, you increase your chances of earning rewards from elected validators. The nomination algorithm automagically determines how best to allocate your nominated ROOT equally across active and earning validators for each Era. It's worth noting that most nominators will likely see only one active and earning validator during an Era. That means all your staked ROOT will be nominated to the one active validator. **Note**: Some validators may become oversubscribed. If this happens, only the top 256 nominators (sorted by the amount of ROOT nominated) will earn rewards. Oversubscribed validators will have badges clearly indicating their status. You can also exclude them by clicking **filter** and selecting **exclude oversubscribed validators**. ## Validating Validating is tailored for more technically-minded participants. Validators play a critical role in forging blocks and completing transactions on the network. This role demands technical knowledge, infrastructure cost, and entails higher rewards, albeit with additional risks. For a comprehensive guide on how to become a validator, see [Become a Validator](/participate/validator-guide/become-a-validator). ### Slashing In The Root Network, slashing is a pivotal tool to counteract harmful actions by imposing penalties on validators acting counter to the network's welfare and that of their backers (nominators). Such deterrents ensure that validators, driven by the potential loss of their staked tokens, are incentivized to act favorably for the network. A validator's misstep or adversarial conduct triggers the slashing mechanism. Such behaviors could range from prolonged unavailability, like being offline with numerous others, launching attacks on the network, or employing altered software. The magnitude of the slashed amount is directly proportional to the gravity of the misdeed. Slashed ROOT will go to The Root Network Treasury. Minor offenses (like a validator being offline for a prolonged period) will not incur slashing. They will stop validating until the issue is fixed, and they re-declare their intention to validate. The slashing mechanism is triggered only if 10% or more active validators simultaneously go offline (which could mean there’s an attack on the network). ## Staking Dashboard Staking Dashboard Pn ### Nominator Status On the staking dashboard, when you nominate a validator (or multiple validators), you will see one of three statuses: * **Inactive**: This means that the validator you nominated is not nominating in this current Era (if you’ve nominated several validators, all but one will display as inactive). * **Waiting**: You will see this status when you first nominate a validator or change nominations. This means the nomination will not be confirmed until the next Era. * **Active and earning**: This means the validator was chosen, and your nomination actively supports it in this Era. * Please note: If you already have ROOT staked and have added additional ROOT to your staking balance, it will not show as Active and earning until the next Era. # XRPL Bridge Source: https://docs.therootnetwork.com/learn/features/xrpl-bridge The Root Network XRPL Bridge allows the secure transfer of tokens between The Root Network and the XRP Ledger. It allows two-way transfers of native XRPL tokens. ## Benefits and Functions The XRPL Bridge provides several key functions and benefits: * Secure transfer of tokens: Transferring tokens between The Root Network and the XRP Ledger is seamless and secure. The bridge provides a decentralised and cryptographically secure way to move tokens and assets between the two chains. * Liquidity: Asset bridges unlock more liquidity for the network. Developers, metaverse projects and community members can utilise The Root Network for building while receiving payments in XRP-supported currencies. * Cross-chain functionality: Connecting blockchains means you can combine their strengths. This means non-fungible assets on the XRPL can be bridged to The Root Network to gain additional utility. * An open metaverse: Web3 infrastructure must be open and interoperable with portable assets. Bridges allow for this level of interoperability by connecting chains to create broader ecosystems of diverse utility. ## How does the Bridge work? ### XRP Ledger → The Root Network 1. The user sends a deposit request to The Root Network door account on XRP Ledger. This request contains: * The recipient’s Root Network address * The XRPL deposit amount 2. The XRPL Bridge relayer service picks up the transaction and sends a deposit claim to The Root Network with relevant information. 3. A challenge period is initiated on The Root Network once the deposit claim is received. * If a challenge is submitted, validators will query the claim and check the transaction’s validity against the XRPL full node. The validators will determine who is correct (the challenger or the transaction requester) and slash the incorrect party. There will be some pay-out portion to the correct party. 4. Once the challenge period ends, the claim is considered valid. The token is minted and transferred to the intended recipient's address. ### The Root Network → XRP Ledger 1. The user sends a withdrawal request to the XRPL Bridge module on The Root Network. This request contains: * The recipient address on XRP Ledger * The withdrawn XRPL amount 2. Validators sign a message stating that The Root Network has burnt the requested token amount. The validators will also issue a withdrawal proof. 3. The XRPL Bridge relayer service picks up the event and submits the withdrawal claim to the door account. 4. The door account checks that the signatures are legitimate and releases the tokens to the intended recipient address. # null Source: https://docs.therootnetwork.com/learn/glossary
TermDefinition
Bootstrap Rewards

As outlined in The Root Network whitepaper, we reward up to 10% of the total supply of ROOT tokens over 260 weeks as a bootstrap to early backers.

Stakers, nominators, and validators are rewarded ROOT based on ROOT staked by duration for the reward cycle. Rewarded ROOT is transferred into The Vortex and paid out in Vortex tokens at the end of the reward cycle.

EraA 24-hour period. For each Era, validators are selected by voting to do the work.
ExtrinsicThe term extrinsic is generally used to mean any information that originates outside of the runtime. However, for practical purposes, it is more useful to consider each transaction type independently and identify scenarios where each type would be most applicable.
FuturePass It is an all-in-one smart wallet. FuturePass is a unified platform to manage identity data, assets, permissions and status across various apps, experiences and worlds, ensuring a simpler and safer journey. It also provides access to the FutureScore engine and FutureScore Quests, acting as a portal to rewarding challenges and experiences.
Network FeesFees from DEX, marketplaces, communication protocols, material world and other experiences, and paying gas on the network.
Network TokensThese are tokens used on the network to pay gas and network fees.
NominatorA participant who stakes ROOT and chooses to nominate one or more validators. This is a higher risk (see Slashing) and comes with a higher reward relative to staking.
NounceA number used to protect private communications by preventing replay attacks. Nonces are random or pseudo-random numbers that authentication protocols attach to communications. In Ethereum, this number is contained within a transaction payload to keep track of the number of transactions the address has sent. This value ensures that transactions sent from the wallet are executed in order and cannot be replayed.
Reward CycleA 90-day period. At the end of the reward cycle, participants are rewarded proportionally to their participation level.
ROOTThe token used to power The Root Network.
SlashingThis is the risk validators and nominators take on. It happens when a validator misbehaves e.g., the validator node becomes unavailable. Slashed ROOT is transferred to the Treasury.
StakerA participant who stakes ROOT and doesn’t nominate a validator. It is a lower risk and comes with lower rewards relative to nominating.
ValidatorA participant who stakes ROOT and operates one or more validator nodes to forge blocks and complete transactions on the network.
The Vortex

This is where all fees collected on the network are stored. It also includes the ROOT from Bootstrap Rewards.

Tokens in The Vortex should generally go up. It decreases when people unroll their Vortex token. In this case, they get their proportion from The Vortex.

For example, if you unroll 10 Vortex tokens and there are 100 Vortex tokens in circulation, you have 10% of the market supply. By unrolling, you get back 10% of all tokens in The Vortex at that time.

TransactionsTransactions in a blockchain are fundamental data units that represent a transfer of value or the execution of a specific action within the blockchain network. They are the building blocks of the blockchain and are used to record changes to the ledger securely and verifiable. There are three types of Ethereum network transactions:  transferring cryptocurrency from one account to another, deploying a smart contract, and interacting with a smart contract.
Vortex Tokens

Participants on The Root Network are rewarded with Vortex tokens.

Vortex tokens are backed by the underlying tokens in The Vortex.

They are tradable on DEX, assuming there is a liquidity pool with a pair of your choice.

Work Points

Work points are earned by validators for doing work to complete blocks and transactions on the network.

As a nominator, you earn a percentage commission of Work points your selected validators earn. For more details on how they work, see [Tokenomics](/learn/tokenomics).

# Create a Fungible Asset Source: https://docs.therootnetwork.com/learn/how-to/create-fungible-asset Fungible asset is an essential component of any blockchain. The Root Network comes with pre-built pallets `asset` and `assetsExt` that make fungible asset management easy and intuitive, highly optimized for efficiency and stable transaction fees. Additionally, fungible assets on The Root Network are ERC-20 compatible, once created they are tradable on both native and EVM layers. The following guide will walk you through how to create, mint, and manage a fungible asset using The Root Network Portal. ## Requirements * An account with `100 ROOT` to reserve the asset in the chain storage and at least `0.1 XRP` for initial asset creation. ## Instructions ### Step 1: Connect an account with the Portal 1. Go to the [Portal Account page](https://portal.rootnet.live/#/accounts) and select **From Ethereum Wallet**. 2. Select an account you wish to be the asset owner, when the "Connect with MetaMask" dialog opens up, click **Next**. 3. Confirm your account appears on the Account page under the *Extensions* section. ### Step 2: Create an asset 1. Go to the [Portal Extrinsics page](https://portal.rootnet.live/#/extrinsics) and input the values as per the screenshot below: * Extrinsic: `assetsExt.createAsset()` * Parameters: * `name`: The name of the asset. * `symbol`: The symbol of the asset. * `decimals`: The number of decimals in the asset, max is 18 decimals. * `minBalance` (optional): The minimum balance of this new asset that any single account must have. If an account’s balance is reduced below this, then it collapses to zero. * `owner` (optional): The owner of the asset, defaults to the caller. 2. Click **Submit Transaction** when done and select **Sign** when prompted by MetaMask. 3. The transaction is confirmed when a green tick appears on the top right corner. ### Step 3: Confirm asset creation * Go to [the Portal Assets page](https://portal.rootnet.live/#/assets) and confirm your asset has been created. ### Step 4: Mint asset to account 1. Go to the [Portal Extrinsics page](https://portal.rootnet.live/#/extrinsics) and input the values as per the screenshot below: * Extrinsic: `assetsExt.mint()` * Parameters: * `assetId`: The asset ID to mint. The caller must be the owner of the asset. * `beneficiary`: The account to receive the minted tokens. * `amount`: The amount to mint in the smallest unit. If your asset has `6` decimals, to mint 1 million tokens, it will be `1000000000000` (with 12 zeros). 2. Click **Submit Transaction** when done and select **Sign** when prompted by MetaMask. 3. The transaction is confirmed when a green tick appears on the top right corner. ### Step 5: Transfer asset to account 1. Go to the [Portal Extrinsics page](https://portal.rootnet.live/#/extrinsics) and input the values as per the screenshot below: * Extrinsic: `assetsExt.transfer()` * Parameters: * `assetId`: The asset ID to mint. The caller must be the owner of the asset. * `destination`: The account to be transferred to. * `amount`: The amount to transfer in the smallest unit. If your asset has `6` decimals, to mint 1 million tokens, it will be `1000000000000` (with 12 zeros). * `keepAlive`: The flag to ensure caller still have enough existence balance. 2. Click **Submit Transaction** when done and select **Sign** when prompted by MetaMask. 3. The transaction is confirmed when a green tick appears on the top right corner. ## Use FuturePass It's possible to have your FuturePass account own an asset instead of a standard account. Follow the above steps but wrap all of the extrinsics in the `futurepass.proxyExtrinsic`, as per the screenshot: ## Use Asset on EVM Once the asset is created in Step 2, you can convert your asset ID to an ERC-20 compatible format to use it on the EVM layer. The native asset has the following ERC-20 address convention: ``` 0xCCCCCCCC[asset-id in hex padded 0 up to 8 chars]000000000000000000000000 ``` For example, if your asset id is `69372`, which is `11064` in hex or `00011064` with padded `"0"` up to 8 characters, your asset ERC-20 address will be: ``` 0xCCCCCCCC00011064000000000000000000000000 ``` You can verify this by importing the above address to MetaMask, make sure you add The Root Network to MetaMask using the details [here](/build/connecting-to-the-root-network). # How to buy ROOT tokens Source: https://docs.therootnetwork.com/learn/how-to/how-to-buy-root ## What is The Root Network and \$ROOT The Root Network is a layer 1 blockchain designed as a hub for the open metaverse. Purpose-built for open metaverse activations, utilizing core, UX, and digital content focused protocols to enable seamless user experience and enhance content interoperability. The Root Network features include account abstraction and any token gas economy, enabling some of the world's largest content brands to onboard users seamlessly and safely. The Root Network is EVM compatible, built on Substrate, integrated to XRPL and ETH with other networks on the horizon, allowing content on those networks to access deeper functionality and interoperability. ROOT is the native token of The Root Network. Used for securing the proof-of-stake network, network fees, and as a base currency within the network. Refer to the [Tokenomics](https://docs.therootnetwork.com/learn/tokenomics) section for more information on supply and distribution. ## Storing and Acquiring ROOT You will first need a cryptocurrency wallet to store, trade, and receive ROOT tokens. ROOT tokens are available natively on The Root Network as well as ERC-20 on Ethereum. > [**FuturePass**](https://www.futureverse.com/futurepass)**:** Your native smart wallet on The Root Network, powered by Futureverse. It’s just like using your Ethereum wallet; safe, secure, with account delegation for enhanced security, and multiple wallet integration options for interoperability. In order to transfer ROOT tokens to and from The Root Network, they will need to be [bridged](/learn/how-to/how-to-buy-root#how-to-bridge-root) using the [FuturePass Dashboard](https://futurepass.futureverse.app/). ## Where to buy ROOT There are several ways to purchase ROOT, through centralized exchanges (CEX) and decentralized exchanges (DEX). ### Centralized Exchanges (CEX) ROOT is currently listed on the following centralized exchanges. It’s important to note some exchanges list native ROOT and some the ERC-20 variant, ensure you are aware of which variant you are purchasing. **Centralized exchanges with native ROOT** * [Gate.io](https://www.gate.io/) (Native L1 ROOT) * [MEXC](https://www.mexc.com/) (Native L1 ROOT) * [BitMart](https://www.bitmart.com/) (Native L1 ROOT) * [CoinDCX](https://coindcx.com/) (Native L1 ROOT) Note: If you have purchased native ROOT from one of these exchanges you can transfer directly to your FuturePass or the EOA associated with your FuturePass. We always recommend a small test transfer first. **Centralized exchanges with ERC-20 ROOT** * [Kucoin](https://www.kucoin.com/) (ERC-20 ROOT) * [ByBit](https://www.bybit.com/) (ERC-20 ROOT) * [Huobi](https://www.htx.com/) (ERC-20 ROOT) * [Uphold](https://uphold.com/prices/crypto/root) (ERC-20 ROOT) * [EasyCrypto](https://easycrypto.com/) (ERC-20 ROOT) IMPORTANT NOTE: Never send your tokens directly across different blockchains. Always utilize the Bridge when transferring between networks. Your FuturePass address is only accessible within The Root Network and any ERC-20 tokens sent to your 0xffff (FuturePass) address without using the bridge will be lost. Before bridging to The Root Network, you will need to send the ROOT tokens to an Ethereum wallet (EOA) that you hold the private keys for (e.g MetaMask, Wallet Connect, Coinbase). Once you have the ERC-20 ROOT tokens in your self-custody wallet, bridging can be completed in your [FuturePass dashboard](https://futurepass.futureverse.app/). ### Decentralized Exchanges (DEX) You can purchase ROOT through decentralized exchanges (DEX). As with the centralized exchanges, there are both native and ERC-20 ROOT decentralized exchanges. **Decentralized exchanges with native ROOT** Users should first acquire funds on The Root Network either through withdrawing from CEXes with native ROOT or ERC-20 ROOT via the bridge (see ‘How to Bridge’ section below). * [Dexter](https://app.dexter.trade/) (Native L1 ROOT) * [MOAI Finance](https://app.moai-finance.xyz/) (Native L1 ROOT) *These DEXes are also an avenue for users to purchase other tokens on The Root Network like ASTO and \$XRP.* **Decentralized exchange with ERC-20 ROOT** * [UNISWAP](https://app.uniswap.org/tokens/ethereum/0xa3d4bee77b05d4a0c943877558ce21a763c4fa29?chain=mainnet) (ERC-20 ROOT) IMPORTANT NOTE: Always be mindful of slippage and price changes when making trades. Please review your transactions carefully before executing them. ## How to Bridge ROOT ROOT can be bridged between The Root Network and the Ethereum blockchain. If you purchase tokens from CEX with ERC-20 ROOT, you will need to send the tokens to a self-custody Ethereum wallet and then bridge your tokens to The Root Network to get them into your FuturePass. To do this you can follow the below steps: 1. Log into your [FuturePass dashboard](https://futurepass.futureverse.app/). 2. On the ‘Stuff’ page click on the ‘Tokens’ tab. 3. Click on ‘Bridge’. 4. Under ‘Token Name’, select the ROOT you wish to bridge, the small icons signify what chain the tokens are on. 5. Enter the amount you wish to bridge. 6. In the ‘Destination Address’ ensure you are bridging to the desired address. 1. If bridging to The Root Network it should default to your FuturePass address 2. If bridging to Ethereum blockchain it should default to your EOA wallet address 7. Click ‘Bridge’. 8. Approve the transactions. It will take approximately 15-20 minutes for the tokens to bridge. 9. If bridging ROOT from The Root Network to Ethereum, there is one additional step. You will need to navigate to the ‘Activity’ tab and ‘claim’ your bridged ROOT. *Note: when bridging to the Ethereum network, there will be an Ethereum gas fees to claim the bridge.* For questions and support please contact: [support@therootnetwork.com](mailto:support@therootnetwork.com). # How to create and mint NFT/SFT? Source: https://docs.therootnetwork.com/learn/how-to/how-to-create-and-mint-nft-sft ### How do I create and mint an NFT? To create your NFT collection, call the `nft.createCollection()` extrinsic with the following parameters: ```typescript await api.tx.nft.createCollection( collectionName, initialIssuance, maxIssuance, tokenOwner, metadataScheme, royaltiesSchedule, crossChainCompatibility ); ``` **Caution**: The `royaltiesSchedule` is in per mill (parts per million) scaling, so if you want a 10% royalty, that would be `100,000` (as `100_000 / 1_000_000 = 0.1`). Once your collection is created, the collection owner can call the `nft.mint()` method on the collection to start minting additional tokens so long as the max issuance has not been reached: ```typescript await api.tx.nft.mint(collectionId, quantity, beneficiary); ``` ### How do I create and mint an SFT? SFTs are similar to NFTs however due to their similarity to ERC1155, there can be multiple tokens per SFT collection. Each SFT token has a unique ID, and the collection owner can mint multiple tokens with the same ID. To create your SFT collection, call the `sft.createCollection()` extrinsic with the following parameters: ```typescript await api.tx.sft.createCollection( collectionName, collectionOwner, metadataScheme, royaltiesSchedule ) ``` To create an SFT token within the collection, call the `sft.createToken()` extrinsic with the following parameters: ```typescript await api.tx.sft.createToken( collectionId, tokenName, initialIssuance, maxIssuance, tokenOwner ) ``` Once your token is created, the collection owner can call the `sft.mint()` method to start minting additional tokens so long as the max issuance for that token has not been reached. The owner can pass in a tuple of serialNumbers and quantities to mint multiple tokens at once. ```typescript await api.tx.sft.mint(collectionId, serialNumbers, tokenOwner); ``` # How to Stake Source: https://docs.therootnetwork.com/learn/how-to/how-to-stake ## Overview The Root Network is a proof-of-stake blockchain. Help secure The Root Network by staking ROOT and receiving rewards for participating. Anyone can use ROOT tokens to get involved. For early participants, The Root Network has allocated 10% of the total ROOT supply for the first 260 weeks as an additional Bootstrap Reward. Gas and network fees are collected during the reward cycle and transferred into The Vortex. In each reward cycle, participants are rewarded with newly minted Vortex tokens based on their stake and participation in the network. ## How to participate * **Stake:** Stake ROOT without nominating. The low-risk way of participating. * **Nominate:** Stake ROOT & nominate validators of your choice to secure the network. You share the risks and rewards with validators. [Learn more](/learn/features/staking-protocol) about staking on The Root Network. ## Choosing which validators to nominate If you choose to [**Nominate**](/learn/features/staking-protocol#nominating) validators to stake with, consider the following factors to maximize your rewards: * A higher uptime means the validator is more reliable by keeping their node consistently running. * Commission rates vary which impacts your rewards. * Ensure the validator is not oversubscribed. ## Prerequisites You require a minimum of 25 ROOT tokens in your FuturePass to participate in staking or nominating. Follow the steps in the [How to buy ROOT](/learn/how-to/how-to-buy-root) guide to get started. ## Stake your ROOT