@mysten/sui 2.1.0 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/bcs/bcs.d.mts +6 -6
  3. package/dist/bcs/index.d.mts +20 -20
  4. package/dist/client/client.d.mts.map +1 -1
  5. package/dist/client/client.mjs +3 -2
  6. package/dist/client/client.mjs.map +1 -1
  7. package/dist/client/core-resolver.d.mts.map +1 -1
  8. package/dist/client/core-resolver.mjs +6 -2
  9. package/dist/client/core-resolver.mjs.map +1 -1
  10. package/dist/client/core.d.mts +1 -0
  11. package/dist/client/core.d.mts.map +1 -1
  12. package/dist/client/core.mjs.map +1 -1
  13. package/dist/client/errors.d.mts +15 -0
  14. package/dist/client/errors.d.mts.map +1 -0
  15. package/dist/client/errors.mjs +7 -1
  16. package/dist/client/errors.mjs.map +1 -1
  17. package/dist/client/index.d.mts +2 -1
  18. package/dist/client/index.mjs +2 -1
  19. package/dist/client/types.d.mts +18 -0
  20. package/dist/client/types.d.mts.map +1 -1
  21. package/dist/client/utils.d.mts.map +1 -1
  22. package/dist/client/utils.mjs +20 -14
  23. package/dist/client/utils.mjs.map +1 -1
  24. package/dist/cryptography/signature.d.mts +6 -6
  25. package/dist/graphql/client.d.mts +1 -0
  26. package/dist/graphql/client.d.mts.map +1 -1
  27. package/dist/graphql/client.mjs +3 -0
  28. package/dist/graphql/client.mjs.map +1 -1
  29. package/dist/graphql/core.d.mts +1 -0
  30. package/dist/graphql/core.d.mts.map +1 -1
  31. package/dist/graphql/core.mjs +59 -17
  32. package/dist/graphql/core.mjs.map +1 -1
  33. package/dist/graphql/generated/queries.d.mts.map +1 -1
  34. package/dist/graphql/generated/queries.mjs +33 -1
  35. package/dist/graphql/generated/queries.mjs.map +1 -1
  36. package/dist/grpc/client.d.mts +1 -0
  37. package/dist/grpc/client.d.mts.map +1 -1
  38. package/dist/grpc/client.mjs +3 -0
  39. package/dist/grpc/client.mjs.map +1 -1
  40. package/dist/grpc/core.d.mts +1 -0
  41. package/dist/grpc/core.d.mts.map +1 -1
  42. package/dist/grpc/core.mjs +27 -6
  43. package/dist/grpc/core.mjs.map +1 -1
  44. package/dist/grpc/proto/sui/rpc/v2/ledger_service.client.d.mts +4 -4
  45. package/dist/grpc/proto/sui/rpc/v2/move_package_service.client.d.mts +4 -4
  46. package/dist/grpc/proto/sui/rpc/v2/signature_verification_service.client.d.mts +4 -4
  47. package/dist/grpc/proto/sui/rpc/v2/state_service.client.d.mts +4 -4
  48. package/dist/grpc/proto/sui/rpc/v2/subscription_service.client.d.mts +4 -4
  49. package/dist/grpc/proto/sui/rpc/v2/transaction.d.mts.map +1 -1
  50. package/dist/grpc/proto/sui/rpc/v2/transaction_execution_service.client.d.mts +4 -4
  51. package/dist/jsonRpc/core.d.mts +1 -0
  52. package/dist/jsonRpc/core.d.mts.map +1 -1
  53. package/dist/jsonRpc/core.mjs +17 -1
  54. package/dist/jsonRpc/core.mjs.map +1 -1
  55. package/dist/transactions/Transaction.d.mts +9 -9
  56. package/dist/transactions/Transaction.d.mts.map +1 -1
  57. package/dist/version.mjs +1 -1
  58. package/dist/version.mjs.map +1 -1
  59. package/dist/zklogin/bcs.d.mts +14 -14
  60. package/dist/zklogin/bcs.d.mts.map +1 -1
  61. package/package.json +1 -1
  62. package/src/client/client.ts +5 -2
  63. package/src/client/core-resolver.ts +7 -7
  64. package/src/client/core.ts +4 -0
  65. package/src/client/errors.ts +13 -0
  66. package/src/client/index.ts +2 -0
  67. package/src/client/types.ts +22 -0
  68. package/src/client/utils.ts +26 -19
  69. package/src/graphql/client.ts +6 -0
  70. package/src/graphql/core.ts +78 -11
  71. package/src/graphql/generated/queries.ts +41 -2
  72. package/src/graphql/queries/getCoinMetadata.graphql +13 -0
  73. package/src/graphql/queries/transactions.graphql +20 -0
  74. package/src/grpc/client.ts +6 -0
  75. package/src/grpc/core.ts +50 -4
  76. package/src/jsonRpc/core.ts +26 -0
  77. package/src/version.ts +1 -1
