@suigar/sdk 2.0.0-beta.1 → 2.0.0-beta.11

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/dist/index.js CHANGED
@@ -1,292 +1,414 @@
1
- import { normalizeSuiAddress, toBase64, normalizeStructTag, SUI_TYPE_ARG } from '@mysten/sui/utils';
2
- import { bcs, BcsStruct, TypeTagSerializer } from '@mysten/sui/bcs';
3
- import { Transaction, isArgument } from '@mysten/sui/transactions';
1
+ import { MoveStruct, Float, parseCoinType, toBigInt, toU8, DEFAULT_GAS_BUDGET_MIST, normalizeMoveArguments, DEFAULT_LIMBO_MULTIPLIER_SCALE, DEFAULT_RANGE_SCALE } from './chunk-TBJ5TYYE.js';
2
+ import { toBase64, normalizeStructTag, parseStructTag, normalizeSuiAddress, fromHex } from '@mysten/sui/utils';
3
+ import { bcs } from '@mysten/sui/bcs';
4
+ import { Transaction } from '@mysten/sui/transactions';
5
+ import { ClientCache } from '@mysten/sui/client';
4
6
 
5
- // src/utils/config.ts
7
+ var $moduleName = "0x0000000000000000000000000000000000000000000000000000000000000001::type_name";
8
+ var TypeName = new MoveStruct({
9
+ name: `${$moduleName}::TypeName`,
10
+ fields: {
11
+ name: bcs.string()
12
+ }
13
+ });
14
+ var $moduleName2 = "0x2::vec_map";
15
+ function Entry(...typeParameters) {
16
+ return new MoveStruct({
17
+ name: `${$moduleName2}::Entry<${typeParameters[0].name}, ${typeParameters[1].name}>`,
18
+ fields: {
19
+ key: typeParameters[0],
20
+ value: typeParameters[1]
21
+ }
22
+ });
23
+ }
24
+ function VecMap(...typeParameters) {
25
+ return new MoveStruct({
26
+ name: `${$moduleName2}::VecMap<${typeParameters[0].name}, ${typeParameters[1].name}>`,
27
+ fields: {
28
+ contents: bcs.vector(Entry(typeParameters[0], typeParameters[1]))
29
+ }
30
+ });
31
+ }
6
32
 
