|
@@ -3,18 +3,19 @@ import { CLIError } from '@oclif/errors'
|
|
import StateAwareCommandBase from './StateAwareCommandBase'
|
|
import StateAwareCommandBase from './StateAwareCommandBase'
|
|
import Api from '../Api'
|
|
import Api from '../Api'
|
|
import { getTypeDef, Option, Tuple } from '@polkadot/types'
|
|
import { getTypeDef, Option, Tuple } from '@polkadot/types'
|
|
-import { Registry, Codec, TypeDef, TypeDefInfo, IEvent } from '@polkadot/types/types'
|
|
|
|
|
|
+import { Registry, Codec, TypeDef, TypeDefInfo, IEvent, DetectCodec } from '@polkadot/types/types'
|
|
import { Vec, Struct, Enum } from '@polkadot/types/codec'
|
|
import { Vec, Struct, Enum } from '@polkadot/types/codec'
|
|
-import { SubmittableResult, WsProvider } from '@polkadot/api'
|
|
|
|
|
|
+import { SubmittableResult, WsProvider, ApiPromise } from '@polkadot/api'
|
|
import { KeyringPair } from '@polkadot/keyring/types'
|
|
import { KeyringPair } from '@polkadot/keyring/types'
|
|
import chalk from 'chalk'
|
|
import chalk from 'chalk'
|
|
import { InterfaceTypes } from '@polkadot/types/types/registry'
|
|
import { InterfaceTypes } from '@polkadot/types/types/registry'
|
|
-import { ApiMethodArg, ApiMethodNamedArgs, ApiParamsOptions, ApiParamOptions } from '../Types'
|
|
|
|
|
|
+import { ApiMethodArg, ApiMethodNamedArgs, ApiParamsOptions, ApiParamOptions, UnaugmentedApiPromise } from '../Types'
|
|
import { createParamOptions } from '../helpers/promptOptions'
|
|
import { createParamOptions } from '../helpers/promptOptions'
|
|
import { AugmentedSubmittables, SubmittableExtrinsic, AugmentedEvents, AugmentedEvent } from '@polkadot/api/types'
|
|
import { AugmentedSubmittables, SubmittableExtrinsic, AugmentedEvents, AugmentedEvent } from '@polkadot/api/types'
|
|
import { DistinctQuestion } from 'inquirer'
|
|
import { DistinctQuestion } from 'inquirer'
|
|
import { BOOL_PROMPT_OPTIONS } from '../helpers/prompting'
|
|
import { BOOL_PROMPT_OPTIONS } from '../helpers/prompting'
|
|
import { DispatchError } from '@polkadot/types/interfaces/system'
|
|
import { DispatchError } from '@polkadot/types/interfaces/system'
|
|
|
|
+import QueryNodeApi from '../QueryNodeApi'
|
|
import { formatBalance } from '@polkadot/util'
|
|
import { formatBalance } from '@polkadot/util'
|
|
import BN from 'bn.js'
|
|
import BN from 'bn.js'
|
|
import _ from 'lodash'
|
|
import _ from 'lodash'
|
|
@@ -25,19 +26,38 @@ export class ExtrinsicFailedError extends Error {}
|
|
* Abstract base class for commands that require access to the API.
|
|
* Abstract base class for commands that require access to the API.
|
|
*/
|
|
*/
|
|
export default abstract class ApiCommandBase extends StateAwareCommandBase {
|
|
export default abstract class ApiCommandBase extends StateAwareCommandBase {
|
|
- private api: Api | null = null
|
|
|
|
|
|
+ private api: Api | undefined
|
|
|
|
+ private queryNodeApi: QueryNodeApi | null | undefined
|
|
|
|
+
|
|
|
|
+ // Command configuration
|
|
|
|
+ protected requiresApiConnection = true
|
|
|
|
+ protected requiresQueryNode = false
|
|
|
|
|
|
getApi(): Api {
|
|
getApi(): Api {
|
|
- if (!this.api) throw new CLIError('Tried to get API before initialization.', { exit: ExitCodes.ApiError })
|
|
|
|
|
|
+ if (!this.api) {
|
|
|
|
+ throw new CLIError('Tried to access API before initialization.', { exit: ExitCodes.ApiError })
|
|
|
|
+ }
|
|
return this.api
|
|
return this.api
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ getQNApi(): QueryNodeApi {
|
|
|
|
+ if (this.queryNodeApi === undefined) {
|
|
|
|
+ throw new CLIError('Tried to access QueryNodeApi before initialization.', { exit: ExitCodes.QueryNodeError })
|
|
|
|
+ }
|
|
|
|
+ if (this.queryNodeApi === null) {
|
|
|
|
+ throw new CLIError('Query node endpoint uri is required in order to run this command!', {
|
|
|
|
+ exit: ExitCodes.QueryNodeError,
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ return this.queryNodeApi
|
|
|
|
+ }
|
|
|
|
+
|
|
// Shortcuts
|
|
// Shortcuts
|
|
- getOriginalApi() {
|
|
|
|
|
|
+ getOriginalApi(): ApiPromise {
|
|
return this.getApi().getOriginalApi()
|
|
return this.getApi().getOriginalApi()
|
|
}
|
|
}
|
|
|
|
|
|
- getUnaugmentedApi() {
|
|
|
|
|
|
+ getUnaugmentedApi(): UnaugmentedApiPromise {
|
|
return this.getApi().getUnaugmentedApi()
|
|
return this.getApi().getUnaugmentedApi()
|
|
}
|
|
}
|
|
|
|
|
|
@@ -45,13 +65,18 @@ export default abstract class ApiCommandBase extends StateAwareCommandBase {
|
|
return this.getOriginalApi().registry
|
|
return this.getOriginalApi().registry
|
|
}
|
|
}
|
|
|
|
|
|
- createType<K extends keyof InterfaceTypes>(typeName: K, value?: unknown): InterfaceTypes[K] {
|
|
|
|
- return this.getOriginalApi().createType(typeName, value)
|
|
|
|
|
|
+ createType<T extends Codec = Codec, TN extends string = string>(typeName: TN, value?: unknown): DetectCodec<T, TN> {
|
|
|
|
+ return this.getOriginalApi().createType<T, TN>(typeName, value)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ isQueryNodeUriSet(): boolean {
|
|
|
|
+ const { queryNodeUri } = this.getPreservedState()
|
|
|
|
+ return !!queryNodeUri
|
|
}
|
|
}
|
|
|
|
|
|
- async init(skipConnection = false): Promise<void> {
|
|
|
|
|
|
+ async init(): Promise<void> {
|
|
await super.init()
|
|
await super.init()
|
|
- if (!skipConnection) {
|
|
|
|
|
|
+ if (this.requiresApiConnection) {
|
|
let apiUri: string = this.getPreservedState().apiUri
|
|
let apiUri: string = this.getPreservedState().apiUri
|
|
|
|
|
|
if (!apiUri) {
|
|
if (!apiUri) {
|
|
@@ -59,8 +84,12 @@ export default abstract class ApiCommandBase extends StateAwareCommandBase {
|
|
apiUri = await this.promptForApiUri()
|
|
apiUri = await this.promptForApiUri()
|
|
}
|
|
}
|
|
|
|
|
|
- let queryNodeUri: string = this.getPreservedState().queryNodeUri
|
|
|
|
- if (!queryNodeUri) {
|
|
|
|
|
|
+ let queryNodeUri: string | null | undefined = this.getPreservedState().queryNodeUri
|
|
|
|
+
|
|
|
|
+ if (this.requiresQueryNode && !queryNodeUri) {
|
|
|
|
+ this.warn('Query node endpoint uri is required in order to run this command!')
|
|
|
|
+ queryNodeUri = await this.promptForQueryNodeUri(true)
|
|
|
|
+ } else if (queryNodeUri === undefined) {
|
|
this.warn("You haven't provided a Joystream query node uri for the CLI to connect to yet!")
|
|
this.warn("You haven't provided a Joystream query node uri for the CLI to connect to yet!")
|
|
queryNodeUri = await this.promptForQueryNodeUri()
|
|
queryNodeUri = await this.promptForQueryNodeUri()
|
|
}
|
|
}
|
|
@@ -75,6 +104,12 @@ export default abstract class ApiCommandBase extends StateAwareCommandBase {
|
|
metadataCache[metadataKey] = await this.getOriginalApi().runtimeMetadata.toJSON()
|
|
metadataCache[metadataKey] = await this.getOriginalApi().runtimeMetadata.toJSON()
|
|
await this.setPreservedState({ metadataCache })
|
|
await this.setPreservedState({ metadataCache })
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ this.queryNodeApi = queryNodeUri
|
|
|
|
+ ? new QueryNodeApi(queryNodeUri, (err) => {
|
|
|
|
+ this.warn(`Query node error: ${err.networkError?.message || err.graphQLErrors?.join('\n')}`)
|
|
|
|
+ })
|
|
|
|
+ : null
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -115,28 +150,31 @@ export default abstract class ApiCommandBase extends StateAwareCommandBase {
|
|
return selectedNodeUri
|
|
return selectedNodeUri
|
|
}
|
|
}
|
|
|
|
|
|
- async promptForQueryNodeUri(): Promise<string> {
|
|
|
|
- let selectedUri = await this.simplePrompt({
|
|
|
|
|
|
+ async promptForQueryNodeUri(isRequired = false): Promise<string | null> {
|
|
|
|
+ const choices = [
|
|
|
|
+ {
|
|
|
|
+ name: 'Local query node (http://localhost:8081/graphql)',
|
|
|
|
+ value: 'http://localhost:8081/graphql',
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ name: 'Jsgenesis-hosted query node (https://hydra.joystream.org/graphql)',
|
|
|
|
+ value: 'https://hydra.joystream.org/graphql',
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ name: 'Custom endpoint',
|
|
|
|
+ value: '',
|
|
|
|
+ },
|
|
|
|
+ ]
|
|
|
|
+ if (!isRequired) {
|
|
|
|
+ choices.push({
|
|
|
|
+ name: "No endpoint (if you don't use query node some features will not be available)",
|
|
|
|
+ value: 'none',
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ let selectedUri: string = await this.simplePrompt({
|
|
type: 'list',
|
|
type: 'list',
|
|
message: 'Choose a query node endpoint:',
|
|
message: 'Choose a query node endpoint:',
|
|
- choices: [
|
|
|
|
- {
|
|
|
|
- name: 'Local query node (http://localhost:8081/graphql)',
|
|
|
|
- value: 'http://localhost:8081/graphql',
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- name: 'Jsgenesis-hosted query node (https://hydra.joystream.org/graphql)',
|
|
|
|
- value: 'https://hydra.joystream.org/graphql',
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- name: 'Custom endpoint',
|
|
|
|
- value: '',
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- name: "No endpoint (if you don't use query node some features will not be available)",
|
|
|
|
- value: 'none',
|
|
|
|
- },
|
|
|
|
- ],
|
|
|
|
|
|
+ choices,
|
|
})
|
|
})
|
|
|
|
|
|
if (!selectedUri) {
|
|
if (!selectedUri) {
|
|
@@ -145,18 +183,20 @@ export default abstract class ApiCommandBase extends StateAwareCommandBase {
|
|
type: 'input',
|
|
type: 'input',
|
|
message: 'Provide a query node endpoint',
|
|
message: 'Provide a query node endpoint',
|
|
})
|
|
})
|
|
- if (!this.isApiUriValid(selectedUri)) {
|
|
|
|
|
|
+ if (!this.isQueryNodeUriValid(selectedUri)) {
|
|
this.warn('Provided uri seems incorrect! Please try again...')
|
|
this.warn('Provided uri seems incorrect! Please try again...')
|
|
}
|
|
}
|
|
- } while (!this.isApiUriValid(selectedUri))
|
|
|
|
|
|
+ } while (!this.isQueryNodeUriValid(selectedUri))
|
|
}
|
|
}
|
|
|
|
|
|
- await this.setPreservedState({ queryNodeUri: selectedUri })
|
|
|
|
|
|
+ const queryNodeUri = selectedUri === 'none' ? null : selectedUri
|
|
|
|
|
|
- return selectedUri
|
|
|
|
|
|
+ await this.setPreservedState({ queryNodeUri })
|
|
|
|
+
|
|
|
|
+ return queryNodeUri
|
|
}
|
|
}
|
|
|
|
|
|
- isApiUriValid(uri: string) {
|
|
|
|
|
|
+ isApiUriValid(uri: string): boolean {
|
|
try {
|
|
try {
|
|
// eslint-disable-next-line no-new
|
|
// eslint-disable-next-line no-new
|
|
new WsProvider(uri)
|
|
new WsProvider(uri)
|
|
@@ -166,7 +206,7 @@ export default abstract class ApiCommandBase extends StateAwareCommandBase {
|
|
return true
|
|
return true
|
|
}
|
|
}
|
|
|
|
|
|
- isQueryNodeUriValid(uri: string) {
|
|
|
|
|
|
+ isQueryNodeUriValid(uri: string): boolean {
|
|
let url: URL
|
|
let url: URL
|
|
try {
|
|
try {
|
|
url = new URL(uri)
|
|
url = new URL(uri)
|
|
@@ -179,13 +219,13 @@ export default abstract class ApiCommandBase extends StateAwareCommandBase {
|
|
|
|
|
|
// This is needed to correctly handle some structs, enums etc.
|
|
// This is needed to correctly handle some structs, enums etc.
|
|
// Where the main typeDef doesn't provide enough information
|
|
// Where the main typeDef doesn't provide enough information
|
|
- protected getRawTypeDef(type: keyof InterfaceTypes) {
|
|
|
|
|
|
+ protected getRawTypeDef(type: keyof InterfaceTypes): TypeDef {
|
|
const instance = this.createType(type)
|
|
const instance = this.createType(type)
|
|
return getTypeDef(instance.toRawType())
|
|
return getTypeDef(instance.toRawType())
|
|
}
|
|
}
|
|
|
|
|
|
// Prettifier for type names which are actually JSON strings
|
|
// Prettifier for type names which are actually JSON strings
|
|
- protected prettifyJsonTypeName(json: string) {
|
|
|
|
|
|
+ protected prettifyJsonTypeName(json: string): string {
|
|
const obj = JSON.parse(json) as { [key: string]: string }
|
|
const obj = JSON.parse(json) as { [key: string]: string }
|
|
return (
|
|
return (
|
|
'{\n' +
|
|
'{\n' +
|
|
@@ -197,7 +237,7 @@ export default abstract class ApiCommandBase extends StateAwareCommandBase {
|
|
}
|
|
}
|
|
|
|
|
|
// Get param name based on TypeDef object
|
|
// Get param name based on TypeDef object
|
|
- protected paramName(typeDef: TypeDef) {
|
|
|
|
|
|
+ protected paramName(typeDef: TypeDef): string {
|
|
return chalk.green(
|
|
return chalk.green(
|
|
typeDef.displayName ||
|
|
typeDef.displayName ||
|
|
typeDef.name ||
|
|
typeDef.name ||
|
|
@@ -244,10 +284,10 @@ export default abstract class ApiCommandBase extends StateAwareCommandBase {
|
|
createParamOptions(subtype.name, defaultValue?.unwrapOr(undefined))
|
|
createParamOptions(subtype.name, defaultValue?.unwrapOr(undefined))
|
|
)
|
|
)
|
|
this.closeIndentGroup()
|
|
this.closeIndentGroup()
|
|
- return this.createType(`Option<${subtype.type}>` as any, value)
|
|
|
|
|
|
+ return this.createType<Option<Codec>>(`Option<${subtype.type}>`, value)
|
|
}
|
|
}
|
|
|
|
|
|
- return this.createType(`Option<${subtype.type}>` as any, null)
|
|
|
|
|
|
+ return this.createType<Option<Codec>>(`Option<${subtype.type}>`, null)
|
|
}
|
|
}
|
|
|
|
|
|
// Prompt for Tuple
|
|
// Prompt for Tuple
|
|
@@ -268,7 +308,11 @@ export default abstract class ApiCommandBase extends StateAwareCommandBase {
|
|
}
|
|
}
|
|
this.closeIndentGroup()
|
|
this.closeIndentGroup()
|
|
|
|
|
|
- return new Tuple(this.getTypesRegistry(), subtypes.map((subtype) => subtype.type) as any, result)
|
|
|
|
|
|
+ return new Tuple(
|
|
|
|
+ this.getTypesRegistry(),
|
|
|
|
+ subtypes.map((subtype) => subtype.type),
|
|
|
|
+ result
|
|
|
|
+ )
|
|
}
|
|
}
|
|
|
|
|
|
// Prompt for Struct
|
|
// Prompt for Struct
|
|
@@ -295,7 +339,7 @@ export default abstract class ApiCommandBase extends StateAwareCommandBase {
|
|
}
|
|
}
|
|
this.closeIndentGroup()
|
|
this.closeIndentGroup()
|
|
|
|
|
|
- return this.createType(structType as any, structValues)
|
|
|
|
|
|
+ return this.createType(structType, structValues)
|
|
}
|
|
}
|
|
|
|
|
|
// Prompt for Vec
|
|
// Prompt for Vec
|
|
@@ -323,7 +367,7 @@ export default abstract class ApiCommandBase extends StateAwareCommandBase {
|
|
} while (addAnother)
|
|
} while (addAnother)
|
|
this.closeIndentGroup()
|
|
this.closeIndentGroup()
|
|
|
|
|
|
- return this.createType(`Vec<${subtype.type}>` as any, entries)
|
|
|
|
|
|
+ return this.createType<Vec<Codec>>(`Vec<${subtype.type}>`, entries)
|
|
}
|
|
}
|
|
|
|
|
|
// Prompt for Enum
|
|
// Prompt for Enum
|
|
@@ -348,12 +392,12 @@ export default abstract class ApiCommandBase extends StateAwareCommandBase {
|
|
|
|
|
|
if (enumSubtype.type !== 'Null') {
|
|
if (enumSubtype.type !== 'Null') {
|
|
const subtypeOptions = createParamOptions(enumSubtype.name, defaultValue?.value)
|
|
const subtypeOptions = createParamOptions(enumSubtype.name, defaultValue?.value)
|
|
- return this.createType(enumType as any, {
|
|
|
|
|
|
+ return this.createType<Enum>(enumType, {
|
|
[enumSubtype.name!]: await this.promptForParam(enumSubtype.type, subtypeOptions),
|
|
[enumSubtype.name!]: await this.promptForParam(enumSubtype.type, subtypeOptions),
|
|
})
|
|
})
|
|
}
|
|
}
|
|
|
|
|
|
- return this.createType(enumType as any, enumSubtype.name)
|
|
|
|
|
|
+ return this.createType<Enum>(enumType, enumSubtype.name)
|
|
}
|
|
}
|
|
|
|
|
|
// Prompt for param based on "paramType" string (ie. Option<MemeberId>)
|
|
// Prompt for param based on "paramType" string (ie. Option<MemeberId>)
|
|
@@ -389,7 +433,7 @@ export default abstract class ApiCommandBase extends StateAwareCommandBase {
|
|
}
|
|
}
|
|
|
|
|
|
// More typesafe version
|
|
// More typesafe version
|
|
- async promptForType(type: keyof InterfaceTypes, options?: ApiParamOptions) {
|
|
|
|
|
|
+ async promptForType(type: keyof InterfaceTypes, options?: ApiParamOptions): Promise<Codec> {
|
|
return await this.promptForParam(type, options)
|
|
return await this.promptForParam(type, options)
|
|
}
|
|
}
|
|
|
|
|
|
@@ -458,11 +502,7 @@ export default abstract class ApiCommandBase extends StateAwareCommandBase {
|
|
})
|
|
})
|
|
}
|
|
}
|
|
|
|
|
|
- async sendAndFollowTx(
|
|
|
|
- account: KeyringPair,
|
|
|
|
- tx: SubmittableExtrinsic<'promise'>,
|
|
|
|
- warnOnly = false // If specified - only warning will be displayed in case of failure (instead of error beeing thrown)
|
|
|
|
- ): Promise<SubmittableResult | false> {
|
|
|
|
|
|
+ async sendAndFollowTx(account: KeyringPair, tx: SubmittableExtrinsic<'promise'>): Promise<SubmittableResult> {
|
|
// Calculate fee and ask for confirmation
|
|
// Calculate fee and ask for confirmation
|
|
const fee = await this.getApi().estimateFee(account, tx)
|
|
const fee = await this.getApi().estimateFee(account, tx)
|
|
|
|
|
|
@@ -475,10 +515,7 @@ export default abstract class ApiCommandBase extends StateAwareCommandBase {
|
|
this.log(chalk.green(`Extrinsic successful!`))
|
|
this.log(chalk.green(`Extrinsic successful!`))
|
|
return res
|
|
return res
|
|
} catch (e) {
|
|
} catch (e) {
|
|
- if (e instanceof ExtrinsicFailedError && warnOnly) {
|
|
|
|
- this.warn(`Extrinsic failed! ${e.message}`)
|
|
|
|
- return false
|
|
|
|
- } else if (e instanceof ExtrinsicFailedError) {
|
|
|
|
|
|
+ if (e instanceof ExtrinsicFailedError) {
|
|
throw new CLIError(`Extrinsic failed! ${e.message}`, { exit: ExitCodes.ApiError })
|
|
throw new CLIError(`Extrinsic failed! ${e.message}`, { exit: ExitCodes.ApiError })
|
|
} else {
|
|
} else {
|
|
throw e
|
|
throw e
|
|
@@ -510,17 +547,16 @@ export default abstract class ApiCommandBase extends StateAwareCommandBase {
|
|
account: KeyringPair,
|
|
account: KeyringPair,
|
|
module: Module,
|
|
module: Module,
|
|
method: Method,
|
|
method: Method,
|
|
- params: Submittable extends (...args: any[]) => any ? Parameters<Submittable> : [],
|
|
|
|
- warnOnly = false
|
|
|
|
- ): Promise<SubmittableResult | false> {
|
|
|
|
|
|
+ params: Submittable extends (...args: any[]) => any ? Parameters<Submittable> : []
|
|
|
|
+ ): Promise<SubmittableResult> {
|
|
this.log(
|
|
this.log(
|
|
chalk.magentaBright(
|
|
chalk.magentaBright(
|
|
`\nSending ${module}.${method} extrinsic from ${account.meta.name ? account.meta.name : account.address}...`
|
|
`\nSending ${module}.${method} extrinsic from ${account.meta.name ? account.meta.name : account.address}...`
|
|
)
|
|
)
|
|
)
|
|
)
|
|
- console.log('Params:', this.humanize(params))
|
|
|
|
|
|
+ this.log('Tx params:', this.humanize(params))
|
|
const tx = await this.getUnaugmentedApi().tx[module][method](...params)
|
|
const tx = await this.getUnaugmentedApi().tx[module][method](...params)
|
|
- return await this.sendAndFollowTx(account, tx, warnOnly)
|
|
|
|
|
|
+ return this.sendAndFollowTx(account, tx)
|
|
}
|
|
}
|
|
|
|
|
|
public findEvent<
|
|
public findEvent<
|
|
@@ -534,15 +570,9 @@ export default abstract class ApiCommandBase extends StateAwareCommandBase {
|
|
async buildAndSendExtrinsic<
|
|
async buildAndSendExtrinsic<
|
|
Module extends keyof AugmentedSubmittables<'promise'>,
|
|
Module extends keyof AugmentedSubmittables<'promise'>,
|
|
Method extends keyof AugmentedSubmittables<'promise'>[Module] & string
|
|
Method extends keyof AugmentedSubmittables<'promise'>[Module] & string
|
|
- >(
|
|
|
|
- account: KeyringPair,
|
|
|
|
- module: Module,
|
|
|
|
- method: Method,
|
|
|
|
- paramsOptions?: ApiParamsOptions,
|
|
|
|
- warnOnly = false // If specified - only warning will be displayed (instead of error beeing thrown)
|
|
|
|
- ): Promise<ApiMethodArg[]> {
|
|
|
|
|
|
+ >(account: KeyringPair, module: Module, method: Method, paramsOptions?: ApiParamsOptions): Promise<ApiMethodArg[]> {
|
|
const params = await this.promptForExtrinsicParams(module, method, paramsOptions)
|
|
const params = await this.promptForExtrinsicParams(module, method, paramsOptions)
|
|
- await this.sendAndFollowNamedTx(account, module, method, params as any, warnOnly)
|
|
|
|
|
|
+ await this.sendAndFollowNamedTx(account, module, method, params as any)
|
|
|
|
|
|
return params
|
|
return params
|
|
}
|
|
}
|
|
@@ -564,7 +594,7 @@ export default abstract class ApiCommandBase extends StateAwareCommandBase {
|
|
const argName = arg.name.toString()
|
|
const argName = arg.name.toString()
|
|
const argType = arg.type.toString()
|
|
const argType = arg.type.toString()
|
|
try {
|
|
try {
|
|
- parsedArgs.push({ name: argName, value: this.createType(argType as any, draftJSONObj[parseInt(index)]) })
|
|
|
|
|
|
+ parsedArgs.push({ name: argName, value: this.createType(argType, draftJSONObj[parseInt(index)]) })
|
|
} catch (e) {
|
|
} catch (e) {
|
|
throw new CLIError(`Couldn't parse ${argName} value from draft at ${draftFilePath}!`, {
|
|
throw new CLIError(`Couldn't parse ${argName} value from draft at ${draftFilePath}!`, {
|
|
exit: ExitCodes.InvalidFile,
|
|
exit: ExitCodes.InvalidFile,
|