@suigar/mcp 0.1.0 → 0.2.0-beta.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 +37 -0
  2. package/LICENSE +201 -0
  3. package/README.md +79 -110
  4. package/dist/app/index.html +181 -0
  5. package/dist/bin.mjs +3 -7
  6. package/dist/bin.mjs.map +1 -0
  7. package/dist/client.d.mts +41 -11
  8. package/dist/client.d.mts.map +1 -0
  9. package/dist/client.mjs +107 -34
  10. package/dist/client.mjs.map +1 -0
  11. package/dist/dry-run.mjs +163 -0
  12. package/dist/dry-run.mjs.map +1 -0
  13. package/dist/format.mjs +24 -0
  14. package/dist/format.mjs.map +1 -0
  15. package/dist/index.d.mts +5 -9
  16. package/dist/index.mjs +4 -8
  17. package/dist/schemas.d.mts +642 -0
  18. package/dist/schemas.d.mts.map +1 -0
  19. package/dist/schemas.mjs +113 -0
  20. package/dist/schemas.mjs.map +1 -0
  21. package/dist/server.d.mts +21 -69
  22. package/dist/server.d.mts.map +1 -0
  23. package/dist/server.mjs +172 -411
  24. package/dist/server.mjs.map +1 -0
  25. package/dist/tools.d.mts +14 -155
  26. package/dist/tools.d.mts.map +1 -0
  27. package/dist/tools.mjs +297 -553
  28. package/dist/tools.mjs.map +1 -0
  29. package/dist/types.d.mts +109 -83
  30. package/dist/types.d.mts.map +1 -0
  31. package/package.json +83 -61
  32. package/dist/bin.cjs +0 -11
  33. package/dist/bin.d.cts +0 -1
  34. package/dist/client.cjs +0 -46
  35. package/dist/client.d.cts +0 -17
  36. package/dist/coin.cjs +0 -86
  37. package/dist/coin.d.cts +0 -35
  38. package/dist/coin.d.mts +0 -35
  39. package/dist/coin.mjs +0 -86
  40. package/dist/config.cjs +0 -183
  41. package/dist/config.d.cts +0 -15
  42. package/dist/config.d.mts +0 -15
  43. package/dist/config.mjs +0 -174
  44. package/dist/index.cjs +0 -53
  45. package/dist/index.d.cts +0 -10
  46. package/dist/mcp-support.cjs +0 -62
  47. package/dist/mcp-support.d.cts +0 -16
  48. package/dist/mcp-support.d.mts +0 -16
  49. package/dist/mcp-support.mjs +0 -60
  50. package/dist/metadata.cjs +0 -51
  51. package/dist/metadata.d.cts +0 -52
  52. package/dist/metadata.d.mts +0 -52
  53. package/dist/metadata.mjs +0 -47
  54. package/dist/server.cjs +0 -433
  55. package/dist/server.d.cts +0 -73
  56. package/dist/tools.cjs +0 -617
  57. package/dist/tools.d.cts +0 -158
  58. package/dist/transactions.cjs +0 -294
  59. package/dist/transactions.d.cts +0 -40
  60. package/dist/transactions.d.mts +0 -40
  61. package/dist/transactions.mjs +0 -286
  62. package/dist/types.d.cts +0 -111
  63. package/node_modules/@suigar/currency-registry/dist/index.cjs +0 -121
  64. package/node_modules/@suigar/currency-registry/dist/index.d.cts +0 -50
  65. package/node_modules/@suigar/currency-registry/dist/index.d.mts +0 -50
  66. package/node_modules/@suigar/currency-registry/dist/index.mjs +0 -110
  67. package/node_modules/@suigar/currency-registry/package.json +0 -31
  68. package/node_modules/@suigar/game-registry/dist/index.cjs +0 -310
  69. package/node_modules/@suigar/game-registry/dist/index.d.cts +0 -65
  70. package/node_modules/@suigar/game-registry/dist/index.d.mts +0 -65
  71. package/node_modules/@suigar/game-registry/dist/index.mjs +0 -292
  72. package/node_modules/@suigar/game-registry/package.json +0 -31
  73. package/node_modules/@suigar/sui-rpc-pool/dist/index.cjs +0 -45590
  74. package/node_modules/@suigar/sui-rpc-pool/dist/index.d.cts +0 -465
  75. package/node_modules/@suigar/sui-rpc-pool/dist/index.d.mts +0 -465
  76. package/node_modules/@suigar/sui-rpc-pool/dist/index.mjs +0 -45570
  77. package/node_modules/@suigar/sui-rpc-pool/package.json +0 -31
package/dist/bin.mjs CHANGED
@@ -1,12 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import { startSuigarMcpServer } from "./server.mjs";
3
3
  //#region src/bin.ts
4
- const main = async () => {
5
- await startSuigarMcpServer();
6
- };
7
- main().catch((error) => {
8
- console.error(error);
9
- process.exitCode = 1;
10
- });
4
+ await startSuigarMcpServer();
11
5
  //#endregion
12
6
  export {};
7
+
8
+ //# sourceMappingURL=bin.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bin.mjs","names":[],"sources":["../src/bin.ts"],"sourcesContent":["#!/usr/bin/env node\n// Copyright (c) Suigar\n// SPDX-License-Identifier: Apache-2.0\nimport { startSuigarMcpServer } from './server.js';\n\nawait startSuigarMcpServer();\n"],"mappings":";;;AAKA,MAAM,qBAAqB"}
package/dist/client.d.mts CHANGED
@@ -1,17 +1,47 @@
1
- import { SuigarConfig, SuigarConfigInput } from "./types.mjs";
1
+ import { BuildTransactionResult, BuilderMode, JsonValue, RawDryRunResult, ResolvedMcpConfig, SuigarMcpConfigInput, TransactionSummary } from "./types.mjs";
2
+ import { SuigarClient, SuigarNetwork } from "@suigar/sdk";
3
+ import { Game, PvPCoinflipAction } from "@suigar/sdk/games";
2
4
  import { SuiGrpcClient } from "@mysten/sui/grpc";
3
- import { SuiCompatClient } from "@suigar/sui-rpc-pool";
5
+ import { ClientWithExtensions } from "@mysten/sui/client";
4
6
  import { Transaction } from "@mysten/sui/transactions";
5
7
 
6
8
  //#region src/client.d.ts