7
- // src/configs/package-id.ts
8
- var DEFAULT_SWEETHOUSE_PACKAGE_ID = "0xb7f64e5a273aba1ede00caa0a6f8027cc7490c279d17eab12e7100ed20660603";
9
- var DEFAULT_GAMES_PACKAGE_ID = {
33
+ // src/contracts/core/core.ts
34
+ var $moduleName3 = "0xf391858d2a08473e8d4defcc8df89976bd7b123d3865c6b9341b237f7853dbbc::core";
35
+ var BetResultEvent = new MoveStruct({
36
+ name: `${$moduleName3}::BetResultEvent<phantom T0>`,
37
+ fields: {
38
+ player: bcs.Address,
39
+ coin_type: TypeName,
40
+ stake_amount: bcs.u64(),
41
+ unsafe_oracle_usd_coin_price: Float,
42
+ adjusted_oracle_usd_coin_price: Float,
43
+ outcome_amount: bcs.u64(),
44
+ game_details: VecMap(bcs.string(), bcs.vector(bcs.u8())),
45
+ metadata: VecMap(bcs.string(), bcs.vector(bcs.u8()))
46
+ }
47
+ });
48
+ var $moduleName4 = "0x0000000000000000000000000000000000000000000000000000000000000001::type_name";
49
+ var TypeName2 = new MoveStruct({
50
+ name: `${$moduleName4}::TypeName`,
51
+ fields: {
52
+ name: bcs.string()
53
+ }
54
+ });
55
+ var $moduleName5 = "0x2::balance";
56
+ var Balance = new MoveStruct({
57
+ name: `${$moduleName5}::Balance<phantom T0>`,
58
+ fields: {
59
+ value: bcs.u64()
60
+ }
61
+ });
62
+ var $moduleName6 = "0x2::vec_map";
63
+ function Entry2(...typeParameters) {
64
+ return new MoveStruct({
65
+ name: `${$moduleName6}::Entry<${typeParameters[0].name}, ${typeParameters[1].name}>`,
66
+ fields: {
67
+ key: typeParameters[0],
68
+ value: typeParameters[1]
69
+ }
70
+ });
71
+ }
72
+ function VecMap2(...typeParameters) {
73
+ return new MoveStruct({
74
+ name: `${$moduleName6}::VecMap<${typeParameters[0].name}, ${typeParameters[1].name}>`,
75
+ fields: {
76
+ contents: bcs.vector(Entry2(typeParameters[0], typeParameters[1]))
77
+ }
78
+ });
79
+ }
80
+
81
+ // src/contracts/pvp-coinflip/pvp_coinflip.ts
82
+ var $moduleName7 = "0xb43cf6583c0c15315c7e66f173af4be79ac40c38aad1fd92ec08638ab2026202::pvp_coinflip";
83
+ var PvpCoinflipSettingsKey = new MoveStruct({
84
+ name: `${$moduleName7}::PvpCoinflipSettingsKey`,
85
+ fields: {
86
+ dummy_field: bcs.bool()
87
+ }
88
+ });
89
+ var Game = new MoveStruct({
90
+ name: `${$moduleName7}::Game<phantom T0>`,
91
+ fields: {
92
+ id: bcs.Address,
93
+ creator: bcs.Address,
94
+ creator_is_tails: bcs.bool(),
95
+ is_private: bcs.bool(),
96
+ creator_metadata: VecMap2(bcs.string(), bcs.vector(bcs.u8())),
97
+ joiner: bcs.Address,
98
+ winner: bcs.Address,
99
+ stake_per_player: bcs.u64(),
100
+ house_edge_bps: bcs.u64(),
101
+ stake_pot: Balance
102
+ }
103
+ });
104
+ var GameCreatedEvent = new MoveStruct({
105
+ name: `${$moduleName7}::GameCreatedEvent<phantom T0>`,
106
+ fields: {
107
+ game_id: bcs.Address,
108
+ creator: bcs.Address,
109
+ creator_is_tails: bcs.bool(),
110
+ is_private: bcs.bool(),
111
+ joiner_is_tails: bcs.bool(),
112
+ stake_per_player: bcs.u64(),
113
+ house_edge_bps: bcs.u64(),
114
+ coin_type: TypeName2
115
+ }
116
+ });
117
+ var GameResolvedEvent = new MoveStruct({
118
+ name: `${$moduleName7}::GameResolvedEvent<phantom T0>`,
119
+ fields: {
120
+ game_id: bcs.Address,
121
+ creator: bcs.Address,
122
+ joiner: bcs.Address,
123
+ winner: bcs.Address,
124
+ creator_is_tails: bcs.bool(),
125
+ is_private: bcs.bool(),
126
+ joiner_is_tails: bcs.bool(),
127
+ stake_per_player: bcs.u64(),
128
+ total_pot: bcs.u64(),
129
+ house_edge_amount: bcs.u64(),
130
+ payout_amount: bcs.u64(),
131
+ coin_type: TypeName2
132
+ }
133
+ });
134
+ var GameCancelledEvent = new MoveStruct({
135
+ name: `${$moduleName7}::GameCancelledEvent<phantom T0>`,
136
+ fields: {
137
+ game_id: bcs.Address,
138
+ creator: bcs.Address,
139
+ creator_is_tails: bcs.bool(),
140
+ is_private: bcs.bool(),
141
+ stake_per_player: bcs.u64(),
142
+ coin_type: TypeName2
143
+ }
144
+ });
145
+ var Parameters = new MoveStruct({
146
+ name: `${$moduleName7}::Parameters<phantom T0>`,
147
+ fields: {
148
+ id: bcs.Address,
149
+ house_edge_bps: bcs.u64(),
150
+ min_stake: bcs.u64()
151
+ }
152
+ });
153
+ function createGame(options) {
154
+ const packageAddress = options.package ?? "0xb43cf6583c0c15315c7e66f173af4be79ac40c38aad1fd92ec08638ab2026202";
155
+ const argumentsTypes = [
156
+ null,
157
+ null,
158
+ "bool",
159
+ "bool",
160
+ "vector<0x1::string::String>",
161
+ "vector<vector<u8>>"
162
+ ];
163
+ return (tx) => tx.moveCall({
164
+ package: packageAddress,
165
+ module: "pvp_coinflip",
166
+ function: "create_game",
167
+ arguments: normalizeMoveArguments(options.arguments, argumentsTypes),
168
+ typeArguments: options.typeArguments
169
+ });
170
+ }
171
+ function joinGame(options) {
172
+ const packageAddress = options.package ?? "0xb43cf6583c0c15315c7e66f173af4be79ac40c38aad1fd92ec08638ab2026202";
173
+ const argumentsTypes = [
174
+ "0x2::object::ID",
175
+ null,
176
+ null,
177
+ "vector<0x1::string::String>",
178
+ "vector<vector<u8>>",
179
+ null,
180
+ "0x2::clock::Clock",
181
+ "0x2::random::Random"
182
+ ];
183
+ return (tx) => tx.moveCall({
184
+ package: packageAddress,
185
+ module: "pvp_coinflip",
186
+ function: "join_game",
187
+ arguments: normalizeMoveArguments(options.arguments, argumentsTypes),
188
+ typeArguments: options.typeArguments
189
+ });
190
+ }
191
+ function cancelGame(options) {
192
+ const packageAddress = options.package ?? "0xb43cf6583c0c15315c7e66f173af4be79ac40c38aad1fd92ec08638ab2026202";
193
+ const argumentsTypes = ["0x2::object::ID", null];
194
+ return (tx) => tx.moveCall({
195
+ package: packageAddress,
196
+ module: "pvp_coinflip",
197
+ function: "cancel_game",
198
+ arguments: normalizeMoveArguments(options.arguments, argumentsTypes),
199
+ typeArguments: options.typeArguments
200
+ });
201
+ }
202
+
203
+ // src/configs/package.mainnet.ts
204
+ var MAINNET_PACKAGE_IDS = {
205
+ sweetHouse: "0xa1549d73230118716bc08865b8d62454f360ddaf40eee2158e458e52125d4ef1",
206
+ core: "0xcbb0929f21450013ebe5e86e7139f2409da2e3ed212c51126a7e6448b795a43f",
207
+ coinflip: "0xca96885371150f55653f7fab9e9b146f5a19698b1002bdff42159ea9d2ba7d7e",
208
+ limbo: "0x89db6a55ad4e650cad641b6f9fd90b391b22b1d9adbb2cabbfeb94a9eeda7026",
209
+ plinko: "0x74a73daff11c11ed05299c93ed770c62ec4dc6756fa99e271e251c2399f49fef",
210
+ pvpCoinflip: "0x29162faf01a8135630e0a32bbe4ce47f69607b24dbb1edea3800861f91d0030a",
211
+ range: "0xd19e32b0f2a5e541fbd345b4602f8a93a2eee25c16029595b6fef0b1e0461a54",
212
+ wheel: "0x6791eac73fe7bf463b7f3b1ea391df265fbc1b96201270664a5a11e2441e9955"
213
+ };
214
+ var MAINNET_COIN_TYPES = {
215
+ sui: "0x2::sui::SUI",
216
+ usdc: "0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC"
217
+ };
218
+ var MAINNET_PRICE_INFO_OBJECT_IDS = {
219
+ sui: "0x801dbc2f0053d34734814b2d6df491ce7807a725fe9a01ad74a07e9c51396c37",
220
+ usdc: "0x5dec622733a204ca27f5a90d8c2fad453cc6665186fd5dff13a83d0b6c9027ab"
221
+ };
222
+
223
+ // src/configs/package.testnet.ts
224
+ var TESTNET_PACKAGE_IDS = {
225
+ sweetHouse: "0xb7f64e5a273aba1ede00caa0a6f8027cc7490c279d17eab12e7100ed20660603",
226
+ core: "0xf391858d2a08473e8d4defcc8df89976bd7b123d3865c6b9341b237f7853dbbc",
10
227
  coinflip: "0xb35c5f286c443752afc8ccb40125a578a4f32df35617170ccfa17fe180ab80ea",
11
228
  limbo: "0x96c7841b9b32c59a219760fd656f1c3aceb53cc74a68ec9844a3a696374309f4",
12
229
  plinko: "0xd3dd2200883af10811724f0bed97591ad155a02efd6332d471ff8b346030dfb7",
13
- pvp_coinflip: "0xb43cf6583c0c15315c7e66f173af4be79ac40c38aad1fd92ec08638ab2026202",
230
+ pvpCoinflip: "0xb43cf6583c0c15315c7e66f173af4be79ac40c38aad1fd92ec08638ab2026202",
14
231
  range: "0x096a4cf18b3661e76b2c62b90785418345d52f45b272448794f123a4cb6b6416",
15
232
  wheel: "0x0997852ded7e13301c42317004bc49704a893aa82997c5706cebee59053a31b7"
16
233
  };
234
+ var TESTNET_COIN_TYPES = {
235
+ sui: "0x47c67b9594069c32caa7a6e875ddf31d7fa52602dd22ccb9ebd8d3482aed76dc::test_sui::TEST_SUI",
236
+ usdc: "0x47c67b9594069c32caa7a6e875ddf31d7fa52602dd22ccb9ebd8d3482aed76dc::test_usdc::TEST_USDC"
237
+ };
238
+ var TESTNET_PRICE_INFO_OBJECT_IDS = {
239
+ sui: "0x1ebb295c789cc42b3b2a1606482cd1c7124076a0f5676718501fda8c7fd075a0",
240
+ usdc: "0x9c4dd4008297ffa5e480684b8100ec21cc934405ed9a25d4e4d7b6259aad9c81"
241
+ };
17
242
 
18
- // src/configs/usdc-coin-type.ts
19
- var DEFAULT_USDC_COIN_TYPE = "0xdba34672e30cb065b1f93e3a0e89fd79d1f22e12e55e88edbbcbac48609f4af0::usdc::USDC";
20
- var DEFAULT_USDC_FLOWX_COIN_TYPE = "0xbde4ba4c7f1193c4f1f5b9e8a9c1cdec42c6f3f3a73cf40e1f4cb12cc7e6a4c0::usdc::USDC";
243
+ // src/configs/package.ts
244
+ var PACKAGE_IDS = {
245
+ mainnet: { ...MAINNET_PACKAGE_IDS },
246
+ testnet: { ...TESTNET_PACKAGE_IDS }
247
+ };
248
+ var COIN_TYPES = {
249
+ mainnet: { ...MAINNET_COIN_TYPES },
250
+ testnet: { ...TESTNET_COIN_TYPES }
251
+ };
252
+ var PRICE_INFO_OBJECT_IDS = {
253
+ mainnet: { ...MAINNET_PRICE_INFO_OBJECT_IDS },
254
+ testnet: { ...TESTNET_PRICE_INFO_OBJECT_IDS }
255
+ };
21
256
 
22
- // src/utils/config.ts
23
- var trim = (value) => value?.trim() ?? "";
24
- function resolveSuigarConfig(options) {
25
- const suiCoinType = normalizeStructTag(
26
- options.coinTypes?.sui ?? SUI_TYPE_ARG
27
- );
28
- const usdcCoinType = normalizeStructTag(
29
- options.coinTypes?.usdc ?? DEFAULT_USDC_COIN_TYPE
30
- );
31
- const usdcFlowxCoinType = normalizeStructTag(
32
- options.coinTypes?.usdcFlowx ?? DEFAULT_USDC_FLOWX_COIN_TYPE
33
- );
34
- const explicitPriceInfoObjectIds = Object.fromEntries(
35
- Object.entries(options.pyth?.priceInfoObjectIds ?? {}).map(
36
- ([coinType, objectId]) => [normalizeStructTag(coinType), objectId]
37
- )
38
- );
257
+ // src/configs/registry.mainnet.ts
258
+ var PVP_COINFLIP_REGISTRY_ID = "0x3d73568546c539c1da3eb2b8fe917faef3c0acdbec78a67fe6d52800a0729349";
259
+
260
+ // src/configs/registry.testnet.ts
261
+ var PVP_COINFLIP_REGISTRY_ID2 = "0x99f20d8e4be012ea14a681144ae72ac349d0a1a1585205880183eb167f075bad";
262
+
263
+ // src/configs/registry.ts
264
+ var REGISTRY_IDS = {
265
+ mainnet: {
266
+ pvpCoinflip: PVP_COINFLIP_REGISTRY_ID
267
+ },
268
+ testnet: {
269
+ pvpCoinflip: PVP_COINFLIP_REGISTRY_ID2
270
+ }
271
+ };
272
+
273
+ // src/helpers/config.ts
274
+ var DEFAULT_CACHE_TTL_MS = 30 * 60 * 1e3;
275
+ function resolveSuigarConfig(network) {
276
+ const packageIds = PACKAGE_IDS[network];
277
+ const registryIds = REGISTRY_IDS[network];
278
+ const coinTypes = COIN_TYPES[network];
279
+ const priceInfoObjectIds = PRICE_INFO_OBJECT_IDS[network];
39
280
  return {
40
- sweetHousePackageId: trim(options.sweetHousePackageId) || trim(DEFAULT_SWEETHOUSE_PACKAGE_ID),
281
+ packageIds: { ...packageIds },
282
+ registryIds: { ...registryIds },
41
283
  coinTypes: {
42
- sui: suiCoinType,
43
- usdc: usdcCoinType,
44
- usdcFlowx: usdcFlowxCoinType
45
- },
46
- gamesPackageId: {
47
- coinflip: trim(options.gamesPackageId?.coinflip) || DEFAULT_GAMES_PACKAGE_ID.coinflip,
48
- limbo: trim(options.gamesPackageId?.limbo) || DEFAULT_GAMES_PACKAGE_ID.limbo,
49
- plinko: trim(options.gamesPackageId?.plinko) || DEFAULT_GAMES_PACKAGE_ID.plinko,
50
- "pvp-coinflip": trim(options.gamesPackageId?.["pvp-coinflip"]) || DEFAULT_GAMES_PACKAGE_ID.pvp_coinflip,
51
- range: trim(options.gamesPackageId?.range) || DEFAULT_GAMES_PACKAGE_ID.range,
52
- wheel: trim(options.gamesPackageId?.wheel) || DEFAULT_GAMES_PACKAGE_ID.wheel
284
+ sui: normalizeStructTag(coinTypes.sui),
285
+ usdc: normalizeStructTag(coinTypes.usdc)
53
286
  },
54
- pyth: {
55
- packageId: trim(options.pyth?.packageId) || void 0,
56
- suiPriceInfoObjectId: trim(options.pyth?.suiPriceInfoObjectId),
57
- usdcPriceInfoObjectId: trim(options.pyth?.usdcPriceInfoObjectId),
58
- priceInfoObjectIds: explicitPriceInfoObjectIds
287
+ priceInfoObjectIds: {
288
+ sui: priceInfoObjectIds.sui,
289
+ usdc: priceInfoObjectIds.usdc
59
290
  }
60
291
  };
61
292
  }
62
- function resolvePythPriceInfoObjectId(config, coinType) {
63
- const normalizedCoinType = normalizeStructTag(coinType);
64
- const explicitObjectId = config.pyth.priceInfoObjectIds[normalizedCoinType];
65
- if (explicitObjectId) {
66
- return explicitObjectId;
293
+ function assertConfiguredBetGame(config, game) {
294
+ if (!resolveGamePackageId(config, game)) {
295
+ throw new Error(`Missing required config for ${game}: packageIds.${game}`);
67
296
  }
68
- if (normalizedCoinType === config.coinTypes.sui && config.pyth.suiPriceInfoObjectId) {
69
- return config.pyth.suiPriceInfoObjectId;
297
+ }
298
+ function resolveGamePackageId(config, game) {
299
+ switch (game) {
300
+ case "coinflip":
301
+ return config.packageIds.coinflip;
302
+ case "limbo":
303
+ return config.packageIds.limbo;
304
+ case "plinko":
305
+ return config.packageIds.plinko;
306
+ case "pvp-coinflip":
307
+ return config.packageIds.pvpCoinflip;
308
+ case "range":
309
+ return config.packageIds.range;
310
+ case "wheel":
311
+ return config.packageIds.wheel;
70
312
  }
71
- if ((normalizedCoinType === config.coinTypes.usdc || normalizedCoinType === config.coinTypes.usdcFlowx) && config.pyth.usdcPriceInfoObjectId) {
72
- return config.pyth.usdcPriceInfoObjectId;
313
+ }
314
+ function resolvePriceInfoObjectId(config, coinType) {
315
+ const normalizedCoinType = normalizeStructTag(coinType);
316
+ const supportedCoin = resolveSupportedCoin(config, normalizedCoinType);
317
+ const objectId = config.priceInfoObjectIds[supportedCoin];
318
+ if (!objectId) {
319
+ throw new Error(
320
+ `Missing price info object configuration for coin type ${coinType}`
321
+ );
73
322
  }
74
- throw new Error(
75
- `Missing Pyth price object configuration for coin type ${coinType}`
76
- );
323
+ return objectId;
77
324
  }
78
- function assertConfiguredBetGame(config, game) {
79
- if (!config.gamesPackageId[game]) {
325
+ function resolveSupportedCoin(config, coinType) {
326
+ const [supportedCoin] = Object.entries(config.coinTypes).find(([_, value]) => value === coinType) ?? [];
327
+ if (!supportedCoin) {
80
328
  throw new Error(
81
- `Missing required config for ${game}: gamesPackageId.${game}`
329
+ `Unsupported coin type ${coinType}. Supported coin types: ${Object.values(
330
+ config.coinTypes
331
+ ).join(", ")}`
82
332
  );
83
333
  }
334
+ return supportedCoin;
335
+ }
336
+ function replaceStructTagAddress(structName, address) {
337
+ return normalizeStructTag({
338
+ ...parseStructTag(structName),
339
+ address
340
+ });
84
341
  }
85
- var ADDRESS_METADATA_KEYS = /* @__PURE__ */ new Set(["referrer", "partner"]);
342
+ function resolveGameSettingsKeyType(structName, packageId) {
343
+ return replaceStructTagAddress(structName, packageId);
344
+ }
345
+ function resolveCoinTypeNameForTypeNameKey(structName) {
346
+ const { address } = parseStructTag(structName);
347
+ return replaceStructTagAddress(
348
+ structName,
349
+ normalizeSuiAddress(address).replace(/^0x/, "")
350
+ );
351
+ }
352
+ var PARTNER_METADATA_KEY = "partner";
353
+ var RESERVED_METADATA_KEYS = /* @__PURE__ */ new Set([PARTNER_METADATA_KEY, "referrer"]);
86
354
  var textEncoder = new TextEncoder();
87
- var parseHexAddress = (value) => {
88
- const trimmed = value.trim();
89
- if (!trimmed) return null;
355
+ function encodeString(value) {
90
356
  try {
91
- const normalized = normalizeSuiAddress(trimmed).slice(2);
92
- const bytes = new Uint8Array(normalized.length / 2);
93
- for (let index = 0; index < normalized.length; index += 2) {
94
- bytes[index / 2] = Number.parseInt(
95
- normalized.slice(index, index + 2),
96
- 16
97
- );
98
- }
99
- return bytes;
357
+ return fromHex(value);
100
358
  } catch {
101
- return null;
359
+ return textEncoder.encode(value);
102
360
  }
103
- };
104
- function encodeBetMetadata(metadata) {
105
- const keys = [];
106
- const values = [];
107
- for (const [key, value] of Object.entries(metadata ?? {})) {
108
- if (value === void 0 || value === null) {
109
- continue;
110
- }
111
- let encodedValue;
112
- if (value instanceof Uint8Array) {
113
- encodedValue = Array.from(value);
114
- } else if (Array.isArray(value)) {
115
- encodedValue = value;
116
- } else if (typeof value === "string" && ADDRESS_METADATA_KEYS.has(key)) {
117
- encodedValue = Array.from(
118
- parseHexAddress(value) ?? textEncoder.encode(value)
119
- );
120
- } else {
121
- encodedValue = Array.from(textEncoder.encode(String(value)));
122
- }
123
- keys.push(key);
124
- values.push(encodedValue);
125
- }
126
- return { keys, values };
127
361
  }
128
-
129
- // src/utils/shared.ts
130
- var DEFAULT_GAS_BUDGET_MIST = 5e7;
131
- var RANGE_FIXED_POINT_SCALE = 1e6;
132
- var LIMBO_MULTIPLIER_SCALE = 100;
133
- function toBigIntAmount(value, fieldName) {
134
- if (typeof value === "bigint") {
135
- if (value < 0n) {
136
- throw new Error(`${fieldName} must be non-negative`);
137
- }
138
- return value;
362
+ function encodeMetadataValue(value) {
363
+ if (value instanceof Uint8Array) {
364
+ return Array.from(value);
139
365
  }
140
- if (!Number.isFinite(value) || value < 0) {
141
- throw new Error(`${fieldName} must be a finite non-negative number`);
142
- }
143
- return BigInt(Math.trunc(value));
144
- }
145
- function toU8Number(value, fieldName) {
146
- if (!Number.isInteger(value) || value < 0 || value > 255) {
147
- throw new Error(`${fieldName} must be an integer between 0 and 255`);
148
- }
149
- return value;
150
- }
151
- var MOVE_STDLIB_ADDRESS = normalizeSuiAddress("0x1");
152
- var SUI_FRAMEWORK_ADDRESS = normalizeSuiAddress("0x2");
153
- function getPureBcsSchema(typeTag) {
154
- const parsedTag = typeof typeTag === "string" ? TypeTagSerializer.parseFromStr(typeTag) : typeTag;
155
- if ("u8" in parsedTag) {
156
- return bcs.U8;
157
- } else if ("u16" in parsedTag) {
158
- return bcs.U16;
159
- } else if ("u32" in parsedTag) {
160
- return bcs.U32;
161
- } else if ("u64" in parsedTag) {
162
- return bcs.U64;
163
- } else if ("u128" in parsedTag) {
164
- return bcs.U128;
165
- } else if ("u256" in parsedTag) {
166
- return bcs.U256;
167
- } else if ("address" in parsedTag) {
168
- return bcs.Address;
169
- } else if ("bool" in parsedTag) {
170
- return bcs.Bool;
171
- } else if ("vector" in parsedTag) {
172
- const type = getPureBcsSchema(parsedTag.vector);
173
- return type ? bcs.vector(type) : null;
174
- } else if ("struct" in parsedTag) {
175
- const structTag = parsedTag.struct;
176
- const pkg = normalizeSuiAddress(structTag.address);
177
- if (pkg === MOVE_STDLIB_ADDRESS) {
178
- if ((structTag.module === "ascii" || structTag.module === "string") && structTag.name === "String") {
179
- return bcs.String;
180
- }
181
- if (structTag.module === "option" && structTag.name === "Option") {
182
- const type = getPureBcsSchema(structTag.typeParams[0]);
183
- return type ? bcs.option(type) : null;
184
- }
185
- }
186
- if (pkg === SUI_FRAMEWORK_ADDRESS && structTag.module === "object" && (structTag.name === "ID" || structTag.name === "UID")) {
187
- return bcs.Address;
188
- }
366
+ if (Array.isArray(value)) {
367
+ return value;
189
368
  }
190
- return null;
369
+ return Array.from(encodeString(String(value)));
191
370
  }
192
- function normalizeMoveArguments(args, argTypes, parameterNames) {
193
- Array.isArray(args) ? args.length : Object.keys(args).length;
194
- const normalizedArgs = [];
195
- let index = 0;
196
- for (const [i, argType] of argTypes.entries()) {
197
- if (argType === "0x2::clock::Clock") {
198
- normalizedArgs.push((tx) => tx.object.clock());
199
- continue;
200
- }
201
- if (argType === "0x2::random::Random") {
202
- normalizedArgs.push((tx) => tx.object.random());
203
- continue;
204
- }
205
- if (argType === "0x2::deny_list::DenyList") {
206
- normalizedArgs.push((tx) => tx.object.denyList());
207
- continue;
208
- }
209
- if (argType === "0x3::sui_system::SuiSystemState") {
210
- normalizedArgs.push((tx) => tx.object.system());
211
- continue;
212
- }
213
- let arg;
214
- if (Array.isArray(args)) {
215
- if (index >= args.length) {
216
- throw new Error(
217
- `Invalid number of arguments, expected at least ${index + 1}, got ${args.length}`
218
- );
219
- }
220
- arg = args[index];
221
- } else {
222
- {
223
- throw new Error(`Expected arguments to be passed as an array`);
224
- }
225
- }
226
- index += 1;
227
- if (typeof arg === "function" || isArgument(arg)) {
228
- normalizedArgs.push(arg);
229
- continue;
230
- }
231
- const type = argTypes[i];
232
- const bcsType = type === null ? null : getPureBcsSchema(type);
233
- if (bcsType) {
234
- const bytes = bcsType.serialize(arg);
235
- normalizedArgs.push((tx) => tx.pure(bytes));
371
+ function encodeBetMetadata(metadata, partner) {
372
+ const keys = [];
373
+ const values = [];
374
+ for (const [key, value] of Object.entries(metadata ?? {})) {
375
+ if (RESERVED_METADATA_KEYS.has(key)) {
376
+ console.warn(
377
+ `Metadata key "${key}" is reserved and will be ignored when parsing metadata.`
378
+ );
236
379
  continue;
237
380
  }
238
- if (typeof arg === "string") {
239
- normalizedArgs.push((tx) => tx.object(arg));
381
+ if (value == null) {
240
382
  continue;
241
383
  }
242
- throw new Error(`Invalid argument ${stringify(arg)} for type ${type}`);
243
- }
244
- return normalizedArgs;
245
- }
246
- var MoveStruct = class extends BcsStruct {
247
- async get({
248
- objectId,
249
- ...options
250
- }) {
251
- const [res] = await this.getMany({
252
- ...options,
253
- objectIds: [objectId]
254
- });
255
- return res;
384
+ keys.push(key);
385
+ values.push(encodeMetadataValue(value));
256
386
  }
257
- async getMany({
258
- client,
259
- ...options
260
- }) {
261
- const response = await client.core.getObjects({
262
- ...options,
263
- include: {
264
- ...options.include,
265
- content: true
266
- }
267
- });
268
- return response.objects.map((obj) => {
269
- if (obj instanceof Error) {
270
- throw obj;
271
- }
272
- return {
273
- ...obj,
274
- json: this.parse(obj.content)
275
- };
276
- });
387
+ if (partner?.trim()) {
388
+ keys.unshift(PARTNER_METADATA_KEY);
389
+ values.unshift(encodeMetadataValue(partner));
277
390
  }
278
- };
279
- function stringify(val) {
280
- if (typeof val === "object") {
281
- return JSON.stringify(val, (val2) => val2);
391
+ return {
392
+ keys,
393
+ values
394
+ };
395
+ }
396
+ var $moduleName8 = "0xb35c5f286c443752afc8ccb40125a578a4f32df35617170ccfa17fe180ab80ea::coinflip";
397
+ var CoinFlipSettingsKey = new MoveStruct({
398
+ name: `${$moduleName8}::CoinFlipSettingsKey`,
399
+ fields: {
400
+ dummy_field: bcs.bool()
282
401
  }
283
- if (typeof val === "bigint") {
284
- return val.toString();
402
+ });
403
+ var Parameters2 = new MoveStruct({
404
+ name: `${$moduleName8}::Parameters<phantom T0>`,
405
+ fields: {
406
+ id: bcs.Address,
407
+ house_edge: bcs.u64(),
408
+ min_stake: bcs.u64(),
409
+ max_stake: bcs.u64()
285
410
  }
286
- return val;
287
- }
288
-
289
- // src/contracts/coinflip/coinflip.ts
411
+ });
290
412
  function play(options) {
291
413
  const packageAddress = options.package ?? "0xb35c5f286c443752afc8ccb40125a578a4f32df35617170ccfa17fe180ab80ea";
292
414
  const argumentsTypes = [
@@ -309,39 +431,46 @@ function play(options) {
309
431
  typeArguments: options.typeArguments
310
432
  });
311
433
  }
434
+
435
+ // src/types/network.type.ts
436
+ var SUPPORTED_SUI_NETWORKS = [
437
+ "mainnet",
438
+ "testnet"
439
+ ];
440
+
441
+ // src/transactions/shared.ts
312
442
  function createBaseGameTransaction({
313
443
  config,
314
444
  game,
315
- owner,
316
- sender,
445
+ playerAddress,
317
446
  gasBudget
318
447
  }) {
319
448
  assertConfiguredBetGame(config, game);
320
449
  const tx = new Transaction();
321
- tx.setSenderIfNotSet(normalizeSuiAddress(sender ?? owner));
450
+ tx.setSenderIfNotSet(normalizeSuiAddress(playerAddress));
322
451
  tx.setGasBudgetIfNotSet(gasBudget ?? DEFAULT_GAS_BUDGET_MIST);
323
452
  return tx;
324
453
  }
325
454
  function buildSharedStandardGameBetCall({
326
455
  config,
327
- owner,
328
- sender,
456
+ playerAddress,
329
457
  coinType,
330
458
  stake,
331
459
  cashStake,
332
460
  betCount,
333
461
  metadata,
462
+ partner,
334
463
  allowGasCoinShortcut = true,
335
464
  buildRewardCoin
336
465
  }) {
337
466
  return (tx) => {
338
- const normalizedOwner = normalizeSuiAddress(sender ?? owner);
467
+ const normalizedPlayerAddress = normalizeSuiAddress(playerAddress);
339
468
  const normalizedCoinType = normalizeStructTag(coinType);
340
- const resolvedStake = toBigIntAmount(stake, "stake");
341
- const resolvedCashStake = toBigIntAmount(cashStake ?? stake, "cashStake");
342
- const resolvedBetCount = toBigIntAmount(betCount ?? 1, "betCount");
343
- const encodedMetadata = encodeBetMetadata(metadata);
344
- const pythPriceInfoObjectId = resolvePythPriceInfoObjectId(
469
+ const resolvedStake = toBigInt(stake);
470
+ const resolvedCashStake = toBigInt(cashStake ?? stake);
471
+ const resolvedBetCount = toBigInt(betCount ?? 1);
472
+ const encodedMetadata = encodeBetMetadata(metadata, partner);
473
+ const priceInfoObjectId = resolvePriceInfoObjectId(
345
474
  config,
346
475
  normalizedCoinType
347
476
  );
@@ -353,16 +482,16 @@ function buildSharedStandardGameBetCall({
353
482
  const rewardCoin = buildRewardCoin({
354
483
  tx,
355
484
  config,
356
- owner: normalizedOwner,
485
+ playerAddress: normalizedPlayerAddress,
357
486
  coinType: normalizedCoinType,
358
487
  stake: resolvedStake,
359
488
  cashStake: resolvedCashStake,
360
489
  betCount: resolvedBetCount,
361
490
  metadata: encodedMetadata,
362
- pythPriceInfoObjectId,
491
+ priceInfoObjectId,
363
492
  betCoin
364
493
  });
365
- tx.transferObjects([rewardCoin], tx.pure.address(normalizedOwner));
494
+ tx.transferObjects([rewardCoin], tx.pure.address(normalizedPlayerAddress));
366
495
  return rewardCoin;
367
496
  };
368
497
  }
@@ -384,26 +513,65 @@ function buildCoinflipTransaction(options) {
384
513
  stake,
385
514
  betCount,
386
515
  metadata,
387
- pythPriceInfoObjectId,
516
+ priceInfoObjectId,
388
517
  betCoin
389
518
  }) => play({
390
- package: config.gamesPackageId.coinflip,
519
+ package: config.packageIds.coinflip,
391
520
  typeArguments: [coinType],
392
521
  arguments: [
393
- config.sweetHousePackageId,
522
+ config.packageIds.sweetHouse,
394
523
  stake,
395
524
  betCoin,
396
525
  betCount,
397
526
  options.side === "tails",
398
527
  metadata.keys,
399
528
  metadata.values,
400
- pythPriceInfoObjectId
529
+ priceInfoObjectId
401
530
  ]
402
531
  })(tx)
403
532
  });
404
533
  }
534
+ var $moduleName9 = "0xf391858d2a08473e8d4defcc8df89976bd7b123d3865c6b9341b237f7853dbbc::i64";
535
+ var I64 = new MoveStruct({
536
+ name: `${$moduleName9}::I64`,
537
+ fields: {
538
+ bits: bcs.u64()
539
+ }
540
+ });
541
+
542
+ // src/contracts/limbo/deps/0xf391858d2a08473e8d4defcc8df89976bd7b123d3865c6b9341b237f7853dbbc/float.ts
543
+ var $moduleName10 = "0xf391858d2a08473e8d4defcc8df89976bd7b123d3865c6b9341b237f7853dbbc::float";
544
+ var Float2 = new MoveStruct({
545
+ name: `${$moduleName10}::Float`,
546
+ fields: {
547
+ is_negative: bcs.bool(),
548
+ exp: I64,
549
+ mant: bcs.u64()
550
+ }
551
+ });
405
552
 
406
553
  // src/contracts/limbo/limbo.ts
554
+ var $moduleName11 = "0x96c7841b9b32c59a219760fd656f1c3aceb53cc74a68ec9844a3a696374309f4::limbo";
555
+ var LimboSettingsKey = new MoveStruct({
556
+ name: `${$moduleName11}::LimboSettingsKey`,
557
+ fields: {
558
+ dummy_field: bcs.bool()
559
+ }
560
+ });
561
+ var Parameters3 = new MoveStruct({
562
+ name: `${$moduleName11}::Parameters<phantom T0>`,
563
+ fields: {
564
+ id: bcs.Address,
565
+ min_stake: bcs.u64(),
566
+ max_stake: bcs.u64(),
567
+ max_payout: bcs.u64(),
568
+ min_target_multiplier: Float2,
569
+ max_target_multiplier: Float2,
570
+ max_number_of_games: bcs.u64(),
571
+ min_rtp: Float2,
572
+ max_rtp: Float2
573
+ }
574
+ });
407
575
  function play2(options) {
408
576
  const packageAddress = options.package ?? "0x96c7841b9b32c59a219760fd656f1c3aceb53cc74a68ec9844a3a696374309f4";
409
577
  const argumentsTypes = [
@@ -430,7 +598,7 @@ function play2(options) {
430
598
 
431
599
  // src/transactions/limbo.ts
432
600
  function buildLimboTransaction(options) {
433
- const scale = options.scale ?? LIMBO_MULTIPLIER_SCALE;
601
+ const scale = options.scale ?? DEFAULT_LIMBO_MULTIPLIER_SCALE;
434
602
  const numerator = Math.round(options.targetMultiplier * scale);
435
603
  return buildSharedStandardGameBetTransaction({
436
604
  ...options,
@@ -442,13 +610,13 @@ function buildLimboTransaction(options) {
442
610
  stake,
443
611
  betCount,
444
612
  metadata,
445
- pythPriceInfoObjectId,
613
+ priceInfoObjectId,
446
614
  betCoin
447
615
  }) => play2({
448
- package: config.gamesPackageId.limbo,
616
+ package: config.packageIds.limbo,
449
617
  typeArguments: [coinType],
450
618
  arguments: [
451
- config.sweetHousePackageId,
619
+ config.packageIds.sweetHouse,
452
620
  stake,
453
621
  betCoin,
454
622
  betCount,
@@ -456,13 +624,76 @@ function buildLimboTransaction(options) {
456
624
  BigInt(scale),
457
625
  metadata.keys,
458
626
  metadata.values,
459
- pythPriceInfoObjectId
627
+ priceInfoObjectId
460
628
  ]
461
629
  })(tx)
462
630
  });
463
631
  }
632
+ var $moduleName12 = "0x2::vec_map";
633
+ function Entry3(...typeParameters) {
634
+ return new MoveStruct({
635
+ name: `${$moduleName12}::Entry<${typeParameters[0].name}, ${typeParameters[1].name}>`,
636
+ fields: {
637
+ key: typeParameters[0],
638
+ value: typeParameters[1]
639
+ }
640
+ });
641
+ }
642
+ function VecMap3(...typeParameters) {
643
+ return new MoveStruct({
644
+ name: `${$moduleName12}::VecMap<${typeParameters[0].name}, ${typeParameters[1].name}>`,
645
+ fields: {
646
+ contents: bcs.vector(Entry3(typeParameters[0], typeParameters[1]))
647
+ }
648
+ });
649
+ }
650
+ var $moduleName13 = "0xf391858d2a08473e8d4defcc8df89976bd7b123d3865c6b9341b237f7853dbbc::i64";
651
+ var I642 = new MoveStruct({
652
+ name: `${$moduleName13}::I64`,
653
+ fields: {
654
+ bits: bcs.u64()
655
+ }
656
+ });
657
+
658
+ // src/contracts/plinko/deps/0xf391858d2a08473e8d4defcc8df89976bd7b123d3865c6b9341b237f7853dbbc/float.ts
659
+ var $moduleName14 = "0xf391858d2a08473e8d4defcc8df89976bd7b123d3865c6b9341b237f7853dbbc::float";
660
+ var Float3 = new MoveStruct({
661
+ name: `${$moduleName14}::Float`,
662
+ fields: {
663
+ is_negative: bcs.bool(),
664
+ exp: I642,
665
+ mant: bcs.u64()
666
+ }
667
+ });
464
668
 
465
669
  // src/contracts/plinko/plinko.ts
670
+ var $moduleName15 = "0xd3dd2200883af10811724f0bed97591ad155a02efd6332d471ff8b346030dfb7::plinko";
671
+ var PlinkoSettingsKey = new MoveStruct({
672
+ name: `${$moduleName15}::PlinkoSettingsKey`,
673
+ fields: {
674
+ dummy_field: bcs.bool()
675
+ }
676
+ });
677
+ var PlinkoConfig = new MoveStruct({
678
+ name: `${$moduleName15}::PlinkoConfig`,
679
+ fields: {
680
+ num_rows: bcs.u8(),
681
+ multipliers: bcs.vector(Float3),
682
+ min_stake: bcs.u64(),
683
+ max_stake: bcs.u64(),
684
+ is_playable: bcs.bool()
685
+ }
686
+ });
687
+ var Parameters4 = new MoveStruct({
688
+ name: `${$moduleName15}::Parameters<phantom T0>`,
689
+ fields: {
690
+ id: bcs.Address,
691
+ min_stake: bcs.u64(),
692
+ max_stake: bcs.u64(),
693
+ max_number_of_balls: bcs.u64(),
694
+ configs: VecMap3(bcs.u8(), PlinkoConfig)
695
+ }
696
+ });
466
697
  function play3(options) {
467
698
  const packageAddress = options.package ?? "0xd3dd2200883af10811724f0bed97591ad155a02efd6332d471ff8b346030dfb7";
468
699
  const argumentsTypes = [
@@ -488,7 +719,7 @@ function play3(options) {
488
719
 
489
720
  // src/transactions/plinko.ts
490
721
  function buildPlinkoTransaction(options) {
491
- const configId = toU8Number(options.configId, "configId");
722
+ const configId = toU8(options.configId);
492
723
  return buildSharedStandardGameBetTransaction({
493
724
  ...options,
494
725
  game: "plinko",
@@ -499,134 +730,35 @@ function buildPlinkoTransaction(options) {
499
730
  stake,
500
731
  betCount,
501
732
  metadata,
502
- pythPriceInfoObjectId,
733
+ priceInfoObjectId,
503
734
  betCoin
504
735
  }) => play3({
505
- package: config.gamesPackageId.plinko,
736
+ package: config.packageIds.plinko,
506
737
  typeArguments: [coinType],
507
738
  arguments: [
508
- config.sweetHousePackageId,
739
+ config.packageIds.sweetHouse,
509
740
  stake,
510
741
  betCoin,
511
742
  betCount,
512
743
  configId,
513
744
  metadata.keys,
514
745
  metadata.values,
515
- pythPriceInfoObjectId
746
+ priceInfoObjectId
516
747
  ]
517
748
  })(tx)
518
749
  });
519
750
  }
520
- var $moduleName = "0x0000000000000000000000000000000000000000000000000000000000000001::type_name";
521
- var TypeName = new MoveStruct({ name: `${$moduleName}::TypeName`, fields: {
522
- name: bcs.string()
523
- } });
524
-
525
- // src/contracts/pvp-coinflip/pvp_coinflip.ts
526
- var $moduleName2 = "0xb43cf6583c0c15315c7e66f173af4be79ac40c38aad1fd92ec08638ab2026202::pvp_coinflip";
527
- function GameCreatedEvent(...typeParameters) {
528
- return new MoveStruct({ name: `${$moduleName2}::GameCreatedEvent<${typeParameters[0].name}>`, fields: {
529
- game_id: bcs.Address,
530
- creator: bcs.Address,
531
- creator_is_tails: bcs.bool(),
532
- is_private: bcs.bool(),
533
- joiner_is_tails: bcs.bool(),
534
- stake_per_player: bcs.u64(),
535
- house_edge_bps: bcs.u64(),
536
- coin_type: TypeName
537
- } });
538
- }
539
- function GameResolvedEvent(...typeParameters) {
540
- return new MoveStruct({ name: `${$moduleName2}::GameResolvedEvent<${typeParameters[0].name}>`, fields: {
541
- game_id: bcs.Address,
542
- creator: bcs.Address,
543
- joiner: bcs.Address,
544
- winner: bcs.Address,
545
- creator_is_tails: bcs.bool(),
546
- is_private: bcs.bool(),
547
- joiner_is_tails: bcs.bool(),
548
- stake_per_player: bcs.u64(),
549
- total_pot: bcs.u64(),
550
- house_edge_amount: bcs.u64(),
551
- payout_amount: bcs.u64(),
552
- coin_type: TypeName
553
- } });
554
- }
555
- function GameCancelledEvent(...typeParameters) {
556
- return new MoveStruct({ name: `${$moduleName2}::GameCancelledEvent<${typeParameters[0].name}>`, fields: {
557
- game_id: bcs.Address,
558
- creator: bcs.Address,
559
- creator_is_tails: bcs.bool(),
560
- is_private: bcs.bool(),
561
- stake_per_player: bcs.u64(),
562
- coin_type: TypeName
563
- } });
564
- }
565
- function createGame(options) {
566
- const packageAddress = options.package ?? "0xb43cf6583c0c15315c7e66f173af4be79ac40c38aad1fd92ec08638ab2026202";
567
- const argumentsTypes = [
568
- null,
569
- null,
570
- "bool",
571
- "bool",
572
- "vector<0x1::string::String>",
573
- "vector<vector<u8>>"
574
- ];
575
- return (tx) => tx.moveCall({
576
- package: packageAddress,
577
- module: "pvp_coinflip",
578
- function: "create_game",
579
- arguments: normalizeMoveArguments(options.arguments, argumentsTypes),
580
- typeArguments: options.typeArguments
581
- });
582
- }
583
- function joinGame(options) {
584
- const packageAddress = options.package ?? "0xb43cf6583c0c15315c7e66f173af4be79ac40c38aad1fd92ec08638ab2026202";
585
- const argumentsTypes = [
586
- "0x2::object::ID",
587
- null,
588
- null,
589
- "vector<0x1::string::String>",
590
- "vector<vector<u8>>",
591
- null,
592
- "0x2::clock::Clock",
593
- "0x2::random::Random"
594
- ];
595
- return (tx) => tx.moveCall({
596
- package: packageAddress,
597
- module: "pvp_coinflip",
598
- function: "join_game",
599
- arguments: normalizeMoveArguments(options.arguments, argumentsTypes),
600
- typeArguments: options.typeArguments
601
- });
602
- }
603
- function cancelGame(options) {
604
- const packageAddress = options.package ?? "0xb43cf6583c0c15315c7e66f173af4be79ac40c38aad1fd92ec08638ab2026202";
605
- const argumentsTypes = [
606
- "0x2::object::ID",
607
- null
608
- ];
609
- return (tx) => tx.moveCall({
610
- package: packageAddress,
611
- module: "pvp_coinflip",
612
- function: "cancel_game",
613
- arguments: normalizeMoveArguments(options.arguments, argumentsTypes),
614
- typeArguments: options.typeArguments
615
- });
616
- }
617
-
618
- // src/transactions/pvp-coinflip.ts
619
751
  function buildPvPCoinflipTransaction(action, options) {
620
752
  const tx = createBaseGameTransaction({
621
753
  ...options,
622
754
  game: "pvp-coinflip"
623
755
  });
624
756
  const normalizedCoinType = normalizeStructTag(options.coinType);
625
- const encodedMetadata = encodeBetMetadata(options.metadata);
757
+ const encodedMetadata = encodeBetMetadata(options.metadata, options.partner);
626
758
  switch (action) {
627
759
  case "create": {
628
760
  const createOptions = options;
629
- const stake = toBigIntAmount(createOptions.stake, "stake");
761
+ const stake = toBigInt(createOptions.stake);
630
762
  const betCoin = tx.coin({
631
763
  type: normalizedCoinType,
632
764
  balance: stake,
@@ -634,10 +766,10 @@ function buildPvPCoinflipTransaction(action, options) {
634
766
  });
635
767
  tx.add(
636
768
  createGame({
637
- package: createOptions.config.gamesPackageId["pvp-coinflip"],
769
+ package: createOptions.config.packageIds.pvpCoinflip,
638
770
  typeArguments: [normalizedCoinType],
639
771
  arguments: [
640
- createOptions.config.sweetHousePackageId,
772
+ createOptions.config.packageIds.sweetHouse,
641
773
  betCoin,
642
774
  createOptions.side === "tails",
643
775
  Boolean(createOptions.isPrivate),
@@ -650,23 +782,21 @@ function buildPvPCoinflipTransaction(action, options) {
650
782
  }
651
783
  case "join": {
652
784
  const joinOptions = options;
653
- const stake = toBigIntAmount(joinOptions.stake, "stake");
654
- const betCoin = tx.coin({
655
- type: normalizedCoinType,
656
- balance: stake,
657
- useGasCoin: joinOptions.allowGasCoinShortcut
658
- });
785
+ const priceInfoObjectId = resolvePriceInfoObjectId(
786
+ joinOptions.config,
787
+ normalizedCoinType
788
+ );
659
789
  tx.add(
660
790
  joinGame({
661
- package: joinOptions.config.gamesPackageId["pvp-coinflip"],
791
+ package: joinOptions.config.packageIds.pvpCoinflip,
662
792
  typeArguments: [normalizedCoinType],
663
793
  arguments: [
664
794
  joinOptions.gameId,
665
- joinOptions.config.sweetHousePackageId,
666
- betCoin,
795
+ joinOptions.config.packageIds.sweetHouse,
796
+ tx.add(joinOptions.betCoin),
667
797
  encodedMetadata.keys,
668
798
  encodedMetadata.values,
669
- joinOptions.extraObjectId
799
+ priceInfoObjectId
670
800
  ]
671
801
  })
672
802
  );
@@ -676,11 +806,11 @@ function buildPvPCoinflipTransaction(action, options) {
676
806
  const cancelOptions = options;
677
807
  tx.add(
678
808
  cancelGame({
679
- package: cancelOptions.config.gamesPackageId["pvp-coinflip"],
809
+ package: cancelOptions.config.packageIds.pvpCoinflip,
680
810
  typeArguments: [normalizedCoinType],
681
811
  arguments: [
682
812
  cancelOptions.gameId,
683
- cancelOptions.config.sweetHousePackageId
813
+ cancelOptions.config.packageIds.sweetHouse
684
814
  ]
685
815
  })
686
816
  );
@@ -690,8 +820,46 @@ function buildPvPCoinflipTransaction(action, options) {
690
820
  throw new Error(`Unsupported PvP coinflip action: ${action}`);
691
821
  }
692
822
  }
823
+ var $moduleName16 = "0xf391858d2a08473e8d4defcc8df89976bd7b123d3865c6b9341b237f7853dbbc::i64";
824
+ var I643 = new MoveStruct({
825
+ name: `${$moduleName16}::I64`,
826
+ fields: {
827
+ bits: bcs.u64()
828
+ }
829
+ });
830
+
831
+ // src/contracts/range/deps/0xf391858d2a08473e8d4defcc8df89976bd7b123d3865c6b9341b237f7853dbbc/float.ts
832
+ var $moduleName17 = "0xf391858d2a08473e8d4defcc8df89976bd7b123d3865c6b9341b237f7853dbbc::float";
833
+ var Float4 = new MoveStruct({
834
+ name: `${$moduleName17}::Float`,
835
+ fields: {
836
+ is_negative: bcs.bool(),
837
+ exp: I643,
838
+ mant: bcs.u64()
839
+ }
840
+ });
693
841
 
694
842
  // src/contracts/range/range.ts
843
+ var $moduleName18 = "0x096a4cf18b3661e76b2c62b90785418345d52f45b272448794f123a4cb6b6416::range";
844
+ var RangeSettingsKey = new MoveStruct({
845
+ name: `${$moduleName18}::RangeSettingsKey`,
846
+ fields: {
847
+ dummy_field: bcs.bool()
848
+ }
849
+ });
850
+ var Parameters5 = new MoveStruct({
851
+ name: `${$moduleName18}::Parameters<phantom T0>`,
852
+ fields: {
853
+ id: bcs.Address,
854
+ min_stake: bcs.u64(),
855
+ max_stake: bcs.u64(),
856
+ min_zone_size: bcs.u64(),
857
+ max_zone_size: bcs.u64(),
858
+ max_number_of_games: bcs.u64(),
859
+ min_rtp: Float4,
860
+ max_rtp: Float4
861
+ }
862
+ });
695
863
  function play4(options) {
696
864
  const packageAddress = options.package ?? "0x096a4cf18b3661e76b2c62b90785418345d52f45b272448794f123a4cb6b6416";
697
865
  const argumentsTypes = [
@@ -719,7 +887,7 @@ function play4(options) {
719
887
 
720
888
  // src/transactions/range.ts
721
889
  function buildRangeTransaction(options) {
722
- const scale = options.scale ?? RANGE_FIXED_POINT_SCALE;
890
+ const scale = options.scale ?? DEFAULT_RANGE_SCALE;
723
891
  const leftPoint = Math.round(options.leftPoint * scale);
724
892
  const rightPoint = Math.round(options.rightPoint * scale);
725
893
  return buildSharedStandardGameBetTransaction({
@@ -732,13 +900,13 @@ function buildRangeTransaction(options) {
732
900
  stake,
733
901
  betCount,
734
902
  metadata,
735
- pythPriceInfoObjectId,
903
+ priceInfoObjectId,
736
904
  betCoin
737
905
  }) => play4({
738
- package: config.gamesPackageId.range,
906
+ package: config.packageIds.range,
739
907
  typeArguments: [coinType],
740
908
  arguments: [
741
- config.sweetHousePackageId,
909
+ config.packageIds.sweetHouse,
742
910
  stake,
743
911
  betCoin,
744
912
  betCount,
@@ -747,13 +915,76 @@ function buildRangeTransaction(options) {
747
915
  Boolean(options.outOfRange),
748
916
  metadata.keys,
749
917
  metadata.values,
750
- pythPriceInfoObjectId
918
+ priceInfoObjectId
751
919
  ]
752
920
  })(tx)
753
921
  });
754
922
  }
923
+ var $moduleName19 = "0x2::vec_map";
924
+ function Entry4(...typeParameters) {
925
+ return new MoveStruct({
926
+ name: `${$moduleName19}::Entry<${typeParameters[0].name}, ${typeParameters[1].name}>`,
927
+ fields: {
928
+ key: typeParameters[0],
929
+ value: typeParameters[1]
930
+ }
931
+ });
932
+ }
933
+ function VecMap4(...typeParameters) {
934
+ return new MoveStruct({
935
+ name: `${$moduleName19}::VecMap<${typeParameters[0].name}, ${typeParameters[1].name}>`,
936
+ fields: {
937
+ contents: bcs.vector(Entry4(typeParameters[0], typeParameters[1]))
938
+ }
939
+ });
940
+ }
941
+ var $moduleName20 = "0xf391858d2a08473e8d4defcc8df89976bd7b123d3865c6b9341b237f7853dbbc::i64";
942
+ var I644 = new MoveStruct({
943
+ name: `${$moduleName20}::I64`,
944
+ fields: {
945
+ bits: bcs.u64()
946
+ }
947
+ });
948
+
949
+ // src/contracts/wheel/deps/0xf391858d2a08473e8d4defcc8df89976bd7b123d3865c6b9341b237f7853dbbc/float.ts
950
+ var $moduleName21 = "0xf391858d2a08473e8d4defcc8df89976bd7b123d3865c6b9341b237f7853dbbc::float";
951
+ var Float5 = new MoveStruct({
952
+ name: `${$moduleName21}::Float`,
953
+ fields: {
954
+ is_negative: bcs.bool(),
955
+ exp: I644,
956
+ mant: bcs.u64()
957
+ }
958
+ });
755
959
 
756
960
  // src/contracts/wheel/wheel.ts
961
+ var $moduleName22 = "0x0997852ded7e13301c42317004bc49704a893aa82997c5706cebee59053a31b7::wheel";
962
+ var WheelSettingsKey = new MoveStruct({
963
+ name: `${$moduleName22}::WheelSettingsKey`,
964
+ fields: {
965
+ dummy_field: bcs.bool()
966
+ }
967
+ });
968
+ var WheelConfig = new MoveStruct({
969
+ name: `${$moduleName22}::WheelConfig`,
970
+ fields: {
971
+ num_cases: bcs.u8(),
972
+ multipliers: bcs.vector(Float5),
973
+ min_stake: bcs.u64(),
974
+ max_stake: bcs.u64(),
975
+ is_playable: bcs.bool()
976
+ }
977
+ });
978
+ var Parameters6 = new MoveStruct({
979
+ name: `${$moduleName22}::Parameters<phantom T0>`,
980
+ fields: {
981
+ id: bcs.Address,
982
+ min_stake: bcs.u64(),
983
+ max_stake: bcs.u64(),
984
+ max_number_of_spins: bcs.u64(),
985
+ configs: VecMap4(bcs.u8(), WheelConfig)
986
+ }
987
+ });
757
988
  function play5(options) {
758
989
  const packageAddress = options.package ?? "0x0997852ded7e13301c42317004bc49704a893aa82997c5706cebee59053a31b7";
759
990
  const argumentsTypes = [
@@ -779,7 +1010,7 @@ function play5(options) {
779
1010
 
780
1011
  // src/transactions/wheel.ts
781
1012
  function buildWheelTransaction(options) {
782
- const configId = toU8Number(options.configId, "configId");
1013
+ const configId = toU8(options.configId);
783
1014
  return buildSharedStandardGameBetTransaction({
784
1015
  ...options,
785
1016
  game: "wheel",
@@ -790,87 +1021,183 @@ function buildWheelTransaction(options) {
790
1021
  stake,
791
1022
  betCount,
792
1023
  metadata,
793
- pythPriceInfoObjectId,
1024
+ priceInfoObjectId,
794
1025
  betCoin
795
1026
  }) => play5({
796
- package: config.gamesPackageId.wheel,
1027
+ package: config.packageIds.wheel,
797
1028
  typeArguments: [coinType],
798
1029
  arguments: [
799
- config.sweetHousePackageId,
1030
+ config.packageIds.sweetHouse,
800
1031
  stake,
801
1032
  betCoin,
802
1033
  betCount,
803
1034
  configId,
804
1035
  metadata.keys,
805
1036
  metadata.values,
806
- pythPriceInfoObjectId
1037
+ priceInfoObjectId
807
1038
  ]
808
1039
  })(tx)
809
1040
  });
810
1041
  }
811
- var $moduleName3 = "0x0000000000000000000000000000000000000000000000000000000000000001::type_name";
812
- var TypeName2 = new MoveStruct({ name: `${$moduleName3}::TypeName`, fields: {
813
- name: bcs.string()
814
- } });
815
- var $moduleName4 = "0xf391858d2a08473e8d4defcc8df89976bd7b123d3865c6b9341b237f7853dbbc::i64";
816
- var I64 = new MoveStruct({ name: `${$moduleName4}::I64`, fields: {
817
- bits: bcs.u64()
818
- } });
819
-
820
- // src/contracts/core/float.ts
821
- var $moduleName5 = "0xf391858d2a08473e8d4defcc8df89976bd7b123d3865c6b9341b237f7853dbbc::float";
822
- var Float = new MoveStruct({ name: `${$moduleName5}::Float`, fields: {
823
- is_negative: bcs.bool(),
824
- exp: I64,
825
- mant: bcs.u64()
826
- } });
827
- var $moduleName6 = "0x2::vec_map";
828
- function Entry(...typeParameters) {
829
- return new MoveStruct({ name: `${$moduleName6}::Entry<${typeParameters[0].name}, ${typeParameters[1].name}>`, fields: {
830
- key: typeParameters[0],
831
- value: typeParameters[1]
832
- } });
833
- }
834
- function VecMap(...typeParameters) {
835
- return new MoveStruct({ name: `${$moduleName6}::VecMap<${typeParameters[0].name}, ${typeParameters[1].name}>`, fields: {
836
- contents: bcs.vector(Entry(typeParameters[0], typeParameters[1]))
837
- } });
1042
+ var TtlClientCache = class extends ClientCache {
1043
+ #ttlMs;
1044
+ constructor({ ttlMs, ...options }) {
1045
+ super({
1046
+ ...options,
1047
+ prefix: options.prefix ?? ["ttl"]
1048
+ });
1049
+ this.#ttlMs = ttlMs;
1050
+ }
1051
+ read(key, load, options) {
1052
+ if (options?.ignoreCache) {
1053
+ super.clear(key);
1054
+ }
1055
+ if (this.#ttlMs <= 0) {
1056
+ return load();
1057
+ }
1058
+ const cached = super.read(
1059
+ key,
1060
+ () => this.#loadEntry(key, load)
1061
+ );
1062
+ if (cached && cached.expiresAt > Date.now()) {
1063
+ return cached.value;
1064
+ }
1065
+ super.clear(key);
1066
+ return super.read(
1067
+ key,
1068
+ () => this.#loadEntry(key, load)
1069
+ ).value;
1070
+ }
1071
+ readSync(key, load, options) {
1072
+ if (options?.ignoreCache) {
1073
+ super.clear(key);
1074
+ }
1075
+ if (this.#ttlMs <= 0) {
1076
+ return load();
1077
+ }
1078
+ const cached = super.readSync(
1079
+ key,
1080
+ () => this.#loadSyncEntry(load)
1081
+ );
1082
+ if (cached.expiresAt > Date.now()) {
1083
+ return cached.value;
1084
+ }
1085
+ super.clear(key);
1086
+ return super.readSync(key, () => this.#loadSyncEntry(load)).value;
1087
+ }
1088
+ #loadEntry(key, load) {
1089
+ const value = load();
1090
+ const entry = {
1091
+ value,
1092
+ expiresAt: Date.now() + this.#ttlMs
1093
+ };
1094
+ if (isPromiseLike(value)) {
1095
+ entry.value = Promise.resolve(value).then((resolved) => {
1096
+ super.clear(key);
1097
+ super.read(key, () => ({
1098
+ value: resolved,
1099
+ expiresAt: Date.now() + this.#ttlMs
1100
+ }));
1101
+ return resolved;
1102
+ }).catch((error) => {
1103
+ super.clear(key);
1104
+ throw error;
1105
+ });
1106
+ }
1107
+ return entry;
1108
+ }
1109
+ #loadSyncEntry(load) {
1110
+ return {
1111
+ value: load(),
1112
+ expiresAt: Date.now() + this.#ttlMs
1113
+ };
1114
+ }
1115
+ };
1116
+ function isPromiseLike(value) {
1117
+ return (typeof value === "object" || typeof value === "function") && value !== null && "then" in value;
838
1118
  }
839
1119
 
840
- // src/contracts/core/core.ts
841
- var $moduleName7 = "0xf391858d2a08473e8d4defcc8df89976bd7b123d3865c6b9341b237f7853dbbc::core";
842
- function BetResultEvent(...typeParameters) {
843
- return new MoveStruct({ name: `${$moduleName7}::BetResultEvent<${typeParameters[0].name}>`, fields: {
844
- player: bcs.Address,
845
- coin_type: TypeName2,
846
- stake_amount: bcs.u64(),
847
- unsafe_oracle_usd_coin_price: Float,
848
- adjusted_oracle_usd_coin_price: Float,
849
- outcome_amount: bcs.u64(),
850
- game_details: VecMap(bcs.string(), bcs.vector(bcs.u8())),
851
- metadata: VecMap(bcs.string(), bcs.vector(bcs.u8()))
852
- } });
853
- }
1120
+ // src/types/game-settings.type.ts
1121
+ var GAME_SETTINGS = {
1122
+ coinflip: {
1123
+ settingsKey: CoinFlipSettingsKey,
1124
+ parameters: Parameters2
1125
+ },
1126
+ limbo: {
1127
+ settingsKey: LimboSettingsKey,
1128
+ parameters: Parameters3
1129
+ },
1130
+ plinko: {
1131
+ settingsKey: PlinkoSettingsKey,
1132
+ parameters: Parameters4
1133
+ },
1134
+ "pvp-coinflip": {
1135
+ settingsKey: PvpCoinflipSettingsKey,
1136
+ parameters: Parameters
1137
+ },
1138
+ range: {
1139
+ settingsKey: RangeSettingsKey,
1140
+ parameters: Parameters5
1141
+ },
1142
+ wheel: {
1143
+ settingsKey: WheelSettingsKey,
1144
+ parameters: Parameters6
1145
+ }
1146
+ };
1147
+
1148
+ // src/client.ts
854
1149
  function suigar({
855
1150
  name = "suigar",
856
- ...options
1151
+ partner,
1152
+ cacheTtl
857
1153
  } = {}) {
858
1154
  return {
859
1155
  name,
860
1156
  register: (client) => {
861
- return new SuigarClient({ client, options });
1157
+ return new SuigarClient({
1158
+ client,
1159
+ name: String(name),
1160
+ partner,
1161
+ cacheTtl
1162
+ });
862
1163
  }
863
1164
  };
864
1165
  }
865
1166
  var SuigarClient = class {
866
1167
  #client;
867
1168
  #config;
1169
+ #partner;
1170
+ #cache;
868
1171
  constructor({
869
1172
  client,
870
- options
1173
+ name,
1174
+ partner,
1175
+ cacheTtl
871
1176
  }) {
872
1177
  this.#client = client;
873
- this.#config = resolveSuigarConfig(options);
1178
+ this.#partner = partner;
1179
+ this.#cache = client.cache.scope("@suigar/sdk").readSync([name, "ttl-cache"], () => {
1180
+ return new TtlClientCache({
1181
+ ttlMs: cacheTtl ?? DEFAULT_CACHE_TTL_MS
1182
+ });
1183
+ });
1184
+ const network = this.#client.network;
1185
+ if (!SUPPORTED_SUI_NETWORKS.includes(network)) {
1186
+ throw new Error(`Unsupported network: ${network}`);
1187
+ }
1188
+ this.#config = resolveSuigarConfig(network);
1189
+ }
1190
+ /**
1191
+ * Returns the resolved SDK configuration for the connected network.
1192
+ *
1193
+ * This is primarily useful for debugging or inspecting which package ids,
1194
+ * registry ids, supported coin types, and price info object ids the SDK
1195
+ * resolved for the current client network.
1196
+ *
1197
+ * @returns Network-resolved Suigar configuration.
1198
+ */
1199
+ getConfig() {
1200
+ return this.#config;
874
1201
  }
875
1202
  /**
876
1203
  * Builds a transaction with the configured Sui client and encodes the resulting BCS bytes as base64.
@@ -888,9 +1215,144 @@ var SuigarClient = class {
888
1215
  return toBase64(bytes);
889
1216
  }
890
1217
  /**
891
- * BCS struct constructors for decoding Suigar events emitted on-chain.
1218
+ * Reads on-chain game parameters for the requested game.
1219
+ *
1220
+ * The SDK first reads the selected game's settings object from SweetHouse,
1221
+ * then reads that game's coin-specific `Parameters<T>` object. Results are
1222
+ * cached according to the extension `cacheTtl` option. Pass
1223
+ * `ignoreCache: true` to refresh the onchain read and replace the cached
1224
+ * value.
1225
+ *
1226
+ * @param game Game whose parameters should be loaded.
1227
+ * @param options Optional coin type, cache override, and abort signal.
1228
+ * @returns Parsed game parameters typed for the requested game.
1229
+ */
1230
+ async getGameParameters(game, options = {}) {
1231
+ const coinType = normalizeStructTag(
1232
+ options.coinType ?? this.#config.coinTypes.sui
1233
+ );
1234
+ return this.#cache.read(
1235
+ ["parameters", this.#client.network, game, coinType],
1236
+ () => this.#fetchGameParameters(game, coinType, options.signal),
1237
+ { ignoreCache: options.ignoreCache }
1238
+ );
1239
+ }
1240
+ /**
1241
+ * Lists unresolved PvP coinflip games from the configured registry and resolves
1242
+ * each entry into parsed onchain game state.
1243
+ *
1244
+ * This fetches dynamic fields from the PvP coinflip registry object, then bulk
1245
+ * loads the referenced game objects through `client.core.getObjects()`. Registry
1246
+ * membership is the unresolved-state signal: when a game is joined and resolved,
1247
+ * the Move flow removes it from the registry and deletes the live `Game` object.
1248
+ * Use this when a product needs the current set of open PvP coinflip matches for
1249
+ * browsing or lobby views.
1250
+ *
1251
+ * @param options Optional dynamic field pagination forwarded to `listDynamicFields()`, excluding `parentId`.
1252
+ * Supported options such as `limit`, `cursor`, and `signal` are forwarded to the
1253
+ * underlying lookup calls. Pass `throwOnError: true` to fail the whole lookup
1254
+ * when any referenced game object cannot be fetched or parsed. By default,
1255
+ * failed per-object lookups are skipped and only successfully parsed unresolved
1256
+ * games are returned.
1257
+ * @returns Parsed unresolved PvP coinflip game objects for the requested
1258
+ * registry page. When `throwOnError` is `false`, entries that fail object fetch
1259
+ * or parse are omitted from the returned array.
1260
+ */
1261
+ async getPvPCoinflipGames(options = {
1262
+ limit: 50
1263
+ }) {
1264
+ const { throwOnError = false, ...listOptions } = options;
1265
+ const { dynamicFields } = await this.#client.core.listDynamicFields({
1266
+ ...listOptions,
1267
+ parentId: this.#config.registryIds.pvpCoinflip
1268
+ });
1269
+ const { objects } = await this.#client.core.getObjects({
1270
+ objectIds: dynamicFields.map(({ childId }) => childId),
1271
+ signal: listOptions.signal,
1272
+ include: {
1273
+ content: true
1274
+ }
1275
+ });
1276
+ const resolvedGames = objects.map((object) => {
1277
+ try {
1278
+ if (object instanceof Error) {
1279
+ throw object;
1280
+ }
1281
+ if (!object.content) {
1282
+ throw new Error(
1283
+ "Unable to resolve PvP coinflip game from retrieved object"
1284
+ );
1285
+ }
1286
+ return {
1287
+ ...Game.parse(object.content),
1288
+ coinType: parseCoinType(object.type)
1289
+ };
1290
+ } catch (error) {
1291
+ return error instanceof Error ? error : new Error(String(error));
1292
+ }
1293
+ });
1294
+ if (throwOnError) {
1295
+ const firstError = resolvedGames.find((game) => game instanceof Error);
1296
+ if (firstError) {
1297
+ throw firstError;
1298
+ }
1299
+ }
1300
+ return resolvedGames.flatMap(
1301
+ (game) => game instanceof Error ? [] : [game]
1302
+ );
1303
+ }
1304
+ async #fetchGameParameters(game, coinType, signal) {
1305
+ const gameDefinition = GAME_SETTINGS[game];
1306
+ const { object: settingsObject } = await this.#client.core.getDynamicObjectField({
1307
+ parentId: this.#config.packageIds.sweetHouse,
1308
+ name: {
1309
+ type: resolveGameSettingsKeyType(
1310
+ gameDefinition.settingsKey.name,
1311
+ resolveGamePackageId(this.#config, game)
1312
+ ),
1313
+ bcs: gameDefinition.settingsKey.serialize({ dummy_field: false }).toBytes()
1314
+ },
1315
+ signal
1316
+ });
1317
+ const { object } = await this.#client.core.getDynamicObjectField({
1318
+ parentId: settingsObject.objectId,
1319
+ name: {
1320
+ type: TypeName.name,
1321
+ bcs: TypeName.serialize({
1322
+ name: resolveCoinTypeNameForTypeNameKey(coinType)
1323
+ }).toBytes()
1324
+ },
1325
+ include: {
1326
+ content: true
1327
+ },
1328
+ signal
1329
+ });
1330
+ if (!object?.content) {
1331
+ throw new Error(
1332
+ `Missing parameters object content for ${game} and coin type ${coinType}`
1333
+ );
1334
+ }
1335
+ return gameDefinition.parameters.parse(
1336
+ object.content
1337
+ );
1338
+ }
1339
+ /**
1340
+ * BCS struct constructors for decoding on-chain objects and events related to Suigar games.
1341
+ *
1342
+ * These can be used to parse the `content` field of on-chain objects and events into structured data with the
1343
+ * expected types. For example, use `client.suigar.bcs.PvPCoinflipGame.parse(object.content)` to decode a PvP
1344
+ * coinflip game object.
1345
+ *
1346
+ * Note that these constructors are not meant for encoding transaction arguments, as the SDK's transaction
1347
+ * builders handle argument serialization internally. Use these primarily for decoding and parsing on-chain data.
892
1348
  */
893
1349
  bcs = {
1350
+ // Objects
1351
+ /**
1352
+ * Object representing the state of a PvP coinflip game, as stored on-chain.
1353
+ */
1354
+ PvPCoinflipGame: Game,
1355
+ // Events
894
1356
  /**
895
1357
  * Event emitted at the end of a standard game (e.g., Coinflip, Limbo), containing the result and payout information.
896
1358
  */
@@ -898,15 +1360,15 @@ var SuigarClient = class {
898
1360
  /**
899
1361
  * Event emitted when a PvP Coinflip game is created, containing the game configuration and initial state.
900
1362
  */
901
- PvPCoinflipGameCreated: GameCreatedEvent,
1363
+ PvPCoinflipGameCreatedEvent: GameCreatedEvent,
902
1364
  /**
903
1365
  * Event emitted when a PvP Coinflip game is resolved, containing the final outcome.
904
1366
  */
905
- PvPCoinflipGameResolved: GameResolvedEvent,
1367
+ PvPCoinflipGameResolvedEvent: GameResolvedEvent,
906
1368
  /**
907
1369
  * Event emitted when a PvP Coinflip game is cancelled.
908
1370
  */
909
- PvPCoinflipGameCancelled: GameCancelledEvent
1371
+ PvPCoinflipGameCancelledEvent: GameCancelledEvent
910
1372
  };
911
1373
  /**
912
1374
  * Transaction builders for Suigar games.
@@ -924,27 +1386,32 @@ var SuigarClient = class {
924
1386
  case "coinflip":
925
1387
  return buildCoinflipTransaction({
926
1388
  ...options,
927
- config: this.#config
1389
+ config: this.#config,
1390
+ partner: this.#partner
928
1391
  });
929
1392
  case "limbo":
930
1393
  return buildLimboTransaction({
931
1394
  ...options,
932
- config: this.#config
1395
+ config: this.#config,
1396
+ partner: this.#partner
933
1397
  });
934
1398
  case "plinko":
935
1399
  return buildPlinkoTransaction({
936
1400
  ...options,
937
- config: this.#config
1401
+ config: this.#config,
1402
+ partner: this.#partner
938
1403
  });
939
1404
  case "range":
940
1405
  return buildRangeTransaction({
941
1406
  ...options,
942
- config: this.#config
1407
+ config: this.#config,
1408
+ partner: this.#partner
943
1409
  });
944
1410
  case "wheel":
945
1411
  return buildWheelTransaction({
946
1412
  ...options,
947
- config: this.#config
1413
+ config: this.#config,
1414
+ partner: this.#partner
948
1415
  });
949
1416
  default:
950
1417
  throw new Error(`Unsupported game: ${gameId}`);
@@ -958,12 +1425,46 @@ var SuigarClient = class {
958
1425
  * @returns Prepared PvP coinflip transaction.
959
1426
  */
960
1427
  createPvPCoinflipTransaction: (action, options) => {
961
- return buildPvPCoinflipTransaction(action, {
962
- ...options,
963
- config: this.#config
964
- });
1428
+ switch (action) {
1429
+ case "create":
1430
+ return buildPvPCoinflipTransaction("create", {
1431
+ ...options,
1432
+ config: this.#config,
1433
+ partner: this.#partner
1434
+ });
1435
+ case "join": {
1436
+ const joinOptions = options;
1437
+ return buildPvPCoinflipTransaction("join", {
1438
+ ...joinOptions,
1439
+ betCoin: this.#createPvPCoinflipBetCoin(joinOptions),
1440
+ config: this.#config,
1441
+ partner: this.#partner
1442
+ });
1443
+ }
1444
+ case "cancel":
1445
+ return buildPvPCoinflipTransaction("cancel", {
1446
+ ...options,
1447
+ config: this.#config,
1448
+ partner: this.#partner
1449
+ });
1450
+ default:
1451
+ throw new Error(`Unsupported PvP coinflip action: ${action}`);
1452
+ }
965
1453
  }
966
1454
  };
1455
+ #createPvPCoinflipBetCoin(options) {
1456
+ return async (tx) => {
1457
+ const { json } = await Game.get({
1458
+ client: this.#client,
1459
+ objectId: options.gameId
1460
+ });
1461
+ return tx.coin({
1462
+ type: options.coinType,
1463
+ balance: BigInt(json.stake_per_player),
1464
+ useGasCoin: options.allowGasCoinShortcut
1465
+ });
1466
+ };
1467
+ }
967
1468
  };
968
1469
 
969
- export { suigar };
1470
+ export { SuigarClient, suigar };