@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.
- package/CHANGELOG.md +37 -0
- package/LICENSE +201 -0
- package/README.md +79 -110
- package/dist/app/index.html +181 -0
- package/dist/bin.mjs +3 -7
- package/dist/bin.mjs.map +1 -0
- package/dist/client.d.mts +41 -11
- package/dist/client.d.mts.map +1 -0
- package/dist/client.mjs +107 -34
- package/dist/client.mjs.map +1 -0
- package/dist/dry-run.mjs +163 -0
- package/dist/dry-run.mjs.map +1 -0
- package/dist/format.mjs +24 -0
- package/dist/format.mjs.map +1 -0
- package/dist/index.d.mts +5 -9
- package/dist/index.mjs +4 -8
- package/dist/schemas.d.mts +642 -0
- package/dist/schemas.d.mts.map +1 -0
- package/dist/schemas.mjs +113 -0
- package/dist/schemas.mjs.map +1 -0
- package/dist/server.d.mts +21 -69
- package/dist/server.d.mts.map +1 -0
- package/dist/server.mjs +172 -411
- package/dist/server.mjs.map +1 -0
- package/dist/tools.d.mts +14 -155
- package/dist/tools.d.mts.map +1 -0
- package/dist/tools.mjs +297 -553
- package/dist/tools.mjs.map +1 -0
- package/dist/types.d.mts +109 -83
- package/dist/types.d.mts.map +1 -0
- package/package.json +83 -61
- package/dist/bin.cjs +0 -11
- package/dist/bin.d.cts +0 -1
- package/dist/client.cjs +0 -46
- package/dist/client.d.cts +0 -17
- package/dist/coin.cjs +0 -86
- package/dist/coin.d.cts +0 -35
- package/dist/coin.d.mts +0 -35
- package/dist/coin.mjs +0 -86
- package/dist/config.cjs +0 -183
- package/dist/config.d.cts +0 -15
- package/dist/config.d.mts +0 -15
- package/dist/config.mjs +0 -174
- package/dist/index.cjs +0 -53
- package/dist/index.d.cts +0 -10
- package/dist/mcp-support.cjs +0 -62
- package/dist/mcp-support.d.cts +0 -16
- package/dist/mcp-support.d.mts +0 -16
- package/dist/mcp-support.mjs +0 -60
- package/dist/metadata.cjs +0 -51
- package/dist/metadata.d.cts +0 -52
- package/dist/metadata.d.mts +0 -52
- package/dist/metadata.mjs +0 -47
- package/dist/server.cjs +0 -433
- package/dist/server.d.cts +0 -73
- package/dist/tools.cjs +0 -617
- package/dist/tools.d.cts +0 -158
- package/dist/transactions.cjs +0 -294
- package/dist/transactions.d.cts +0 -40
- package/dist/transactions.d.mts +0 -40
- package/dist/transactions.mjs +0 -286
- package/dist/types.d.cts +0 -111
- package/node_modules/@suigar/currency-registry/dist/index.cjs +0 -121
- package/node_modules/@suigar/currency-registry/dist/index.d.cts +0 -50
- package/node_modules/@suigar/currency-registry/dist/index.d.mts +0 -50
- package/node_modules/@suigar/currency-registry/dist/index.mjs +0 -110
- package/node_modules/@suigar/currency-registry/package.json +0 -31
- package/node_modules/@suigar/game-registry/dist/index.cjs +0 -310
- package/node_modules/@suigar/game-registry/dist/index.d.cts +0 -65
- package/node_modules/@suigar/game-registry/dist/index.d.mts +0 -65
- package/node_modules/@suigar/game-registry/dist/index.mjs +0 -292
- package/node_modules/@suigar/game-registry/package.json +0 -31
- package/node_modules/@suigar/sui-rpc-pool/dist/index.cjs +0 -45590
- package/node_modules/@suigar/sui-rpc-pool/dist/index.d.cts +0 -465
- package/node_modules/@suigar/sui-rpc-pool/dist/index.d.mts +0 -465
- package/node_modules/@suigar/sui-rpc-pool/dist/index.mjs +0 -45570
- package/node_modules/@suigar/sui-rpc-pool/package.json +0 -31
package/dist/tools.mjs
CHANGED
|
@@ -1,608 +1,352 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { createReadOnlyClientBundle, dryRunTransaction, serializeTransactionToBase64 } from "./client.mjs";
|
|
4
|
-
import { buildCoinflipTransaction, buildLimboTransaction, buildPlinkoTransaction, buildPvpCoinflipCancelTransaction, buildPvpCoinflipCreateTransaction, buildPvpCoinflipJoinTransaction, buildRangeTransaction, buildWheelTransaction, summarizeTransaction } from "./transactions.mjs";
|
|
5
|
-
import { normalizeCoinType } from "@suigar/currency-registry";
|
|
6
|
-
import { SuiGrpcClient } from "@mysten/sui/grpc";
|
|
7
|
-
import { suigar } from "@suigar/sdk";
|
|
1
|
+
import { buildTransactionResult, createSuigarClient, resolveDefaultCoinType, resolveOwnerAddress } from "./client.mjs";
|
|
2
|
+
import { GAMES } from "@suigar/sdk/games";
|
|
8
3
|
//#region src/tools.ts
|
|
9
|
-
const
|
|
10
|
-
|
|
4
|
+
const GAME_LABELS = {
|
|
5
|
+
coinflip: "Coinflip",
|
|
6
|
+
limbo: "Limbo",
|
|
7
|
+
plinko: "Plinko",
|
|
8
|
+
range: "Range",
|
|
9
|
+
wheel: "Wheel",
|
|
10
|
+
"pvp-coinflip": "PvP Coinflip"
|
|
11
|
+
};
|
|
12
|
+
const GAME_TO_PACKAGE_KEY = {
|
|
13
|
+
coinflip: "coinflip",
|
|
14
|
+
limbo: "limbo",
|
|
15
|
+
plinko: "plinko",
|
|
16
|
+
range: "range",
|
|
17
|
+
wheel: "wheel",
|
|
18
|
+
"pvp-coinflip": "pvpCoinflip"
|
|
19
|
+
};
|
|
20
|
+
const GAME_TO_TOOLS = {
|
|
21
|
+
coinflip: ["build_coinflip_transaction"],
|
|
22
|
+
limbo: ["build_limbo_transaction"],
|
|
23
|
+
plinko: ["build_plinko_transaction"],
|
|
24
|
+
range: ["build_range_transaction"],
|
|
25
|
+
wheel: ["build_wheel_transaction"],
|
|
26
|
+
"pvp-coinflip": [
|
|
27
|
+
"build_pvp_coinflip_create_transaction",
|
|
28
|
+
"build_pvp_coinflip_join_transaction",
|
|
29
|
+
"build_pvp_coinflip_cancel_transaction"
|
|
30
|
+
]
|
|
31
|
+
};
|
|
32
|
+
const json = (value) => JSON.stringify(value, (_key, item) => typeof item === "bigint" ? item.toString() : item, 2);
|
|
33
|
+
const asTextResponse = (structuredContent) => ({
|
|
34
|
+
content: [{
|
|
35
|
+
type: "text",
|
|
36
|
+
text: json(structuredContent)
|
|
37
|
+
}],
|
|
38
|
+
structuredContent
|
|
39
|
+
});
|
|
40
|
+
const currencyAmountPattern = /^(?:\d+|\d+\.\d+|\.\d+)$/u;
|
|
41
|
+
const coinMetadataForAmount = (config, coinType) => {
|
|
42
|
+
const resolvedCoinType = resolveDefaultCoinType(config, coinType);
|
|
43
|
+
const coin = Object.values(config.sdk.coins).find((metadata) => resolveDefaultCoinType(config, metadata.coinType) === resolvedCoinType);
|
|
44
|
+
if (!coin) throw new RangeError(`Unable to resolve decimals for coin type ${resolvedCoinType}. Add the coin to config.coins before using currency-denominated amounts.`);
|
|
45
|
+
return {
|
|
46
|
+
coinType: resolvedCoinType,
|
|
47
|
+
decimals: coin.decimals
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
const toCurrencyAmountText = (value, fieldName) => {
|
|
51
|
+
if (typeof value === "number" && Number.isFinite(value) && value >= 0) return String(value);
|
|
52
|
+
if (typeof value === "string" && currencyAmountPattern.test(value.trim())) return value.trim();
|
|
53
|
+
throw new TypeError(`Missing or invalid ${fieldName}. Provide a non-negative currency amount such as 1, 2, or 1.5.`);
|
|
54
|
+
};
|
|
55
|
+
const toBaseUnits = (value, fieldName, decimals) => {
|
|
56
|
+
const [rawWhole, rawFraction = ""] = toCurrencyAmountText(value, fieldName).split(".");
|
|
57
|
+
const whole = rawWhole === "" ? "0" : rawWhole;
|
|
58
|
+
const overflow = rawFraction.slice(decimals);
|
|
59
|
+
if (/[^0]/u.test(overflow)) throw new RangeError(`${fieldName} has more fractional digits than the configured coin decimals (${decimals}).`);
|
|
60
|
+
const fraction = rawFraction.slice(0, decimals).padEnd(decimals, "0");
|
|
61
|
+
return BigInt(whole) * 10n ** BigInt(decimals) + BigInt(fraction || "0");
|
|
62
|
+
};
|
|
63
|
+
const toPositiveInteger = (value, fieldName) => {
|
|
64
|
+
if (typeof value === "number" && Number.isSafeInteger(value) && value > 0) return value;
|
|
65
|
+
if (typeof value === "string" && /^[1-9]\d*$/u.test(value)) return BigInt(value);
|
|
66
|
+
throw new TypeError(`Missing or invalid ${fieldName}. Provide a positive integer.`);
|
|
67
|
+
};
|
|
68
|
+
const requireString = (value, fieldName) => {
|
|
11
69
|
if (typeof value === "string" && value.trim()) return value.trim();
|
|
12
|
-
|
|
13
|
-
|
|
70
|
+
throw new TypeError(`Missing required field: ${fieldName}.`);
|
|
71
|
+
};
|
|
72
|
+
const requireNumber = (value, fieldName) => {
|
|
73
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
74
|
+
throw new TypeError(`Missing or invalid numeric field: ${fieldName}.`);
|
|
14
75
|
};
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
76
|
+
const getMode = (mode) => mode ?? "build";
|
|
77
|
+
const getConfigInput = (input) => ({
|
|
78
|
+
network: input.network,
|
|
79
|
+
providerUrl: input.providerUrl,
|
|
80
|
+
config: input.config,
|
|
81
|
+
partner: input.partner
|
|
82
|
+
});
|
|
83
|
+
const supportedGames = () => GAMES.map((id) => ({
|
|
84
|
+
id,
|
|
85
|
+
label: GAME_LABELS[id],
|
|
86
|
+
tools: [...GAME_TO_TOOLS[id]]
|
|
87
|
+
}));
|
|
88
|
+
const getPackageId = (config, game) => config.sdk.packageIds[GAME_TO_PACKAGE_KEY[game]];
|
|
89
|
+
const getTarget = (config, game, action) => {
|
|
90
|
+
const packageId = getPackageId(config, game);
|
|
91
|
+
if (game === "pvp-coinflip") return `${packageId}::pvp_coinflip::${action === "join" ? "join_game" : action === "cancel" ? "cancel_game" : "create_game"}`;
|
|
92
|
+
return `${packageId}::${game}::play`;
|
|
20
93
|
};
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
const
|
|
24
|
-
const SDK_BUILD_NETWORKS = /* @__PURE__ */ new Set(["mainnet", "testnet"]);
|
|
25
|
-
const SDK_UNSUPPORTED_CONFIG_OVERRIDE_KEYS = [
|
|
26
|
-
"suigarPackageId",
|
|
27
|
-
"coinflipPackageId",
|
|
28
|
-
"pvpCoinflipPackageId",
|
|
29
|
-
"plinkoPackageId",
|
|
30
|
-
"limboPackageId",
|
|
31
|
-
"rangePackageId",
|
|
32
|
-
"wheelPackageId",
|
|
33
|
-
"sweethouseId",
|
|
34
|
-
"suiPythPriceInfoObjectId",
|
|
35
|
-
"usdcPythPriceInfoObjectId",
|
|
36
|
-
"pvpCoinflipRegistryId"
|
|
37
|
-
];
|
|
38
|
-
const buildReadOnlyPlan = ({ game, config, coinType, targetSuffix, notes }) => {
|
|
39
|
-
const resolvedConfig = resolveSuigarConfig(config);
|
|
40
|
-
const packageId = resolveGamePackageId(game, resolvedConfig);
|
|
94
|
+
const readOnlyPlan = ({ input, game, action, requiredInputs, notes }) => {
|
|
95
|
+
const { config } = createSuigarClient(getConfigInput(input));
|
|
96
|
+
const coinType = resolveDefaultCoinType(config, input.coinType);
|
|
41
97
|
return {
|
|
42
98
|
mode: "read-only",
|
|
43
|
-
network:
|
|
99
|
+
network: config.network,
|
|
44
100
|
game,
|
|
45
|
-
|
|
101
|
+
action,
|
|
102
|
+
config,
|
|
46
103
|
plan: {
|
|
47
|
-
target:
|
|
48
|
-
typeArguments:
|
|
49
|
-
|
|
104
|
+
target: getTarget(config, game, action),
|
|
105
|
+
typeArguments: [coinType],
|
|
106
|
+
requiredInputs,
|
|
50
107
|
notes
|
|
51
108
|
}
|
|
52
109
|
};
|
|
53
110
|
};
|
|
54
|
-
const
|
|
55
|
-
const bundle = createReadOnlyClientBundle(config);
|
|
56
|
-
const summary = summarizeTransaction(transaction, context);
|
|
57
|
-
if (mode === "dry-run") return {
|
|
58
|
-
mode,
|
|
59
|
-
network: bundle.config.network,
|
|
60
|
-
config: inspectResolvedConfig(bundle.config),
|
|
61
|
-
summary,
|
|
62
|
-
dryRun: await dryRunTransaction(transaction, bundle.config)
|
|
63
|
-
};
|
|
111
|
+
const commonOptions = async (input, bundle) => {
|
|
64
112
|
return {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
113
|
+
owner: await resolveOwnerAddress(requireString(input.owner, "owner"), bundle),
|
|
114
|
+
coinType: resolveDefaultCoinType(bundle.config, input.coinType),
|
|
115
|
+
metadata: input.metadata,
|
|
116
|
+
gasBudget: input.gasBudget,
|
|
117
|
+
useGasCoin: input.useGasCoin
|
|
70
118
|
};
|
|
71
119
|
};
|
|
72
|
-
const
|
|
73
|
-
const
|
|
120
|
+
const stakeOptions = async (input, bundle) => {
|
|
121
|
+
const { decimals } = coinMetadataForAmount(bundle.config, input.coinType);
|
|
74
122
|
return {
|
|
75
|
-
...
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
};
|
|
80
|
-
};
|
|
81
|
-
const extractPartner = (input) => asOptionalString(input.partner) ?? asOptionalString(asRecord(input.config).partner);
|
|
82
|
-
const hasSdkUnsupportedConfigOverrides = (input) => {
|
|
83
|
-
const mergedInput = {
|
|
84
|
-
...asRecord(input.config),
|
|
85
|
-
...input
|
|
123
|
+
...await commonOptions(input, bundle),
|
|
124
|
+
stake: toBaseUnits(input.stake, "stake", decimals),
|
|
125
|
+
...input.cashStake == null ? {} : { cashStake: toBaseUnits(input.cashStake, "cashStake", decimals) },
|
|
126
|
+
...input.betCount == null ? {} : { betCount: toPositiveInteger(input.betCount, "betCount") }
|
|
86
127
|
};
|
|
87
|
-
return SDK_UNSUPPORTED_CONFIG_OVERRIDE_KEYS.some((key) => asOptionalString(mergedInput[key]));
|
|
88
128
|
};
|
|
89
|
-
const
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
allowGasCoinShortcut: asBoolean(record.allowGasCoinShortcut, true),
|
|
97
|
-
...record.gasBudget == null ? {} : { gasBudget: asNumber(record.gasBudget, "gasBudget") }
|
|
98
|
-
};
|
|
99
|
-
};
|
|
100
|
-
const buildStakeSdkOptions = (record, coinType) => ({
|
|
101
|
-
...buildCommonSdkOptions(record, coinType),
|
|
102
|
-
stake: asNumber(record.stake, "stake"),
|
|
103
|
-
...record.cashStake == null ? {} : { cashStake: asNumber(record.cashStake, "cashStake") },
|
|
104
|
-
...record.betCount == null ? {} : { betCount: asNumber(record.betCount, "betCount") }
|
|
105
|
-
});
|
|
106
|
-
const tryBuildSdkTransaction = ({ record, config, coinType, game, pvpAction }) => {
|
|
107
|
-
if (asStringArray(record.coinObjectIds).length > 0 || hasSdkUnsupportedConfigOverrides(record)) return null;
|
|
108
|
-
const resolvedConfig = resolveSuigarConfig(config);
|
|
109
|
-
if (!SDK_BUILD_NETWORKS.has(resolvedConfig.network)) return null;
|
|
110
|
-
const partner = extractPartner(record);
|
|
111
|
-
const client = new SuiGrpcClient({
|
|
112
|
-
baseUrl: resolvedConfig.providerUrl,
|
|
113
|
-
network: resolvedConfig.network
|
|
114
|
-
}).$extend(suigar(partner ? { partner } : void 0));
|
|
115
|
-
try {
|
|
116
|
-
switch (game) {
|
|
117
|
-
case "coinflip": return client.suigar.tx.createBetTransaction("coinflip", {
|
|
118
|
-
...buildStakeSdkOptions(record, coinType),
|
|
119
|
-
side: asString(record.side, "side")
|
|
120
|
-
});
|
|
121
|
-
case "limbo": return client.suigar.tx.createBetTransaction("limbo", {
|
|
122
|
-
...buildStakeSdkOptions(record, coinType),
|
|
123
|
-
targetMultiplier: asNumber(record.targetMultiplier, "targetMultiplier")
|
|
124
|
-
});
|
|
125
|
-
case "plinko": return client.suigar.tx.createBetTransaction("plinko", {
|
|
126
|
-
...buildStakeSdkOptions(record, coinType),
|
|
127
|
-
configId: asNumber(record.configId, "configId")
|
|
128
|
-
});
|
|
129
|
-
case "wheel": return client.suigar.tx.createBetTransaction("wheel", {
|
|
130
|
-
...buildStakeSdkOptions(record, coinType),
|
|
131
|
-
configId: asNumber(record.configId, "configId")
|
|
132
|
-
});
|
|
133
|
-
case "range": return client.suigar.tx.createBetTransaction("range", {
|
|
134
|
-
...buildStakeSdkOptions(record, coinType),
|
|
135
|
-
leftPoint: asNumber(record.leftPoint, "leftPoint"),
|
|
136
|
-
rightPoint: asNumber(record.rightPoint, "rightPoint"),
|
|
137
|
-
outOfRange: asBoolean(record.outOfRange)
|
|
138
|
-
});
|
|
139
|
-
case "pvp-coinflip":
|
|
140
|
-
if (pvpAction === "join" || pvpAction === "cancel") return client.suigar.tx.createPvPCoinflipTransaction(pvpAction, {
|
|
141
|
-
...buildCommonSdkOptions(record, coinType),
|
|
142
|
-
config: client.suigar.getConfig(),
|
|
143
|
-
gameId: asString(record.gameId, "gameId")
|
|
144
|
-
});
|
|
145
|
-
return client.suigar.tx.createPvPCoinflipTransaction("create", {
|
|
146
|
-
...buildCommonSdkOptions(record, coinType),
|
|
147
|
-
config: client.suigar.getConfig(),
|
|
148
|
-
stake: asNumber(record.stake, "stake"),
|
|
149
|
-
side: asString(record.creatorSide, "creatorSide"),
|
|
150
|
-
isPrivate: asBoolean(record.isPrivate)
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
} catch {
|
|
154
|
-
return null;
|
|
155
|
-
}
|
|
156
|
-
};
|
|
157
|
-
const readConfigTool = async (input = {}) => {
|
|
158
|
-
return readConfigMetadata(extractConfigInput(asRecord(input)));
|
|
159
|
-
};
|
|
160
|
-
const readGameMetadataTool = async (input = {}) => {
|
|
161
|
-
const record = asRecord(input);
|
|
162
|
-
const config = extractConfigInput(record);
|
|
163
|
-
const game = asOptionalString(record.game);
|
|
164
|
-
const coinType = asOptionalString(record.coinType);
|
|
165
|
-
return {
|
|
166
|
-
config: readConfigMetadata(config),
|
|
167
|
-
game: game ? getGameMetadata(game, config) : null,
|
|
168
|
-
currency: coinType ? getCurrencyInfo(coinType, config) : null
|
|
169
|
-
};
|
|
170
|
-
};
|
|
171
|
-
const buildCoinflipTransactionTool = async (input = {}) => {
|
|
172
|
-
const record = asRecord(input);
|
|
173
|
-
const config = extractConfigInput(record);
|
|
174
|
-
const mode = asMode(record.mode);
|
|
175
|
-
const coinType = asString(record.coinType, "coinType", resolveSuigarConfig(config).suiCoinType);
|
|
176
|
-
if (mode === "read-only") return buildReadOnlyPlan({
|
|
177
|
-
game: "coinflip",
|
|
178
|
-
config,
|
|
179
|
-
coinType,
|
|
180
|
-
targetSuffix: "::coinflip::play",
|
|
181
|
-
notes: ["Uses the sweethouse shared object, a prepared bet coin, Pyth price info, clock, and random."]
|
|
182
|
-
});
|
|
183
|
-
const sdkTransaction = tryBuildSdkTransaction({
|
|
184
|
-
record,
|
|
185
|
-
config,
|
|
186
|
-
coinType,
|
|
187
|
-
game: "coinflip"
|
|
188
|
-
});
|
|
189
|
-
if (sdkTransaction) return buildTransactionResult({
|
|
190
|
-
mode,
|
|
191
|
-
config,
|
|
192
|
-
transaction: sdkTransaction,
|
|
193
|
-
context: {
|
|
194
|
-
game: "coinflip",
|
|
195
|
-
coinType,
|
|
196
|
-
stake: asNumber(record.stake, "stake")
|
|
197
|
-
}
|
|
198
|
-
});
|
|
199
|
-
const bundle = createReadOnlyClientBundle(config);
|
|
200
|
-
const transaction = await buildCoinflipTransaction({
|
|
201
|
-
client: bundle.client,
|
|
202
|
-
config: bundle.config,
|
|
203
|
-
owner: asString(record.owner, "owner"),
|
|
204
|
-
coinType,
|
|
205
|
-
stake: asNumber(record.stake, "stake"),
|
|
206
|
-
cashStake: record.cashStake == null ? void 0 : asNumber(record.cashStake, "cashStake"),
|
|
207
|
-
betCount: record.betCount == null ? void 0 : asNumber(record.betCount, "betCount"),
|
|
208
|
-
side: asString(record.side, "side"),
|
|
209
|
-
metadata: asRecord(record.metadata),
|
|
210
|
-
partner: extractPartner(record),
|
|
211
|
-
coinSource: asStringArray(record.coinObjectIds).length > 0 ? {
|
|
212
|
-
kind: "object-ids",
|
|
213
|
-
objectIds: asStringArray(record.coinObjectIds)
|
|
214
|
-
} : void 0
|
|
215
|
-
});
|
|
216
|
-
return buildTransactionResult({
|
|
129
|
+
const executeTransactionTool = async ({ input, game, action, createTransaction, stake, stakeDisplay, gameInputs }) => {
|
|
130
|
+
const mode = getMode(input.mode);
|
|
131
|
+
if (mode === "read-only") throw new Error("read-only mode must be handled before transaction execution.");
|
|
132
|
+
const bundle = createSuigarClient(getConfigInput(input));
|
|
133
|
+
const coin = coinMetadataForAmount(bundle.config, input.coinType);
|
|
134
|
+
const baseStake = stake ?? (stakeDisplay == null ? void 0 : toBaseUnits(stakeDisplay, "stake", coin.decimals));
|
|
135
|
+
return asTextResponse(await buildTransactionResult({
|
|
217
136
|
mode,
|
|
137
|
+
transaction: await createTransaction(bundle),
|
|
218
138
|
config: bundle.config,
|
|
219
|
-
transaction,
|
|
220
|
-
context: {
|
|
221
|
-
game: "coinflip",
|
|
222
|
-
coinType,
|
|
223
|
-
stake: asNumber(record.stake, "stake")
|
|
224
|
-
}
|
|
225
|
-
});
|
|
226
|
-
};
|
|
227
|
-
const buildLimboTransactionTool = async (input = {}) => {
|
|
228
|
-
const record = asRecord(input);
|
|
229
|
-
const config = extractConfigInput(record);
|
|
230
|
-
const mode = asMode(record.mode);
|
|
231
|
-
const coinType = asString(record.coinType, "coinType", resolveSuigarConfig(config).suiCoinType);
|
|
232
|
-
if (mode === "read-only") return buildReadOnlyPlan({
|
|
233
|
-
game: "limbo",
|
|
234
|
-
config,
|
|
235
|
-
coinType,
|
|
236
|
-
targetSuffix: "::limbo::play",
|
|
237
|
-
notes: ["Target multiplier is encoded as a fixed-point numerator and denominator."]
|
|
238
|
-
});
|
|
239
|
-
const sdkTransaction = tryBuildSdkTransaction({
|
|
240
|
-
record,
|
|
241
|
-
config,
|
|
242
|
-
coinType,
|
|
243
|
-
game: "limbo"
|
|
244
|
-
});
|
|
245
|
-
if (sdkTransaction) return buildTransactionResult({
|
|
246
|
-
mode,
|
|
247
|
-
config,
|
|
248
|
-
transaction: sdkTransaction,
|
|
249
|
-
context: {
|
|
250
|
-
game: "limbo",
|
|
251
|
-
coinType,
|
|
252
|
-
stake: asNumber(record.stake, "stake")
|
|
253
|
-
}
|
|
254
|
-
});
|
|
255
|
-
const bundle = createReadOnlyClientBundle(config);
|
|
256
|
-
const transaction = await buildLimboTransaction({
|
|
257
139
|
client: bundle.client,
|
|
258
|
-
config: bundle.config,
|
|
259
|
-
owner: asString(record.owner, "owner"),
|
|
260
|
-
coinType,
|
|
261
|
-
stake: asNumber(record.stake, "stake"),
|
|
262
|
-
cashStake: record.cashStake == null ? void 0 : asNumber(record.cashStake, "cashStake"),
|
|
263
|
-
betCount: record.betCount == null ? void 0 : asNumber(record.betCount, "betCount"),
|
|
264
|
-
targetMultiplier: asNumber(record.targetMultiplier, "targetMultiplier"),
|
|
265
|
-
metadata: asRecord(record.metadata),
|
|
266
|
-
partner: extractPartner(record),
|
|
267
|
-
coinSource: asStringArray(record.coinObjectIds).length > 0 ? {
|
|
268
|
-
kind: "object-ids",
|
|
269
|
-
objectIds: asStringArray(record.coinObjectIds)
|
|
270
|
-
} : void 0
|
|
271
|
-
});
|
|
272
|
-
return buildTransactionResult({
|
|
273
|
-
mode,
|
|
274
|
-
config: bundle.config,
|
|
275
|
-
transaction,
|
|
276
140
|
context: {
|
|
277
|
-
game
|
|
278
|
-
|
|
279
|
-
|
|
141
|
+
game,
|
|
142
|
+
action,
|
|
143
|
+
coinType: coin.coinType,
|
|
144
|
+
stake: baseStake,
|
|
145
|
+
stakeDisplay,
|
|
146
|
+
coinDecimals: coin.decimals,
|
|
147
|
+
gameInputs
|
|
280
148
|
}
|
|
281
|
-
});
|
|
149
|
+
}));
|
|
282
150
|
};
|
|
283
|
-
const
|
|
284
|
-
const
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
const coinType = asString(record.coinType, "coinType", resolveSuigarConfig(config).suiCoinType);
|
|
288
|
-
if (mode === "read-only") return buildReadOnlyPlan({
|
|
289
|
-
game: "plinko",
|
|
290
|
-
config,
|
|
291
|
-
coinType,
|
|
292
|
-
targetSuffix: "::plinko::play",
|
|
293
|
-
notes: ["The config id is a u8 that selects the on-chain plinko board setup."]
|
|
294
|
-
});
|
|
295
|
-
const sdkTransaction = tryBuildSdkTransaction({
|
|
296
|
-
record,
|
|
151
|
+
const readConfigTool = async (input = {}) => {
|
|
152
|
+
const { config } = createSuigarClient(getConfigInput(input));
|
|
153
|
+
return asTextResponse({
|
|
154
|
+
network: config.network,
|
|
297
155
|
config,
|
|
298
|
-
|
|
299
|
-
game: "plinko"
|
|
156
|
+
supportedGames: supportedGames()
|
|
300
157
|
});
|
|
301
|
-
|
|
302
|
-
|
|
158
|
+
};
|
|
159
|
+
const readGameMetadataTool = async (input = {}) => {
|
|
160
|
+
const { config } = createSuigarClient(getConfigInput(input));
|
|
161
|
+
const game = input.game ?? null;
|
|
162
|
+
const coinType = resolveDefaultCoinType(config, input.coinType);
|
|
163
|
+
return asTextResponse({
|
|
164
|
+
network: config.network,
|
|
303
165
|
config,
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
}
|
|
310
|
-
});
|
|
311
|
-
const bundle = createReadOnlyClientBundle(config);
|
|
312
|
-
const transaction = await buildPlinkoTransaction({
|
|
313
|
-
client: bundle.client,
|
|
314
|
-
config: bundle.config,
|
|
315
|
-
owner: asString(record.owner, "owner"),
|
|
316
|
-
coinType,
|
|
317
|
-
stake: asNumber(record.stake, "stake"),
|
|
318
|
-
cashStake: record.cashStake == null ? void 0 : asNumber(record.cashStake, "cashStake"),
|
|
319
|
-
betCount: record.betCount == null ? void 0 : asNumber(record.betCount, "betCount"),
|
|
320
|
-
configId: asNumber(record.configId, "configId"),
|
|
321
|
-
metadata: asRecord(record.metadata),
|
|
322
|
-
partner: extractPartner(record),
|
|
323
|
-
coinSource: asStringArray(record.coinObjectIds).length > 0 ? {
|
|
324
|
-
kind: "object-ids",
|
|
325
|
-
objectIds: asStringArray(record.coinObjectIds)
|
|
326
|
-
} : void 0
|
|
327
|
-
});
|
|
328
|
-
return buildTransactionResult({
|
|
329
|
-
mode,
|
|
330
|
-
config: bundle.config,
|
|
331
|
-
transaction,
|
|
332
|
-
context: {
|
|
333
|
-
game: "plinko",
|
|
166
|
+
supportedGames: supportedGames(),
|
|
167
|
+
game: game ? {
|
|
168
|
+
id: game,
|
|
169
|
+
label: GAME_LABELS[game],
|
|
170
|
+
packageId: getPackageId(config, game),
|
|
334
171
|
coinType,
|
|
335
|
-
|
|
336
|
-
}
|
|
172
|
+
notes: [game === "pvp-coinflip" ? "PvP coinflip uses dedicated create, join, and cancel transaction builders." : "Standard games use client.suigar.tx.createBetTransaction().", "Transactions are unsigned and are never executed by the MCP server."]
|
|
173
|
+
} : null
|
|
337
174
|
});
|
|
338
175
|
};
|
|
339
|
-
const
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
transaction: sdkTransaction,
|
|
361
|
-
context: {
|
|
362
|
-
game: "wheel",
|
|
363
|
-
coinType,
|
|
364
|
-
stake: asNumber(record.stake, "stake")
|
|
365
|
-
}
|
|
176
|
+
const buildCoinflipTransactionTool = async (input = {}) => {
|
|
177
|
+
if (getMode(input.mode) === "read-only") return asTextResponse(readOnlyPlan({
|
|
178
|
+
input,
|
|
179
|
+
game: "coinflip",
|
|
180
|
+
requiredInputs: [
|
|
181
|
+
"owner",
|
|
182
|
+
"stake",
|
|
183
|
+
"side"
|
|
184
|
+
],
|
|
185
|
+
notes: ["Uses the configured SweetHouse object, Pyth price info, clock, and randomness objects."]
|
|
186
|
+
}));
|
|
187
|
+
const side = requireString(input.side, "side");
|
|
188
|
+
return executeTransactionTool({
|
|
189
|
+
input,
|
|
190
|
+
game: "coinflip",
|
|
191
|
+
stakeDisplay: toCurrencyAmountText(input.stake, "stake"),
|
|
192
|
+
gameInputs: { side },
|
|
193
|
+
createTransaction: async (bundle) => bundle.client.suigar.tx.createBetTransaction("coinflip", {
|
|
194
|
+
...await stakeOptions(input, bundle),
|
|
195
|
+
side
|
|
196
|
+
})
|
|
366
197
|
});
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
198
|
+
};
|
|
199
|
+
const buildLimboTransactionTool = async (input = {}) => {
|
|
200
|
+
if (getMode(input.mode) === "read-only") return asTextResponse(readOnlyPlan({
|
|
201
|
+
input,
|
|
202
|
+
game: "limbo",
|
|
203
|
+
requiredInputs: [
|
|
204
|
+
"owner",
|
|
205
|
+
"stake",
|
|
206
|
+
"targetMultiplier"
|
|
207
|
+
],
|
|
208
|
+
notes: ["Target multiplier is encoded by @suigar/sdk using the public fixed-point utility defaults."]
|
|
209
|
+
}));
|
|
210
|
+
const targetMultiplier = requireNumber(input.targetMultiplier, "targetMultiplier");
|
|
211
|
+
return executeTransactionTool({
|
|
212
|
+
input,
|
|
213
|
+
game: "limbo",
|
|
214
|
+
stakeDisplay: toCurrencyAmountText(input.stake, "stake"),
|
|
215
|
+
gameInputs: { targetMultiplier },
|
|
216
|
+
createTransaction: async (bundle) => bundle.client.suigar.tx.createBetTransaction("limbo", {
|
|
217
|
+
...await stakeOptions(input, bundle),
|
|
218
|
+
targetMultiplier
|
|
219
|
+
})
|
|
383
220
|
});
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
221
|
+
};
|
|
222
|
+
const buildConfigIdTransactionTool = async (input, game) => {
|
|
223
|
+
if (getMode(input.mode) === "read-only") return asTextResponse(readOnlyPlan({
|
|
224
|
+
input,
|
|
225
|
+
game,
|
|
226
|
+
requiredInputs: [
|
|
227
|
+
"owner",
|
|
228
|
+
"stake",
|
|
229
|
+
"configId"
|
|
230
|
+
],
|
|
231
|
+
notes: ["Config id selects the on-chain game configuration."]
|
|
232
|
+
}));
|
|
233
|
+
const configId = requireNumber(input.configId, "configId");
|
|
234
|
+
return executeTransactionTool({
|
|
235
|
+
input,
|
|
236
|
+
game,
|
|
237
|
+
stakeDisplay: toCurrencyAmountText(input.stake, "stake"),
|
|
238
|
+
gameInputs: { configId },
|
|
239
|
+
createTransaction: async (bundle) => bundle.client.suigar.tx.createBetTransaction(game, {
|
|
240
|
+
...await stakeOptions(input, bundle),
|
|
241
|
+
configId
|
|
242
|
+
})
|
|
393
243
|
});
|
|
394
244
|
};
|
|
245
|
+
const buildPlinkoTransactionTool = (input = {}) => buildConfigIdTransactionTool(input, "plinko");
|
|
246
|
+
const buildWheelTransactionTool = (input = {}) => buildConfigIdTransactionTool(input, "wheel");
|
|
395
247
|
const buildRangeTransactionTool = async (input = {}) => {
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
const mode = asMode(record.mode);
|
|
399
|
-
const coinType = asString(record.coinType, "coinType", resolveSuigarConfig(config).suiCoinType);
|
|
400
|
-
if (mode === "read-only") return buildReadOnlyPlan({
|
|
248
|
+
if (getMode(input.mode) === "read-only") return asTextResponse(readOnlyPlan({
|
|
249
|
+
input,
|
|
401
250
|
game: "range",
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
coinType,
|
|
429
|
-
stake: asNumber(record.stake, "stake"),
|
|
430
|
-
cashStake: record.cashStake == null ? void 0 : asNumber(record.cashStake, "cashStake"),
|
|
431
|
-
betCount: record.betCount == null ? void 0 : asNumber(record.betCount, "betCount"),
|
|
432
|
-
leftPoint: asNumber(record.leftPoint, "leftPoint"),
|
|
433
|
-
rightPoint: asNumber(record.rightPoint, "rightPoint"),
|
|
434
|
-
outOfRange: asBoolean(record.outOfRange),
|
|
435
|
-
metadata: asRecord(record.metadata),
|
|
436
|
-
partner: extractPartner(record),
|
|
437
|
-
coinSource: asStringArray(record.coinObjectIds).length > 0 ? {
|
|
438
|
-
kind: "object-ids",
|
|
439
|
-
objectIds: asStringArray(record.coinObjectIds)
|
|
440
|
-
} : void 0
|
|
441
|
-
});
|
|
442
|
-
return buildTransactionResult({
|
|
443
|
-
mode,
|
|
444
|
-
config: bundle.config,
|
|
445
|
-
transaction,
|
|
446
|
-
context: {
|
|
447
|
-
game: "range",
|
|
448
|
-
coinType,
|
|
449
|
-
stake: asNumber(record.stake, "stake")
|
|
450
|
-
}
|
|
251
|
+
requiredInputs: [
|
|
252
|
+
"owner",
|
|
253
|
+
"stake",
|
|
254
|
+
"leftPoint",
|
|
255
|
+
"rightPoint"
|
|
256
|
+
],
|
|
257
|
+
notes: ["Range points are normalized by @suigar/sdk before Move call construction."]
|
|
258
|
+
}));
|
|
259
|
+
const leftPoint = requireNumber(input.leftPoint, "leftPoint");
|
|
260
|
+
const rightPoint = requireNumber(input.rightPoint, "rightPoint");
|
|
261
|
+
const outOfRange = Boolean(input.outOfRange);
|
|
262
|
+
return executeTransactionTool({
|
|
263
|
+
input,
|
|
264
|
+
game: "range",
|
|
265
|
+
stakeDisplay: toCurrencyAmountText(input.stake, "stake"),
|
|
266
|
+
gameInputs: {
|
|
267
|
+
leftPoint,
|
|
268
|
+
rightPoint,
|
|
269
|
+
outOfRange
|
|
270
|
+
},
|
|
271
|
+
createTransaction: async (bundle) => bundle.client.suigar.tx.createBetTransaction("range", {
|
|
272
|
+
...await stakeOptions(input, bundle),
|
|
273
|
+
leftPoint,
|
|
274
|
+
rightPoint,
|
|
275
|
+
outOfRange
|
|
276
|
+
})
|
|
451
277
|
});
|
|
452
278
|
};
|
|
453
279
|
const buildPvpCoinflipCreateTransactionTool = async (input = {}) => {
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
const mode = asMode(record.mode);
|
|
457
|
-
const coinType = asString(record.coinType, "coinType", resolveSuigarConfig(config).suiCoinType);
|
|
458
|
-
if (mode === "read-only") return buildReadOnlyPlan({
|
|
280
|
+
if (getMode(input.mode) === "read-only") return asTextResponse(readOnlyPlan({
|
|
281
|
+
input,
|
|
459
282
|
game: "pvp-coinflip",
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
283
|
+
action: "create",
|
|
284
|
+
requiredInputs: [
|
|
285
|
+
"owner",
|
|
286
|
+
"stake",
|
|
287
|
+
"creatorSide"
|
|
288
|
+
],
|
|
289
|
+
notes: ["Creates an unresolved PvP coinflip lobby without signing or executing the transaction."]
|
|
290
|
+
}));
|
|
291
|
+
const creatorSide = requireString(input.creatorSide, "creatorSide");
|
|
292
|
+
return executeTransactionTool({
|
|
293
|
+
input,
|
|
469
294
|
game: "pvp-coinflip",
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
coinType,
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
const bundle = createReadOnlyClientBundle(config);
|
|
483
|
-
const transaction = await buildPvpCoinflipCreateTransaction({
|
|
484
|
-
client: bundle.client,
|
|
485
|
-
config: bundle.config,
|
|
486
|
-
owner: asString(record.owner, "owner"),
|
|
487
|
-
coinType,
|
|
488
|
-
stake: asNumber(record.stake, "stake"),
|
|
489
|
-
creatorSide: asString(record.creatorSide, "creatorSide"),
|
|
490
|
-
isPrivate: asBoolean(record.isPrivate),
|
|
491
|
-
metadata: asRecord(record.metadata),
|
|
492
|
-
partner: extractPartner(record),
|
|
493
|
-
coinSource: asStringArray(record.coinObjectIds).length > 0 ? {
|
|
494
|
-
kind: "object-ids",
|
|
495
|
-
objectIds: asStringArray(record.coinObjectIds)
|
|
496
|
-
} : void 0
|
|
497
|
-
});
|
|
498
|
-
return buildTransactionResult({
|
|
499
|
-
mode,
|
|
500
|
-
config: bundle.config,
|
|
501
|
-
transaction,
|
|
502
|
-
context: {
|
|
503
|
-
game: "pvp-coinflip",
|
|
504
|
-
coinType,
|
|
505
|
-
stake: asNumber(record.stake, "stake")
|
|
506
|
-
}
|
|
295
|
+
action: "create",
|
|
296
|
+
stakeDisplay: toCurrencyAmountText(input.stake, "stake"),
|
|
297
|
+
gameInputs: {
|
|
298
|
+
creatorSide,
|
|
299
|
+
...input.isPrivate == null ? {} : { isPrivate: input.isPrivate }
|
|
300
|
+
},
|
|
301
|
+
createTransaction: async (bundle) => bundle.client.suigar.tx.createPvPCoinflipTransaction("create", {
|
|
302
|
+
...await commonOptions(input, bundle),
|
|
303
|
+
stake: toBaseUnits(input.stake, "stake", coinMetadataForAmount(bundle.config, input.coinType).decimals),
|
|
304
|
+
side: creatorSide,
|
|
305
|
+
isPrivate: input.isPrivate
|
|
306
|
+
})
|
|
507
307
|
});
|
|
508
308
|
};
|
|
509
309
|
const buildPvpCoinflipJoinTransactionTool = async (input = {}) => {
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
const mode = asMode(record.mode);
|
|
513
|
-
const coinType = asString(record.coinType, "coinType", resolveSuigarConfig(config).suiCoinType);
|
|
514
|
-
if (mode === "read-only") return buildReadOnlyPlan({
|
|
310
|
+
if (getMode(input.mode) === "read-only") return asTextResponse(readOnlyPlan({
|
|
311
|
+
input,
|
|
515
312
|
game: "pvp-coinflip",
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
config,
|
|
524
|
-
coinType,
|
|
313
|
+
action: "join",
|
|
314
|
+
requiredInputs: ["owner", "gameId"],
|
|
315
|
+
notes: ["Join resolves the live game object during transaction build so the SDK can source the matching stake."]
|
|
316
|
+
}));
|
|
317
|
+
const gameId = requireString(input.gameId, "gameId");
|
|
318
|
+
return executeTransactionTool({
|
|
319
|
+
input,
|
|
525
320
|
game: "pvp-coinflip",
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
context: {
|
|
533
|
-
game: "pvp-coinflip",
|
|
534
|
-
coinType,
|
|
535
|
-
stake: asNumber(record.stake, "stake")
|
|
536
|
-
}
|
|
537
|
-
});
|
|
538
|
-
const bundle = createReadOnlyClientBundle(config);
|
|
539
|
-
const transaction = await buildPvpCoinflipJoinTransaction({
|
|
540
|
-
client: bundle.client,
|
|
541
|
-
config: bundle.config,
|
|
542
|
-
owner: asString(record.owner, "owner"),
|
|
543
|
-
gameId: asString(record.gameId, "gameId"),
|
|
544
|
-
coinType,
|
|
545
|
-
stake: asNumber(record.stake, "stake"),
|
|
546
|
-
metadata: asRecord(record.metadata),
|
|
547
|
-
partner: extractPartner(record),
|
|
548
|
-
coinSource: asStringArray(record.coinObjectIds).length > 0 ? {
|
|
549
|
-
kind: "object-ids",
|
|
550
|
-
objectIds: asStringArray(record.coinObjectIds)
|
|
551
|
-
} : void 0
|
|
552
|
-
});
|
|
553
|
-
return buildTransactionResult({
|
|
554
|
-
mode,
|
|
555
|
-
config: bundle.config,
|
|
556
|
-
transaction,
|
|
557
|
-
context: {
|
|
558
|
-
game: "pvp-coinflip",
|
|
559
|
-
coinType,
|
|
560
|
-
stake: asNumber(record.stake, "stake")
|
|
561
|
-
}
|
|
321
|
+
action: "join",
|
|
322
|
+
gameInputs: { gameId },
|
|
323
|
+
createTransaction: async (bundle) => bundle.client.suigar.tx.createPvPCoinflipTransaction("join", {
|
|
324
|
+
...await commonOptions(input, bundle),
|
|
325
|
+
gameId
|
|
326
|
+
})
|
|
562
327
|
});
|
|
563
328
|
};
|
|
564
329
|
const buildPvpCoinflipCancelTransactionTool = async (input = {}) => {
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
const mode = asMode(record.mode);
|
|
568
|
-
const coinType = asString(record.coinType, "coinType", resolveSuigarConfig(config).suiCoinType);
|
|
569
|
-
if (mode === "read-only") return buildReadOnlyPlan({
|
|
330
|
+
if (getMode(input.mode) === "read-only") return asTextResponse(readOnlyPlan({
|
|
331
|
+
input,
|
|
570
332
|
game: "pvp-coinflip",
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
config,
|
|
579
|
-
coinType,
|
|
333
|
+
action: "cancel",
|
|
334
|
+
requiredInputs: ["owner", "gameId"],
|
|
335
|
+
notes: ["Cancel only prepares the unsigned cancellation transaction for the game creator."]
|
|
336
|
+
}));
|
|
337
|
+
const gameId = requireString(input.gameId, "gameId");
|
|
338
|
+
return executeTransactionTool({
|
|
339
|
+
input,
|
|
580
340
|
game: "pvp-coinflip",
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
context: {
|
|
588
|
-
game: "pvp-coinflip",
|
|
589
|
-
coinType
|
|
590
|
-
}
|
|
591
|
-
});
|
|
592
|
-
return buildTransactionResult({
|
|
593
|
-
mode,
|
|
594
|
-
config,
|
|
595
|
-
transaction: buildPvpCoinflipCancelTransaction({
|
|
596
|
-
config,
|
|
597
|
-
owner: asString(record.owner, "owner"),
|
|
598
|
-
gameId: asString(record.gameId, "gameId"),
|
|
599
|
-
coinType
|
|
600
|
-
}),
|
|
601
|
-
context: {
|
|
602
|
-
game: "pvp-coinflip",
|
|
603
|
-
coinType
|
|
604
|
-
}
|
|
341
|
+
action: "cancel",
|
|
342
|
+
gameInputs: { gameId },
|
|
343
|
+
createTransaction: async (bundle) => bundle.client.suigar.tx.createPvPCoinflipTransaction("cancel", {
|
|
344
|
+
...await commonOptions(input, bundle),
|
|
345
|
+
gameId
|
|
346
|
+
})
|
|
605
347
|
});
|
|
606
348
|
};
|
|
607
349
|
//#endregion
|
|
608
350
|
export { buildCoinflipTransactionTool, buildLimboTransactionTool, buildPlinkoTransactionTool, buildPvpCoinflipCancelTransactionTool, buildPvpCoinflipCreateTransactionTool, buildPvpCoinflipJoinTransactionTool, buildRangeTransactionTool, buildWheelTransactionTool, readConfigTool, readGameMetadataTool };
|
|
351
|
+
|
|
352
|
+
//# sourceMappingURL=tools.mjs.map
|