From d8bb7d39c3447adb68a3e3336b98cdb2242c28bd Mon Sep 17 00:00:00 2001 From: Jort Date: Tue, 16 Jun 2026 15:13:42 -0700 Subject: [PATCH] [client] add execution error metadata to grpc and gql responses --- .changeset/grpc-graphql-error-metadata.md | 5 +++ packages/sui/src/client/types.ts | 5 +++ packages/sui/src/graphql/core.ts | 16 ++++++++++ packages/sui/src/graphql/generated/queries.ts | 17 +++++++--- .../sui/src/graphql/generated/schema.graphql | 4 +++ .../sui/src/graphql/generated/tada-env.ts | 9 ++++++ .../src/graphql/queries/transactions.graphql | 2 ++ packages/sui/src/grpc/core.ts | 29 +++++++++++++++-- .../grpc/proto/sui/rpc/v2/execution_status.ts | 31 +++++++++++++++++++ 9 files changed, 111 insertions(+), 7 deletions(-) create mode 100644 .changeset/grpc-graphql-error-metadata.md diff --git a/.changeset/grpc-graphql-error-metadata.md b/.changeset/grpc-graphql-error-metadata.md new file mode 100644 index 000000000..bc55e9a14 --- /dev/null +++ b/.changeset/grpc-graphql-error-metadata.md @@ -0,0 +1,5 @@ +--- +'@mysten/sui': minor +--- + +Expose execution error metadata in Core API transaction results for gRPC and GraphQL clients. diff --git a/packages/sui/src/client/types.ts b/packages/sui/src/client/types.ts index f9635bc31..43d7a83ce 100644 --- a/packages/sui/src/client/types.ts +++ b/packages/sui/src/client/types.ts @@ -975,9 +975,14 @@ export namespace SuiClientTypes { objectId: string; } + export interface ExecutionErrorMetadata { + message?: string; + } + export type ExecutionError = { message: string; command?: number; + metadata?: ExecutionErrorMetadata; } & EnumOutputShape<{ MoveAbort: MoveAbort; SizeError: SizeError; diff --git a/packages/sui/src/graphql/core.ts b/packages/sui/src/graphql/core.ts index c644948fe..4954f0341 100644 --- a/packages/sui/src/graphql/core.ts +++ b/packages/sui/src/graphql/core.ts @@ -973,6 +973,9 @@ function parseGraphQLExecutionError( executionError: GraphQLExecutionError | null | undefined, ): SuiClientTypes.ExecutionError { const name = mapGraphQLExecutionErrorKind(executionError); + const metadata = parseGraphQLExecutionErrorMetadata( + (executionError as { metadata?: unknown } | null | undefined)?.metadata, + ); if (name === 'MoveAbort' && executionError?.abortCode != null) { const location = parseGraphQLMoveLocation(executionError); @@ -1002,6 +1005,7 @@ function parseGraphQLExecutionError( : undefined, }), command, + metadata, MoveAbort: { abortCode: executionError.abortCode!, location, @@ -1013,10 +1017,22 @@ function parseGraphQLExecutionError( return { $kind: 'Unknown', message: executionError?.message ?? 'Transaction failed', + metadata, Unknown: null, }; } +function parseGraphQLExecutionErrorMetadata( + metadata: unknown, +): SuiClientTypes.ExecutionError['metadata'] { + if (!metadata || typeof metadata !== 'object' || Array.isArray(metadata)) { + return undefined; + } + + const message = (metadata as { message?: unknown }).message; + return typeof message === 'string' ? { message } : undefined; +} + function mapGraphQLExecutionErrorKind( executionError: GraphQLExecutionError | null | undefined, ): string { diff --git a/packages/sui/src/graphql/generated/queries.ts b/packages/sui/src/graphql/generated/queries.ts index 09419dc1e..a68d4da24 100644 --- a/packages/sui/src/graphql/generated/queries.ts +++ b/packages/sui/src/graphql/generated/queries.ts @@ -1626,6 +1626,8 @@ export type ExecutionError = { * For Move aborts, the error message will be resolved to a human-readable form if possible, otherwise it will fall back to displaying the abort code and location. */ message: Scalars['String']['output']; + /** Additional error metadata, when available. */ + metadata?: Maybe; /** The module that the abort originated from. Only populated for Move aborts and primitive runtime errors. */ module?: Maybe; /** The source line number for the abort. Only populated for clever errors. */ @@ -5017,7 +5019,7 @@ export type SimulateTransactionQueryVariables = Exact<{ }>; -export type SimulateTransactionQuery = { __typename?: 'Query', simulateTransaction: { __typename?: 'SimulationResult', effects?: { __typename?: 'TransactionEffects', transaction?: { __typename?: 'Transaction', digest: string, transactionJson?: unknown | null, transactionBcs?: string | null, signatures: Array<{ __typename?: 'UserSignature', signatureBytes?: string | null }>, effects?: { __typename?: 'TransactionEffects', status?: ExecutionStatus | null, effectsBcs?: string | null, effectsJson?: unknown | null, balanceChangesJson?: unknown | null, executionError?: { __typename?: 'ExecutionError', message: string, abortCode?: string | null, identifier?: string | null, constant?: string | null, sourceLineNumber?: number | null, instructionOffset?: number | null, module?: { __typename?: 'MoveModule', name: string, package?: { __typename?: 'MovePackage', address: string } | null } | null, function?: { __typename?: 'MoveFunction', name: string } | null } | null, epoch?: { __typename?: 'Epoch', epochId: number } | null, objectChanges?: { __typename?: 'ObjectChangeConnection', nodes: Array<{ __typename?: 'ObjectChange', address: string, outputState?: { __typename?: 'Object', asMoveObject?: { __typename?: 'MoveObject', contents?: { __typename?: 'MoveValue', type?: { __typename?: 'MoveType', repr: string } | null } | null } | null } | null }> } | null, events?: { __typename?: 'EventConnection', pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean }, nodes: Array<{ __typename?: 'Event', transactionModule?: { __typename?: 'MoveModule', name: string, package?: { __typename?: 'MovePackage', address: string } | null } | null, sender?: { __typename?: 'Address', address: string } | null, contents?: { __typename?: 'MoveValue', bcs?: string | null, json?: unknown | null, type?: { __typename?: 'MoveType', repr: string } | null } | null }> } | null } | null } | null } | null, outputs?: Array<{ __typename?: 'CommandResult', returnValues?: Array<{ __typename?: 'CommandOutput', value?: { __typename?: 'MoveValue', bcs?: string | null } | null }> | null, mutatedReferences?: Array<{ __typename?: 'CommandOutput', value?: { __typename?: 'MoveValue', bcs?: string | null } | null }> | null }> | null } }; +export type SimulateTransactionQuery = { __typename?: 'Query', simulateTransaction: { __typename?: 'SimulationResult', effects?: { __typename?: 'TransactionEffects', transaction?: { __typename?: 'Transaction', digest: string, transactionJson?: unknown | null, transactionBcs?: string | null, signatures: Array<{ __typename?: 'UserSignature', signatureBytes?: string | null }>, effects?: { __typename?: 'TransactionEffects', status?: ExecutionStatus | null, effectsBcs?: string | null, effectsJson?: unknown | null, balanceChangesJson?: unknown | null, executionError?: { __typename?: 'ExecutionError', message: string, metadata?: unknown | null, abortCode?: string | null, identifier?: string | null, constant?: string | null, sourceLineNumber?: number | null, instructionOffset?: number | null, module?: { __typename?: 'MoveModule', name: string, package?: { __typename?: 'MovePackage', address: string } | null } | null, function?: { __typename?: 'MoveFunction', name: string } | null } | null, epoch?: { __typename?: 'Epoch', epochId: number } | null, objectChanges?: { __typename?: 'ObjectChangeConnection', nodes: Array<{ __typename?: 'ObjectChange', address: string, outputState?: { __typename?: 'Object', asMoveObject?: { __typename?: 'MoveObject', contents?: { __typename?: 'MoveValue', type?: { __typename?: 'MoveType', repr: string } | null } | null } | null } | null }> } | null, events?: { __typename?: 'EventConnection', pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean }, nodes: Array<{ __typename?: 'Event', transactionModule?: { __typename?: 'MoveModule', name: string, package?: { __typename?: 'MovePackage', address: string } | null } | null, sender?: { __typename?: 'Address', address: string } | null, contents?: { __typename?: 'MoveValue', bcs?: string | null, json?: unknown | null, type?: { __typename?: 'MoveType', repr: string } | null } | null }> } | null } | null } | null } | null, outputs?: Array<{ __typename?: 'CommandResult', returnValues?: Array<{ __typename?: 'CommandOutput', value?: { __typename?: 'MoveValue', bcs?: string | null } | null }> | null, mutatedReferences?: Array<{ __typename?: 'CommandOutput', value?: { __typename?: 'MoveValue', bcs?: string | null } | null }> | null }> | null } }; export type ExecuteTransactionMutationVariables = Exact<{ transactionDataBcs: Scalars['Base64']['input']; @@ -5031,7 +5033,7 @@ export type ExecuteTransactionMutationVariables = Exact<{ }>; -export type ExecuteTransactionMutation = { __typename?: 'Mutation', executeTransaction: { __typename?: 'ExecutionResult', effects?: { __typename?: 'TransactionEffects', transaction?: { __typename?: 'Transaction', digest: string, transactionJson?: unknown | null, transactionBcs?: string | null, signatures: Array<{ __typename?: 'UserSignature', signatureBytes?: string | null }>, effects?: { __typename?: 'TransactionEffects', status?: ExecutionStatus | null, effectsBcs?: string | null, effectsJson?: unknown | null, balanceChangesJson?: unknown | null, executionError?: { __typename?: 'ExecutionError', message: string, abortCode?: string | null, identifier?: string | null, constant?: string | null, sourceLineNumber?: number | null, instructionOffset?: number | null, module?: { __typename?: 'MoveModule', name: string, package?: { __typename?: 'MovePackage', address: string } | null } | null, function?: { __typename?: 'MoveFunction', name: string } | null } | null, epoch?: { __typename?: 'Epoch', epochId: number } | null, objectChanges?: { __typename?: 'ObjectChangeConnection', nodes: Array<{ __typename?: 'ObjectChange', address: string, outputState?: { __typename?: 'Object', asMoveObject?: { __typename?: 'MoveObject', contents?: { __typename?: 'MoveValue', type?: { __typename?: 'MoveType', repr: string } | null } | null } | null } | null }> } | null, events?: { __typename?: 'EventConnection', pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean }, nodes: Array<{ __typename?: 'Event', transactionModule?: { __typename?: 'MoveModule', name: string, package?: { __typename?: 'MovePackage', address: string } | null } | null, sender?: { __typename?: 'Address', address: string } | null, contents?: { __typename?: 'MoveValue', bcs?: string | null, json?: unknown | null, type?: { __typename?: 'MoveType', repr: string } | null } | null }> } | null } | null } | null } | null } }; +export type ExecuteTransactionMutation = { __typename?: 'Mutation', executeTransaction: { __typename?: 'ExecutionResult', effects?: { __typename?: 'TransactionEffects', transaction?: { __typename?: 'Transaction', digest: string, transactionJson?: unknown | null, transactionBcs?: string | null, signatures: Array<{ __typename?: 'UserSignature', signatureBytes?: string | null }>, effects?: { __typename?: 'TransactionEffects', status?: ExecutionStatus | null, effectsBcs?: string | null, effectsJson?: unknown | null, balanceChangesJson?: unknown | null, executionError?: { __typename?: 'ExecutionError', message: string, metadata?: unknown | null, abortCode?: string | null, identifier?: string | null, constant?: string | null, sourceLineNumber?: number | null, instructionOffset?: number | null, module?: { __typename?: 'MoveModule', name: string, package?: { __typename?: 'MovePackage', address: string } | null } | null, function?: { __typename?: 'MoveFunction', name: string } | null } | null, epoch?: { __typename?: 'Epoch', epochId: number } | null, objectChanges?: { __typename?: 'ObjectChangeConnection', nodes: Array<{ __typename?: 'ObjectChange', address: string, outputState?: { __typename?: 'Object', asMoveObject?: { __typename?: 'MoveObject', contents?: { __typename?: 'MoveValue', type?: { __typename?: 'MoveType', repr: string } | null } | null } | null } | null }> } | null, events?: { __typename?: 'EventConnection', pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean }, nodes: Array<{ __typename?: 'Event', transactionModule?: { __typename?: 'MoveModule', name: string, package?: { __typename?: 'MovePackage', address: string } | null } | null, sender?: { __typename?: 'Address', address: string } | null, contents?: { __typename?: 'MoveValue', bcs?: string | null, json?: unknown | null, type?: { __typename?: 'MoveType', repr: string } | null } | null }> } | null } | null } | null } | null } }; export type GetTransactionBlockQueryVariables = Exact<{ digest: Scalars['String']['input']; @@ -5044,9 +5046,9 @@ export type GetTransactionBlockQueryVariables = Exact<{ }>; -export type GetTransactionBlockQuery = { __typename?: 'Query', transaction?: { __typename?: 'Transaction', digest: string, transactionJson?: unknown | null, transactionBcs?: string | null, signatures: Array<{ __typename?: 'UserSignature', signatureBytes?: string | null }>, effects?: { __typename?: 'TransactionEffects', status?: ExecutionStatus | null, effectsBcs?: string | null, effectsJson?: unknown | null, balanceChangesJson?: unknown | null, executionError?: { __typename?: 'ExecutionError', message: string, abortCode?: string | null, identifier?: string | null, constant?: string | null, sourceLineNumber?: number | null, instructionOffset?: number | null, module?: { __typename?: 'MoveModule', name: string, package?: { __typename?: 'MovePackage', address: string } | null } | null, function?: { __typename?: 'MoveFunction', name: string } | null } | null, epoch?: { __typename?: 'Epoch', epochId: number } | null, objectChanges?: { __typename?: 'ObjectChangeConnection', nodes: Array<{ __typename?: 'ObjectChange', address: string, outputState?: { __typename?: 'Object', asMoveObject?: { __typename?: 'MoveObject', contents?: { __typename?: 'MoveValue', type?: { __typename?: 'MoveType', repr: string } | null } | null } | null } | null }> } | null, events?: { __typename?: 'EventConnection', pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean }, nodes: Array<{ __typename?: 'Event', transactionModule?: { __typename?: 'MoveModule', name: string, package?: { __typename?: 'MovePackage', address: string } | null } | null, sender?: { __typename?: 'Address', address: string } | null, contents?: { __typename?: 'MoveValue', bcs?: string | null, json?: unknown | null, type?: { __typename?: 'MoveType', repr: string } | null } | null }> } | null } | null } | null }; +export type GetTransactionBlockQuery = { __typename?: 'Query', transaction?: { __typename?: 'Transaction', digest: string, transactionJson?: unknown | null, transactionBcs?: string | null, signatures: Array<{ __typename?: 'UserSignature', signatureBytes?: string | null }>, effects?: { __typename?: 'TransactionEffects', status?: ExecutionStatus | null, effectsBcs?: string | null, effectsJson?: unknown | null, balanceChangesJson?: unknown | null, executionError?: { __typename?: 'ExecutionError', message: string, metadata?: unknown | null, abortCode?: string | null, identifier?: string | null, constant?: string | null, sourceLineNumber?: number | null, instructionOffset?: number | null, module?: { __typename?: 'MoveModule', name: string, package?: { __typename?: 'MovePackage', address: string } | null } | null, function?: { __typename?: 'MoveFunction', name: string } | null } | null, epoch?: { __typename?: 'Epoch', epochId: number } | null, objectChanges?: { __typename?: 'ObjectChangeConnection', nodes: Array<{ __typename?: 'ObjectChange', address: string, outputState?: { __typename?: 'Object', asMoveObject?: { __typename?: 'MoveObject', contents?: { __typename?: 'MoveValue', type?: { __typename?: 'MoveType', repr: string } | null } | null } | null } | null }> } | null, events?: { __typename?: 'EventConnection', pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean }, nodes: Array<{ __typename?: 'Event', transactionModule?: { __typename?: 'MoveModule', name: string, package?: { __typename?: 'MovePackage', address: string } | null } | null, sender?: { __typename?: 'Address', address: string } | null, contents?: { __typename?: 'MoveValue', bcs?: string | null, json?: unknown | null, type?: { __typename?: 'MoveType', repr: string } | null } | null }> } | null } | null } | null }; -export type Transaction_FieldsFragment = { __typename?: 'Transaction', digest: string, transactionJson?: unknown | null, transactionBcs?: string | null, signatures: Array<{ __typename?: 'UserSignature', signatureBytes?: string | null }>, effects?: { __typename?: 'TransactionEffects', status?: ExecutionStatus | null, effectsBcs?: string | null, effectsJson?: unknown | null, balanceChangesJson?: unknown | null, executionError?: { __typename?: 'ExecutionError', message: string, abortCode?: string | null, identifier?: string | null, constant?: string | null, sourceLineNumber?: number | null, instructionOffset?: number | null, module?: { __typename?: 'MoveModule', name: string, package?: { __typename?: 'MovePackage', address: string } | null } | null, function?: { __typename?: 'MoveFunction', name: string } | null } | null, epoch?: { __typename?: 'Epoch', epochId: number } | null, objectChanges?: { __typename?: 'ObjectChangeConnection', nodes: Array<{ __typename?: 'ObjectChange', address: string, outputState?: { __typename?: 'Object', asMoveObject?: { __typename?: 'MoveObject', contents?: { __typename?: 'MoveValue', type?: { __typename?: 'MoveType', repr: string } | null } | null } | null } | null }> } | null, events?: { __typename?: 'EventConnection', pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean }, nodes: Array<{ __typename?: 'Event', transactionModule?: { __typename?: 'MoveModule', name: string, package?: { __typename?: 'MovePackage', address: string } | null } | null, sender?: { __typename?: 'Address', address: string } | null, contents?: { __typename?: 'MoveValue', bcs?: string | null, json?: unknown | null, type?: { __typename?: 'MoveType', repr: string } | null } | null }> } | null } | null }; +export type Transaction_FieldsFragment = { __typename?: 'Transaction', digest: string, transactionJson?: unknown | null, transactionBcs?: string | null, signatures: Array<{ __typename?: 'UserSignature', signatureBytes?: string | null }>, effects?: { __typename?: 'TransactionEffects', status?: ExecutionStatus | null, effectsBcs?: string | null, effectsJson?: unknown | null, balanceChangesJson?: unknown | null, executionError?: { __typename?: 'ExecutionError', message: string, metadata?: unknown | null, abortCode?: string | null, identifier?: string | null, constant?: string | null, sourceLineNumber?: number | null, instructionOffset?: number | null, module?: { __typename?: 'MoveModule', name: string, package?: { __typename?: 'MovePackage', address: string } | null } | null, function?: { __typename?: 'MoveFunction', name: string } | null } | null, epoch?: { __typename?: 'Epoch', epochId: number } | null, objectChanges?: { __typename?: 'ObjectChangeConnection', nodes: Array<{ __typename?: 'ObjectChange', address: string, outputState?: { __typename?: 'Object', asMoveObject?: { __typename?: 'MoveObject', contents?: { __typename?: 'MoveValue', type?: { __typename?: 'MoveType', repr: string } | null } | null } | null } | null }> } | null, events?: { __typename?: 'EventConnection', pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean }, nodes: Array<{ __typename?: 'Event', transactionModule?: { __typename?: 'MoveModule', name: string, package?: { __typename?: 'MovePackage', address: string } | null } | null, sender?: { __typename?: 'Address', address: string } | null, contents?: { __typename?: 'MoveValue', bcs?: string | null, json?: unknown | null, type?: { __typename?: 'MoveType', repr: string } | null } | null }> } | null } | null }; export type ResolveTransactionQueryVariables = Exact<{ transaction: Scalars['JSON']['input']; @@ -5054,7 +5056,7 @@ export type ResolveTransactionQueryVariables = Exact<{ }>; -export type ResolveTransactionQuery = { __typename?: 'Query', simulateTransaction: { __typename?: 'SimulationResult', effects?: { __typename?: 'TransactionEffects', transaction?: { __typename?: 'Transaction', transactionBcs?: string | null, effects?: { __typename?: 'TransactionEffects', status?: ExecutionStatus | null, executionError?: { __typename?: 'ExecutionError', message: string, abortCode?: string | null, identifier?: string | null, constant?: string | null, sourceLineNumber?: number | null, instructionOffset?: number | null, module?: { __typename?: 'MoveModule', name: string, package?: { __typename?: 'MovePackage', address: string } | null } | null, function?: { __typename?: 'MoveFunction', name: string } | null } | null } | null } | null } | null } }; +export type ResolveTransactionQuery = { __typename?: 'Query', simulateTransaction: { __typename?: 'SimulationResult', effects?: { __typename?: 'TransactionEffects', transaction?: { __typename?: 'Transaction', transactionBcs?: string | null, effects?: { __typename?: 'TransactionEffects', status?: ExecutionStatus | null, executionError?: { __typename?: 'ExecutionError', message: string, metadata?: unknown | null, abortCode?: string | null, identifier?: string | null, constant?: string | null, sourceLineNumber?: number | null, instructionOffset?: number | null, module?: { __typename?: 'MoveModule', name: string, package?: { __typename?: 'MovePackage', address: string } | null } | null, function?: { __typename?: 'MoveFunction', name: string } | null } | null } | null } | null } | null } }; export type VerifyZkLoginSignatureQueryVariables = Exact<{ bytes: Scalars['Base64']['input']; @@ -5217,6 +5219,7 @@ export const Transaction_FieldsFragmentDoc = new TypedDocumentString(` status executionError { message + metadata abortCode identifier constant @@ -5637,6 +5640,7 @@ export const SimulateTransactionDocument = new TypedDocumentString(` status executionError { message + metadata abortCode identifier constant @@ -5721,6 +5725,7 @@ export const ExecuteTransactionDocument = new TypedDocumentString(` status executionError { message + metadata abortCode identifier constant @@ -5798,6 +5803,7 @@ export const GetTransactionBlockDocument = new TypedDocumentString(` status executionError { message + metadata abortCode identifier constant @@ -5868,6 +5874,7 @@ export const ResolveTransactionDocument = new TypedDocumentString(` status executionError { message + metadata abortCode identifier constant diff --git a/packages/sui/src/graphql/generated/schema.graphql b/packages/sui/src/graphql/generated/schema.graphql index 603669b41..9a2660b04 100644 --- a/packages/sui/src/graphql/generated/schema.graphql +++ b/packages/sui/src/graphql/generated/schema.graphql @@ -1500,6 +1500,10 @@ type ExecutionError { """ message: String! """ + Additional error metadata, when available. + """ + metadata: JSON + """ The module that the abort originated from. Only populated for Move aborts and primitive runtime errors. """ module: MoveModule diff --git a/packages/sui/src/graphql/generated/tada-env.ts b/packages/sui/src/graphql/generated/tada-env.ts index 6a3489a3a..dbf433df5 100644 --- a/packages/sui/src/graphql/generated/tada-env.ts +++ b/packages/sui/src/graphql/generated/tada-env.ts @@ -4418,6 +4418,15 @@ const introspection = { "args": [], "isDeprecated": false }, + { + "name": "metadata", + "type": { + "kind": "SCALAR", + "name": "JSON" + }, + "args": [], + "isDeprecated": false + }, { "name": "module", "type": { diff --git a/packages/sui/src/graphql/queries/transactions.graphql b/packages/sui/src/graphql/queries/transactions.graphql index a66ef719e..96e1619cd 100644 --- a/packages/sui/src/graphql/queries/transactions.graphql +++ b/packages/sui/src/graphql/queries/transactions.graphql @@ -82,6 +82,7 @@ fragment TRANSACTION_FIELDS on Transaction { status executionError { message + metadata abortCode identifier constant @@ -152,6 +153,7 @@ query resolveTransaction($transaction: JSON!, $doGasSelection: Boolean = true) { status executionError { message + metadata abortCode identifier constant diff --git a/packages/sui/src/grpc/core.ts b/packages/sui/src/grpc/core.ts index 795fed56f..bfb9284d9 100644 --- a/packages/sui/src/grpc/core.ts +++ b/packages/sui/src/grpc/core.ts @@ -304,7 +304,13 @@ export class GrpcCoreClient extends CoreClient { async getTransaction( options: SuiClientTypes.GetTransactionOptions, ): Promise> { - const paths = ['digest', 'transaction.digest', 'signatures', 'effects.status']; + const paths = [ + 'digest', + 'transaction.digest', + 'signatures', + 'effects.status', + 'effects.status.error.metadata', + ]; if (options.include?.transaction) { paths.push( 'transaction.sender', @@ -346,7 +352,13 @@ export class GrpcCoreClient extends CoreClient { async executeTransaction( options: SuiClientTypes.ExecuteTransactionOptions, ): Promise> { - const paths = ['digest', 'transaction.digest', 'signatures', 'effects.status']; + const paths = [ + 'digest', + 'transaction.digest', + 'signatures', + 'effects.status', + 'effects.status.error.metadata', + ]; if (options.include?.transaction) { paths.push( 'transaction.sender', @@ -401,6 +413,7 @@ export class GrpcCoreClient extends CoreClient { 'transaction.transaction.digest', 'transaction.signatures', 'transaction.effects.status', + 'transaction.effects.status.error.metadata', ]; if (options.include?.transaction) { paths.push( @@ -763,6 +776,7 @@ export class GrpcCoreClient extends CoreClient { 'transaction.transaction.expiration', 'transaction.transaction.kind', 'transaction.effects.status', + 'transaction.effects.status.error.metadata', ], }, }); @@ -869,6 +883,7 @@ function parseGrpcExecutionError(error: GrpcExecutionError): SuiClientTypes.Exec const message = error.description ?? 'Unknown error'; const command = error.command != null ? Number(error.command) : undefined; const details = error.errorDetails; + const metadata = error.metadata; switch (details?.oneofKind) { case 'abort': { @@ -893,6 +908,7 @@ function parseGrpcExecutionError(error: GrpcExecutionError): SuiClientTypes.Exec : undefined, }), command, + metadata, MoveAbort: parseMoveAbort(abort), }; } @@ -902,6 +918,7 @@ function parseGrpcExecutionError(error: GrpcExecutionError): SuiClientTypes.Exec $kind: 'SizeError', message, command, + metadata, SizeError: { name: mapErrorName(error.kind), size: Number(details.sizeError.size ?? 0n), @@ -914,6 +931,7 @@ function parseGrpcExecutionError(error: GrpcExecutionError): SuiClientTypes.Exec $kind: 'CommandArgumentError', message, command, + metadata, CommandArgumentError: { argument: details.commandArgumentError.argument ?? 0, name: mapErrorName(details.commandArgumentError.kind), @@ -925,6 +943,7 @@ function parseGrpcExecutionError(error: GrpcExecutionError): SuiClientTypes.Exec $kind: 'TypeArgumentError', message, command, + metadata, TypeArgumentError: { typeArgument: details.typeArgumentError.typeArgument ?? 0, name: mapErrorName(details.typeArgumentError.kind), @@ -936,6 +955,7 @@ function parseGrpcExecutionError(error: GrpcExecutionError): SuiClientTypes.Exec $kind: 'PackageUpgradeError', message, command, + metadata, PackageUpgradeError: { name: mapErrorName(details.packageUpgradeError.kind), packageId: details.packageUpgradeError.packageId, @@ -948,6 +968,7 @@ function parseGrpcExecutionError(error: GrpcExecutionError): SuiClientTypes.Exec $kind: 'IndexError', message, command, + metadata, IndexError: { index: details.indexError.index, subresult: details.indexError.subresult, @@ -959,6 +980,7 @@ function parseGrpcExecutionError(error: GrpcExecutionError): SuiClientTypes.Exec $kind: 'CoinDenyListError', message, command, + metadata, CoinDenyListError: { name: mapErrorName(error.kind), coinType: details.coinDenyListError.coinType!, @@ -971,6 +993,7 @@ function parseGrpcExecutionError(error: GrpcExecutionError): SuiClientTypes.Exec $kind: 'CongestedObjects', message, command, + metadata, CongestedObjects: { name: mapErrorName(error.kind), objects: details.congestedObjects.objects, @@ -982,6 +1005,7 @@ function parseGrpcExecutionError(error: GrpcExecutionError): SuiClientTypes.Exec $kind: 'ObjectIdError', message, command, + metadata, ObjectIdError: { name: mapErrorName(error.kind), objectId: details.objectId, @@ -993,6 +1017,7 @@ function parseGrpcExecutionError(error: GrpcExecutionError): SuiClientTypes.Exec $kind: 'Unknown', message, command, + metadata, Unknown: null, }; } diff --git a/packages/sui/src/grpc/proto/sui/rpc/v2/execution_status.ts b/packages/sui/src/grpc/proto/sui/rpc/v2/execution_status.ts index e7054f90e..1bc7c4510 100644 --- a/packages/sui/src/grpc/proto/sui/rpc/v2/execution_status.ts +++ b/packages/sui/src/grpc/proto/sui/rpc/v2/execution_status.ts @@ -123,6 +123,15 @@ export interface ExecutionError { | { oneofKind: undefined; }; + /** + * Additional non-consensus metadata associated with this execution error. + * + * This metadata is produced by the executing node and is not part of the + * certified transaction effects. + * + * @generated from protobuf field: optional sui.rpc.v2.ExecutionErrorMetadata metadata = 100; + */ + metadata?: ExecutionErrorMetadata; } /** * @generated from protobuf enum sui.rpc.v2.ExecutionError.ExecutionErrorKind @@ -399,6 +408,15 @@ export enum ExecutionError_ExecutionErrorKind { */ NON_EXCLUSIVE_WRITE_INPUT_OBJECT_MODIFIED = 42, } +/** + * @generated from protobuf message sui.rpc.v2.ExecutionErrorMetadata + */ +export interface ExecutionErrorMetadata { + /** + * @generated from protobuf field: optional string message = 1; + */ + message?: string; +} /** * @generated from protobuf message sui.rpc.v2.MoveAbort */ @@ -927,6 +945,7 @@ class ExecutionError$Type extends MessageType { oneof: 'errorDetails', T: () => CongestedObjects, }, + { no: 100, name: 'metadata', kind: 'message', T: () => ExecutionErrorMetadata }, ]); } } @@ -935,6 +954,18 @@ class ExecutionError$Type extends MessageType { */ export const ExecutionError = new ExecutionError$Type(); // @generated message type with reflection information, may provide speed optimized methods +class ExecutionErrorMetadata$Type extends MessageType { + constructor() { + super('sui.rpc.v2.ExecutionErrorMetadata', [ + { no: 1, name: 'message', kind: 'scalar', opt: true, T: 9 /*ScalarType.STRING*/ }, + ]); + } +} +/** + * @generated MessageType for protobuf message sui.rpc.v2.ExecutionErrorMetadata + */ +export const ExecutionErrorMetadata = new ExecutionErrorMetadata$Type(); +// @generated message type with reflection information, may provide speed optimized methods class MoveAbort$Type extends MessageType { constructor() { super('sui.rpc.v2.MoveAbort', [