@suigar/sdk 2.0.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs ADDED
@@ -0,0 +1,969 @@
1
+ 'use strict';
2
+
3
+ var utils = require('@mysten/sui/utils');
4
+ var bcs = require('@mysten/sui/bcs');
5
+ var transactions = require('@mysten/sui/transactions');
6
+
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
+ }
153
+ var MOVE_STDLIB_ADDRESS = utils.normalizeSuiAddress("0x1");
154
+ var SUI_FRAMEWORK_ADDRESS = utils.normalizeSuiAddress("0x2");
155
+ function getPureBcsSchema(typeTag) {
156
+ const parsedTag = typeof typeTag === "string" ? bcs.TypeTagSerializer.parseFromStr(typeTag) : typeTag;
157
+ if ("u8" in parsedTag) {
158
+ return bcs.bcs.U8;
159
+ } else if ("u16" in parsedTag) {
160
+ return bcs.bcs.U16;
161
+ } else if ("u32" in parsedTag) {
162
+ return bcs.bcs.U32;
163
+ } else if ("u64" in parsedTag) {
164
+ return bcs.bcs.U64;
165
+ } else if ("u128" in parsedTag) {
166
+ return bcs.bcs.U128;
167
+ } else if ("u256" in parsedTag) {
168
+ return bcs.bcs.U256;
169
+ } else if ("address" in parsedTag) {
170
+ return bcs.bcs.Address;
171
+ } else if ("bool" in parsedTag) {
172
+ return bcs.bcs.Bool;
173
+ } else if ("vector" in parsedTag) {
174
+ const type = getPureBcsSchema(parsedTag.vector);
175
+ return type ? bcs.bcs.vector(type) : null;
176
+ } else if ("struct" in parsedTag) {
177
+ const structTag = parsedTag.struct;
178
+ const pkg = utils.normalizeSuiAddress(structTag.address);
179
+ if (pkg === MOVE_STDLIB_ADDRESS) {
180
+ if ((structTag.module === "ascii" || structTag.module === "string") && structTag.name === "String") {
181
+ return bcs.bcs.String;
182
+ }
183
+ if (structTag.module === "option" && structTag.name === "Option") {
184
+ const type = getPureBcsSchema(structTag.typeParams[0]);
185
+ return type ? bcs.bcs.option(type) : null;
186
+ }
187
+ }
188
+ if (pkg === SUI_FRAMEWORK_ADDRESS && structTag.module === "object" && (structTag.name === "ID" || structTag.name === "UID")) {
189
+ return bcs.bcs.Address;
190
+ }
191
+ }
192
+ return null;
193
+ }
194
+ function normalizeMoveArguments(args, argTypes, parameterNames) {
195
+ Array.isArray(args) ? args.length : Object.keys(args).length;
196
+ const normalizedArgs = [];
197
+ let index = 0;
198
+ for (const [i, argType] of argTypes.entries()) {
199
+ if (argType === "0x2::clock::Clock") {
200
+ normalizedArgs.push((tx) => tx.object.clock());
201
+ continue;
202
+ }
203
+ if (argType === "0x2::random::Random") {
204
+ normalizedArgs.push((tx) => tx.object.random());
205
+ continue;
206
+ }
207
+ if (argType === "0x2::deny_list::DenyList") {
208
+ normalizedArgs.push((tx) => tx.object.denyList());
209
+ continue;
210
+ }
211
+ if (argType === "0x3::sui_system::SuiSystemState") {
212
+ normalizedArgs.push((tx) => tx.object.system());
213
+ continue;
214
+ }
215
+ let arg;
216
+ if (Array.isArray(args)) {
217
+ if (index >= args.length) {
218
+ throw new Error(
219
+ `Invalid number of arguments, expected at least ${index + 1}, got ${args.length}`
220
+ );
221
+ }
222
+ arg = args[index];
223
+ } else {
224
+ {
225
+ throw new Error(`Expected arguments to be passed as an array`);
226
+ }
227
+ }
228
+ index += 1;
229
+ if (typeof arg === "function" || transactions.isArgument(arg)) {
230
+ normalizedArgs.push(arg);
231
+ continue;
232
+ }
233
+ const type = argTypes[i];
234
+ const bcsType = type === null ? null : getPureBcsSchema(type);
235
+ if (bcsType) {
236
+ const bytes = bcsType.serialize(arg);
237
+ normalizedArgs.push((tx) => tx.pure(bytes));
238
+ continue;
239
+ }
240
+ if (typeof arg === "string") {
241
+ normalizedArgs.push((tx) => tx.object(arg));
242
+ continue;
243
+ }
244
+ throw new Error(`Invalid argument ${stringify(arg)} for type ${type}`);
245
+ }
246
+ return normalizedArgs;
247
+ }
248
+ var MoveStruct = class extends bcs.BcsStruct {
249
+ async get({
250
+ objectId,
251
+ ...options
252
+ }) {
253
+ const [res] = await this.getMany({
254
+ ...options,
255
+ objectIds: [objectId]
256
+ });
257
+ return res;
258
+ }
259
+ async getMany({
260
+ client,
261
+ ...options
262
+ }) {
263
+ const response = await client.core.getObjects({
264
+ ...options,
265
+ include: {
266
+ ...options.include,
267
+ content: true
268
+ }
269
+ });
270
+ return response.objects.map((obj) => {
271
+ if (obj instanceof Error) {
272
+ throw obj;
273
+ }
274
+ return {
275
+ ...obj,
276
+ json: this.parse(obj.content)
277
+ };
278
+ });
279
+ }
280
+ };
281
+ function stringify(val) {
282
+ if (typeof val === "object") {
283
+ return JSON.stringify(val, (val2) => val2);
284
+ }
285
+ if (typeof val === "bigint") {
286
+ return val.toString();
287
+ }
288
+ return val;
289
+ }
290
+
291
+ // src/contracts/coinflip/coinflip.ts
292
+ function play(options) {
293
+ const packageAddress = options.package ?? "0xb35c5f286c443752afc8ccb40125a578a4f32df35617170ccfa17fe180ab80ea";
294
+ const argumentsTypes = [
295
+ null,
296
+ "u64",
297
+ null,
298
+ "u64",
299
+ "bool",
300
+ "vector<0x1::string::String>",
301
+ "vector<vector<u8>>",
302
+ null,
303
+ "0x2::clock::Clock",
304
+ "0x2::random::Random"
305
+ ];
306
+ return (tx) => tx.moveCall({
307
+ package: packageAddress,
308
+ module: "coinflip",
309
+ function: "play",
310
+ arguments: normalizeMoveArguments(options.arguments, argumentsTypes),
311
+ typeArguments: options.typeArguments
312
+ });
313
+ }
314
+ function createBaseGameTransaction({
315
+ config,
316
+ game,
317
+ owner,
318
+ sender,
319
+ gasBudget
320
+ }) {
321
+ assertConfiguredBetGame(config, game);
322
+ const tx = new transactions.Transaction();
323
+ tx.setSenderIfNotSet(utils.normalizeSuiAddress(sender ?? owner));
324
+ tx.setGasBudgetIfNotSet(gasBudget ?? DEFAULT_GAS_BUDGET_MIST);
325
+ return tx;
326
+ }
327
+ function buildSharedStandardGameBetCall({
328
+ config,
329
+ owner,
330
+ sender,
331
+ coinType,
332
+ stake,
333
+ cashStake,
334
+ betCount,
335
+ metadata,
336
+ allowGasCoinShortcut = true,
337
+ buildRewardCoin
338
+ }) {
339
+ return (tx) => {
340
+ const normalizedOwner = utils.normalizeSuiAddress(sender ?? owner);
341
+ 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(
347
+ config,
348
+ normalizedCoinType
349
+ );
350
+ const betCoin = tx.coin({
351
+ type: normalizedCoinType,
352
+ balance: resolvedCashStake,
353
+ useGasCoin: allowGasCoinShortcut
354
+ });
355
+ const rewardCoin = buildRewardCoin({
356
+ tx,
357
+ config,
358
+ owner: normalizedOwner,
359
+ coinType: normalizedCoinType,
360
+ stake: resolvedStake,
361
+ cashStake: resolvedCashStake,
362
+ betCount: resolvedBetCount,
363
+ metadata: encodedMetadata,
364
+ pythPriceInfoObjectId,
365
+ betCoin
366
+ });
367
+ tx.transferObjects([rewardCoin], tx.pure.address(normalizedOwner));
368
+ return rewardCoin;
369
+ };
370
+ }
371
+ function buildSharedStandardGameBetTransaction(options) {
372
+ const tx = createBaseGameTransaction(options);
373
+ tx.add(buildSharedStandardGameBetCall(options));
374
+ return tx;
375
+ }
376
+
377
+ // src/transactions/coinflip.ts
378
+ function buildCoinflipTransaction(options) {
379
+ return buildSharedStandardGameBetTransaction({
380
+ ...options,
381
+ game: "coinflip",
382
+ buildRewardCoin: ({
383
+ tx,
384
+ config,
385
+ coinType,
386
+ stake,
387
+ betCount,
388
+ metadata,
389
+ pythPriceInfoObjectId,
390
+ betCoin
391
+ }) => play({
392
+ package: config.gamesPackageId.coinflip,
393
+ typeArguments: [coinType],
394
+ arguments: [
395
+ config.sweetHousePackageId,
396
+ stake,
397
+ betCoin,
398
+ betCount,
399
+ options.side === "tails",
400
+ metadata.keys,
401
+ metadata.values,
402
+ pythPriceInfoObjectId
403
+ ]
404
+ })(tx)
405
+ });
406
+ }
407
+
408
+ // src/contracts/limbo/limbo.ts
409
+ function play2(options) {
410
+ const packageAddress = options.package ?? "0x96c7841b9b32c59a219760fd656f1c3aceb53cc74a68ec9844a3a696374309f4";
411
+ const argumentsTypes = [
412
+ null,
413
+ "u64",
414
+ null,
415
+ "u64",
416
+ "u64",
417
+ "u64",
418
+ "vector<0x1::string::String>",
419
+ "vector<vector<u8>>",
420
+ null,
421
+ "0x2::clock::Clock",
422
+ "0x2::random::Random"
423
+ ];
424
+ return (tx) => tx.moveCall({
425
+ package: packageAddress,
426
+ module: "limbo",
427
+ function: "play",
428
+ arguments: normalizeMoveArguments(options.arguments, argumentsTypes),
429
+ typeArguments: options.typeArguments
430
+ });
431
+ }
432
+
433
+ // src/transactions/limbo.ts
434
+ function buildLimboTransaction(options) {
435
+ const scale = options.scale ?? LIMBO_MULTIPLIER_SCALE;
436
+ const numerator = Math.round(options.targetMultiplier * scale);
437
+ return buildSharedStandardGameBetTransaction({
438
+ ...options,
439
+ game: "limbo",
440
+ buildRewardCoin: ({
441
+ tx,
442
+ config,
443
+ coinType,
444
+ stake,
445
+ betCount,
446
+ metadata,
447
+ pythPriceInfoObjectId,
448
+ betCoin
449
+ }) => play2({
450
+ package: config.gamesPackageId.limbo,
451
+ typeArguments: [coinType],
452
+ arguments: [
453
+ config.sweetHousePackageId,
454
+ stake,
455
+ betCoin,
456
+ betCount,
457
+ BigInt(numerator),
458
+ BigInt(scale),
459
+ metadata.keys,
460
+ metadata.values,
461
+ pythPriceInfoObjectId
462
+ ]
463
+ })(tx)
464
+ });
465
+ }
466
+
467
+ // src/contracts/plinko/plinko.ts
468
+ function play3(options) {
469
+ const packageAddress = options.package ?? "0xd3dd2200883af10811724f0bed97591ad155a02efd6332d471ff8b346030dfb7";
470
+ const argumentsTypes = [
471
+ null,
472
+ "u64",
473
+ null,
474
+ "u64",
475
+ "u8",
476
+ "vector<0x1::string::String>",
477
+ "vector<vector<u8>>",
478
+ null,
479
+ "0x2::clock::Clock",
480
+ "0x2::random::Random"
481
+ ];
482
+ return (tx) => tx.moveCall({
483
+ package: packageAddress,
484
+ module: "plinko",
485
+ function: "play",
486
+ arguments: normalizeMoveArguments(options.arguments, argumentsTypes),
487
+ typeArguments: options.typeArguments
488
+ });
489
+ }
490
+
491
+ // src/transactions/plinko.ts
492
+ function buildPlinkoTransaction(options) {
493
+ const configId = toU8Number(options.configId, "configId");
494
+ return buildSharedStandardGameBetTransaction({
495
+ ...options,
496
+ game: "plinko",
497
+ buildRewardCoin: ({
498
+ tx,
499
+ config,
500
+ coinType,
501
+ stake,
502
+ betCount,
503
+ metadata,
504
+ pythPriceInfoObjectId,
505
+ betCoin
506
+ }) => play3({
507
+ package: config.gamesPackageId.plinko,
508
+ typeArguments: [coinType],
509
+ arguments: [
510
+ config.sweetHousePackageId,
511
+ stake,
512
+ betCoin,
513
+ betCount,
514
+ configId,
515
+ metadata.keys,
516
+ metadata.values,
517
+ pythPriceInfoObjectId
518
+ ]
519
+ })(tx)
520
+ });
521
+ }
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
+ function buildPvPCoinflipTransaction(action, options) {
622
+ const tx = createBaseGameTransaction({
623
+ ...options,
624
+ game: "pvp-coinflip"
625
+ });
626
+ const normalizedCoinType = utils.normalizeStructTag(options.coinType);
627
+ const encodedMetadata = encodeBetMetadata(options.metadata);
628
+ switch (action) {
629
+ case "create": {
630
+ const createOptions = options;
631
+ const stake = toBigIntAmount(createOptions.stake, "stake");
632
+ const betCoin = tx.coin({
633
+ type: normalizedCoinType,
634
+ balance: stake,
635
+ useGasCoin: createOptions.allowGasCoinShortcut
636
+ });
637
+ tx.add(
638
+ createGame({
639
+ package: createOptions.config.gamesPackageId["pvp-coinflip"],
640
+ typeArguments: [normalizedCoinType],
641
+ arguments: [
642
+ createOptions.config.sweetHousePackageId,
643
+ betCoin,
644
+ createOptions.side === "tails",
645
+ Boolean(createOptions.isPrivate),
646
+ encodedMetadata.keys,
647
+ encodedMetadata.values
648
+ ]
649
+ })
650
+ );
651
+ return tx;
652
+ }
653
+ case "join": {
654
+ 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
+ });
661
+ tx.add(
662
+ joinGame({
663
+ package: joinOptions.config.gamesPackageId["pvp-coinflip"],
664
+ typeArguments: [normalizedCoinType],
665
+ arguments: [
666
+ joinOptions.gameId,
667
+ joinOptions.config.sweetHousePackageId,
668
+ betCoin,
669
+ encodedMetadata.keys,
670
+ encodedMetadata.values,
671
+ joinOptions.extraObjectId
672
+ ]
673
+ })
674
+ );
675
+ return tx;
676
+ }
677
+ case "cancel": {
678
+ const cancelOptions = options;
679
+ tx.add(
680
+ cancelGame({
681
+ package: cancelOptions.config.gamesPackageId["pvp-coinflip"],
682
+ typeArguments: [normalizedCoinType],
683
+ arguments: [
684
+ cancelOptions.gameId,
685
+ cancelOptions.config.sweetHousePackageId
686
+ ]
687
+ })
688
+ );
689
+ return tx;
690
+ }
691
+ default:
692
+ throw new Error(`Unsupported PvP coinflip action: ${action}`);
693
+ }
694
+ }
695
+
696
+ // src/contracts/range/range.ts
697
+ function play4(options) {
698
+ const packageAddress = options.package ?? "0x096a4cf18b3661e76b2c62b90785418345d52f45b272448794f123a4cb6b6416";
699
+ const argumentsTypes = [
700
+ null,
701
+ "u64",
702
+ null,
703
+ "u64",
704
+ "u64",
705
+ "u64",
706
+ "bool",
707
+ "vector<0x1::string::String>",
708
+ "vector<vector<u8>>",
709
+ null,
710
+ "0x2::clock::Clock",
711
+ "0x2::random::Random"
712
+ ];
713
+ return (tx) => tx.moveCall({
714
+ package: packageAddress,
715
+ module: "range",
716
+ function: "play",
717
+ arguments: normalizeMoveArguments(options.arguments, argumentsTypes),
718
+ typeArguments: options.typeArguments
719
+ });
720
+ }
721
+
722
+ // src/transactions/range.ts
723
+ function buildRangeTransaction(options) {
724
+ const scale = options.scale ?? RANGE_FIXED_POINT_SCALE;
725
+ const leftPoint = Math.round(options.leftPoint * scale);
726
+ const rightPoint = Math.round(options.rightPoint * scale);
727
+ return buildSharedStandardGameBetTransaction({
728
+ ...options,
729
+ game: "range",
730
+ buildRewardCoin: ({
731
+ tx,
732
+ config,
733
+ coinType,
734
+ stake,
735
+ betCount,
736
+ metadata,
737
+ pythPriceInfoObjectId,
738
+ betCoin
739
+ }) => play4({
740
+ package: config.gamesPackageId.range,
741
+ typeArguments: [coinType],
742
+ arguments: [
743
+ config.sweetHousePackageId,
744
+ stake,
745
+ betCoin,
746
+ betCount,
747
+ BigInt(leftPoint),
748
+ BigInt(rightPoint),
749
+ Boolean(options.outOfRange),
750
+ metadata.keys,
751
+ metadata.values,
752
+ pythPriceInfoObjectId
753
+ ]
754
+ })(tx)
755
+ });
756
+ }
757
+
758
+ // src/contracts/wheel/wheel.ts
759
+ function play5(options) {
760
+ const packageAddress = options.package ?? "0x0997852ded7e13301c42317004bc49704a893aa82997c5706cebee59053a31b7";
761
+ const argumentsTypes = [
762
+ null,
763
+ "u64",
764
+ null,
765
+ "u64",
766
+ "u8",
767
+ "vector<0x1::string::String>",
768
+ "vector<vector<u8>>",
769
+ null,
770
+ "0x2::clock::Clock",
771
+ "0x2::random::Random"
772
+ ];
773
+ return (tx) => tx.moveCall({
774
+ package: packageAddress,
775
+ module: "wheel",
776
+ function: "play",
777
+ arguments: normalizeMoveArguments(options.arguments, argumentsTypes),
778
+ typeArguments: options.typeArguments
779
+ });
780
+ }
781
+
782
+ // src/transactions/wheel.ts
783
+ function buildWheelTransaction(options) {
784
+ const configId = toU8Number(options.configId, "configId");
785
+ return buildSharedStandardGameBetTransaction({
786
+ ...options,
787
+ game: "wheel",
788
+ buildRewardCoin: ({
789
+ tx,
790
+ config,
791
+ coinType,
792
+ stake,
793
+ betCount,
794
+ metadata,
795
+ pythPriceInfoObjectId,
796
+ betCoin
797
+ }) => play5({
798
+ package: config.gamesPackageId.wheel,
799
+ typeArguments: [coinType],
800
+ arguments: [
801
+ config.sweetHousePackageId,
802
+ stake,
803
+ betCoin,
804
+ betCount,
805
+ configId,
806
+ metadata.keys,
807
+ metadata.values,
808
+ pythPriceInfoObjectId
809
+ ]
810
+ })(tx)
811
+ });
812
+ }
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
+ } });
840
+ }
841
+
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
+ }
856
+
857
+ // src/client.ts
858
+ function suigar({
859
+ name = "suigar",
860
+ ...options
861
+ } = {}) {
862
+ return {
863
+ name,
864
+ register: (client) => {
865
+ return new SuigarClient({ client, options });
866
+ }
867
+ };
868
+ }
869
+ var SuigarClient = class {
870
+ #client;
871
+ #config;
872
+ constructor({
873
+ client,
874
+ options
875
+ }) {
876
+ this.#client = client;
877
+ this.#config = resolveSuigarConfig(options);
878
+ }
879
+ /**
880
+ * Builds a transaction with the configured Sui client and returns the BCS bytes as a base64 string.
881
+ *
882
+ * @param transaction Transaction block to serialize.
883
+ * @returns Base64-encoded transaction bytes ready to send over the wire.
884
+ */
885
+ async serializeTransactionToBase64(transaction) {
886
+ const bytes = await transaction.build({ client: this.#client });
887
+ return Buffer.from(bytes).toString("base64");
888
+ }
889
+ /**
890
+ * BCS struct constructors for decoding Suigar events emitted on-chain.
891
+ */
892
+ bcs = {
893
+ /**
894
+ * Event emitted at the end of a standard game (e.g., Coinflip, Limbo), containing the result and payout information.
895
+ */
896
+ BetResultEvent,
897
+ /**
898
+ * Event emitted when a PvP Coinflip game is created, containing the game configuration and initial state.
899
+ */
900
+ PvPCoinflipGameCreated: GameCreatedEvent,
901
+ /**
902
+ * Event emitted when a PvP Coinflip game is resolved, containing the final outcome.
903
+ */
904
+ PvPCoinflipGameResolved: GameResolvedEvent,
905
+ /**
906
+ * Event emitted when a PvP Coinflip game is cancelled.
907
+ */
908
+ PvPCoinflipGameCancelled: GameCancelledEvent
909
+ };
910
+ /**
911
+ * Transaction builders for Suigar games.
912
+ */
913
+ tx = {
914
+ /**
915
+ * Creates a standard game transaction for the provided game id.
916
+ *
917
+ * @param gameId Supported standard game identifier.
918
+ * @param options Transaction builder options for the selected game.
919
+ * @returns Prepared transaction for the selected game.
920
+ */
921
+ createBetTransaction: (gameId, options) => {
922
+ switch (gameId) {
923
+ case "coinflip":
924
+ return buildCoinflipTransaction({
925
+ ...options,
926
+ config: this.#config
927
+ });
928
+ case "limbo":
929
+ return buildLimboTransaction({
930
+ ...options,
931
+ config: this.#config
932
+ });
933
+ case "plinko":
934
+ return buildPlinkoTransaction({
935
+ ...options,
936
+ config: this.#config
937
+ });
938
+ case "range":
939
+ return buildRangeTransaction({
940
+ ...options,
941
+ config: this.#config
942
+ });
943
+ case "wheel":
944
+ return buildWheelTransaction({
945
+ ...options,
946
+ config: this.#config
947
+ });
948
+ default:
949
+ throw new Error(`Unsupported game: ${gameId}`);
950
+ }
951
+ },
952
+ /**
953
+ * Creates a PvP coinflip transaction for the requested action.
954
+ *
955
+ * @param action PvP coinflip action to perform.
956
+ * @param options Transaction builder options for the selected action.
957
+ * @returns Prepared PvP coinflip transaction.
958
+ */
959
+ createPvPCoinflipTransaction: (action, options) => {
960
+ return buildPvPCoinflipTransaction(action, {
961
+ ...options,
962
+ config: this.#config
963
+ });
964
+ }
965
+ };
966
+ };
967
+
968
+ exports.SuigarClient = SuigarClient;
969
+ exports.suigar = suigar;