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