Full JSON-RPC docs + sync tests. (#4335)
* Extended Markdown generator * Synced and extended all JSON-RPC interfaces * Fix linter errors * Format `parity_listAccounts` output in API * typo * Check if interfaces are synced in JS spec tests * Fixing missing interface errors * Better #[rpc] attribute parsing * Fixed RPC JS spec tests * More examples * Refactored how dummy data appears in examples * Complete trace docs! * fix typo * Less copy-paste * All the docs! * Fix differences between CallRequest and TransactionRequest * Fix differences between CallRequest and TransactionRequest * Missing examples * Grumble fixes
This commit is contained in:
parent
b2ecf1c5a4
commit
ed09a76c91
@ -17,9 +17,9 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import chalk from 'chalk';
|
||||
import { isPlainObject } from 'lodash';
|
||||
|
||||
import { DUMMY } from '../src/jsonrpc/helpers';
|
||||
import { BlockNumber } from '../src/jsonrpc/types';
|
||||
import { Dummy } from '../src/jsonrpc/helpers';
|
||||
import interfaces from '../src/jsonrpc';
|
||||
|
||||
const ROOT_DIR = path.join(__dirname, '../docs');
|
||||
@ -28,10 +28,6 @@ if (!fs.existsSync(ROOT_DIR)) {
|
||||
fs.mkdirSync(ROOT_DIR);
|
||||
}
|
||||
|
||||
const type2print = new WeakMap();
|
||||
|
||||
type2print.set(BlockNumber, 'Quantity|Tag');
|
||||
|
||||
// INFO Logging helper
|
||||
function info (log) {
|
||||
console.log(chalk.blue(`INFO:\t${log}`));
|
||||
@ -48,24 +44,26 @@ function error (log) {
|
||||
}
|
||||
|
||||
function printType (type) {
|
||||
return type2print.get(type) || type.name;
|
||||
return type.print || `\`${type.name}\``;
|
||||
}
|
||||
|
||||
function formatDescription (obj, prefix = '', indent = '') {
|
||||
const optional = obj.optional ? '(optional) ' : '';
|
||||
const defaults = obj.default ? `(default: \`${obj.default}\`) ` : '';
|
||||
|
||||
return `${indent}${prefix}\`${printType(obj.type)}\` - ${optional}${defaults}${obj.desc}`;
|
||||
return `${indent}${prefix}${printType(obj.type)} - ${optional}${defaults}${obj.desc}`;
|
||||
}
|
||||
|
||||
function formatType (obj) {
|
||||
if (obj == null) {
|
||||
if (obj == null || obj.type == null) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
if (obj.type === Object && obj.details) {
|
||||
const sub = Object.keys(obj.details).map((key) => {
|
||||
return formatDescription(obj.details[key], `\`${key}\`: `, ' - ');
|
||||
const details = obj.details || obj.type.details;
|
||||
|
||||
if (details) {
|
||||
const sub = Object.keys(details).map((key) => {
|
||||
return formatDescription(details[key], `\`${key}\`: `, ' - ');
|
||||
}).join('\n');
|
||||
|
||||
return `${formatDescription(obj)}\n${sub}`;
|
||||
@ -83,18 +81,9 @@ const rpcReqTemplate = {
|
||||
jsonrpc: '2.0'
|
||||
};
|
||||
|
||||
// Checks if the value passed in is a DUMMY object placeholder for `{ ... }``
|
||||
function isDummy (val) {
|
||||
return val === DUMMY;
|
||||
}
|
||||
|
||||
const { isDummy } = Dummy;
|
||||
const { isArray } = Array;
|
||||
|
||||
// Checks if the value passed is a plain old JS object
|
||||
function isObject (val) {
|
||||
return val != null && val.constructor === Object;
|
||||
}
|
||||
|
||||
// Checks if a field definition has an example,
|
||||
// or describes an object with fields that recursively have examples of their own,
|
||||
// or is optional.
|
||||
@ -143,8 +132,8 @@ function getExample (obj) {
|
||||
function stringifyExample (example, dent = '') {
|
||||
const indent = `${dent} `;
|
||||
|
||||
if (example === DUMMY) {
|
||||
return '{ ... }';
|
||||
if (isDummy(example)) {
|
||||
return example.toString();
|
||||
}
|
||||
|
||||
if (isArray(example)) {
|
||||
@ -153,13 +142,13 @@ function stringifyExample (example, dent = '') {
|
||||
// If all elements are dummies, print out a single line.
|
||||
// Also covers empty arrays.
|
||||
if (example.every(isDummy)) {
|
||||
const dummies = example.map(_ => '{ ... }');
|
||||
const dummies = example.map(d => d.toString());
|
||||
|
||||
return `[${dummies.join(', ')}]`;
|
||||
}
|
||||
|
||||
// For arrays containing just one object or string, don't unwind the array to multiline
|
||||
if (last === 0 && (isObject(example[0]) || typeof example[0] === 'string')) {
|
||||
if (last === 0 && (isPlainObject(example[0]) || typeof example[0] === 'string')) {
|
||||
return `[${stringifyExample(example[0], dent)}]`;
|
||||
}
|
||||
|
||||
@ -173,7 +162,7 @@ function stringifyExample (example, dent = '') {
|
||||
return `[\n${indent}${elements.join(`\n${indent}`)}\n${dent}]`;
|
||||
}
|
||||
|
||||
if (isObject(example)) {
|
||||
if (isPlainObject(example)) {
|
||||
const keys = Object.keys(example);
|
||||
const last = keys.length - 1;
|
||||
|
||||
@ -193,7 +182,7 @@ function stringifyExample (example, dent = '') {
|
||||
return `{\n${indent}${elements.join(`\n${indent}`)}\n${dent}}`;
|
||||
}
|
||||
|
||||
return JSON.stringify(example); // .replace(/"\$DUMMY\$"/g, '{ ... }');
|
||||
return JSON.stringify(example);
|
||||
}
|
||||
|
||||
function buildExample (name, method) {
|
||||
@ -217,7 +206,7 @@ function buildExample (name, method) {
|
||||
|
||||
if (hasReqExample) {
|
||||
const params = getExample(method.params);
|
||||
const req = JSON.stringify(Object.assign({}, rpcReqTemplate, { method: name, params })).replace(/"\$DUMMY\$"/g, '{ ... }');
|
||||
const req = Dummy.stringifyJSON(Object.assign({}, rpcReqTemplate, { method: name, params }));
|
||||
|
||||
examples.push(`Request\n\`\`\`bash\ncurl --data '${req}' -H "Content-Type: application/json" -X POST localhost:8545\n\`\`\``);
|
||||
} else {
|
||||
@ -250,7 +239,7 @@ function buildParameters (params) {
|
||||
|
||||
let md = `0. ${params.map(formatType).join('\n0. ')}`;
|
||||
|
||||
if (params.length > 0 && params.every(hasExample) && params[0].example !== DUMMY) {
|
||||
if (params.length > 0 && params.every(hasExample) && !isDummy(params[0].example)) {
|
||||
const example = getExample(params);
|
||||
|
||||
md = `${md}\n\n\`\`\`js\nparams: ${stringifyExample(example)}\n\`\`\``;
|
||||
@ -292,7 +281,15 @@ Object.keys(interfaces).sort().forEach((group) => {
|
||||
const tocMain = [];
|
||||
const tocSections = {};
|
||||
|
||||
Object.keys(spec).sort().forEach((iname) => {
|
||||
// Comparator that will sort by sections first, names second
|
||||
function methodComparator (a, b) {
|
||||
const sectionA = spec[a].section || '';
|
||||
const sectionB = spec[b].section || '';
|
||||
|
||||
return sectionA.localeCompare(sectionB) || a.localeCompare(b);
|
||||
}
|
||||
|
||||
Object.keys(spec).sort(methodComparator).forEach((iname) => {
|
||||
const method = spec[iname];
|
||||
const name = `${group.replace(/_.*$/, '')}_${iname}`;
|
||||
|
||||
|
@ -76,6 +76,11 @@ export default class Parity {
|
||||
.execute('parity_dappsInterface');
|
||||
}
|
||||
|
||||
decryptMessage (address, data) {
|
||||
return this._transport
|
||||
.execute('parity_decryptMessage', inAddress(address), inHex(data));
|
||||
}
|
||||
|
||||
defaultExtraData () {
|
||||
return this._transport
|
||||
.execute('parity_defaultExtraData');
|
||||
@ -292,6 +297,11 @@ export default class Parity {
|
||||
.then(outAddress);
|
||||
}
|
||||
|
||||
postSign (address, hash) {
|
||||
return this._transport
|
||||
.execute('parity_postSign', inAddress(address), inHex(hash));
|
||||
}
|
||||
|
||||
postTransaction (options) {
|
||||
return this._transport
|
||||
.execute('parity_postTransaction', inOptions(options));
|
||||
|
@ -32,6 +32,11 @@ export default class Signer {
|
||||
.execute('signer_confirmRequestRaw', inNumber16(requestId), inData(data));
|
||||
}
|
||||
|
||||
confirmRequestWithToken (requestId, options, password) {
|
||||
return this._transport
|
||||
.execute('signer_confirmRequestWithToken', inNumber16(requestId), inOptions(options), password);
|
||||
}
|
||||
|
||||
generateAuthorizationToken () {
|
||||
return this._transport
|
||||
.execute('signer_generateAuthorizationToken');
|
||||
|
@ -14,8 +14,38 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// Placeholders for objects with undefined fields, will show up in docs as `{ ... }`
|
||||
export const DUMMY = '$DUMMY$';
|
||||
// A dummy placeholder object that will stringify literally to anything
|
||||
// in the example source.
|
||||
//
|
||||
// { {
|
||||
// foo: new Dummy('{ ... }') -------> "foo": { ... }
|
||||
// } {
|
||||
//
|
||||
export class Dummy {
|
||||
constructor (value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
toString () {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
toJSON () {
|
||||
return `##${this.value}##`;
|
||||
}
|
||||
|
||||
static fixJSON (json) {
|
||||
return json.replace(/"##([^#]+)##"/g, '$1');
|
||||
}
|
||||
|
||||
static isDummy (obj) {
|
||||
return obj instanceof Dummy;
|
||||
}
|
||||
|
||||
static stringifyJSON (any) {
|
||||
return Dummy.fixJSON(JSON.stringify(any));
|
||||
}
|
||||
}
|
||||
|
||||
// Enrich the API spec by additional markdown-formatted preamble
|
||||
export function withPreamble (preamble, spec) {
|
||||
|
@ -14,37 +14,104 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import interfaces from './';
|
||||
import { Address, BlockNumber, Data, Hash, Integer, Quantity } from './types';
|
||||
import * as customTypes from './types';
|
||||
|
||||
const flatlist = {};
|
||||
const allowedTypes = [Array, Boolean, Object, String].concat(Object.values(customTypes));
|
||||
|
||||
function verifyType (obj) {
|
||||
if (typeof obj !== 'string') {
|
||||
expect(obj).to.satisfy(() => {
|
||||
return obj.type === Array ||
|
||||
obj.type === Boolean ||
|
||||
obj.type === Object ||
|
||||
obj.type === String ||
|
||||
obj.type === Address ||
|
||||
obj.type === BlockNumber ||
|
||||
obj.type === Data ||
|
||||
obj.type === Hash ||
|
||||
obj.type === Integer ||
|
||||
obj.type === Quantity;
|
||||
});
|
||||
expect(obj).to.satisfy(() => allowedTypes.includes(obj.type));
|
||||
}
|
||||
}
|
||||
|
||||
// Get a list of JSON-RPC from Rust trait source code
|
||||
function parseMethodsFromRust (source) {
|
||||
// Matching the custom `rpc` attribute with it's doc comment
|
||||
const attributePattern = /((?:\s*\/\/\/.*$)*)\s*#\[rpc\(([^)]+)\)]/gm;
|
||||
const commentPattern = /\s*\/\/\/\s*/g;
|
||||
const separatorPattern = /\s*,\s*/g;
|
||||
const assignPattern = /([\S]+)\s*=\s*"([^"]*)"/;
|
||||
const ignorePattern = /@(ignore|deprecated|unimplemented|alias)\b/i;
|
||||
|
||||
const methods = [];
|
||||
|
||||
source.toString().replace(attributePattern, (match, comment, props) => {
|
||||
comment = comment.replace(commentPattern, '\n').trim();
|
||||
|
||||
// Skip deprecated methods
|
||||
if (ignorePattern.test(comment)) {
|
||||
return match;
|
||||
}
|
||||
|
||||
props.split(separatorPattern).forEach((prop) => {
|
||||
const [, key, value] = prop.split(assignPattern) || [];
|
||||
|
||||
if (key === 'name' && value != null) {
|
||||
methods.push(value);
|
||||
}
|
||||
});
|
||||
|
||||
return match;
|
||||
});
|
||||
|
||||
return methods;
|
||||
}
|
||||
|
||||
// Get a list of all JSON-RPC methods from all defined traits
|
||||
function getMethodsFromRustTraits () {
|
||||
const traitsDir = path.join(__dirname, '../../../rpc/src/v1/traits');
|
||||
|
||||
return fs.readdirSync(traitsDir)
|
||||
.filter((name) => name !== 'mod.rs' && /\.rs$/.test(name))
|
||||
.map((name) => fs.readFileSync(path.join(traitsDir, name)))
|
||||
.map(parseMethodsFromRust)
|
||||
.reduce((a, b) => a.concat(b));
|
||||
}
|
||||
|
||||
const rustMethods = {};
|
||||
|
||||
getMethodsFromRustTraits().sort().forEach((method) => {
|
||||
const [group, name] = method.split('_');
|
||||
|
||||
// Skip methods with malformed names
|
||||
if (group == null || name == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
rustMethods[group] = rustMethods[group] || {};
|
||||
rustMethods[group][name] = true;
|
||||
});
|
||||
|
||||
describe('jsonrpc/interfaces', () => {
|
||||
describe('Rust trait methods', () => {
|
||||
Object.keys(rustMethods).forEach((group) => {
|
||||
describe(group, () => {
|
||||
Object.keys(rustMethods[group]).forEach((name) => {
|
||||
describe(name, () => {
|
||||
it('has a defined JS interface', () => {
|
||||
expect(interfaces[group][name]).to.exist;
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Object.keys(interfaces).forEach((group) => {
|
||||
describe(group, () => {
|
||||
Object.keys(interfaces[group]).forEach((name) => {
|
||||
const method = interfaces[group][name];
|
||||
|
||||
flatlist[`${group}_${name}`] = true;
|
||||
|
||||
describe(name, () => {
|
||||
if (!method.nodoc) {
|
||||
it('is present in Rust codebase', () => {
|
||||
expect(rustMethods[group][name]).to.exist;
|
||||
});
|
||||
}
|
||||
|
||||
it('has the correct interface', () => {
|
||||
expect(method.desc).to.be.a('string');
|
||||
expect(method.params).to.be.an('array');
|
||||
|
@ -18,6 +18,7 @@ import { Data } from '../types';
|
||||
|
||||
export default {
|
||||
getHex: {
|
||||
nodoc: 'Not present in Rust code',
|
||||
desc: 'Returns binary data from the local database.',
|
||||
params: [
|
||||
{
|
||||
@ -37,6 +38,7 @@ export default {
|
||||
},
|
||||
|
||||
getString: {
|
||||
nodoc: 'Not present in Rust code',
|
||||
desc: 'Returns string from the local database.',
|
||||
params: [
|
||||
{
|
||||
@ -56,6 +58,7 @@ export default {
|
||||
},
|
||||
|
||||
putHex: {
|
||||
nodoc: 'Not present in Rust code',
|
||||
desc: 'Stores binary data in the local database.',
|
||||
params: [
|
||||
{
|
||||
@ -79,6 +82,7 @@ export default {
|
||||
},
|
||||
|
||||
putString: {
|
||||
nodoc: 'Not present in Rust code',
|
||||
desc: 'Stores a string in the local database.',
|
||||
params: [
|
||||
{
|
||||
|
@ -14,8 +14,8 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { Address, BlockNumber, Data, Hash, Quantity } from '../types';
|
||||
import { withPreamble, fromDecimal, withComment, DUMMY } from '../helpers';
|
||||
import { Address, BlockNumber, Data, Hash, Quantity, CallRequest, TransactionRequest } from '../types';
|
||||
import { withPreamble, fromDecimal, withComment, Dummy } from '../helpers';
|
||||
|
||||
export default withPreamble(`
|
||||
|
||||
@ -64,40 +64,9 @@ The following options are possible for the \`defaultBlock\` parameter:
|
||||
desc: 'Executes a new message call immediately without creating a transaction on the block chain.',
|
||||
params: [
|
||||
{
|
||||
type: Object,
|
||||
type: CallRequest,
|
||||
desc: 'The transaction call object.',
|
||||
format: 'inputCallFormatter',
|
||||
details: {
|
||||
from: {
|
||||
type: Address,
|
||||
desc: '20 Bytes - The address the transaction is send from.',
|
||||
optional: true
|
||||
},
|
||||
to: {
|
||||
type: Address,
|
||||
desc: '20 Bytes - The address the transaction is directed to.'
|
||||
},
|
||||
gas: {
|
||||
type: Quantity,
|
||||
desc: 'Integer of the gas provided for the transaction execution. eth_call consumes zero gas, but this parameter may be needed by some executions.',
|
||||
optional: true
|
||||
},
|
||||
gasPrice: {
|
||||
type: Quantity,
|
||||
desc: 'Integer of the gasPrice used for each paid gas.',
|
||||
optional: true
|
||||
},
|
||||
value: {
|
||||
type: Quantity,
|
||||
desc: 'Integer of the value sent with this transaction.',
|
||||
optional: true
|
||||
},
|
||||
data: {
|
||||
type: Data,
|
||||
desc: '4 byte hash of the method signature followed by encoded parameters. For details see [Ethereum Contract ABI](https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI).',
|
||||
optional: true
|
||||
}
|
||||
},
|
||||
example: {
|
||||
from: '0x407d73d8a49eeb85d32cf465507dd71d507100c1',
|
||||
to: '0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b',
|
||||
@ -180,10 +149,10 @@ The following options are possible for the \`defaultBlock\` parameter:
|
||||
desc: 'Makes a call or transaction, which won\'t be added to the blockchain and returns the used gas, which can be used for estimating the used gas.',
|
||||
params: [
|
||||
{
|
||||
type: Object,
|
||||
desc: 'See [eth_call](#eth_call) parameters, expect that all properties are optional.',
|
||||
type: CallRequest,
|
||||
desc: 'Same as [eth_call](#eth_call) parameters, except that all properties are optional.',
|
||||
format: 'inputCallFormatter',
|
||||
example: DUMMY // will be replaced with { ... } by the generator
|
||||
example: new Dummy('{ ... }')
|
||||
},
|
||||
{
|
||||
type: BlockNumber,
|
||||
@ -368,7 +337,7 @@ The following options are possible for the \`defaultBlock\` parameter:
|
||||
minGasPrice: fromDecimal(653145),
|
||||
gasUsed: fromDecimal(653145),
|
||||
timestamp: fromDecimal(1424182926),
|
||||
transactions: [DUMMY, DUMMY], // will be replaced with [{ ... }, { ... }] by the generator
|
||||
transactions: [new Dummy('{ ... }, { ... }, ...')],
|
||||
uncles: ['0x1606e5...', '0xd5145a9...']
|
||||
}
|
||||
}
|
||||
@ -479,7 +448,7 @@ The following options are possible for the \`defaultBlock\` parameter:
|
||||
data: '0x0000000000000000000000000000000000000000000000000000000000000000',
|
||||
topics: ['0x59ebeb90bc63057b6515673c3ecf9438e5058bca0f92585014eced636878c9a5']
|
||||
},
|
||||
DUMMY // will be replaced with { ... } by the generator
|
||||
new Dummy('...')
|
||||
]
|
||||
}
|
||||
},
|
||||
@ -762,10 +731,7 @@ The following options are possible for the \`defaultBlock\` parameter:
|
||||
cumulativeGasUsed: fromDecimal(13244),
|
||||
gasUsed: fromDecimal(1244),
|
||||
contractAddress: withComment('0xb60e8dd61c5d32be8058bb8eb970870f07233155', 'or null, if none was created'),
|
||||
logs: withComment(
|
||||
[DUMMY, DUMMY], // will be replaced with [{ ... }, { ... }] by the generator
|
||||
'logs as returned by eth_getFilterLogs, etc.'
|
||||
)
|
||||
logs: withComment([new Dummy('{ ... }, { ... }, ...]')], 'logs as returned by eth_getFilterLogs, etc.')
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -1040,45 +1006,9 @@ The following options are possible for the \`defaultBlock\` parameter:
|
||||
desc: 'Creates new message call transaction or a contract creation, if the data field contains code.',
|
||||
params: [
|
||||
{
|
||||
type: Object,
|
||||
type: TransactionRequest,
|
||||
desc: 'The transaction object.',
|
||||
format: 'inputTransactionFormatter',
|
||||
details: {
|
||||
from: {
|
||||
type: Address,
|
||||
desc: '20 Bytes - The address the transaction is send from.'
|
||||
},
|
||||
to: {
|
||||
type: Address,
|
||||
desc: '20 Bytes - (optional when creating new contract) The address the transaction is directed to.'
|
||||
},
|
||||
gas: {
|
||||
type: Quantity,
|
||||
desc: 'Integer of the gas provided for the transaction execution. It will return unused gas.',
|
||||
optional: true,
|
||||
default: 90000
|
||||
},
|
||||
gasPrice: {
|
||||
type: Quantity,
|
||||
desc: 'Integer of the gasPrice used for each paid gas.',
|
||||
optional: true,
|
||||
default: 'To-Be-Determined'
|
||||
},
|
||||
value: {
|
||||
type: Quantity,
|
||||
desc: 'Integer of the value sent with this transaction.',
|
||||
optional: true
|
||||
},
|
||||
data: {
|
||||
type: Data,
|
||||
desc: 'The compiled code of a contract OR the hash of the invoked method signature and encoded parameters. For details see [Ethereum Contract ABI](https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI)'
|
||||
},
|
||||
nonce: {
|
||||
type: Quantity,
|
||||
desc: 'Integer of a nonce. This allows to overwrite your own pending transactions that use the same nonce.',
|
||||
optional: true
|
||||
}
|
||||
},
|
||||
example: {
|
||||
from: '0xb60e8dd61c5d32be8058bb8eb970870f07233155',
|
||||
to: '0xd46e8dd67c5d32be8058bb8eb970870f072445675',
|
||||
@ -1122,10 +1052,10 @@ The following options are possible for the \`defaultBlock\` parameter:
|
||||
desc: 'Signs transactions without dispatching it to the network. It can be later submitted using [eth_sendRawTransaction](#eth_sendrawtransaction).',
|
||||
params: [
|
||||
{
|
||||
type: Object,
|
||||
desc: 'see [eth_sendTransaction](#eth_sendTransaction).',
|
||||
type: TransactionRequest,
|
||||
desc: 'Transaction object, see [eth_sendTransaction](#eth_sendTransaction).',
|
||||
format: 'inputCallFormatter',
|
||||
example: DUMMY // will be replaced with { ... } by the generator
|
||||
example: new Dummy('{ ... }')
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
|
@ -14,8 +14,8 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { Address, Data, Hash, Quantity, BlockNumber } from '../types';
|
||||
import { fromDecimal, withComment, DUMMY } from '../helpers';
|
||||
import { Address, Data, Hash, Quantity, BlockNumber, TransactionRequest } from '../types';
|
||||
import { fromDecimal, withComment, Dummy } from '../helpers';
|
||||
|
||||
const SECTION_MINING = 'Block Authoring (aka "mining")';
|
||||
const SECTION_DEV = 'Development';
|
||||
@ -23,6 +23,9 @@ const SECTION_NODE = 'Node Settings';
|
||||
const SECTION_NET = 'Network Information';
|
||||
const SECTION_ACCOUNTS = 'Accounts (read-only) and Signatures';
|
||||
|
||||
const SUBDOC_SET = 'set';
|
||||
const SUBDOC_ACCOUNTS = 'accounts';
|
||||
|
||||
const transactionDetails = {
|
||||
hash: {
|
||||
type: Hash,
|
||||
@ -332,7 +335,7 @@ export default {
|
||||
transactionIndex: null
|
||||
}
|
||||
},
|
||||
'0x...': DUMMY
|
||||
'0x...': new Dummy('{ ... }')
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -400,7 +403,7 @@ export default {
|
||||
active: 0,
|
||||
connected: 25,
|
||||
max: 25,
|
||||
peers: [DUMMY, DUMMY, DUMMY, DUMMY]
|
||||
peers: [new Dummy('{ ... }, { ... }, { ... }, ...')]
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -475,8 +478,8 @@ export default {
|
||||
v: '0x26',
|
||||
value: '0x0'
|
||||
},
|
||||
DUMMY,
|
||||
DUMMY
|
||||
new Dummy('{ ... }'),
|
||||
new Dummy('{ ... }')
|
||||
]
|
||||
}
|
||||
},
|
||||
@ -769,8 +772,7 @@ export default {
|
||||
s: '0x6bf770ab08119e67dc29817e1412a0e3086f43da308c314db1b3bca9fb6d32bd',
|
||||
minBlock: null
|
||||
},
|
||||
DUMMY,
|
||||
DUMMY
|
||||
new Dummy('{ ... }, { ... }, ...')
|
||||
]
|
||||
}
|
||||
},
|
||||
@ -780,7 +782,7 @@ export default {
|
||||
* ================================
|
||||
*/
|
||||
allAccountsInfo: {
|
||||
subdoc: 'accounts',
|
||||
subdoc: SUBDOC_ACCOUNTS,
|
||||
desc: 'returns a map of accounts as an object.',
|
||||
params: [],
|
||||
returns: {
|
||||
@ -811,7 +813,7 @@ export default {
|
||||
},
|
||||
|
||||
newAccountFromPhrase: {
|
||||
subdoc: 'accounts',
|
||||
subdoc: SUBDOC_ACCOUNTS,
|
||||
desc: 'Creates a new account from a recovery phrase.',
|
||||
params: [
|
||||
{
|
||||
@ -833,7 +835,7 @@ export default {
|
||||
},
|
||||
|
||||
newAccountFromSecret: {
|
||||
subdoc: 'accounts',
|
||||
subdoc: SUBDOC_ACCOUNTS,
|
||||
desc: 'Creates a new account from a private ethstore secret key.',
|
||||
params: [
|
||||
{
|
||||
@ -855,26 +857,29 @@ export default {
|
||||
},
|
||||
|
||||
newAccountFromWallet: {
|
||||
subdoc: 'accounts',
|
||||
subdoc: SUBDOC_ACCOUNTS,
|
||||
desc: 'Creates a new account from a JSON import',
|
||||
params: [
|
||||
{
|
||||
type: String,
|
||||
desc: 'JSON'
|
||||
desc: 'Wallet JSON encoded to a string.',
|
||||
example: '{"id": "9c62e86b-3cf9...", ...}'
|
||||
},
|
||||
{
|
||||
type: String,
|
||||
desc: 'Password'
|
||||
desc: 'Password.',
|
||||
example: 'hunter2'
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: Address,
|
||||
desc: 'The created address'
|
||||
desc: 'The created address',
|
||||
example: '0x407d73d8a49eeb85d32cf465507dd71d507100c1'
|
||||
}
|
||||
},
|
||||
|
||||
setAccountName: {
|
||||
subdoc: 'accounts',
|
||||
subdoc: SUBDOC_ACCOUNTS,
|
||||
desc: 'Sets a name for the account',
|
||||
params: [
|
||||
{
|
||||
@ -896,7 +901,7 @@ export default {
|
||||
},
|
||||
|
||||
setAccountMeta: {
|
||||
subdoc: 'accounts',
|
||||
subdoc: SUBDOC_ACCOUNTS,
|
||||
desc: 'Sets metadata for the account',
|
||||
params: [
|
||||
{
|
||||
@ -918,7 +923,7 @@ export default {
|
||||
},
|
||||
|
||||
testPassword: {
|
||||
subdoc: 'accounts',
|
||||
subdoc: SUBDOC_ACCOUNTS,
|
||||
desc: 'Checks if a given password can unlock a given account, without actually unlocking it.',
|
||||
params: [
|
||||
{
|
||||
@ -940,7 +945,7 @@ export default {
|
||||
},
|
||||
|
||||
changePassword: {
|
||||
subdoc: 'accounts',
|
||||
subdoc: SUBDOC_ACCOUNTS,
|
||||
desc: 'Change the password for a given account.',
|
||||
params: [
|
||||
{
|
||||
@ -967,7 +972,7 @@ export default {
|
||||
},
|
||||
|
||||
killAccount: {
|
||||
subdoc: 'accounts',
|
||||
subdoc: SUBDOC_ACCOUNTS,
|
||||
desc: 'Deletes an account.',
|
||||
params: [
|
||||
{
|
||||
@ -989,7 +994,7 @@ export default {
|
||||
},
|
||||
|
||||
removeAddress: {
|
||||
subdoc: 'accounts',
|
||||
subdoc: SUBDOC_ACCOUNTS,
|
||||
desc: 'Removes an address from the addressbook.',
|
||||
params: [
|
||||
{
|
||||
@ -1006,7 +1011,7 @@ export default {
|
||||
},
|
||||
|
||||
setDappsAddresses: {
|
||||
subdoc: 'accounts',
|
||||
subdoc: SUBDOC_ACCOUNTS,
|
||||
desc: 'Sets the available addresses for a dapp.',
|
||||
params: [
|
||||
{
|
||||
@ -1028,7 +1033,7 @@ export default {
|
||||
},
|
||||
|
||||
getDappsAddresses: {
|
||||
subdoc: 'accounts',
|
||||
subdoc: SUBDOC_ACCOUNTS,
|
||||
desc: 'Returns the list of accounts available to a specific dapp.',
|
||||
params: [
|
||||
{
|
||||
@ -1045,7 +1050,7 @@ export default {
|
||||
},
|
||||
|
||||
setNewDappsWhitelist: {
|
||||
subdoc: 'accounts',
|
||||
subdoc: SUBDOC_ACCOUNTS,
|
||||
desc: 'Sets the list of accounts available to new dapps.',
|
||||
params: [
|
||||
{
|
||||
@ -1062,7 +1067,7 @@ export default {
|
||||
},
|
||||
|
||||
getNewDappsWhitelist: {
|
||||
subdoc: 'accounts',
|
||||
subdoc: SUBDOC_ACCOUNTS,
|
||||
desc: 'Returns the list of accounts available to a new dapps.',
|
||||
params: [],
|
||||
returns: {
|
||||
@ -1073,7 +1078,7 @@ export default {
|
||||
},
|
||||
|
||||
listRecentDapps: {
|
||||
subdoc: 'accounts',
|
||||
subdoc: SUBDOC_ACCOUNTS,
|
||||
desc: 'Returns a list of the most recent active dapps.',
|
||||
params: [],
|
||||
returns: {
|
||||
@ -1084,7 +1089,7 @@ export default {
|
||||
},
|
||||
|
||||
importGethAccounts: {
|
||||
subdoc: 'accounts',
|
||||
subdoc: SUBDOC_ACCOUNTS,
|
||||
desc: 'Imports a list of accounts from Geth.',
|
||||
params: [
|
||||
{
|
||||
@ -1099,7 +1104,7 @@ export default {
|
||||
},
|
||||
|
||||
listGethAccounts: {
|
||||
subdoc: 'accounts',
|
||||
subdoc: SUBDOC_ACCOUNTS,
|
||||
desc: 'Returns a list of the accounts available from Geth.',
|
||||
params: [],
|
||||
returns: {
|
||||
@ -1113,7 +1118,7 @@ export default {
|
||||
* ===========================
|
||||
*/
|
||||
setMinGasPrice: {
|
||||
subdoc: 'set',
|
||||
subdoc: SUBDOC_SET,
|
||||
desc: 'Changes minimal gas price for transaction to be accepted to the queue.',
|
||||
params: [
|
||||
{
|
||||
@ -1131,7 +1136,7 @@ export default {
|
||||
},
|
||||
|
||||
setGasFloorTarget: {
|
||||
subdoc: 'set',
|
||||
subdoc: SUBDOC_SET,
|
||||
desc: 'Sets a new gas floor target for mined blocks..',
|
||||
params: [
|
||||
{
|
||||
@ -1149,7 +1154,7 @@ export default {
|
||||
},
|
||||
|
||||
setGasCeilTarget: {
|
||||
subdoc: 'set',
|
||||
subdoc: SUBDOC_SET,
|
||||
desc: 'Sets new gas ceiling target for mined blocks.',
|
||||
params: [
|
||||
{
|
||||
@ -1167,7 +1172,7 @@ export default {
|
||||
},
|
||||
|
||||
setExtraData: {
|
||||
subdoc: 'set',
|
||||
subdoc: SUBDOC_SET,
|
||||
desc: 'Changes extra data for newly mined blocks',
|
||||
params: [
|
||||
{
|
||||
@ -1185,7 +1190,7 @@ export default {
|
||||
},
|
||||
|
||||
setAuthor: {
|
||||
subdoc: 'set',
|
||||
subdoc: SUBDOC_SET,
|
||||
desc: 'Changes author (coinbase) for mined blocks.',
|
||||
params: [
|
||||
{
|
||||
@ -1203,7 +1208,7 @@ export default {
|
||||
},
|
||||
|
||||
setMaxTransactionGas: {
|
||||
subdoc: 'set',
|
||||
subdoc: SUBDOC_SET,
|
||||
desc: 'Sets the maximum amount of gas a single transaction may consume.',
|
||||
params: [
|
||||
{
|
||||
@ -1221,7 +1226,7 @@ export default {
|
||||
},
|
||||
|
||||
setTransactionsLimit: {
|
||||
subdoc: 'set',
|
||||
subdoc: SUBDOC_SET,
|
||||
desc: 'Changes limit for transactions in queue.',
|
||||
params: [
|
||||
{
|
||||
@ -1239,7 +1244,7 @@ export default {
|
||||
},
|
||||
|
||||
addReservedPeer: {
|
||||
subdoc: 'set',
|
||||
subdoc: SUBDOC_SET,
|
||||
desc: 'Add a reserved peer.',
|
||||
params: [
|
||||
{
|
||||
@ -1256,7 +1261,7 @@ export default {
|
||||
},
|
||||
|
||||
removeReservedPeer: {
|
||||
subdoc: 'set',
|
||||
subdoc: SUBDOC_SET,
|
||||
desc: 'Remove a reserved peer.',
|
||||
params: [
|
||||
{
|
||||
@ -1273,7 +1278,7 @@ export default {
|
||||
},
|
||||
|
||||
dropNonReservedPeers: {
|
||||
subdoc: 'set',
|
||||
subdoc: SUBDOC_SET,
|
||||
desc: 'Set Parity to drop all non-reserved peers. To restore default behavior call [parity_acceptNonReservedPeers](#parity_acceptnonreservedpeers).',
|
||||
params: [],
|
||||
returns: {
|
||||
@ -1284,7 +1289,7 @@ export default {
|
||||
},
|
||||
|
||||
acceptNonReservedPeers: {
|
||||
subdoc: 'set',
|
||||
subdoc: SUBDOC_SET,
|
||||
desc: 'Set Parity to accept non-reserved peers (default behavior).',
|
||||
params: [],
|
||||
returns: {
|
||||
@ -1295,7 +1300,7 @@ export default {
|
||||
},
|
||||
|
||||
hashContent: {
|
||||
subdoc: 'set',
|
||||
subdoc: SUBDOC_SET,
|
||||
desc: 'Creates a hash of a file at a given URL.',
|
||||
params: [
|
||||
{
|
||||
@ -1312,7 +1317,7 @@ export default {
|
||||
},
|
||||
|
||||
setMode: {
|
||||
subdoc: 'set',
|
||||
subdoc: SUBDOC_SET,
|
||||
desc: 'Changes the operating mode of Parity.',
|
||||
params: [
|
||||
{
|
||||
@ -1329,7 +1334,7 @@ export default {
|
||||
},
|
||||
|
||||
setEngineSigner: {
|
||||
subdoc: 'set',
|
||||
subdoc: SUBDOC_SET,
|
||||
desc: 'Sets an authority account for signing consensus messages. For more information check the [[Proof of Authority Chains]] page.',
|
||||
params: [
|
||||
{
|
||||
@ -1351,7 +1356,7 @@ export default {
|
||||
},
|
||||
|
||||
upgradeReady: {
|
||||
subdoc: 'set',
|
||||
subdoc: SUBDOC_SET,
|
||||
desc: 'Returns a ReleaseInfo object describing the release which is available for upgrade or `null` if none is available.',
|
||||
params: [],
|
||||
returns: {
|
||||
@ -1381,7 +1386,7 @@ export default {
|
||||
},
|
||||
|
||||
executeUpgrade: {
|
||||
subdoc: 'set',
|
||||
subdoc: SUBDOC_SET,
|
||||
desc: 'Attempts to upgrade Parity to the version specified in [parity_upgradeReady](#parity_upgradeready).',
|
||||
params: [],
|
||||
returns: {
|
||||
@ -1389,5 +1394,92 @@ export default {
|
||||
desc: 'returns `true` if the upgrade to the new release was successfully executed, `false` if not.',
|
||||
example: true
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
* `parity_signing` trait methods (rolled into `parity` module)
|
||||
* ============================================================
|
||||
*/
|
||||
postSign: {
|
||||
section: SECTION_ACCOUNTS,
|
||||
desc: 'Request an arbitrary transaction to be signed by an account.',
|
||||
params: [
|
||||
{
|
||||
type: Address,
|
||||
desc: 'Account address.',
|
||||
example: '0xb60e8dd61c5d32be8058bb8eb970870f07233155'
|
||||
},
|
||||
{
|
||||
type: Hash,
|
||||
desc: 'Transaction hash.',
|
||||
example: '0x8cda01991ae267a539135736132f1f987e76868ce0269b7537d3aab37b7b185e'
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: Quantity,
|
||||
desc: 'The id of the request to the signer. If the account was already unlocked, returns `Hash` of the transaction instead.',
|
||||
example: '0x1'
|
||||
}
|
||||
},
|
||||
|
||||
postTransaction: {
|
||||
section: SECTION_ACCOUNTS,
|
||||
desc: 'Posts a transaction to the signer without waiting for the signer response.',
|
||||
params: [
|
||||
{
|
||||
type: TransactionRequest,
|
||||
desc: 'see [`eth_sendTransaction`](JSONRPC-eth-module#eth_sendtransaction).',
|
||||
format: 'inputCallFormatter',
|
||||
example: {
|
||||
from: '0xb60e8dd61c5d32be8058bb8eb970870f07233155',
|
||||
to: '0xd46e8dd67c5d32be8058bb8eb970870f072445675',
|
||||
value: fromDecimal(2441406250)
|
||||
}
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: Quantity,
|
||||
desc: 'The id of the request to the signer. If the account was already unlocked, returns `Hash` of the transaction instead.',
|
||||
format: 'utils.toDecimal',
|
||||
example: '0x1'
|
||||
}
|
||||
},
|
||||
|
||||
checkRequest: {
|
||||
section: SECTION_ACCOUNTS,
|
||||
desc: 'Get the the transaction hash of the request previously posted to [`parity_postTransaction`](#parity_posttransaction) or [`parity_postSign`](#parity_postsign). Will return a JSON-RPC error if the request was rejected.',
|
||||
params: [
|
||||
{
|
||||
type: Quantity,
|
||||
desc: 'The id of the request sent to the signer.',
|
||||
example: '0x1'
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: Hash,
|
||||
desc: '32 Bytes - the transaction hash or `null` if the request hasn\'t been signed yet.',
|
||||
example: '0xde8dfd9642f7eeef12402f2a560dbf40921b4f0bda01fb84709b9d71f6c181be'
|
||||
}
|
||||
},
|
||||
|
||||
decryptMessage: {
|
||||
desc: 'Decrypt a message encrypted with a ECIES public key.',
|
||||
params: [
|
||||
{
|
||||
type: Address,
|
||||
desc: 'Account which can decrypt the message.',
|
||||
example: '0x00a329c0648769a73afac7f9381e08fb43dbea72'
|
||||
},
|
||||
{
|
||||
type: Data,
|
||||
desc: 'Encrypted message.',
|
||||
example: '0x0405afee7fa2ab3e48c27b00d543389270cb7267fc191ca1311f297255a83cbe8d77a4ba135b51560700a582924fa86d2b19029fcb50d2b68d60a7df1ba81df317a19c8def117f2b9cf8c2618be0e3f146a5272fb9e5528719d2d7a1bd91fa620901cffa756305c79c093e7af30fa3c1587029421351c34a7c1e5a2b'
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: Data,
|
||||
desc: 'Decrypted message.',
|
||||
example: withComment('0x68656c6c6f20776f726c64', 'hello world')
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -14,7 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { Address, Data, Quantity } from '../types';
|
||||
import { Address, Data, Quantity, TransactionRequest } from '../types';
|
||||
|
||||
export default {
|
||||
listAccounts: {
|
||||
@ -50,44 +50,8 @@ export default {
|
||||
desc: 'Sends transaction and signs it in a single call. The account does not need to be unlocked to make this call, and will not be left unlocked after.',
|
||||
params: [
|
||||
{
|
||||
type: Object,
|
||||
type: TransactionRequest,
|
||||
desc: 'The transaction object',
|
||||
details: {
|
||||
from: {
|
||||
type: Address,
|
||||
desc: '20 Bytes - The address of the account to unlock and send the transaction from.'
|
||||
},
|
||||
to: {
|
||||
type: Address,
|
||||
desc: '20 Bytes - (optional when creating new contract) The address the transaction is directed to.'
|
||||
},
|
||||
gas: {
|
||||
type: Quantity,
|
||||
desc: 'Integer of the gas provided for the transaction execution. It will return unused gas.',
|
||||
optional: true,
|
||||
default: 90000
|
||||
},
|
||||
gasPrice: {
|
||||
type: Quantity,
|
||||
desc: 'Integer of the gasPrice used for each paid gas.',
|
||||
optional: true,
|
||||
default: 'To-Be-Determined'
|
||||
},
|
||||
value: {
|
||||
type: Quantity,
|
||||
desc: 'Integer of the value send with this transaction.',
|
||||
optional: true
|
||||
},
|
||||
data: {
|
||||
type: Data,
|
||||
desc: 'The compiled code of a contract OR the hash of the invoked method signature and encoded parameters. For details see [Ethereum Contract ABI](https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI).'
|
||||
},
|
||||
nonce: {
|
||||
type: Quantity,
|
||||
desc: 'Integer of a nonce. This allows to overwrite your own pending transactions that use the same nonce.',
|
||||
optional: true
|
||||
}
|
||||
},
|
||||
example: {
|
||||
from: '0x407d73d8a49eeb85d32cf465507dd71d507100c1',
|
||||
to: '0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b',
|
||||
|
@ -18,6 +18,7 @@ import { Data, Quantity } from '../types';
|
||||
|
||||
export default {
|
||||
version: {
|
||||
nodoc: 'Not present in Rust code',
|
||||
desc: 'Returns the current whisper protocol version.',
|
||||
params: [],
|
||||
returns: {
|
||||
@ -27,6 +28,7 @@ export default {
|
||||
},
|
||||
|
||||
post: {
|
||||
nodoc: 'Not present in Rust code',
|
||||
desc: 'Sends a whisper message.',
|
||||
params: [
|
||||
{
|
||||
@ -62,6 +64,7 @@ export default {
|
||||
},
|
||||
|
||||
newIdentity: {
|
||||
nodoc: 'Not present in Rust code',
|
||||
desc: 'Creates new whisper identity in the client.',
|
||||
params: [],
|
||||
returns: {
|
||||
@ -71,6 +74,7 @@ export default {
|
||||
},
|
||||
|
||||
hasIdentity: {
|
||||
nodoc: 'Not present in Rust code',
|
||||
desc: 'Checks if the client hold the private keys for a given identity.',
|
||||
params: [
|
||||
{
|
||||
@ -85,6 +89,7 @@ export default {
|
||||
},
|
||||
|
||||
newGroup: {
|
||||
nodoc: 'Not present in Rust code',
|
||||
desc: '(?)',
|
||||
params: [],
|
||||
returns: {
|
||||
@ -93,6 +98,7 @@ export default {
|
||||
},
|
||||
|
||||
addToGroup: {
|
||||
nodoc: 'Not present in Rust code',
|
||||
desc: '(?)',
|
||||
params: [
|
||||
{
|
||||
@ -107,6 +113,7 @@ export default {
|
||||
},
|
||||
|
||||
newFilter: {
|
||||
nodoc: 'Not present in Rust code',
|
||||
desc: 'Creates filter to notify, when client receives whisper message matching the filter options.',
|
||||
params: [
|
||||
{
|
||||
@ -129,6 +136,7 @@ export default {
|
||||
},
|
||||
|
||||
uninstallFilter: {
|
||||
nodoc: 'Not present in Rust code',
|
||||
desc: 'Uninstalls a filter with given id. Should always be called when watch is no longer needed.\nAdditonally Filters timeout when they aren\'t requested with [shh_getFilterChanges](#shh_getfilterchanges) for a period of time.',
|
||||
params: [
|
||||
{
|
||||
@ -143,6 +151,7 @@ export default {
|
||||
},
|
||||
|
||||
getFilterChanges: {
|
||||
nodoc: 'Not present in Rust code',
|
||||
desc: 'Polling method for whisper filters. Returns new messages since the last call of this method.\n**Note** calling the [shh_getMessages](#shh_getmessages) method, will reset the buffer for this method, so that you won\'t receive duplicate messages.',
|
||||
params: [
|
||||
{
|
||||
@ -157,6 +166,7 @@ export default {
|
||||
},
|
||||
|
||||
getMessages: {
|
||||
nodoc: 'Not present in Rust code',
|
||||
desc: 'Get all messages matching a filter. Unlike `shh_getFilterChanges` this returns all messages.',
|
||||
params: [
|
||||
{
|
||||
|
@ -15,7 +15,7 @@
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { Quantity, Data, BlockNumber } from '../types';
|
||||
import { fromDecimal } from '../helpers';
|
||||
import { fromDecimal, Dummy } from '../helpers';
|
||||
|
||||
export default {
|
||||
generateAuthorizationToken: {
|
||||
@ -45,7 +45,7 @@ export default {
|
||||
// TODO: Types of the fields of transaction objects? Link to a transaction object in another page?
|
||||
type: Array,
|
||||
desc: 'A list of the outstanding transactions.',
|
||||
example: []
|
||||
example: new Dummy('[ ... ]')
|
||||
}
|
||||
},
|
||||
|
||||
@ -86,9 +86,9 @@ export default {
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: Boolean,
|
||||
desc: 'The status of the confirmation',
|
||||
example: true
|
||||
type: Object,
|
||||
desc: 'The status of the confirmation, depending on the request type.',
|
||||
example: {}
|
||||
}
|
||||
},
|
||||
|
||||
@ -107,9 +107,65 @@ export default {
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: Boolean,
|
||||
desc: 'The status of the confirmation',
|
||||
example: true
|
||||
type: Object,
|
||||
desc: 'The status of the confirmation, depending on the request type.',
|
||||
example: {}
|
||||
}
|
||||
},
|
||||
|
||||
confirmRequestWithToken: {
|
||||
desc: 'Confirm specific request with token.',
|
||||
params: [
|
||||
{
|
||||
type: Quantity,
|
||||
desc: 'The request id.',
|
||||
example: fromDecimal(1)
|
||||
},
|
||||
{
|
||||
type: Object,
|
||||
desc: 'Modify the transaction before confirmation.',
|
||||
details: {
|
||||
gasPrice: {
|
||||
type: Quantity,
|
||||
desc: 'Modify the gas price provided by the sender in Wei.',
|
||||
optional: true
|
||||
},
|
||||
gas: {
|
||||
type: Quantity,
|
||||
desc: 'Gas provided by the sender in Wei.',
|
||||
optional: true
|
||||
},
|
||||
minBlock: {
|
||||
type: BlockNumber,
|
||||
desc: 'Integer block number, or the string `\'latest\'`, `\'earliest\'` or `\'pending\'`. Request will not be propagated till the given block is reached.',
|
||||
optional: true
|
||||
}
|
||||
},
|
||||
example: {}
|
||||
},
|
||||
{
|
||||
type: String,
|
||||
desc: 'Password.',
|
||||
example: 'hunter2'
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: Object,
|
||||
desc: 'Status.',
|
||||
details: {
|
||||
result: {
|
||||
type: Object,
|
||||
desc: 'The status of the confirmation, depending on the request type.'
|
||||
},
|
||||
token: {
|
||||
type: String,
|
||||
desc: 'Token used to authenticate the request.'
|
||||
}
|
||||
},
|
||||
example: {
|
||||
result: new Dummy('{ ... }'),
|
||||
token: 'cAF2w5LE7XUZ3v3N'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@ -130,6 +186,7 @@ export default {
|
||||
},
|
||||
|
||||
signerEnabled: {
|
||||
nodoc: 'Not present in Rust code',
|
||||
desc: 'Returns whether signer is enabled/disabled.',
|
||||
params: [],
|
||||
returns: {
|
||||
|
@ -14,124 +14,363 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { BlockNumber, Data, Hash, Integer } from '../types';
|
||||
import { Address, BlockNumber, Data, Hash, CallRequest } from '../types';
|
||||
import { withPreamble, Dummy, fromDecimal } from '../helpers';
|
||||
|
||||
export default {
|
||||
const SECTION_FILTERING = 'Transaction-Trace Filtering';
|
||||
const SECTION_ADHOC = 'Ad-hoc Tracing';
|
||||
|
||||
export default withPreamble(`
|
||||
|
||||
The trace module is for getting a deeper insight into transaction processing.
|
||||
It includes two sets of calls; the transaction trace filtering API and the ad-hoc tracing API.
|
||||
|
||||
**Note:** In order to use these API Parity must be fully synced with flags \`$ parity --tracing on\`.
|
||||
|
||||
## The Ad-hoc Tracing API
|
||||
|
||||
The ad-hoc tracing API allows you to perform a number of different diagnostics on calls or transactions,
|
||||
either historical ones from the chain or hypothetical ones not yet mined. The diagnostics include:
|
||||
|
||||
- \`trace\` **Transaction trace**. An equivalent trace to that in the previous section.
|
||||
- \`vmTrace\` **Virtual Machine execution trace**. Provides a full trace of the VM's state throughout the execution of the transaction, including for any subcalls.
|
||||
- \`stateDiff\` **State difference**. Provides information detailing all altered portions of the Ethereum state made due to the execution of the transaction.
|
||||
|
||||
There are three means of providing a transaction to execute; either providing the same information as when making
|
||||
a call using \`eth_call\` (see \`trace_call\`), through providing raw, signed, transaction data as when using
|
||||
\`eth_sendRawTransaction\` (see \`trace_rawTransaction\`) or simply a transaction hash for a previously mined
|
||||
transaction (see \`trace_replayTransaction\`). In the latter case, your node must be in archive mode or the
|
||||
transaction should be within the most recent 1000 blocks.
|
||||
|
||||
## The Transaction-Trace Filtering API
|
||||
|
||||
These APIs allow you to get a full *externality* trace on any transaction executed throughout the Parity chain.
|
||||
Unlike the log filtering API, you are able to search and filter based only upon address information.
|
||||
Information returned includes the execution of all \`CREATE\`s, \`SUICIDE\`s and all variants of \`CALL\` together
|
||||
with input data, output data, gas usage, amount transferred and the success status of each individual action.
|
||||
|
||||
### \`traceAddress\` field
|
||||
|
||||
The \`traceAddress\` field of all returned traces, gives the exact location in the call trace [index in root,
|
||||
index in first \`CALL\`, index in second \`CALL\`, ...].
|
||||
|
||||
i.e. if the trace is:
|
||||
\`\`\`
|
||||
A
|
||||
CALLs B
|
||||
CALLs G
|
||||
CALLs C
|
||||
CALLs G
|
||||
\`\`\`
|
||||
then it should look something like:
|
||||
|
||||
\`[ {A: []}, {B: [0]}, {G: [0, 0]}, {C: [1]}, {G: [1, 0]} ]\`
|
||||
|
||||
`, {
|
||||
block: {
|
||||
desc: 'Returns traces created at given block',
|
||||
section: SECTION_FILTERING,
|
||||
desc: 'Returns traces created at given block.',
|
||||
params: [
|
||||
{
|
||||
type: BlockNumber,
|
||||
desc: 'Integer block number, or \'latest\' for the last mined block or \'pending\', \'earliest\' for not yet mined transactions'
|
||||
desc: 'Integer of a block number, or the string `\'earliest\'`, `\'latest\'` or `\'pending\'`.',
|
||||
example: fromDecimal(3068185)
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: Array,
|
||||
desc: 'Block traces'
|
||||
}
|
||||
},
|
||||
|
||||
call: {
|
||||
desc: 'Returns traces for a specific call',
|
||||
params: [
|
||||
desc: 'Block traces.',
|
||||
example: [
|
||||
{
|
||||
type: Object,
|
||||
desc: 'Call options'
|
||||
action: {
|
||||
callType: 'call',
|
||||
from: '0xaa7b131dc60b80d3cf5e59b5a21a666aa039c951',
|
||||
gas: '0x0',
|
||||
input: '0x',
|
||||
to: '0xd40aba8166a212d6892125f079c33e6f5ca19814',
|
||||
value: '0x4768d7effc3fbe'
|
||||
},
|
||||
{
|
||||
type: BlockNumber,
|
||||
desc: 'The blockNumber'
|
||||
blockHash: '0x7eb25504e4c202cf3d62fd585d3e238f592c780cca82dacb2ed3cb5b38883add',
|
||||
blockNumber: 3068185,
|
||||
result: {
|
||||
gasUsed: '0x0',
|
||||
output: '0x'
|
||||
},
|
||||
{
|
||||
type: Array,
|
||||
desc: 'Type of trace, one or more of \'vmTrace\', \'trace\' and/or \'stateDiff\''
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: Array,
|
||||
desc: 'Block traces'
|
||||
subtraces: 0,
|
||||
traceAddress: [],
|
||||
transactionHash: '0x07da28d752aba3b9dd7060005e554719c6205c8a3aea358599fc9b245c52f1f6',
|
||||
transactionPosition: 0,
|
||||
type: 'call'
|
||||
},
|
||||
new Dummy('...')
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
filter: {
|
||||
section: SECTION_FILTERING,
|
||||
desc: 'Returns traces matching given filter',
|
||||
params: [
|
||||
{
|
||||
type: Object,
|
||||
desc: 'The filter object'
|
||||
desc: 'The filter object',
|
||||
details: {
|
||||
fromBlock: {
|
||||
type: BlockNumber,
|
||||
desc: 'From this block.',
|
||||
optional: true
|
||||
},
|
||||
toBlock: {
|
||||
type: BlockNumber,
|
||||
desc: 'To this block.',
|
||||
optional: true
|
||||
},
|
||||
fromAddress: {
|
||||
type: Array,
|
||||
desc: 'Sent from these addresses.',
|
||||
optional: true
|
||||
},
|
||||
toAddress: {
|
||||
type: Address,
|
||||
desc: 'Sent to these addresses.',
|
||||
optional: true
|
||||
}
|
||||
},
|
||||
example: {
|
||||
fromBlock: fromDecimal(3068100),
|
||||
toBlock: fromDecimal(3068200),
|
||||
toAddress: ['0x8bbB73BCB5d553B5A556358d27625323Fd781D37']
|
||||
}
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: Array,
|
||||
desc: 'Traces matching given filter'
|
||||
desc: 'Traces matching given filter',
|
||||
example: [
|
||||
{
|
||||
action: {
|
||||
callType: 'call',
|
||||
from: '0x32be343b94f860124dc4fee278fdcbd38c102d88',
|
||||
gas: '0x4c40d',
|
||||
input: '0x',
|
||||
to: '0x8bbb73bcb5d553b5a556358d27625323fd781d37',
|
||||
value: '0x3f0650ec47fd240000'
|
||||
},
|
||||
blockHash: '0x86df301bcdd8248d982dbf039f09faf792684e1aeee99d5b58b77d620008b80f',
|
||||
blockNumber: 3068183,
|
||||
result: {
|
||||
gasUsed: '0x0',
|
||||
output: '0x'
|
||||
},
|
||||
subtraces: 0,
|
||||
traceAddress: [],
|
||||
transactionHash: '0x3321a7708b1083130bd78da0d62ead9f6683033231617c9d268e2c7e3fa6c104',
|
||||
transactionPosition: 3,
|
||||
type: 'call'
|
||||
},
|
||||
new Dummy('...')
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
get: {
|
||||
section: SECTION_FILTERING,
|
||||
desc: 'Returns trace at given position.',
|
||||
params: [
|
||||
{
|
||||
type: Hash,
|
||||
desc: 'Transaction hash'
|
||||
desc: 'Transaction hash.',
|
||||
example: '0x17104ac9d3312d8c136b7f44d4b8b47852618065ebfa534bd2d3b5ef218ca1f3'
|
||||
},
|
||||
{
|
||||
type: Integer,
|
||||
desc: 'Trace position witing transaction'
|
||||
type: Array,
|
||||
desc: 'Index positions of the traces.',
|
||||
example: ['0x0']
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: Object,
|
||||
desc: 'Trace object'
|
||||
}
|
||||
desc: 'Trace object',
|
||||
example: {
|
||||
action: {
|
||||
callType: 'call',
|
||||
from: '0x1c39ba39e4735cb65978d4db400ddd70a72dc750',
|
||||
gas: '0x13e99',
|
||||
input: '0x16c72721',
|
||||
to: '0x2bd2326c993dfaef84f696526064ff22eba5b362',
|
||||
value: '0x0'
|
||||
},
|
||||
|
||||
rawTransaction: {
|
||||
desc: 'Traces a call to eth_sendRawTransaction without making the call, returning the traces',
|
||||
params: [
|
||||
{
|
||||
type: Data,
|
||||
desc: 'Transaction data'
|
||||
blockHash: '0x7eb25504e4c202cf3d62fd585d3e238f592c780cca82dacb2ed3cb5b38883add',
|
||||
blockNumber: 3068185,
|
||||
result: {
|
||||
gasUsed: '0x183',
|
||||
output: '0x0000000000000000000000000000000000000000000000000000000000000001'
|
||||
},
|
||||
{
|
||||
type: Array,
|
||||
desc: 'Type of trace, one or more of \'vmTrace\', \'trace\' and/or \'stateDiff\''
|
||||
subtraces: 0,
|
||||
traceAddress: [0],
|
||||
transactionHash: '0x17104ac9d3312d8c136b7f44d4b8b47852618065ebfa534bd2d3b5ef218ca1f3',
|
||||
transactionPosition: 2,
|
||||
type: 'call'
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: Array,
|
||||
desc: 'Block traces'
|
||||
}
|
||||
},
|
||||
|
||||
replayTransaction: {
|
||||
desc: 'Replays a transaction, returning the traces',
|
||||
params: [
|
||||
{
|
||||
type: Hash,
|
||||
desc: 'Transaction hash'
|
||||
},
|
||||
{
|
||||
type: Array,
|
||||
desc: 'Type of trace, one or more of \'vmTrace\', \'trace\' and/or \'stateDiff\''
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: Array,
|
||||
desc: 'Block traces'
|
||||
}
|
||||
},
|
||||
|
||||
transaction: {
|
||||
section: SECTION_FILTERING,
|
||||
desc: 'Returns all traces of given transaction',
|
||||
params: [
|
||||
{
|
||||
type: Hash,
|
||||
desc: 'Transaction hash'
|
||||
desc: 'Transaction hash',
|
||||
example: '0x17104ac9d3312d8c136b7f44d4b8b47852618065ebfa534bd2d3b5ef218ca1f3'
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: Array,
|
||||
desc: 'Traces of given transaction'
|
||||
desc: 'Traces of given transaction',
|
||||
example: [
|
||||
{
|
||||
action: {
|
||||
callType: 'call',
|
||||
from: '0x1c39ba39e4735cb65978d4db400ddd70a72dc750',
|
||||
gas: '0x13e99',
|
||||
input: '0x16c72721',
|
||||
to: '0x2bd2326c993dfaef84f696526064ff22eba5b362',
|
||||
value: '0x0'
|
||||
},
|
||||
blockHash: '0x7eb25504e4c202cf3d62fd585d3e238f592c780cca82dacb2ed3cb5b38883add',
|
||||
blockNumber: 3068185,
|
||||
result: {
|
||||
gasUsed: '0x183',
|
||||
output: '0x0000000000000000000000000000000000000000000000000000000000000001'
|
||||
},
|
||||
subtraces: 0,
|
||||
traceAddress: [0],
|
||||
transactionHash: '0x17104ac9d3312d8c136b7f44d4b8b47852618065ebfa534bd2d3b5ef218ca1f3',
|
||||
transactionPosition: 2,
|
||||
type: 'call'
|
||||
},
|
||||
new Dummy('...')
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
call: {
|
||||
section: SECTION_ADHOC,
|
||||
desc: 'Executes the given call and returns a number of possible traces for it.',
|
||||
params: [
|
||||
{
|
||||
type: CallRequest,
|
||||
desc: 'Call options, same as `eth_call`.',
|
||||
example: new Dummy('{ ... }')
|
||||
},
|
||||
{
|
||||
type: Array,
|
||||
desc: 'Type of trace, one or more of: `"vmTrace"`, `"trace"`, `"stateDiff"`.',
|
||||
example: ['trace']
|
||||
},
|
||||
{
|
||||
type: BlockNumber,
|
||||
optional: true,
|
||||
desc: 'Integer of a block number, or the string `\'earliest\'`, `\'latest\'` or `\'pending\'`.'
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: Array,
|
||||
desc: 'Block traces',
|
||||
example: {
|
||||
output: '0x',
|
||||
stateDiff: null,
|
||||
trace: [
|
||||
{
|
||||
action: new Dummy('{ ... }'),
|
||||
result: {
|
||||
gasUsed: '0x0',
|
||||
output: '0x'
|
||||
},
|
||||
subtraces: 0,
|
||||
traceAddress: [],
|
||||
type: 'call'
|
||||
}
|
||||
],
|
||||
vmTrace: null
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
rawTransaction: {
|
||||
section: SECTION_ADHOC,
|
||||
desc: 'Traces a call to `eth_sendRawTransaction` without making the call, returning the traces',
|
||||
params: [
|
||||
{
|
||||
type: Data,
|
||||
desc: 'Raw transaction data.',
|
||||
example: '0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675'
|
||||
},
|
||||
{
|
||||
type: Array,
|
||||
desc: 'Type of trace, one or more of: `"vmTrace"`, `"trace"`, `"stateDiff"`.',
|
||||
example: ['trace']
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: Object,
|
||||
desc: 'Block traces.',
|
||||
example: {
|
||||
output: '0x',
|
||||
stateDiff: null,
|
||||
trace: [
|
||||
{
|
||||
action: new Dummy('{ ... }'),
|
||||
result: {
|
||||
gasUsed: '0x0',
|
||||
output: '0x'
|
||||
},
|
||||
subtraces: 0,
|
||||
traceAddress: [],
|
||||
type: 'call'
|
||||
}
|
||||
],
|
||||
vmTrace: null
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
replayTransaction: {
|
||||
section: SECTION_ADHOC,
|
||||
desc: 'Replays a transaction, returning the traces.',
|
||||
params: [
|
||||
{
|
||||
type: Hash,
|
||||
desc: 'Transaction hash.',
|
||||
example: '0x02d4a872e096445e80d05276ee756cefef7f3b376bcec14246469c0cd97dad8f'
|
||||
},
|
||||
{
|
||||
type: Array,
|
||||
desc: 'Type of trace, one or more of: `"vmTrace"`, `"trace"`, `"stateDiff"`.',
|
||||
example: ['trace']
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: Object,
|
||||
desc: 'Block traces.',
|
||||
example: {
|
||||
output: '0x',
|
||||
stateDiff: null,
|
||||
trace: [
|
||||
{
|
||||
action: new Dummy('{ ... }'),
|
||||
result: {
|
||||
gasUsed: '0x0',
|
||||
output: '0x'
|
||||
},
|
||||
subtraces: 0,
|
||||
traceAddress: [],
|
||||
type: 'call'
|
||||
}
|
||||
],
|
||||
vmTrace: null
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -16,8 +16,6 @@
|
||||
|
||||
export class Address {}
|
||||
|
||||
export class BlockNumber {}
|
||||
|
||||
export class Data {}
|
||||
|
||||
export class Hash {}
|
||||
@ -25,3 +23,89 @@ export class Hash {}
|
||||
export class Integer {}
|
||||
|
||||
export class Quantity {}
|
||||
|
||||
export class BlockNumber {
|
||||
static print = '`Quantity` | `Tag`';
|
||||
}
|
||||
|
||||
export class CallRequest {
|
||||
static print = '`Object`';
|
||||
|
||||
static details = {
|
||||
from: {
|
||||
type: Address,
|
||||
desc: '20 Bytes - The address the transaction is send from.',
|
||||
optional: true
|
||||
},
|
||||
to: {
|
||||
type: Address,
|
||||
desc: '(optional when creating new contract) 20 Bytes - The address the transaction is directed to.'
|
||||
},
|
||||
gas: {
|
||||
type: Quantity,
|
||||
desc: 'Integer of the gas provided for the transaction execution. eth_call consumes zero gas, but this parameter may be needed by some executions.',
|
||||
optional: true
|
||||
},
|
||||
gasPrice: {
|
||||
type: Quantity,
|
||||
desc: 'Integer of the gas price used for each paid gas.',
|
||||
optional: true
|
||||
},
|
||||
value: {
|
||||
type: Quantity,
|
||||
desc: 'Integer of the value sent with this transaction.',
|
||||
optional: true
|
||||
},
|
||||
data: {
|
||||
type: Data,
|
||||
desc: '4 byte hash of the method signature followed by encoded parameters. For details see [Ethereum Contract ABI](https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI).',
|
||||
optional: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class TransactionRequest {
|
||||
static print = '`Object`';
|
||||
|
||||
static details = {
|
||||
from: {
|
||||
type: Address,
|
||||
desc: '20 Bytes - The address the transaction is send from.'
|
||||
},
|
||||
to: {
|
||||
type: Address,
|
||||
desc: '20 Bytes - The address the transaction is directed to.',
|
||||
optional: true
|
||||
},
|
||||
gas: {
|
||||
type: Quantity,
|
||||
desc: 'Integer of the gas provided for the transaction execution. eth_call consumes zero gas, but this parameter may be needed by some executions.',
|
||||
optional: true
|
||||
},
|
||||
gasPrice: {
|
||||
type: Quantity,
|
||||
desc: 'Integer of the gas price used for each paid gas.',
|
||||
optional: true
|
||||
},
|
||||
value: {
|
||||
type: Quantity,
|
||||
desc: 'Integer of the value sent with this transaction.',
|
||||
optional: true
|
||||
},
|
||||
data: {
|
||||
type: Data,
|
||||
desc: '4 byte hash of the method signature followed by encoded parameters. For details see [Ethereum Contract ABI](https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI).',
|
||||
optional: true
|
||||
},
|
||||
nonce: {
|
||||
type: Quantity,
|
||||
desc: 'Integer of a nonce. This allows to overwrite your own pending transactions that use the same nonce.',
|
||||
optional: true
|
||||
},
|
||||
minBlock: {
|
||||
type: BlockNumber,
|
||||
desc: 'Delay until this block if specified.',
|
||||
optional: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -105,7 +105,7 @@ build_rpc_trait! {
|
||||
#[rpc(name = "eth_sendRawTransaction")]
|
||||
fn send_raw_transaction(&self, Bytes) -> Result<H256, Error>;
|
||||
|
||||
/// Alias of `eth_sendRawTransaction`.
|
||||
/// @alias of `eth_sendRawTransaction`.
|
||||
#[rpc(name = "eth_submitTransaction")]
|
||||
fn submit_transaction(&self, Bytes) -> Result<H256, Error>;
|
||||
|
||||
|
@ -70,7 +70,8 @@ build_rpc_trait! {
|
||||
#[rpc(name = "parity_setAccountMeta")]
|
||||
fn set_account_meta(&self, H160, String) -> Result<bool, Error>;
|
||||
|
||||
/// Sets account visibility
|
||||
/// Sets account visibility.
|
||||
/// @unimplemented
|
||||
#[rpc(name = "parity_setAccountVisiblity")]
|
||||
fn set_account_visibility(&self, H160, H256, bool) -> Result<bool, Error>;
|
||||
|
||||
|
@ -74,13 +74,13 @@ build_rpc_trait! {
|
||||
|
||||
/// Start the network.
|
||||
///
|
||||
/// Deprecated. Use `set_mode("active")` instead.
|
||||
/// @deprecated - Use `set_mode("active")` instead.
|
||||
#[rpc(name = "parity_startNetwork")]
|
||||
fn start_network(&self) -> Result<bool, Error>;
|
||||
|
||||
/// Stop the network.
|
||||
///
|
||||
/// Deprecated. Use `set_mode("offline")` instead.
|
||||
/// @deprecated - Use `set_mode("offline")` instead.
|
||||
#[rpc(name = "parity_stopNetwork")]
|
||||
fn stop_network(&self) -> Result<bool, Error>;
|
||||
|
||||
|
@ -24,10 +24,12 @@ build_rpc_trait! {
|
||||
/// RPC Interface.
|
||||
pub trait Rpc {
|
||||
/// Returns supported modules for Geth 1.3.6
|
||||
/// @ignore
|
||||
#[rpc(name = "modules")]
|
||||
fn modules(&self) -> Result<BTreeMap<String, String>, Error>;
|
||||
|
||||
/// Returns supported modules for Geth 1.4.0
|
||||
/// @ignore
|
||||
#[rpc(name = "rpc_modules")]
|
||||
fn rpc_modules(&self) -> Result<BTreeMap<String, String>, Error>;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user