7
- declare const createReadOnlyClientBundle: (configInput?: SuigarConfigInput) => {
8
- config: SuigarConfig;
9
- runtime: import("@suigar/sui-rpc-pool").ResilientSuiClientRuntime;
10
- client: SuiCompatClient;
11
- rawClient: SuiGrpcClient;
9
+ declare const DEFAULT_NETWORK: SuigarNetwork;
10
+ declare const normalizeNetwork: (network?: string | undefined) => SuigarNetwork;
11
+ declare const getProviderUrl: (network: SuigarNetwork, providerUrl?: string) => string;
12
+ type SuigarClientBundle = {
13
+ client: ClientWithExtensions<{
14
+ suigar: SuigarClient;
15
+ }, SuiGrpcClient>;
16
+ config: ResolvedMcpConfig;
17
+ resolveSuiNSName(name: string): Promise<string | null>;
12
18
  };
13
- declare const serializeTransactionToBase64: (transaction: Transaction, client: SuiGrpcClient) => Promise<string>;
14
- declare const sanitizeForJson: (value: unknown) => unknown;
15
- declare const dryRunTransaction: (transaction: Transaction, configInput?: SuigarConfigInput) => Promise<unknown>;
19
+ declare const createSuigarClient: (input?: SuigarMcpConfigInput) => SuigarClientBundle;
20
+ declare const resolveDefaultCoinType: (config: ResolvedMcpConfig, coinType?: string) => string;
21
+ declare const resolveOwnerAddress: (owner: string, bundle: SuigarClientBundle) => Promise<string>;
22
+ declare const dryRunTransaction: (transaction: Transaction, client: ReturnType<typeof createSuigarClient>["client"]) => Promise<RawDryRunResult>;
23
+ declare const summarizeTransaction: (transaction: Transaction, context?: {
24
+ game?: Game;
25
+ action?: PvPCoinflipAction;
26
+ coinType?: string;
27
+ stake?: bigint | number;
28
+ stakeDisplay?: string;
29
+ coinDecimals?: number;
30
+ gameInputs?: Record<string, JsonValue>;
31
+ }) => TransactionSummary;
32
+ declare const buildTransactionResult: ({
33
+ mode,
34
+ transaction,
35
+ config,
36
+ client,
37
+ context
38
+ }: {
39
+ mode: Exclude<BuilderMode, "read-only">;
40
+ transaction: Transaction;
41
+ config: ResolvedMcpConfig;
42
+ client: ReturnType<typeof createSuigarClient>["client"];
43
+ context: Parameters<typeof summarizeTransaction>[1];
44
+ }) => Promise<BuildTransactionResult>;
16
45
  //#endregion
17
- export { createReadOnlyClientBundle, dryRunTransaction, sanitizeForJson, serializeTransactionToBase64 };
46
+ export { DEFAULT_NETWORK, SuigarClientBundle, buildTransactionResult, createSuigarClient, dryRunTransaction, getProviderUrl, normalizeNetwork, resolveDefaultCoinType, resolveOwnerAddress, summarizeTransaction };
47
+ //# sourceMappingURL=client.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.mts","names":[],"sources":["../src/client.ts"],"mappings":";;;;;;;;cAuCa,eAAA,EAAiB,aAAyB;AAAA,cAE1C,gBAAA,GACZ,OAAA,0BACE,aAQF;AAAA,cAEY,cAAA,GAAkB,OAAA,EAAS,aAAa,EAAE,WAAA;AAAA,KAG3C,kBAAA;EACX,MAAA,EAAQ,oBAAA;IAEN,MAAA,EAAQ,YAAA;EAAA,GAET,aAAA;EAED,MAAA,EAAQ,iBAAA;EACR,gBAAA,CAAiB,IAAA,WAAe,OAAA;AAAA;AAAA,cAGpB,kBAAA,GACZ,KAAA,GAAO,oBAAA,KACL,kBA2BF;AAAA,cAEY,sBAAA,GACZ,MAAA,EAAQ,iBAAiB,EACzB,QAAA;AAAA,cAGY,mBAAA,GACZ,KAAA,UACA,MAAA,EAAQ,kBAAA,KACN,OAAO;AAAA,cA2BG,iBAAA,GACZ,WAAA,EAAa,WAAA,EACb,MAAA,EAAQ,UAAA,QAAkB,kBAAA,gBACxB,OAAA,CAAQ,eAAA;AAAA,cAUE,oBAAA,GACZ,WAAA,EAAa,WAAA,EACb,OAAA;EACC,IAAA,GAAO,IAAA;EACP,MAAA,GAAS,iBAAA;EACT,QAAA;EACA,KAAA;EACA,YAAA;EACA,YAAA;EACA,UAAA,GAAa,MAAA,SAAe,SAAA;AAAA,MAE3B,kBAAA;AAAA,cAwEU,sBAAA;EAAgC,IAAA;EAAA,WAAA;EAAA,MAAA;EAAA,MAAA;EAAA;AAAA;EAO5C,IAAA,EAAM,OAAA,CAAQ,WAAA;EACd,WAAA,EAAa,WAAA;EACb,MAAA,EAAQ,iBAAA;EACR,MAAA,EAAQ,UAAA,QAAkB,kBAAA;EAC1B,OAAA,EAAS,UAAA,QAAkB,oBAAA;AAAA,MACxB,OAAA,CAAQ,sBAAA"}
package/dist/client.mjs CHANGED
@@ -1,43 +1,116 @@
1
- import { resolveSuigarConfig } from "./config.mjs";
2
- import { getOrCreateResilientSuiClientRuntime } from "@suigar/sui-rpc-pool";
1
+ import { formatBaseUnitAmount } from "./format.mjs";
2
+ import { extractDryRunErrors, summarizeDryRun, toJsonValue } from "./dry-run.mjs";
3
+ import { suigar } from "@suigar/sdk";
4
+ import { SuiGrpcClient } from "@mysten/sui/grpc";
5
+ import { isValidSuiAddress, isValidSuiNSName, normalizeStructTag, normalizeSuiAddress, normalizeSuiNSName } from "@mysten/sui/utils";
3
6
  //#region src/client.ts
4
- const createReadOnlyClientBundle = (configInput = {}) => {
5
- const config = resolveSuigarConfig(configInput);
6
- const runtime = getOrCreateResilientSuiClientRuntime({
7
- network: config.network,
8
- providerUrl: config.providerUrl
7
+ const DEFAULT_PROVIDER_URLS = {
8
+ mainnet: "https://fullnode.mainnet.sui.io:443",
9
+ testnet: "https://fullnode.testnet.sui.io:443"
10
+ };
11
+ const DEFAULT_NETWORK = "testnet";
12
+ const normalizeNetwork = (network = DEFAULT_NETWORK) => {
13
+ if (network === "mainnet" || network === "testnet") return network;
14
+ throw new RangeError(`Unsupported network: ${network}. Use "mainnet" or "testnet".`);
15
+ };
16
+ const getProviderUrl = (network, providerUrl) => providerUrl ?? DEFAULT_PROVIDER_URLS[network];
17
+ const createSuigarClient = (input = {}) => {
18
+ const network = normalizeNetwork(input.network);
19
+ const baseClient = new SuiGrpcClient({
20
+ baseUrl: getProviderUrl(network, input.providerUrl),
21
+ network
9
22
  });
23
+ const client = baseClient.$extend(suigar({
24
+ config: input.config,
25
+ partner: input.partner
26
+ }));
10
27
  return {
11
- config,
12
- runtime,
13
- client: runtime.createCompatClient(),
14
- rawClient: runtime.getGrpcClient()
28
+ client,
29
+ config: {
30
+ network,
31
+ providerUrl: getProviderUrl(network, input.providerUrl),
32
+ sdk: client.suigar.getConfig()
33
+ },
34
+ resolveSuiNSName: async (name) => (await baseClient.nameService.lookupName({ name })).response.record?.targetAddress ?? null
15
35
  };
16
36
  };
17
- const serializeTransactionToBase64 = async (transaction, client) => {
18
- const bytes = await transaction.build({ client });
19
- return Buffer.from(bytes).toString("base64");
37
+ const resolveDefaultCoinType = (config, coinType) => normalizeStructTag(coinType ?? config.sdk.coins.sui.coinType);
38
+ const resolveOwnerAddress = async (owner, bundle) => {
39
+ try {
40
+ const normalizedAddress = normalizeSuiAddress(owner);
41
+ if (isValidSuiAddress(normalizedAddress)) return normalizedAddress;
42
+ } catch {}
43
+ if (!isValidSuiNSName(owner)) throw new TypeError("owner must be a valid Sui address or SuiNS name such as name.sui or sub.name.sui.");
44
+ const normalizedName = normalizeSuiNSName(owner, "dot");
45
+ const resolvedAddress = await bundle.resolveSuiNSName(normalizedName);
46
+ if (!resolvedAddress) throw new Error(`SuiNS name ${normalizedName} did not resolve to an address.`);
47
+ return normalizeSuiAddress(resolvedAddress);
20
48
  };
21
- const sanitizeForJson = (value) => {
22
- if (typeof value === "bigint") return value.toString();
23
- if (value instanceof Uint8Array) return Buffer.from(value).toString("base64");
24
- if (Array.isArray(value)) return value.map((entry) => sanitizeForJson(entry));
25
- if (value && typeof value === "object") return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, sanitizeForJson(entry)]));
26
- return value;
49
+ const dryRunTransaction = async (transaction, client) => client.core.simulateTransaction({
50
+ transaction,
51
+ include: {
52
+ effects: true,
53
+ events: true,
54
+ balanceChanges: true
55
+ }
56
+ });
57
+ const summarizeTransaction = (transaction, context = {}) => {
58
+ const data = transaction.getData();
59
+ const commands = (data.commands ?? []).map((command) => {
60
+ const kind = String(command.$kind ?? Object.keys(command)[0] ?? "Unknown");
61
+ const moveCall = command.MoveCall;
62
+ const target = moveCall?.package && moveCall?.module && moveCall?.function ? `${moveCall.package}::${moveCall.module}::${moveCall.function}` : void 0;
63
+ return {
64
+ kind,
65
+ ...target ? { target } : {},
66
+ ...moveCall?.typeArguments ? { typeArguments: moveCall.typeArguments } : {}
67
+ };
68
+ });
69
+ const objectInputs = (data.inputs ?? []).flatMap((input) => input.$kind === "UnresolvedObject" && input.UnresolvedObject?.objectId ? [input.UnresolvedObject.objectId] : []);
70
+ return {
71
+ sender: data.sender ?? null,
72
+ gasBudget: data.gasData?.budget == null ? null : String(data.gasData.budget),
73
+ gasBudgetDisplay: data.gasData?.budget == null ? null : formatBaseUnitAmount(data.gasData.budget, context.coinDecimals),
74
+ gasPrice: data.gasData?.price == null ? null : String(data.gasData.price),
75
+ commandCount: commands.length,
76
+ commands,
77
+ inputs: data.inputs?.length ?? 0,
78
+ objectInputs,
79
+ ...context.game ? { game: context.game } : {},
80
+ ...context.action ? { action: context.action } : {},
81
+ ...context.coinType ? { coinType: normalizeStructTag(context.coinType) } : {},
82
+ ...context.stake == null ? {} : { stake: String(context.stake) },
83
+ ...context.stakeDisplay ? { stakeDisplay: context.stakeDisplay } : {},
84
+ ...context.coinDecimals == null ? {} : { coinDecimals: context.coinDecimals },
85
+ ...context.gameInputs ? { gameInputs: context.gameInputs } : {}
86
+ };
27
87
  };
28
- const dryRunTransaction = async (transaction, configInput = {}) => {
29
- const { rawClient } = createReadOnlyClientBundle(configInput);
30
- const bytes = await transaction.build({ client: rawClient });
31
- return sanitizeForJson(await rawClient.simulateTransaction({
32
- transaction: bytes,
33
- include: {
34
- effects: true,
35
- events: true,
36
- balanceChanges: true,
37
- objectChanges: true,
38
- input: true
39
- }
40
- }));
88
+ const buildTransactionResult = async ({ mode, transaction, config, client, context }) => {
89
+ const summary = summarizeTransaction(transaction, context);
90
+ if (mode === "dry-run") {
91
+ const rawDryRun = await dryRunTransaction(transaction, client);
92
+ const dryRun = toJsonValue(rawDryRun);
93
+ const dryRunSummary = summarizeDryRun(rawDryRun, client, context);
94
+ const errors = extractDryRunErrors(rawDryRun);
95
+ return {
96
+ mode,
97
+ network: config.network,
98
+ config,
99
+ summary,
100
+ dryRun,
101
+ dryRunSummary,
102
+ ...errors.length > 0 ? { errors } : {}
103
+ };
104
+ }
105
+ return {
106
+ mode,
107
+ network: config.network,
108
+ config,
109
+ summary,
110
+ transactionBytesBase64: await client.suigar.serializeTransactionToBase64(transaction)
111
+ };
41
112
  };
42
113
  //#endregion
43
- export { createReadOnlyClientBundle, dryRunTransaction, sanitizeForJson, serializeTransactionToBase64 };
114
+ export { DEFAULT_NETWORK, buildTransactionResult, createSuigarClient, dryRunTransaction, getProviderUrl, normalizeNetwork, resolveDefaultCoinType, resolveOwnerAddress, summarizeTransaction };
115
+
116
+ //# sourceMappingURL=client.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.mjs","names":[],"sources":["../src/client.ts"],"sourcesContent":["// Copyright (c) Suigar\n// SPDX-License-Identifier: Apache-2.0\n\nimport { ClientWithExtensions } from '@mysten/sui/client';\nimport { SuiGrpcClient } from '@mysten/sui/grpc';\nimport type { Transaction } from '@mysten/sui/transactions';\nimport {\n\tisValidSuiAddress,\n\tisValidSuiNSName,\n\tnormalizeStructTag,\n\tnormalizeSuiAddress,\n\tnormalizeSuiNSName,\n} from '@mysten/sui/utils';\nimport { suigar } from '@suigar/sdk';\nimport type { SuigarClient, SuigarNetwork } from '@suigar/sdk';\nimport type { Game, PvPCoinflipAction } from '@suigar/sdk/games';\nimport {\n\textractDryRunErrors,\n\tsummarizeDryRun,\n\ttoJsonValue,\n} from './dry-run.js';\nimport { formatBaseUnitAmount } from './format.js';\nimport type {\n\tBuilderMode,\n\tBuildTransactionResult,\n\tDryRunResult,\n\tJsonValue,\n\tRawDryRunResult,\n\tResolvedMcpConfig,\n\tSuigarConfigOverrides,\n\tSuigarMcpConfigInput,\n\tTransactionSummary,\n} from './types.js';\n\nconst DEFAULT_PROVIDER_URLS = {\n\tmainnet: 'https://fullnode.mainnet.sui.io:443',\n\ttestnet: 'https://fullnode.testnet.sui.io:443',\n} as const satisfies Record<SuigarNetwork, string>;\n\nexport const DEFAULT_NETWORK: SuigarNetwork = 'testnet';\n\nexport const normalizeNetwork = (\n\tnetwork: string | undefined = DEFAULT_NETWORK,\n): SuigarNetwork => {\n\tif (network === 'mainnet' || network === 'testnet') {\n\t\treturn network;\n\t}\n\n\tthrow new RangeError(\n\t\t`Unsupported network: ${network}. Use \"mainnet\" or \"testnet\".`,\n\t);\n};\n\nexport const getProviderUrl = (network: SuigarNetwork, providerUrl?: string) =>\n\tproviderUrl ?? DEFAULT_PROVIDER_URLS[network];\n\nexport type SuigarClientBundle = {\n\tclient: ClientWithExtensions<\n\t\t{\n\t\t\tsuigar: SuigarClient;\n\t\t},\n\t\tSuiGrpcClient\n\t>;\n\tconfig: ResolvedMcpConfig;\n\tresolveSuiNSName(name: string): Promise<string | null>;\n};\n\nexport const createSuigarClient = (\n\tinput: SuigarMcpConfigInput = {},\n): SuigarClientBundle => {\n\tconst network = normalizeNetwork(input.network);\n\tconst baseClient = new SuiGrpcClient({\n\t\tbaseUrl: getProviderUrl(network, input.providerUrl),\n\t\tnetwork,\n\t});\n\tconst client = baseClient.$extend(\n\t\tsuigar({\n\t\t\tconfig: input.config as SuigarConfigOverrides | undefined,\n\t\t\tpartner: input.partner,\n\t\t}),\n\t);\n\n\treturn {\n\t\tclient,\n\t\tconfig: {\n\t\t\tnetwork,\n\t\t\tproviderUrl: getProviderUrl(network, input.providerUrl),\n\t\t\tsdk: client.suigar.getConfig(),\n\t\t} satisfies ResolvedMcpConfig,\n\t\tresolveSuiNSName: async (name) =>\n\t\t\t(\n\t\t\t\tawait baseClient.nameService.lookupName({\n\t\t\t\t\tname,\n\t\t\t\t})\n\t\t\t).response.record?.targetAddress ?? null,\n\t};\n};\n\nexport const resolveDefaultCoinType = (\n\tconfig: ResolvedMcpConfig,\n\tcoinType?: string,\n) => normalizeStructTag(coinType ?? config.sdk.coins.sui.coinType);\n\nexport const resolveOwnerAddress = async (\n\towner: string,\n\tbundle: SuigarClientBundle,\n): Promise<string> => {\n\ttry {\n\t\tconst normalizedAddress = normalizeSuiAddress(owner);\n\t\tif (isValidSuiAddress(normalizedAddress)) {\n\t\t\treturn normalizedAddress;\n\t\t}\n\t} catch {\n\t\t// Fall through to SuiNS validation.\n\t}\n\n\tif (!isValidSuiNSName(owner)) {\n\t\tthrow new TypeError(\n\t\t\t'owner must be a valid Sui address or SuiNS name such as name.sui or sub.name.sui.',\n\t\t);\n\t}\n\n\tconst normalizedName = normalizeSuiNSName(owner, 'dot');\n\tconst resolvedAddress = await bundle.resolveSuiNSName(normalizedName);\n\tif (!resolvedAddress) {\n\t\tthrow new Error(\n\t\t\t`SuiNS name ${normalizedName} did not resolve to an address.`,\n\t\t);\n\t}\n\n\treturn normalizeSuiAddress(resolvedAddress);\n};\n\nexport const dryRunTransaction = async (\n\ttransaction: Transaction,\n\tclient: ReturnType<typeof createSuigarClient>['client'],\n): Promise<RawDryRunResult> =>\n\tclient.core.simulateTransaction({\n\t\ttransaction,\n\t\tinclude: {\n\t\t\teffects: true,\n\t\t\tevents: true,\n\t\t\tbalanceChanges: true,\n\t\t},\n\t});\n\nexport const summarizeTransaction = (\n\ttransaction: Transaction,\n\tcontext: {\n\t\tgame?: Game;\n\t\taction?: PvPCoinflipAction;\n\t\tcoinType?: string;\n\t\tstake?: bigint | number;\n\t\tstakeDisplay?: string;\n\t\tcoinDecimals?: number;\n\t\tgameInputs?: Record<string, JsonValue>;\n\t} = {},\n): TransactionSummary => {\n\tconst data = transaction.getData() as {\n\t\tsender?: string | null;\n\t\tgasData?: {\n\t\t\tbudget?: string | number | bigint | null;\n\t\t\tprice?: string | number | bigint | null;\n\t\t};\n\t\tcommands?: Array<Record<string, unknown> & { $kind?: string }>;\n\t\tinputs?: Array<{\n\t\t\t$kind?: string;\n\t\t\tUnresolvedObject?: { objectId?: string } | null;\n\t\t}>;\n\t};\n\n\tconst commands = (data.commands ?? []).map((command) => {\n\t\tconst kind = String(command.$kind ?? Object.keys(command)[0] ?? 'Unknown');\n\t\tconst moveCall = (\n\t\t\tcommand as {\n\t\t\t\tMoveCall?: {\n\t\t\t\t\tpackage?: string;\n\t\t\t\t\tmodule?: string;\n\t\t\t\t\tfunction?: string;\n\t\t\t\t\ttypeArguments?: string[];\n\t\t\t\t};\n\t\t\t}\n\t\t).MoveCall;\n\t\tconst target =\n\t\t\tmoveCall?.package && moveCall?.module && moveCall?.function\n\t\t\t\t? `${moveCall.package}::${moveCall.module}::${moveCall.function}`\n\t\t\t\t: undefined;\n\t\treturn {\n\t\t\tkind,\n\t\t\t...(target ? { target } : {}),\n\t\t\t...(moveCall?.typeArguments\n\t\t\t\t? { typeArguments: moveCall.typeArguments }\n\t\t\t\t: {}),\n\t\t};\n\t});\n\n\tconst objectInputs = (data.inputs ?? []).flatMap((input) =>\n\t\tinput.$kind === 'UnresolvedObject' && input.UnresolvedObject?.objectId\n\t\t\t? [input.UnresolvedObject.objectId]\n\t\t\t: [],\n\t);\n\n\treturn {\n\t\tsender: data.sender ?? null,\n\t\tgasBudget:\n\t\t\tdata.gasData?.budget == null ? null : String(data.gasData.budget),\n\t\tgasBudgetDisplay:\n\t\t\tdata.gasData?.budget == null\n\t\t\t\t? null\n\t\t\t\t: formatBaseUnitAmount(data.gasData.budget, context.coinDecimals),\n\t\tgasPrice: data.gasData?.price == null ? null : String(data.gasData.price),\n\t\tcommandCount: commands.length,\n\t\tcommands,\n\t\tinputs: data.inputs?.length ?? 0,\n\t\tobjectInputs,\n\t\t...(context.game ? { game: context.game } : {}),\n\t\t...(context.action ? { action: context.action } : {}),\n\t\t...(context.coinType\n\t\t\t? { coinType: normalizeStructTag(context.coinType) }\n\t\t\t: {}),\n\t\t...(context.stake == null ? {} : { stake: String(context.stake) }),\n\t\t...(context.stakeDisplay ? { stakeDisplay: context.stakeDisplay } : {}),\n\t\t...(context.coinDecimals == null\n\t\t\t? {}\n\t\t\t: { coinDecimals: context.coinDecimals }),\n\t\t...(context.gameInputs ? { gameInputs: context.gameInputs } : {}),\n\t};\n};\n\nexport const buildTransactionResult = async ({\n\tmode,\n\ttransaction,\n\tconfig,\n\tclient,\n\tcontext,\n}: {\n\tmode: Exclude<BuilderMode, 'read-only'>;\n\ttransaction: Transaction;\n\tconfig: ResolvedMcpConfig;\n\tclient: ReturnType<typeof createSuigarClient>['client'];\n\tcontext: Parameters<typeof summarizeTransaction>[1];\n}): Promise<BuildTransactionResult> => {\n\tconst summary = summarizeTransaction(transaction, context);\n\tif (mode === 'dry-run') {\n\t\tconst rawDryRun = await dryRunTransaction(transaction, client);\n\t\tconst dryRun = toJsonValue(rawDryRun) as DryRunResult;\n\t\tconst dryRunSummary = summarizeDryRun(rawDryRun, client, context);\n\t\tconst errors = extractDryRunErrors(rawDryRun);\n\t\treturn {\n\t\t\tmode,\n\t\t\tnetwork: config.network,\n\t\t\tconfig,\n\t\t\tsummary,\n\t\t\tdryRun,\n\t\t\tdryRunSummary,\n\t\t\t...(errors.length > 0 ? { errors } : {}),\n\t\t};\n\t}\n\n\treturn {\n\t\tmode,\n\t\tnetwork: config.network,\n\t\tconfig,\n\t\tsummary,\n\t\ttransactionBytesBase64:\n\t\t\tawait client.suigar.serializeTransactionToBase64(transaction),\n\t};\n};\n"],"mappings":"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"}
@@ -0,0 +1,163 @@
1
+ import { formatAmount } from "./format.mjs";
2
+ import { GAMES } from "@suigar/sdk/games";
3
+ import { parseGameDetails, parseGameEvent } from "@suigar/sdk/utils";
4
+ //#region src/dry-run.ts
5
+ const amountFieldNames = /* @__PURE__ */ new Set([
6
+ "stake_amount",
7
+ "outcome_amount",
8
+ "payout_amount",
9
+ "amount"
10
+ ]);
11
+ const isRecord = (value) => value !== null && typeof value === "object";
12
+ const getDryRunTransaction = (dryRun) => {
13
+ if (!isRecord(dryRun)) return;
14
+ return dryRun.FailedTransaction ?? dryRun.Transaction;
15
+ };
16
+ const toJsonValue = (value) => {
17
+ if (value == null || typeof value === "string" || typeof value === "boolean") return value ?? null;
18
+ if (typeof value === "number") return Number.isFinite(value) ? value : String(value);
19
+ if (typeof value === "bigint") return value.toString();
20
+ if (value instanceof Uint8Array) return Array.from(value);
21
+ if (Array.isArray(value)) return value.map((item) => toJsonValue(item)).filter((item) => item !== void 0);
22
+ if (isRecord(value)) {
23
+ const entries = Object.entries(value).map(([key, item]) => [key, toJsonValue(item)]).filter((entry) => entry[1] !== void 0);
24
+ return Object.fromEntries(entries);
25
+ }
26
+ };
27
+ const collectStrings = (value, path) => {
28
+ if (!isRecord(value)) return [];
29
+ return path.flatMap((key) => {
30
+ const next = value[key];
31
+ if (typeof next === "string" && next.trim()) return [next.trim()];
32
+ if (Array.isArray(next)) return next.filter((item) => typeof item === "string");
33
+ if (isRecord(next)) return collectStrings(next, path);
34
+ return [];
35
+ });
36
+ };
37
+ const extractDryRunErrors = (dryRun) => {
38
+ const source = getDryRunTransaction(dryRun) ?? dryRun;
39
+ const effects = isRecord(source) ? source.effects : void 0;
40
+ const errors = [
41
+ source,
42
+ effects,
43
+ isRecord(effects) ? effects.status : void 0
44
+ ].filter(isRecord).flatMap((item) => collectStrings(item, [
45
+ "error",
46
+ "cleverError",
47
+ "message"
48
+ ]));
49
+ return [...new Set(errors)];
50
+ };
51
+ const stringField = (record, key) => {
52
+ const value = record[key];
53
+ return typeof value === "string" || typeof value === "number" || typeof value === "bigint" ? String(value) : void 0;
54
+ };
55
+ const gasUsedSummary = (effects, decimals) => {
56
+ const gasUsed = isRecord(effects) ? effects.gasUsed : void 0;
57
+ if (!isRecord(gasUsed)) return {
58
+ computation: null,
59
+ storage: null,
60
+ rebate: null,
61
+ nonRefundableStorageFee: null,
62
+ net: null
63
+ };
64
+ const computation = stringField(gasUsed, "computationCost");
65
+ const storage = stringField(gasUsed, "storageCost");
66
+ const rebate = stringField(gasUsed, "storageRebate");
67
+ const nonRefundableStorageFee = stringField(gasUsed, "nonRefundableStorageFee");
68
+ const net = computation && storage && rebate ? String(-(BigInt(computation) + BigInt(storage) - BigInt(rebate))) : void 0;
69
+ return {
70
+ computation: formatAmount(computation, decimals),
71
+ storage: formatAmount(storage, decimals),
72
+ rebate: formatAmount(rebate, decimals),
73
+ nonRefundableStorageFee: formatAmount(nonRefundableStorageFee, decimals),
74
+ net: formatAmount(net, decimals)
75
+ };
76
+ };
77
+ const eventFields = (fields, decimals) => {
78
+ const entries = Object.entries(fields).flatMap(([key, value]) => {
79
+ const jsonValue = toJsonValue(value);
80
+ if (jsonValue === void 0) return [];
81
+ const displayValue = amountFieldNames.has(key) ? formatAmount(value, decimals) : null;
82
+ return displayValue ? [[key, jsonValue], [`${key}_display`, displayValue.display]] : [[key, jsonValue]];
83
+ });
84
+ return Object.fromEntries(entries);
85
+ };
86
+ const parseDryRunEvent = (event, eventType) => {
87
+ const module = typeof event.module === "string" ? event.module : eventType.includes("::core::") ? "core" : eventType.includes("::pvp_coinflip::") ? "pvp_coinflip" : "";
88
+ if (!module) return null;
89
+ try {
90
+ const parsedEvent = parseGameEvent({
91
+ ...event,
92
+ eventType,
93
+ module
94
+ });
95
+ if (parsedEvent) return parsedEvent;
96
+ } catch {}
97
+ const gameId = /::BetResultEvent<[^>]+::([^:<>,]+)::Game>/u.exec(eventType)?.[1]?.replaceAll("_", "-");
98
+ return gameId && GAMES.includes(gameId) ? {
99
+ gameId,
100
+ eventName: "BetResultEvent"
101
+ } : null;
102
+ };
103
+ const summarizeDryRunEvent = (event, client, decimals) => {
104
+ if (!isRecord(event)) return null;
105
+ const eventType = typeof event.eventType === "string" ? event.eventType : typeof event.type === "string" ? event.type : "unknown";
106
+ const baseSummary = { type: eventType };
107
+ let parsedEvent = null;
108
+ try {
109
+ parsedEvent = parseDryRunEvent(event, eventType);
110
+ if (parsedEvent && event.bcs instanceof Uint8Array) {
111
+ const decoded = client.suigar.bcs.BetResultEvent.parse(event.bcs);
112
+ const details = parseGameDetails(parsedEvent.gameId, decoded.game_details);
113
+ return {
114
+ ...baseSummary,
115
+ game: parsedEvent.gameId,
116
+ eventName: parsedEvent.eventName,
117
+ fields: eventFields({
118
+ ...decoded,
119
+ game_details: details,
120
+ ...details
121
+ }, decimals)
122
+ };
123
+ }
124
+ } catch {}
125
+ const json = isRecord(event.json) ? event.json : isRecord(event.parsedJson) ? event.parsedJson : null;
126
+ return json ? {
127
+ ...baseSummary,
128
+ ...parsedEvent ? {
129
+ game: parsedEvent.gameId,
130
+ eventName: parsedEvent.eventName
131
+ } : {},
132
+ fields: eventFields(json, decimals)
133
+ } : null;
134
+ };
135
+ const summarizeDryRun = (dryRun, client, context = {}) => {
136
+ const transaction = getDryRunTransaction(dryRun);
137
+ const transactionRecord = isRecord(transaction) ? transaction : {};
138
+ const effects = transactionRecord.effects;
139
+ const status = isRecord(effects) ? effects.status : void 0;
140
+ const success = isRecord(status) ? status.success === true : false;
141
+ const statusError = isRecord(status) ? status.error : void 0;
142
+ const error = typeof statusError === "string" ? statusError : isRecord(statusError) && typeof statusError.message === "string" ? statusError.message : null;
143
+ const balanceChanges = Array.isArray(transactionRecord.balanceChanges) ? transactionRecord.balanceChanges.filter(isRecord).map((change) => ({
144
+ address: String(change.address ?? ""),
145
+ coinType: String(change.coinType ?? ""),
146
+ amount: formatAmount(change.amount, context.coinDecimals) ?? {
147
+ raw: String(change.amount ?? ""),
148
+ display: ""
149
+ }
150
+ })) : [];
151
+ const events = Array.isArray(transactionRecord.events) ? transactionRecord.events.map((event) => summarizeDryRunEvent(event, client, context.coinDecimals)).filter((event) => event !== null) : [];
152
+ return {
153
+ success,
154
+ error,
155
+ gasUsed: gasUsedSummary(effects, context.coinDecimals),
156
+ balanceChanges,
157
+ events
158
+ };
159
+ };
160
+ //#endregion
161
+ export { extractDryRunErrors, summarizeDryRun, toJsonValue };
162
+
163
+ //# sourceMappingURL=dry-run.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dry-run.mjs","names":[],"sources":["../src/dry-run.ts"],"sourcesContent":["// Copyright (c) Suigar\n// SPDX-License-Identifier: Apache-2.0\n\nimport { GAMES, type Game } from '@suigar/sdk/games';\nimport { parseGameDetails, parseGameEvent } from '@suigar/sdk/utils';\nimport { formatAmount } from './format.js';\nimport type {\n\tDryRunEventSummary,\n\tDryRunSummary,\n\tJsonValue,\n\tRawDryRunResult,\n} from './types.js';\n\ntype DryRunSummaryClient = {\n\tsuigar: {\n\t\tbcs: {\n\t\t\tBetResultEvent: {\n\t\t\t\tparse(value: Uint8Array): Record<string, unknown> & {\n\t\t\t\t\tgame_details: {\n\t\t\t\t\t\tcontents: Array<{\n\t\t\t\t\t\t\tkey: string;\n\t\t\t\t\t\t\tvalue: number[];\n\t\t\t\t\t\t}>;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t};\n\t};\n};\n\nconst amountFieldNames = new Set([\n\t'stake_amount',\n\t'outcome_amount',\n\t'payout_amount',\n\t'amount',\n]);\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n\tvalue !== null && typeof value === 'object';\n\nconst getDryRunTransaction = (dryRun: RawDryRunResult) => {\n\tif (!isRecord(dryRun)) {\n\t\treturn undefined;\n\t}\n\treturn dryRun.FailedTransaction ?? dryRun.Transaction;\n};\n\nexport const toJsonValue = (value: unknown): JsonValue | undefined => {\n\tif (\n\t\tvalue == null ||\n\t\ttypeof value === 'string' ||\n\t\ttypeof value === 'boolean'\n\t) {\n\t\treturn value ?? null;\n\t}\n\tif (typeof value === 'number') {\n\t\treturn Number.isFinite(value) ? value : String(value);\n\t}\n\tif (typeof value === 'bigint') {\n\t\treturn value.toString();\n\t}\n\tif (value instanceof Uint8Array) {\n\t\treturn Array.from(value);\n\t}\n\tif (Array.isArray(value)) {\n\t\treturn value\n\t\t\t.map((item) => toJsonValue(item))\n\t\t\t.filter((item): item is JsonValue => item !== undefined);\n\t}\n\tif (isRecord(value)) {\n\t\tconst entries = Object.entries(value)\n\t\t\t.map(([key, item]) => [key, toJsonValue(item)] as const)\n\t\t\t.filter(\n\t\t\t\t(entry): entry is readonly [string, JsonValue] =>\n\t\t\t\t\tentry[1] !== undefined,\n\t\t\t);\n\t\treturn Object.fromEntries(entries);\n\t}\n\treturn undefined;\n};\n\nconst collectStrings = (value: unknown, path: string[]): string[] => {\n\tif (!isRecord(value)) {\n\t\treturn [];\n\t}\n\n\treturn path.flatMap((key) => {\n\t\tconst next = value[key];\n\t\tif (typeof next === 'string' && next.trim()) {\n\t\t\treturn [next.trim()];\n\t\t}\n\t\tif (Array.isArray(next)) {\n\t\t\treturn next.filter((item): item is string => typeof item === 'string');\n\t\t}\n\t\tif (isRecord(next)) {\n\t\t\treturn collectStrings(next, path);\n\t\t}\n\t\treturn [];\n\t});\n};\n\nexport const extractDryRunErrors = (dryRun: RawDryRunResult): string[] => {\n\tconst source: unknown = getDryRunTransaction(dryRun) ?? dryRun;\n\tconst effects = isRecord(source) ? source.effects : undefined;\n\tconst status = isRecord(effects) ? effects.status : undefined;\n\tconst errorSources = [source, effects, status].filter(isRecord);\n\n\tconst errors = errorSources.flatMap((item) =>\n\t\tcollectStrings(item, ['error', 'cleverError', 'message']),\n\t);\n\treturn [...new Set(errors)];\n};\n\nconst stringField = (record: Record<string, unknown>, key: string) => {\n\tconst value = record[key];\n\treturn typeof value === 'string' ||\n\t\ttypeof value === 'number' ||\n\t\ttypeof value === 'bigint'\n\t\t? String(value)\n\t\t: undefined;\n};\n\nconst gasUsedSummary = (\n\teffects: unknown,\n\tdecimals?: number,\n): DryRunSummary['gasUsed'] => {\n\tconst gasUsed = isRecord(effects) ? effects.gasUsed : undefined;\n\tif (!isRecord(gasUsed)) {\n\t\treturn {\n\t\t\tcomputation: null,\n\t\t\tstorage: null,\n\t\t\trebate: null,\n\t\t\tnonRefundableStorageFee: null,\n\t\t\tnet: null,\n\t\t};\n\t}\n\n\tconst computation = stringField(gasUsed, 'computationCost');\n\tconst storage = stringField(gasUsed, 'storageCost');\n\tconst rebate = stringField(gasUsed, 'storageRebate');\n\tconst nonRefundableStorageFee = stringField(\n\t\tgasUsed,\n\t\t'nonRefundableStorageFee',\n\t);\n\tconst net =\n\t\tcomputation && storage && rebate\n\t\t\t? String(-(BigInt(computation) + BigInt(storage) - BigInt(rebate)))\n\t\t\t: undefined;\n\n\treturn {\n\t\tcomputation: formatAmount(computation, decimals),\n\t\tstorage: formatAmount(storage, decimals),\n\t\trebate: formatAmount(rebate, decimals),\n\t\tnonRefundableStorageFee: formatAmount(nonRefundableStorageFee, decimals),\n\t\tnet: formatAmount(net, decimals),\n\t};\n};\n\nconst eventFields = (\n\tfields: Record<string, unknown>,\n\tdecimals?: number,\n): Record<string, JsonValue> => {\n\tconst entries = Object.entries(fields).flatMap(([key, value]) => {\n\t\tconst jsonValue = toJsonValue(value);\n\t\tif (jsonValue === undefined) {\n\t\t\treturn [];\n\t\t}\n\t\tconst displayValue = amountFieldNames.has(key)\n\t\t\t? formatAmount(value, decimals)\n\t\t\t: null;\n\t\treturn displayValue\n\t\t\t? [\n\t\t\t\t\t[key, jsonValue] as const,\n\t\t\t\t\t[`${key}_display`, displayValue.display] as const,\n\t\t\t\t]\n\t\t\t: [[key, jsonValue] as const];\n\t});\n\treturn Object.fromEntries(entries);\n};\n\nconst parseDryRunEvent = (\n\tevent: Record<string, unknown>,\n\teventType: string,\n): ReturnType<typeof parseGameEvent> => {\n\tconst module =\n\t\ttypeof event.module === 'string'\n\t\t\t? event.module\n\t\t\t: eventType.includes('::core::')\n\t\t\t\t? 'core'\n\t\t\t\t: eventType.includes('::pvp_coinflip::')\n\t\t\t\t\t? 'pvp_coinflip'\n\t\t\t\t\t: '';\n\n\tif (!module) {\n\t\treturn null;\n\t}\n\n\ttry {\n\t\tconst parsedEvent = parseGameEvent({\n\t\t\t...event,\n\t\t\teventType,\n\t\t\tmodule,\n\t\t} as never);\n\t\tif (parsedEvent) {\n\t\t\treturn parsedEvent;\n\t\t}\n\t} catch {\n\t\t// Fall back to string matching below for JSON-only simulated events.\n\t}\n\n\tconst standardBetResult = /::BetResultEvent<[^>]+::([^:<>,]+)::Game>/u.exec(\n\t\teventType,\n\t);\n\tconst gameId = standardBetResult?.[1]?.replaceAll('_', '-');\n\treturn gameId && GAMES.includes(gameId as Game)\n\t\t? {\n\t\t\t\tgameId: gameId as Game,\n\t\t\t\teventName: 'BetResultEvent',\n\t\t\t}\n\t\t: null;\n};\n\nconst summarizeDryRunEvent = (\n\tevent: unknown,\n\tclient: DryRunSummaryClient,\n\tdecimals?: number,\n): DryRunEventSummary | null => {\n\tif (!isRecord(event)) {\n\t\treturn null;\n\t}\n\n\tconst eventType =\n\t\ttypeof event.eventType === 'string'\n\t\t\t? event.eventType\n\t\t\t: typeof event.type === 'string'\n\t\t\t\t? event.type\n\t\t\t\t: 'unknown';\n\tconst baseSummary = {\n\t\ttype: eventType,\n\t};\n\tlet parsedEvent: ReturnType<typeof parseGameEvent> = null;\n\n\ttry {\n\t\tparsedEvent = parseDryRunEvent(event, eventType);\n\t\tif (parsedEvent && event.bcs instanceof Uint8Array) {\n\t\t\tconst decoded = client.suigar.bcs.BetResultEvent.parse(event.bcs);\n\t\t\tconst details = parseGameDetails(\n\t\t\t\tparsedEvent.gameId,\n\t\t\t\tdecoded.game_details,\n\t\t\t);\n\t\t\treturn {\n\t\t\t\t...baseSummary,\n\t\t\t\tgame: parsedEvent.gameId,\n\t\t\t\teventName: parsedEvent.eventName,\n\t\t\t\tfields: eventFields(\n\t\t\t\t\t{\n\t\t\t\t\t\t...decoded,\n\t\t\t\t\t\tgame_details: details,\n\t\t\t\t\t\t...details,\n\t\t\t\t\t},\n\t\t\t\t\tdecimals,\n\t\t\t\t),\n\t\t\t};\n\t\t}\n\t} catch {\n\t\t// Fall back to API-provided JSON below.\n\t}\n\n\tconst json = isRecord(event.json)\n\t\t? event.json\n\t\t: isRecord(event.parsedJson)\n\t\t\t? event.parsedJson\n\t\t\t: null;\n\treturn json\n\t\t? {\n\t\t\t\t...baseSummary,\n\t\t\t\t...(parsedEvent\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tgame: parsedEvent.gameId,\n\t\t\t\t\t\t\teventName: parsedEvent.eventName,\n\t\t\t\t\t\t}\n\t\t\t\t\t: {}),\n\t\t\t\tfields: eventFields(json, decimals),\n\t\t\t}\n\t\t: null;\n};\n\nexport const summarizeDryRun = (\n\tdryRun: RawDryRunResult,\n\tclient: DryRunSummaryClient,\n\tcontext: { coinDecimals?: number } = {},\n): DryRunSummary => {\n\tconst transaction = getDryRunTransaction(dryRun);\n\tconst transactionRecord: Record<string, unknown> = isRecord(transaction)\n\t\t? transaction\n\t\t: {};\n\tconst effects = transactionRecord.effects;\n\tconst status = isRecord(effects) ? effects.status : undefined;\n\tconst success = isRecord(status) ? status.success === true : false;\n\tconst statusError = isRecord(status) ? status.error : undefined;\n\tconst error =\n\t\ttypeof statusError === 'string'\n\t\t\t? statusError\n\t\t\t: isRecord(statusError) && typeof statusError.message === 'string'\n\t\t\t\t? statusError.message\n\t\t\t\t: null;\n\tconst balanceChanges = Array.isArray(transactionRecord.balanceChanges)\n\t\t? transactionRecord.balanceChanges.filter(isRecord).map((change) => ({\n\t\t\t\taddress: String(change.address ?? ''),\n\t\t\t\tcoinType: String(change.coinType ?? ''),\n\t\t\t\tamount:\n\t\t\t\t\tformatAmount(change.amount, context.coinDecimals) ??\n\t\t\t\t\t({ raw: String(change.amount ?? ''), display: '' } as const),\n\t\t\t}))\n\t\t: [];\n\tconst events = Array.isArray(transactionRecord.events)\n\t\t? transactionRecord.events\n\t\t\t\t.map((event) =>\n\t\t\t\t\tsummarizeDryRunEvent(event, client, context.coinDecimals),\n\t\t\t\t)\n\t\t\t\t.filter((event): event is DryRunEventSummary => event !== null)\n\t\t: [];\n\n\treturn {\n\t\tsuccess,\n\t\terror,\n\t\tgasUsed: gasUsedSummary(effects, context.coinDecimals),\n\t\tbalanceChanges,\n\t\tevents,\n\t};\n};\n"],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ //#region src/format.ts
2
+ const formatBaseUnitAmount = (value, decimals = 9) => {
3
+ const raw = String(value);
4
+ const negative = raw.startsWith("-");
5
+ const digits = negative ? raw.slice(1) : raw;
6
+ if (!/^\d+$/u.test(digits)) return raw;
7
+ if (decimals === 0) return `${negative ? "-" : ""}${digits}`;
8
+ const padded = digits.length <= decimals ? digits.padStart(decimals + 1, "0") : digits;
9
+ const whole = padded.slice(0, -decimals) || "0";
10
+ const fraction = padded.slice(-decimals).replace(/0+$/u, "");
11
+ return `${negative ? "-" : ""}${whole}${fraction ? `.${fraction}` : ""}`;
12
+ };
13
+ const formatAmount = (value, decimals) => {
14
+ if (typeof value !== "string" && typeof value !== "number" && typeof value !== "bigint") return null;
15
+ const raw = String(value);
16
+ return {
17
+ raw,
18
+ display: formatBaseUnitAmount(raw, decimals)
19
+ };
20
+ };
21
+ //#endregion
22
+ export { formatAmount, formatBaseUnitAmount };
23
+
24
+ //# sourceMappingURL=format.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.mjs","names":[],"sources":["../src/format.ts"],"sourcesContent":["// Copyright (c) Suigar\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { FormattedAmount } from './types.js';\n\nexport const formatBaseUnitAmount = (\n\tvalue: string | number | bigint,\n\tdecimals = 9,\n): string => {\n\tconst raw = String(value);\n\tconst negative = raw.startsWith('-');\n\tconst digits = negative ? raw.slice(1) : raw;\n\tif (!/^\\d+$/u.test(digits)) {\n\t\treturn raw;\n\t}\n\tif (decimals === 0) {\n\t\treturn `${negative ? '-' : ''}${digits}`;\n\t}\n\n\tconst padded =\n\t\tdigits.length <= decimals ? digits.padStart(decimals + 1, '0') : digits;\n\tconst whole = padded.slice(0, -decimals) || '0';\n\tconst fraction = padded.slice(-decimals).replace(/0+$/u, '');\n\treturn `${negative ? '-' : ''}${whole}${fraction ? `.${fraction}` : ''}`;\n};\n\nexport const formatAmount = (\n\tvalue: unknown,\n\tdecimals?: number,\n): FormattedAmount | null => {\n\tif (\n\t\ttypeof value !== 'string' &&\n\t\ttypeof value !== 'number' &&\n\t\ttypeof value !== 'bigint'\n\t) {\n\t\treturn null;\n\t}\n\tconst raw = String(value);\n\treturn {\n\t\traw,\n\t\tdisplay: formatBaseUnitAmount(raw, decimals),\n\t};\n};\n"],"mappings":";AAKA,MAAa,wBACZ,OACA,WAAW,MACC;CACZ,MAAM,MAAM,OAAO,KAAK;CACxB,MAAM,WAAW,IAAI,WAAW,GAAG;CACnC,MAAM,SAAS,WAAW,IAAI,MAAM,CAAC,IAAI;CACzC,IAAI,CAAC,SAAS,KAAK,MAAM,GACxB,OAAO;CAER,IAAI,aAAa,GAChB,OAAO,GAAG,WAAW,MAAM,KAAK;CAGjC,MAAM,SACL,OAAO,UAAU,WAAW,OAAO,SAAS,WAAW,GAAG,GAAG,IAAI;CAClE,MAAM,QAAQ,OAAO,MAAM,GAAG,CAAC,QAAQ,KAAK;CAC5C,MAAM,WAAW,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC,QAAQ,QAAQ,EAAE;CAC3D,OAAO,GAAG,WAAW,MAAM,KAAK,QAAQ,WAAW,IAAI,aAAa;AACrE;AAEA,MAAa,gBACZ,OACA,aAC4B;CAC5B,IACC,OAAO,UAAU,YACjB,OAAO,UAAU,YACjB,OAAO,UAAU,UAEjB,OAAO;CAER,MAAM,MAAM,OAAO,KAAK;CACxB,OAAO;EACN;EACA,SAAS,qBAAqB,KAAK,QAAQ;CAC5C;AACD"}
package/dist/index.d.mts CHANGED
@@ -1,10 +1,6 @@
1
- import { GameMcpSupport, McpExecutionSurface, SUPPORTED_MCP_TOOL_NAMES, SuigarMcpToolName, buildMcpSupportCatalog, getMcpSupportForGame } from "./mcp-support.mjs";
2
- import { BetCoinSource, BetMetadataInput, BetMetadataInputValue, BetMetadataPrimitive, BuilderMode, CasinoBetGameId, CoinReadClient, CoinSide, ConfigInspection, ReadOnlyPlan, SharedBuildOptions, SuigarConfig, SuigarConfigInput, SuigarNetwork, SupportedGameId, TransactionSummary } from "./types.mjs";
3
- import { assertRequiredConfig, buildGraphqlUrl, buildProviderUrl, getRequiredConfigKeysForGame, inspectResolvedConfig, parseApiUrl, resolveGamePackageId, resolveGameSettingsId, resolvePythPriceInfoId, resolveSuigarConfig } from "./config.mjs";
4
- import { getCurrencyInfo, getGameMetadata, listConfiguredCurrencies, listSupportedGames, readConfigMetadata } from "./metadata.mjs";
5
- import { resolveBetCoin } from "./coin.mjs";
6
- import { createReadOnlyClientBundle, dryRunTransaction, sanitizeForJson, serializeTransactionToBase64 } from "./client.mjs";
7
- import { buildCoinflipTransaction, buildLimboTransaction, buildPlinkoTransaction, buildPvpCoinflipCancelTransaction, buildPvpCoinflipCreateTransaction, buildPvpCoinflipJoinTransaction, buildRangeTransaction, buildWheelTransaction, summarizeTransaction } from "./transactions.mjs";
1
+ import { BuildTransactionResult, BuilderMode, DryRunEventSummary, DryRunResult, DryRunSummary, FormattedAmount, JsonValue, RawDryRunResult, ReadConfigResult, ReadGameMetadataResult, ReadOnlyPlan, ResolvedMcpConfig, SuigarConfig, SuigarConfigOverrides, SuigarMcpConfigInput, ToolStructuredResult, ToolTextResult, TransactionCommandSummary, TransactionSummary } from "./types.mjs";
2
+ import { DEFAULT_NETWORK, SuigarClientBundle, buildTransactionResult, createSuigarClient, dryRunTransaction, getProviderUrl, normalizeNetwork, resolveDefaultCoinType, resolveOwnerAddress, summarizeTransaction } from "./client.mjs";
3
+ import { CoinflipInput, CommonBuildInput, ConfigIdInput, LimboInput, PvpCoinflipCancelInput, PvpCoinflipCreateInput, PvpCoinflipJoinInput, RangeInput, ReadConfigInput, ReadGameMetadataInput, builderModes, coinflipInputSchema, commonBuildInputSchema, configIdInputSchema, configInputSchema, configOverridesSchema, limboInputSchema, metadataSchema, pvpCoinflipCancelInputSchema, pvpCoinflipCreateInputSchema, pvpCoinflipJoinInputSchema, rangeInputSchema, readConfigInputSchema, readGameMetadataInputSchema, stakeBuildInputSchema, toolOutputSchema } from "./schemas.mjs";
4
+ import { SUIGAR_MCP_APP_RESOURCE_URI, createSuigarMcpAppResourceResult, createSuigarMcpServer, readSuigarMcpAppHtml, startSuigarMcpServer } from "./server.mjs";
8
5
  import { buildCoinflipTransactionTool, buildLimboTransactionTool, buildPlinkoTransactionTool, buildPvpCoinflipCancelTransactionTool, buildPvpCoinflipCreateTransactionTool, buildPvpCoinflipJoinTransactionTool, buildRangeTransactionTool, buildWheelTransactionTool, readConfigTool, readGameMetadataTool } from "./tools.mjs";
9
- import { createSuigarMcpServer, startSuigarMcpServer } from "./server.mjs";
10
- export { BetCoinSource, BetMetadataInput, BetMetadataInputValue, BetMetadataPrimitive, BuilderMode, CasinoBetGameId, CoinReadClient, CoinSide, ConfigInspection, GameMcpSupport, McpExecutionSurface, ReadOnlyPlan, SUPPORTED_MCP_TOOL_NAMES, SharedBuildOptions, SuigarConfig, SuigarConfigInput, SuigarMcpToolName, SuigarNetwork, SupportedGameId, TransactionSummary, assertRequiredConfig, buildCoinflipTransaction, buildCoinflipTransactionTool, buildGraphqlUrl, buildLimboTransaction, buildLimboTransactionTool, buildMcpSupportCatalog, buildPlinkoTransaction, buildPlinkoTransactionTool, buildProviderUrl, buildPvpCoinflipCancelTransaction, buildPvpCoinflipCancelTransactionTool, buildPvpCoinflipCreateTransaction, buildPvpCoinflipCreateTransactionTool, buildPvpCoinflipJoinTransaction, buildPvpCoinflipJoinTransactionTool, buildRangeTransaction, buildRangeTransactionTool, buildWheelTransaction, buildWheelTransactionTool, createReadOnlyClientBundle, createSuigarMcpServer, dryRunTransaction, getCurrencyInfo, getGameMetadata, getMcpSupportForGame, getRequiredConfigKeysForGame, inspectResolvedConfig, listConfiguredCurrencies, listSupportedGames, parseApiUrl, readConfigMetadata, readConfigTool, readGameMetadataTool, resolveBetCoin, resolveGamePackageId, resolveGameSettingsId, resolvePythPriceInfoId, resolveSuigarConfig, sanitizeForJson, serializeTransactionToBase64, startSuigarMcpServer, summarizeTransaction };
6
+ export { type BuildTransactionResult, type BuilderMode, CoinflipInput, CommonBuildInput, ConfigIdInput, DEFAULT_NETWORK, type DryRunEventSummary, type DryRunResult, type DryRunSummary, type FormattedAmount, type JsonValue, LimboInput, PvpCoinflipCancelInput, PvpCoinflipCreateInput, PvpCoinflipJoinInput, RangeInput, type RawDryRunResult, ReadConfigInput, type ReadConfigResult, ReadGameMetadataInput, type ReadGameMetadataResult, type ReadOnlyPlan, type ResolvedMcpConfig, SUIGAR_MCP_APP_RESOURCE_URI, SuigarClientBundle, type SuigarConfig, type SuigarConfigOverrides, type SuigarMcpConfigInput, type ToolStructuredResult, type ToolTextResult, type TransactionCommandSummary, type TransactionSummary, buildCoinflipTransactionTool, buildLimboTransactionTool, buildPlinkoTransactionTool, buildPvpCoinflipCancelTransactionTool, buildPvpCoinflipCreateTransactionTool, buildPvpCoinflipJoinTransactionTool, buildRangeTransactionTool, buildTransactionResult, buildWheelTransactionTool, builderModes, coinflipInputSchema, commonBuildInputSchema, configIdInputSchema, configInputSchema, configOverridesSchema, createSuigarClient, createSuigarMcpAppResourceResult, createSuigarMcpServer, dryRunTransaction, getProviderUrl, limboInputSchema, metadataSchema, normalizeNetwork, pvpCoinflipCancelInputSchema, pvpCoinflipCreateInputSchema, pvpCoinflipJoinInputSchema, rangeInputSchema, readConfigInputSchema, readConfigTool, readGameMetadataInputSchema, readGameMetadataTool, readSuigarMcpAppHtml, resolveDefaultCoinType, resolveOwnerAddress, stakeBuildInputSchema, startSuigarMcpServer, summarizeTransaction, toolOutputSchema };
package/dist/index.mjs CHANGED
@@ -1,9 +1,5 @@
1
- import { SUPPORTED_MCP_TOOL_NAMES, buildMcpSupportCatalog, getMcpSupportForGame } from "./mcp-support.mjs";
2
- import { assertRequiredConfig, buildGraphqlUrl, buildProviderUrl, getRequiredConfigKeysForGame, inspectResolvedConfig, parseApiUrl, resolveGamePackageId, resolveGameSettingsId, resolvePythPriceInfoId, resolveSuigarConfig } from "./config.mjs";
3
- import { getCurrencyInfo, getGameMetadata, listConfiguredCurrencies, listSupportedGames, readConfigMetadata } from "./metadata.mjs";
4
- import { resolveBetCoin } from "./coin.mjs";
5
- import { createReadOnlyClientBundle, dryRunTransaction, sanitizeForJson, serializeTransactionToBase64 } from "./client.mjs";
6
- import { buildCoinflipTransaction, buildLimboTransaction, buildPlinkoTransaction, buildPvpCoinflipCancelTransaction, buildPvpCoinflipCreateTransaction, buildPvpCoinflipJoinTransaction, buildRangeTransaction, buildWheelTransaction, summarizeTransaction } from "./transactions.mjs";
1
+ import { builderModes, coinflipInputSchema, commonBuildInputSchema, configIdInputSchema, configInputSchema, configOverridesSchema, limboInputSchema, metadataSchema, pvpCoinflipCancelInputSchema, pvpCoinflipCreateInputSchema, pvpCoinflipJoinInputSchema, rangeInputSchema, readConfigInputSchema, readGameMetadataInputSchema, stakeBuildInputSchema, toolOutputSchema } from "./schemas.mjs";
2
+ import { DEFAULT_NETWORK, buildTransactionResult, createSuigarClient, dryRunTransaction, getProviderUrl, normalizeNetwork, resolveDefaultCoinType, resolveOwnerAddress, summarizeTransaction } from "./client.mjs";
7
3
  import { buildCoinflipTransactionTool, buildLimboTransactionTool, buildPlinkoTransactionTool, buildPvpCoinflipCancelTransactionTool, buildPvpCoinflipCreateTransactionTool, buildPvpCoinflipJoinTransactionTool, buildRangeTransactionTool, buildWheelTransactionTool, readConfigTool, readGameMetadataTool } from "./tools.mjs";
8
- import { createSuigarMcpServer, startSuigarMcpServer } from "./server.mjs";
9
- export { SUPPORTED_MCP_TOOL_NAMES, assertRequiredConfig, buildCoinflipTransaction, buildCoinflipTransactionTool, buildGraphqlUrl, buildLimboTransaction, buildLimboTransactionTool, buildMcpSupportCatalog, buildPlinkoTransaction, buildPlinkoTransactionTool, buildProviderUrl, buildPvpCoinflipCancelTransaction, buildPvpCoinflipCancelTransactionTool, buildPvpCoinflipCreateTransaction, buildPvpCoinflipCreateTransactionTool, buildPvpCoinflipJoinTransaction, buildPvpCoinflipJoinTransactionTool, buildRangeTransaction, buildRangeTransactionTool, buildWheelTransaction, buildWheelTransactionTool, createReadOnlyClientBundle, createSuigarMcpServer, dryRunTransaction, getCurrencyInfo, getGameMetadata, getMcpSupportForGame, getRequiredConfigKeysForGame, inspectResolvedConfig, listConfiguredCurrencies, listSupportedGames, parseApiUrl, readConfigMetadata, readConfigTool, readGameMetadataTool, resolveBetCoin, resolveGamePackageId, resolveGameSettingsId, resolvePythPriceInfoId, resolveSuigarConfig, sanitizeForJson, serializeTransactionToBase64, startSuigarMcpServer, summarizeTransaction };
4
+ import { SUIGAR_MCP_APP_RESOURCE_URI, createSuigarMcpAppResourceResult, createSuigarMcpServer, readSuigarMcpAppHtml, startSuigarMcpServer } from "./server.mjs";
5
+ export { DEFAULT_NETWORK, SUIGAR_MCP_APP_RESOURCE_URI, buildCoinflipTransactionTool, buildLimboTransactionTool, buildPlinkoTransactionTool, buildPvpCoinflipCancelTransactionTool, buildPvpCoinflipCreateTransactionTool, buildPvpCoinflipJoinTransactionTool, buildRangeTransactionTool, buildTransactionResult, buildWheelTransactionTool, builderModes, coinflipInputSchema, commonBuildInputSchema, configIdInputSchema, configInputSchema, configOverridesSchema, createSuigarClient, createSuigarMcpAppResourceResult, createSuigarMcpServer, dryRunTransaction, getProviderUrl, limboInputSchema, metadataSchema, normalizeNetwork, pvpCoinflipCancelInputSchema, pvpCoinflipCreateInputSchema, pvpCoinflipJoinInputSchema, rangeInputSchema, readConfigInputSchema, readConfigTool, readGameMetadataInputSchema, readGameMetadataTool, readSuigarMcpAppHtml, resolveDefaultCoinType, resolveOwnerAddress, stakeBuildInputSchema, startSuigarMcpServer, summarizeTransaction, toolOutputSchema };