@@ -22,5 +22,7 @@ export {
22
22
  type ClientWithCoreApi,
23
23
  };
24
24
 
25
+ export { SimulationError } from './errors.js';
26
+
25
27
  export { ClientCache, type ClientCacheOptions } from './cache.js';
26
28
  export { type NamedPackagesOverrides } from './mvr.js';
@@ -235,6 +235,28 @@ export namespace SuiClientTypes {
235
235
  cursor: string | null;
236
236
  }
237
237
 
238
+ /** Coin metadata methods */
239
+ export interface TransportMethods {
240
+ getCoinMetadata: (options: GetCoinMetadataOptions) => Promise<GetCoinMetadataResponse>;
241
+ }
242
+
243
+ export interface GetCoinMetadataOptions extends CoreClientMethodOptions {
244
+ coinType: string;
245
+ }
246
+
247
+ export interface CoinMetadata {
248
+ id: string | null;
249
+ decimals: number;
250
+ name: string;
251
+ symbol: string;
252
+ description: string;
253
+ iconUrl: string | null;
254
+ }
255
+
256
+ export interface GetCoinMetadataResponse {
257
+ coinMetadata: CoinMetadata | null;
258
+ }
259
+
238
260
  /** Transaction methods */
239
261
  export interface TransportMethods {
240
262
  getTransaction: <Include extends TransactionInclude = {}>(
@@ -39,13 +39,24 @@ export function formatMoveAbortMessage(options: {
39
39
  const parts: string[] = [];
40
40
 
41
41
  if (command != null) {
42
- parts.push(`Error in ${formatOrdinal(command + 1)} command`);
42
+ parts.push(`MoveAbort in ${formatOrdinal(command + 1)} command`);
43
+ } else {
44
+ parts.push('MoveAbort');
45
+ }
46
+
47
+ if (cleverError?.constantName) {
48
+ const errorStr = cleverError!.value
49
+ ? `'${cleverError!.constantName}': ${cleverError!.value}`
50
+ : `'${cleverError!.constantName}'`;
51
+ parts.push(errorStr);
52
+ } else {
53
+ parts.push(`abort code: ${abortCode}`);
43
54
  }
44
55
 
45
56
  if (location?.package && location?.module) {
46
57
  const pkg = location.package.startsWith('0x') ? location.package : `0x${location.package}`;
47
58
  const locationParts = [pkg, location.module, location.functionName].filter(Boolean);
48
- const locationStr = [`from '${locationParts.join('::')}'`];
59
+ const locationStr = [`in '${locationParts.join('::')}'`];
49
60
 
50
61
  if (cleverError?.lineNumber != null) {
51
62
  locationStr.push(`(line ${cleverError.lineNumber})`);
@@ -56,15 +67,6 @@ export function formatMoveAbortMessage(options: {
56
67
  parts.push(locationStr.join(' '));
57
68
  }
58
69
 
59
- if (cleverError?.constantName) {
60
- const abortStr = cleverError.value
61
- ? `abort '${cleverError.constantName}': ${cleverError.value}`
62
- : `abort '${cleverError.constantName}'`;
63
- parts.push(abortStr);
64
- } else {
65
- parts.push(`abort code: ${abortCode}`);
66
- }
67
-
68
70
  return parts.join(', ');
69
71
  }
70
72
 
@@ -118,19 +120,24 @@ function parseBcsExecutionError(failure: {
118
120
  switch (error.$kind) {
119
121
  case 'MoveAbort': {
120
122
  const [location, abortCode] = error.MoveAbort;
123
+ const moveLocation = {
124
+ package: location.module.address,
125
+ module: location.module.name,
126
+ function: location.function,
127
+ functionName: location.functionName ?? undefined,
128
+ instruction: location.instruction,
129
+ };
121
130
  return {
122
131
  $kind: 'MoveAbort',
123
- message: formatErrorMessage('MoveAbort', error.MoveAbort),
132
+ message: formatMoveAbortMessage({
133
+ command,
134
+ location: moveLocation,
135
+ abortCode: String(abortCode),
136
+ }),
124
137
  command,
125
138
  MoveAbort: {
126
139
  abortCode: String(abortCode),
127
- location: {
128
- package: location.module.address,
129
- module: location.module.name,
130
- function: location.function,
131
- functionName: location.functionName ?? undefined,
132
- instruction: location.instruction,
133
- },
140
+ location: moveLocation,
134
141
  },
135
142
  };
136
143
  }
@@ -180,6 +180,12 @@ export class SuiGraphQLClient<Queries extends Record<string, GraphQLDocument> =
180
180
  return this.core.listBalances(input);
181
181
  }
182
182
 
183
+ getCoinMetadata(
184
+ input: SuiClientTypes.GetCoinMetadataOptions,
185
+ ): Promise<SuiClientTypes.GetCoinMetadataResponse> {
186
+ return this.core.getCoinMetadata(input);
187
+ }
188
+
183
189
  getTransaction<Include extends SuiClientTypes.TransactionInclude = {}>(
184
190
  input: SuiClientTypes.GetTransactionOptions<Include>,
185
191
  ): Promise<SuiClientTypes.TransactionResult<Include>> {
@@ -20,6 +20,7 @@ import {
20
20
  GetAllBalancesDocument,
21
21
  GetBalanceDocument,
22
22
  GetChainIdentifierDocument,
23
+ GetCoinMetadataDocument,
23
24
  GetCoinsDocument,
24
25
  GetCurrentSystemStateDocument,
25
26
  GetDynamicFieldsDocument,
@@ -33,11 +34,11 @@ import {
33
34
  VerifyZkLoginSignatureDocument,
34
35
  ZkLoginIntentScope,
35
36
  } from './generated/queries.js';
36
- import { ObjectError } from '../client/errors.js';
37
+ import { ObjectError, SimulationError } from '../client/errors.js';
37
38
  import { chunk, fromBase64, toBase64 } from '@mysten/utils';
38
39
  import { normalizeStructTag, normalizeSuiAddress } from '../utils/sui-types.js';
39
40
  import { deriveDynamicFieldID } from '../utils/dynamic-fields.js';
40
- import { parseTransactionEffectsBcs } from '../client/utils.js';
41
+ import { formatMoveAbortMessage, parseTransactionEffectsBcs } from '../client/utils.js';
41
42
  import type { OpenMoveTypeSignatureBody, OpenMoveTypeSignature } from './types.js';
42
43
  import {
43
44
  transactionDataToGrpcTransaction,
@@ -269,6 +270,36 @@ export class GraphQLCoreClient extends CoreClient {
269
270
  },
270
271
  };
271
272
  }
273
+ async getCoinMetadata(
274
+ options: SuiClientTypes.GetCoinMetadataOptions,
275
+ ): Promise<SuiClientTypes.GetCoinMetadataResponse> {
276
+ const coinType = (await this.mvr.resolveType({ type: options.coinType })).type;
277
+
278
+ const { data, errors } = await this.#graphqlClient.query({
279
+ query: GetCoinMetadataDocument,
280
+ variables: {
281
+ coinType,
282
+ },
283
+ });
284
+
285
+ handleGraphQLErrors(errors);
286
+
287
+ if (!data?.coinMetadata) {
288
+ return { coinMetadata: null };
289
+ }
290
+
291
+ return {
292
+ coinMetadata: {
293
+ id: data.coinMetadata.address!,
294
+ decimals: data.coinMetadata.decimals!,
295
+ name: data.coinMetadata.name!,
296
+ symbol: data.coinMetadata.symbol!,
297
+ description: data.coinMetadata.description!,
298
+ iconUrl: data.coinMetadata.iconUrl ?? null,
299
+ },
300
+ };
301
+ }
302
+
272
303
  async listBalances(
273
304
  options: SuiClientTypes.ListBalancesOptions,
274
305
  ): Promise<SuiClientTypes.ListBalancesResponse> {
@@ -376,8 +407,8 @@ export class GraphQLCoreClient extends CoreClient {
376
407
  (result) => result.simulateTransaction,
377
408
  );
378
409
 
379
- if (result.error) {
380
- throw new Error(result.error);
410
+ if (result.error && !result.effects?.transaction) {
411
+ throw new SimulationError(result.error);
381
412
  }
382
413
 
383
414
  const transactionResult = parseTransaction(result.effects?.transaction!, options.include);
@@ -716,14 +747,27 @@ export class GraphQLCoreClient extends CoreClient {
716
747
  query: ResolveTransactionDocument,
717
748
  variables: {
718
749
  transaction: transactionJson,
719
- doGasSelection: !options.onlyTransactionKind,
750
+ doGasSelection:
751
+ !options.onlyTransactionKind &&
752
+ (snapshot.gasData.budget == null || snapshot.gasData.payment == null),
720
753
  },
721
754
  });
722
755
 
723
756
  handleGraphQLErrors(errors);
724
757
 
725
758
  if (data?.simulateTransaction?.error) {
726
- throw new Error(`Transaction resolution failed: ${data.simulateTransaction.error}`);
759
+ throw new SimulationError(
760
+ `Transaction resolution failed: ${data.simulateTransaction.error}`,
761
+ );
762
+ }
763
+
764
+ const transactionEffects = data?.simulateTransaction?.effects?.transaction?.effects;
765
+ if (!options.onlyTransactionKind && transactionEffects?.status === ExecutionStatus.Failure) {
766
+ const executionError = parseGraphQLExecutionError(transactionEffects.executionError);
767
+ const errorMessage = executionError?.message ?? 'Transaction failed';
768
+ throw new SimulationError(`Transaction resolution failed: ${errorMessage}`, {
769
+ executionError,
770
+ });
727
771
  }
728
772
 
729
773
  const resolvedTransactionBcs =
@@ -935,24 +979,47 @@ function parseNormalizedSuiMoveType(type: OpenMoveTypeSignature): SuiClientTypes
935
979
  function parseGraphQLExecutionError(
936
980
  executionError: GraphQLExecutionError | null | undefined,
937
981
  ): SuiClientTypes.ExecutionError {
938
- const message = executionError?.message ?? 'Transaction failed';
939
982
  const name = mapGraphQLExecutionErrorKind(executionError);
940
983
 
941
984
  if (name === 'MoveAbort' && executionError?.abortCode != null) {
985
+ const location = parseGraphQLMoveLocation(executionError);
986
+ const cleverError = parseGraphQLCleverError(executionError);
987
+ const commandMatch = executionError.message?.match(/in (\d+)\w* command/);
988
+ const command = commandMatch ? parseInt(commandMatch[1], 10) - 1 : undefined;
989
+
942
990
  return {
943
991
  $kind: 'MoveAbort',
944
- message,
992
+ message: formatMoveAbortMessage({
993
+ command,
994
+ location: location
995
+ ? {
996
+ package: location.package,
997
+ module: location.module,
998
+ functionName: location.functionName,
999
+ instruction: location.instruction,
1000
+ }
1001
+ : undefined,
1002
+ abortCode: executionError.abortCode!,
1003
+ cleverError: cleverError
1004
+ ? {
1005
+ lineNumber: cleverError.lineNumber,
1006
+ constantName: cleverError.constantName,
1007
+ value: cleverError.value,
1008
+ }
1009
+ : undefined,
1010
+ }),
1011
+ command,
945
1012
  MoveAbort: {
946
1013
  abortCode: executionError.abortCode!,
947
- location: parseGraphQLMoveLocation(executionError),
948
- cleverError: parseGraphQLCleverError(executionError),
1014
+ location,
1015
+ cleverError,
949
1016
  },
950
1017
  };
951
1018
  }
952
1019
 
953
1020
  return {
954
1021
  $kind: 'Unknown',
955
- message,
1022
+ message: executionError?.message ?? 'Transaction failed',
956
1023
  Unknown: null,
957
1024
  };
958
1025
  }
@@ -3587,7 +3587,7 @@ export type Query = {
3587
3587
  * If the address is fetched by name and the name does not resolve to an address (e.g. the name does not exist or has expired), `null` is returned.
3588
3588
  */
3589
3589
  address?: Maybe<Address>;
3590
- /** First four bytes of the network's genesis checkpoint digest (uniquely identifies the network), hex-encoded. */
3590
+ /** The network's genesis checkpoint digest (uniquely identifies the network), Base58-encoded. */
3591
3591
  chainIdentifier: Scalars['String']['output'];
3592
3592
  /**
3593
3593
  * Fetch a checkpoint by its sequence number, or the latest checkpoint if no sequence number is provided.
@@ -4612,6 +4612,13 @@ export type GetChainIdentifierQueryVariables = Exact<{ [key: string]: never; }>;
4612
4612
 
4613
4613
  export type GetChainIdentifierQuery = { __typename?: 'Query', checkpoint?: { __typename?: 'Checkpoint', digest?: string | null } | null };
4614
4614
 
4615
+ export type GetCoinMetadataQueryVariables = Exact<{
4616
+ coinType: Scalars['String']['input'];
4617
+ }>;
4618
+
4619
+
4620
+ export type GetCoinMetadataQuery = { __typename?: 'Query', coinMetadata?: { __typename?: 'CoinMetadata', address: string, decimals?: number | null, name?: string | null, symbol?: string | null, description?: string | null, iconUrl?: string | null } | null };
4621
+
4615
4622
  export type GetCoinsQueryVariables = Exact<{
4616
4623
  owner: Scalars['SuiAddress']['input'];
4617
4624
  first?: InputMaybe<Scalars['Int']['input']>;
@@ -4788,7 +4795,7 @@ export type ResolveTransactionQueryVariables = Exact<{
4788
4795
  }>;
4789
4796
 
4790
4797
 
4791
- export type ResolveTransactionQuery = { __typename?: 'Query', simulateTransaction: { __typename?: 'SimulationResult', error?: string | null, effects?: { __typename?: 'TransactionEffects', transaction?: { __typename?: 'Transaction', transactionBcs?: string | null } | null } | null } };
4798
+ export type ResolveTransactionQuery = { __typename?: 'Query', simulateTransaction: { __typename?: 'SimulationResult', error?: string | null, 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 } };
4792
4799
 
4793
4800
  export type VerifyZkLoginSignatureQueryVariables = Exact<{
4794
4801
  bytes: Scalars['Base64']['input'];
@@ -5042,6 +5049,18 @@ export const GetChainIdentifierDocument = new TypedDocumentString(`
5042
5049
  }
5043
5050
  }
5044
5051
  `) as unknown as TypedDocumentString<GetChainIdentifierQuery, GetChainIdentifierQueryVariables>;
5052
+ export const GetCoinMetadataDocument = new TypedDocumentString(`
5053
+ query getCoinMetadata($coinType: String!) {
5054
+ coinMetadata(coinType: $coinType) {
5055
+ address
5056
+ decimals
5057
+ name
5058
+ symbol
5059
+ description
5060
+ iconUrl
5061
+ }
5062
+ }
5063
+ `) as unknown as TypedDocumentString<GetCoinMetadataQuery, GetCoinMetadataQueryVariables>;
5045
5064
  export const GetCoinsDocument = new TypedDocumentString(`
5046
5065
  query getCoins($owner: SuiAddress!, $first: Int, $cursor: String, $type: String = "0x2::coin::Coin<0x2::sui::SUI>") {
5047
5066
  address(address: $owner) {
@@ -5549,6 +5568,26 @@ export const ResolveTransactionDocument = new TypedDocumentString(`
5549
5568
  effects {
5550
5569
  transaction {
5551
5570
  transactionBcs
5571
+ effects {
5572
+ status
5573
+ executionError {
5574
+ message
5575
+ abortCode
5576
+ identifier
5577
+ constant
5578
+ sourceLineNumber
5579
+ instructionOffset
5580
+ module {
5581
+ name
5582
+ package {
5583
+ address
5584
+ }
5585
+ }
5586
+ function {
5587
+ name
5588
+ }
5589
+ }
5590
+ }
5552
5591
  }
5553
5592
  }
5554
5593
  }
@@ -0,0 +1,13 @@
1
+ # Copyright (c) Mysten Labs, Inc.
2
+ # SPDX-License-Identifier: Apache-2.0
3
+
4
+ query getCoinMetadata($coinType: String!) {
5
+ coinMetadata(coinType: $coinType) {
6
+ address
7
+ decimals
8
+ name
9
+ symbol
10
+ description
11
+ iconUrl
12
+ }
13
+ }
@@ -150,6 +150,26 @@ query resolveTransaction($transaction: JSON!, $doGasSelection: Boolean = true) {
150
150
  effects {
151
151
  transaction {
152
152
  transactionBcs
153
+ effects {
154
+ status
155
+ executionError {
156
+ message
157
+ abortCode
158
+ identifier
159
+ constant
160
+ sourceLineNumber
161
+ instructionOffset
162
+ module {
163
+ name
164
+ package {
165
+ address
166
+ }
167
+ }
168
+ function {
169
+ name
170
+ }
171
+ }
172
+ }
153
173
  }
154
174
  }
155
175
  }
@@ -108,6 +108,12 @@ export class SuiGrpcClient extends BaseClient implements SuiClientTypes.Transpor
108
108
  return this.core.listBalances(input);
109
109
  }
110
110
 
111
+ getCoinMetadata(
112
+ input: SuiClientTypes.GetCoinMetadataOptions,
113
+ ): Promise<SuiClientTypes.GetCoinMetadataResponse> {
114
+ return this.core.getCoinMetadata(input);
115
+ }
116
+
111
117
  getTransaction<Include extends SuiClientTypes.TransactionInclude = {}>(
112
118
  input: SuiClientTypes.GetTransactionOptions<Include>,
113
119
  ): Promise<SuiClientTypes.TransactionResult<Include>> {
package/src/grpc/core.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
4
  import type { CoreClientOptions, SuiClientTypes } from '../client/index.js';
5
- import { CoreClient, formatMoveAbortMessage } from '../client/index.js';
5
+ import { CoreClient, formatMoveAbortMessage, SimulationError } from '../client/index.js';
6
6
  import type { SuiGrpcClient } from './client.js';
7
7
  import type { Owner } from './proto/sui/rpc/v2/owner.js';
8
8
  import { Owner_OwnerKind } from './proto/sui/rpc/v2/owner.js';
@@ -235,6 +235,36 @@ export class GrpcCoreClient extends CoreClient {
235
235
  };
236
236
  }
237
237
 
238
+ async getCoinMetadata(
239
+ options: SuiClientTypes.GetCoinMetadataOptions,
240
+ ): Promise<SuiClientTypes.GetCoinMetadataResponse> {
241
+ const coinType = (await this.mvr.resolveType({ type: options.coinType })).type;
242
+
243
+ let response;
244
+ try {
245
+ ({ response } = await this.#client.stateService.getCoinInfo({
246
+ coinType,
247
+ }));
248
+ } catch {
249
+ return { coinMetadata: null };
250
+ }
251
+
252
+ if (!response.metadata) {
253
+ return { coinMetadata: null };
254
+ }
255
+
256
+ return {
257
+ coinMetadata: {
258
+ id: response.metadata.id ?? null,
259
+ decimals: response.metadata.decimals ?? 0,
260
+ name: response.metadata.name ?? '',
261
+ symbol: response.metadata.symbol ?? '',
262
+ description: response.metadata.description ?? '',
263
+ iconUrl: response.metadata.iconUrl ?? null,
264
+ },
265
+ };
266
+ }
267
+
238
268
  async listBalances(
239
269
  options: SuiClientTypes.ListBalancesOptions,
240
270
  ): Promise<SuiClientTypes.ListBalancesResponse> {
@@ -703,13 +733,16 @@ export class GrpcCoreClient extends CoreClient {
703
733
  try {
704
734
  const result = await client.transactionExecutionService.simulateTransaction({
705
735
  transaction: grpcTransaction,
706
- doGasSelection: !options.onlyTransactionKind,
736
+ doGasSelection:
737
+ !options.onlyTransactionKind &&
738
+ (snapshot.gasData.budget == null || snapshot.gasData.payment == null),
707
739
  readMask: {
708
740
  paths: [
709
741
  'transaction.transaction.sender',
710
742
  'transaction.transaction.gas_payment',
711
743
  'transaction.transaction.expiration',
712
744
  'transaction.transaction.kind',
745
+ 'transaction.effects.status',
713
746
  ],
714
747
  },
715
748
  });
@@ -717,12 +750,25 @@ export class GrpcCoreClient extends CoreClient {
717
750
  } catch (error) {
718
751
  // https://github.com/timostamm/protobuf-ts/pull/739
719
752
  if (error instanceof Error && error.message) {
720
- const decodedMessage = decodeURIComponent(error.message);
721
- throw new Error(decodedMessage, { cause: error });
753
+ throw new SimulationError(decodeURIComponent(error.message), { cause: error });
722
754
  }
723
755
  throw error;
724
756
  }
725
757
 
758
+ if (
759
+ !options.onlyTransactionKind &&
760
+ response.transaction?.effects?.status &&
761
+ !response.transaction.effects.status.success
762
+ ) {
763
+ const executionError = response.transaction.effects.status.error
764
+ ? parseGrpcExecutionError(response.transaction.effects.status.error)
765
+ : undefined;
766
+ const errorMessage = executionError?.message ?? 'Transaction failed';
767
+ throw new SimulationError(`Transaction resolution failed: ${errorMessage}`, {
768
+ executionError,
769
+ });
770
+ }
771
+
726
772
  if (!response.transaction?.transaction) {
727
773
  throw new Error('simulateTransaction did not return resolved transaction data');
728
774
  }
@@ -239,6 +239,32 @@ export class JSONRpcCoreClient extends CoreClient {
239
239
  },
240
240
  };
241
241
  }
242
+ async getCoinMetadata(
243
+ options: SuiClientTypes.GetCoinMetadataOptions,
244
+ ): Promise<SuiClientTypes.GetCoinMetadataResponse> {
245
+ const coinType = (await this.mvr.resolveType({ type: options.coinType })).type;
246
+
247
+ const result = await this.#jsonRpcClient.getCoinMetadata({
248
+ coinType,
249
+ signal: options.signal,
250
+ });
251
+
252
+ if (!result) {
253
+ return { coinMetadata: null };
254
+ }
255
+
256
+ return {
257
+ coinMetadata: {
258
+ id: result.id ?? null,
259
+ decimals: result.decimals,
260
+ name: result.name,
261
+ symbol: result.symbol,
262
+ description: result.description,
263
+ iconUrl: result.iconUrl ?? null,
264
+ },
265
+ };
266
+ }
267
+
242
268
  async listBalances(options: SuiClientTypes.ListBalancesOptions) {
243
269
  const balances = await this.#jsonRpcClient.getAllBalances({
244
270
  owner: options.owner,
package/src/version.ts CHANGED
@@ -3,5 +3,5 @@
3
3
 
4
4
  // This file is generated by genversion.mjs. Do not edit it directly.
5
5
 
6
- export const PACKAGE_VERSION = '2.1.0';
6
+ export const PACKAGE_VERSION = '2.3.0';
7
7
  export const TARGETED_RPC_VERSION = '1.66.0';