@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.js ADDED
@@ -0,0 +1,966 @@
1
+ import { normalizeSuiAddress, normalizeStructTag, SUI_TYPE_ARG } from '@mysten/sui/utils';
2
+ import { bcs, BcsStruct, TypeTagSerializer } from '@mysten/sui/bcs';
3
+ import { Transaction, isArgument } from '@mysten/sui/transactions';
4
+
5
+ // src/utils/config.ts
6
+
7
+ // src/configs/package-id.ts
8
+ var DEFAULT_SWEETHOUSE_PACKAGE_ID = "0xb7f64e5a273aba1ede00caa0a6f8027cc7490c279d17eab12e7100ed20660603";
9
+ var DEFAULT_GAMES_PACKAGE_ID = {
10
+ coinflip: "0xb35c5f286c443752afc8ccb40125a578a4f32df35617170ccfa17fe180ab80ea",
11
+ limbo: "0x96c7841b9b32c59a219760fd656f1c3aceb53cc74a68ec9844a3a696374309f4",
12
+ plinko: "0xd3dd2200883af10811724f0bed97591ad155a02efd6332d471ff8b346030dfb7",
13
+ pvp_coinflip: "0xb43cf6583c0c15315c7e66f173af4be79ac40c38aad1fd92ec08638ab2026202",
14
+ range: "0x096a4cf18b3661e76b2c62b90785418345d52f45b272448794f123a4cb6b6416",
15
+ wheel: "0x0997852ded7e13301c42317004bc49704a893aa82997c5706cebee59053a31b7"
16
+ };
17
+
18
+ // src/configs/usdc-coin-type.ts
19
+ var DEFAULT_USDC_COIN_TYPE = "0xdba34672e30cb065b1f93e3a0e89fd79d1f22e12e55e88edbbcbac48609f4af0::usdc::USDC";
20
+ var DEFAULT_USDC_FLOWX_COIN_TYPE = "0xbde4ba4c7f1193c4f1f5b9e8a9c1cdec42c6f3f3a73cf40e1f4cb12cc7e6a4c0::usdc::USDC";
21
+
22
+ // src/utils/config.ts
23
+ var trim = (value) => value?.trim() ?? "";
24
+ function resolveSuigarConfig(options) {
25
+ const suiCoinType = normalizeStructTag(
26
+ options.coinTypes?.sui ?? SUI_TYPE_ARG
27
+ );
28
+ const usdcCoinType = normalizeStructTag(
29
+ options.coinTypes?.usdc ?? DEFAULT_USDC_COIN_TYPE
30
+ );
31
+ const usdcFlowxCoinType = normalizeStructTag(
32
+ options.coinTypes?.usdcFlowx ?? DEFAULT_USDC_FLOWX_COIN_TYPE
33
+ );
34
+ const explicitPriceInfoObjectIds = Object.fromEntries(
35
+ Object.entries(options.pyth?.priceInfoObjectIds ?? {}).map(
36
+ ([coinType, objectId]) => [normalizeStructTag(coinType), objectId]
37
+ )
38
+ );
39
+ return {
40
+ sweetHousePackageId: trim(options.sweetHousePackageId) || trim(DEFAULT_SWEETHOUSE_PACKAGE_ID),
41
+ coinTypes: {
42
+ sui: suiCoinType,
43
+ usdc: usdcCoinType,
44
+ usdcFlowx: usdcFlowxCoinType
45
+ },
46
+ gamesPackageId: {
47
+ coinflip: trim(options.gamesPackageId?.coinflip) || DEFAULT_GAMES_PACKAGE_ID.coinflip,
48
+ limbo: trim(options.gamesPackageId?.limbo) || DEFAULT_GAMES_PACKAGE_ID.limbo,
49
+ plinko: trim(options.gamesPackageId?.plinko) || DEFAULT_GAMES_PACKAGE_ID.plinko,
50
+ "pvp-coinflip": trim(options.gamesPackageId?.["pvp-coinflip"]) || DEFAULT_GAMES_PACKAGE_ID.pvp_coinflip,
51
+ range: trim(options.gamesPackageId?.range) || DEFAULT_GAMES_PACKAGE_ID.range,
52
+ wheel: trim(options.gamesPackageId?.wheel) || DEFAULT_GAMES_PACKAGE_ID.wheel
53
+ },
54
+ pyth: {
55
+ packageId: trim(options.pyth?.packageId) || void 0,
56
+ suiPriceInfoObjectId: trim(options.pyth?.suiPriceInfoObjectId),
57
+ usdcPriceInfoObjectId: trim(options.pyth?.usdcPriceInfoObjectId),
58
+ priceInfoObjectIds: explicitPriceInfoObjectIds
59
+ }
60
+ };
61
+ }
62
+ function resolvePythPriceInfoObjectId(config, coinType) {
63
+ const normalizedCoinType = normalizeStructTag(coinType);
64
+ const explicitObjectId = config.pyth.priceInfoObjectIds[normalizedCoinType];
65
+ if (explicitObjectId) {
66
+ return explicitObjectId;
67
+ }
68
+ if (normalizedCoinType === config.coinTypes.sui && config.pyth.suiPriceInfoObjectId) {
69
+ return config.pyth.suiPriceInfoObjectId;
70
+ }
71
+ if ((normalizedCoinType === config.coinTypes.usdc || normalizedCoinType === config.coinTypes.usdcFlowx) && config.pyth.usdcPriceInfoObjectId) {
72
+ return config.pyth.usdcPriceInfoObjectId;
73
+ }
74
+ throw new Error(
75
+ `Missing Pyth price object configuration for coin type ${coinType}`
76
+ );
77
+ }
78
+ function assertConfiguredBetGame(config, game) {
79
+ if (!config.gamesPackageId[game]) {
80
+ throw new Error(
81
+ `Missing required config for ${game}: gamesPackageId.${game}`
82
+ );
83
+ }
84
+ }
85
+ var ADDRESS_METADATA_KEYS = /* @__PURE__ */ new Set(["referrer", "partner"]);
86
+ var textEncoder = new TextEncoder();
87
+ var parseHexAddress = (value) => {
88
+ const trimmed = value.trim();
89
+ if (!trimmed) return null;
90
+ try {
91
+ const normalized = normalizeSuiAddress(trimmed).slice(2);
92
+ const bytes = new Uint8Array(normalized.length / 2);
93
+ for (let index = 0; index < normalized.length; index += 2) {
94
+ bytes[index / 2] = Number.parseInt(
95
+ normalized.slice(index, index + 2),
96
+ 16
97
+ );
98
+ }
99
+ return bytes;
100
+ } catch {
101
+ return null;
102
+ }
103
+ };
104
+ function encodeBetMetadata(metadata) {
105
+ const keys = [];
106
+ const values = [];
107
+ for (const [key, value] of Object.entries(metadata ?? {})) {
108
+ if (value === void 0 || value === null) {
109
+ continue;
110
+ }
111
+ let encodedValue;
112
+ if (value instanceof Uint8Array) {
113
+ encodedValue = Array.from(value);
114
+ } else if (Array.isArray(value)) {
115
+ encodedValue = value;
116
+ } else if (typeof value === "string" && ADDRESS_METADATA_KEYS.has(key)) {
117
+ encodedValue = Array.from(
118
+ parseHexAddress(value) ?? textEncoder.encode(value)
119
+ );
120
+ } else {
121
+ encodedValue = Array.from(textEncoder.encode(String(value)));
122
+ }
123
+ keys.push(key);
124
+ values.push(encodedValue);
125
+ }
126
+ return { keys, values };
127
+ }
128
+
129
+ // src/utils/shared.ts
130
+ var DEFAULT_GAS_BUDGET_MIST = 5e7;
131
+ var RANGE_FIXED_POINT_SCALE = 1e6;
132
+ var LIMBO_MULTIPLIER_SCALE = 100;
133
+ function toBigIntAmount(value, fieldName) {
134
+ if (typeof value === "bigint") {
135
+ if (value < 0n) {
136
+ throw new Error(`${fieldName} must be non-negative`);
137
+ }
138
+ return value;
139
+ }
140
+ if (!Number.isFinite(value) || value < 0) {
141
+ throw new Error(`${fieldName} must be a finite non-negative number`);
142
+ }
143
+ return BigInt(Math.trunc(value));
144
+ }
145
+ function toU8Number(value, fieldName) {
146
+ if (!Number.isInteger(value) || value < 0 || value > 255) {
147
+ throw new Error(`${fieldName} must be an integer between 0 and 255`);
148
+ }
149
+ return value;
150
+ }
151
+ var MOVE_STDLIB_ADDRESS = normalizeSuiAddress("0x1");
152
+ var SUI_FRAMEWORK_ADDRESS = normalizeSuiAddress("0x2");
153
+ function getPureBcsSchema(typeTag) {
154
+ const parsedTag = typeof typeTag === "string" ? TypeTagSerializer.parseFromStr(typeTag) : typeTag;
155
+ if ("u8" in parsedTag) {
156
+ return bcs.U8;
157
+ } else if ("u16" in parsedTag) {
158
+ return bcs.U16;
159
+ } else if ("u32" in parsedTag) {
160
+ return bcs.U32;
161
+ } else if ("u64" in parsedTag) {
162
+ return bcs.U64;
163
+ } else if ("u128" in parsedTag) {
164
+ return bcs.U128;
165
+ } else if ("u256" in parsedTag) {
166
+ return bcs.U256;
167
+ } else if ("address" in parsedTag) {
168
+ return bcs.Address;
169
+ } else if ("bool" in parsedTag) {
170
+ return bcs.Bool;
171
+ } else if ("vector" in parsedTag) {
172
+ const type = getPureBcsSchema(parsedTag.vector);
173
+ return type ? bcs.vector(type) : null;
174
+ } else if ("struct" in parsedTag) {
175
+ const structTag = parsedTag.struct;
176
+ const pkg = normalizeSuiAddress(structTag.address);
177
+ if (pkg === MOVE_STDLIB_ADDRESS) {
178
+ if ((structTag.module === "ascii" || structTag.module === "string") && structTag.name === "String") {
179
+ return bcs.String;
180
+ }
181
+ if (structTag.module === "option" && structTag.name === "Option") {
182
+ const type = getPureBcsSchema(structTag.typeParams[0]);
183
+ return type ? bcs.option(type) : null;
184
+ }
185
+ }
186
+ if (pkg === SUI_FRAMEWORK_ADDRESS && structTag.module === "object" && (structTag.name === "ID" || structTag.name === "UID")) {
187
+ return bcs.Address;
188
+ }
189
+ }
190
+ return null;
191
+ }
192
+ function normalizeMoveArguments(args, argTypes, parameterNames) {
193
+ Array.isArray(args) ? args.length : Object.keys(args).length;
194
+ const normalizedArgs = [];
195
+ let index = 0;
196
+ for (const [i, argType] of argTypes.entries()) {
197
+ if (argType === "0x2::clock::Clock") {
198
+ normalizedArgs.push((tx) => tx.object.clock());
199
+ continue;
200
+ }
201
+ if (argType === "0x2::random::Random") {
202
+ normalizedArgs.push((tx) => tx.object.random());
203
+ continue;
204
+ }
205
+ if (argType === "0x2::deny_list::DenyList") {
206
+ normalizedArgs.push((tx) => tx.object.denyList());
207
+ continue;
208
+ }
209
+ if (argType === "0x3::sui_system::SuiSystemState") {
210
+ normalizedArgs.push((tx) => tx.object.system());
211
+ continue;
212
+ }
213
+ let arg;
214
+ if (Array.isArray(args)) {
215
+ if (index >= args.length) {
216
+ throw new Error(
217
+ `Invalid number of arguments, expected at least ${index + 1}, got ${args.length}`
218
+ );
219
+ }
220
+ arg = args[index];
221
+ } else {
222
+ {
223
+ throw new Error(`Expected arguments to be passed as an array`);
224
+ }
225
+ }
226
+ index += 1;
227
+ if (typeof arg === "function" || isArgument(arg)) {
228
+ normalizedArgs.push(arg);
229
+ continue;
230
+ }
231
+ const type = argTypes[i];
232
+ const bcsType = type === null ? null : getPureBcsSchema(type);
233
+ if (bcsType) {
234
+ const bytes = bcsType.serialize(arg);
235
+ normalizedArgs.push((tx) => tx.pure(bytes));
236
+ continue;
237
+ }
238
+ if (typeof arg === "string") {
239
+ normalizedArgs.push((tx) => tx.object(arg));
240
+ continue;
241
+ }
242
+ throw new Error(`Invalid argument ${stringify(arg)} for type ${type}`);
243
+ }
244
+ return normalizedArgs;
245
+ }
246
+ var MoveStruct = class extends BcsStruct {
247
+ async get({
248
+ objectId,
249
+ ...options
250
+ }) {
251
+ const [res] = await this.getMany({
252
+ ...options,
253
+ objectIds: [objectId]
254
+ });
255
+ return res;
256
+ }
257
+ async getMany({
258
+ client,
259
+ ...options
260
+ }) {
261
+ const response = await client.core.getObjects({
262
+ ...options,
263
+ include: {
264
+ ...options.include,
265
+ content: true
266
+ }
267
+ });
268
+ return response.objects.map((obj) => {
269
+ if (obj instanceof Error) {
270
+ throw obj;
271
+ }
272
+ return {
273
+ ...obj,
274
+ json: this.parse(obj.content)
275
+ };
276
+ });
277
+ }
278
+ };
279
+ function stringify(val) {
280
+ if (typeof val === "object") {
281
+ return JSON.stringify(val, (val2) => val2);
282
+ }
283
+ if (typeof val === "bigint") {
284
+ return val.toString();
285
+ }
286
+ return val;
287
+ }
288
+
289
+ // src/contracts/coinflip/coinflip.ts
290
+ function play(options) {
291
+ const packageAddress = options.package ?? "0xb35c5f286c443752afc8ccb40125a578a4f32df35617170ccfa17fe180ab80ea";
292
+ const argumentsTypes = [
293
+ null,
294
+ "u64",
295
+ null,
296
+ "u64",
297
+ "bool",
298
+ "vector<0x1::string::String>",
299
+ "vector<vector<u8>>",
300
+ null,
301
+ "0x2::clock::Clock",
302
+ "0x2::random::Random"
303
+ ];
304
+ return (tx) => tx.moveCall({
305
+ package: packageAddress,
306
+ module: "coinflip",
307
+ function: "play",
308
+ arguments: normalizeMoveArguments(options.arguments, argumentsTypes),
309
+ typeArguments: options.typeArguments
310
+ });
311
+ }
312
+ function createBaseGameTransaction({
313
+ config,
314
+ game,
315
+ owner,
316
+ sender,
317
+ gasBudget
318
+ }) {
319
+ assertConfiguredBetGame(config, game);
320
+ const tx = new Transaction();
321
+ tx.setSenderIfNotSet(normalizeSuiAddress(sender ?? owner));
322
+ tx.setGasBudgetIfNotSet(gasBudget ?? DEFAULT_GAS_BUDGET_MIST);
323
+ return tx;
324
+ }
325
+ function buildSharedStandardGameBetCall({
326
+ config,
327
+ owner,
328
+ sender,
329
+ coinType,
330
+ stake,
331
+ cashStake,
332
+ betCount,
333
+ metadata,
334
+ allowGasCoinShortcut = true,
335
+ buildRewardCoin
336
+ }) {
337
+ return (tx) => {
338
+ const normalizedOwner = normalizeSuiAddress(sender ?? owner);
339
+ const normalizedCoinType = normalizeStructTag(coinType);
340
+ const resolvedStake = toBigIntAmount(stake, "stake");
341
+ const resolvedCashStake = toBigIntAmount(cashStake ?? stake, "cashStake");
342
+ const resolvedBetCount = toBigIntAmount(betCount ?? 1, "betCount");
343
+ const encodedMetadata = encodeBetMetadata(metadata);
344
+ const pythPriceInfoObjectId = resolvePythPriceInfoObjectId(
345
+ config,
346
+ normalizedCoinType
347
+ );
348
+ const betCoin = tx.coin({
349
+ type: normalizedCoinType,
350
+ balance: resolvedCashStake,
351
+ useGasCoin: allowGasCoinShortcut
352
+ });
353
+ const rewardCoin = buildRewardCoin({
354
+ tx,
355
+ config,
356
+ owner: normalizedOwner,
357
+ coinType: normalizedCoinType,
358
+ stake: resolvedStake,
359
+ cashStake: resolvedCashStake,
360
+ betCount: resolvedBetCount,
361
+ metadata: encodedMetadata,
362
+ pythPriceInfoObjectId,
363
+ betCoin
364
+ });
365
+ tx.transferObjects([rewardCoin], tx.pure.address(normalizedOwner));
366
+ return rewardCoin;
367
+ };
368
+ }
369
+ function buildSharedStandardGameBetTransaction(options) {
370
+ const tx = createBaseGameTransaction(options);
371
+ tx.add(buildSharedStandardGameBetCall(options));
372
+ return tx;
373
+ }
374
+
375
+ // src/transactions/coinflip.ts
376
+ function buildCoinflipTransaction(options) {
377
+ return buildSharedStandardGameBetTransaction({
378
+ ...options,
379
+ game: "coinflip",
380
+ buildRewardCoin: ({
381
+ tx,
382
+ config,
383
+ coinType,
384
+ stake,
385
+ betCount,
386
+ metadata,
387
+ pythPriceInfoObjectId,
388
+ betCoin
389
+ }) => play({
390
+ package: config.gamesPackageId.coinflip,
391
+ typeArguments: [coinType],
392
+ arguments: [
393
+ config.sweetHousePackageId,
394
+ stake,
395
+ betCoin,
396
+ betCount,
397
+ options.side === "tails",
398
+ metadata.keys,
399
+ metadata.values,
400
+ pythPriceInfoObjectId
401
+ ]
402
+ })(tx)
403
+ });
404
+ }
405
+
406
+ // src/contracts/limbo/limbo.ts
407
+ function play2(options) {
408
+ const packageAddress = options.package ?? "0x96c7841b9b32c59a219760fd656f1c3aceb53cc74a68ec9844a3a696374309f4";
409
+ const argumentsTypes = [
410
+ null,
411
+ "u64",
412
+ null,
413
+ "u64",
414
+ "u64",
415
+ "u64",
416
+ "vector<0x1::string::String>",
417
+ "vector<vector<u8>>",
418
+ null,
419
+ "0x2::clock::Clock",
420
+ "0x2::random::Random"
421
+ ];
422
+ return (tx) => tx.moveCall({
423
+ package: packageAddress,
424
+ module: "limbo",
425
+ function: "play",
426
+ arguments: normalizeMoveArguments(options.arguments, argumentsTypes),
427
+ typeArguments: options.typeArguments
428
+ });
429
+ }
430
+
431
+ // src/transactions/limbo.ts
432
+ function buildLimboTransaction(options) {
433
+ const scale = options.scale ?? LIMBO_MULTIPLIER_SCALE;
434
+ const numerator = Math.round(options.targetMultiplier * scale);
435
+ return buildSharedStandardGameBetTransaction({
436
+ ...options,
437
+ game: "limbo",
438
+ buildRewardCoin: ({
439
+ tx,
440
+ config,
441
+ coinType,
442
+ stake,
443
+ betCount,
444
+ metadata,
445
+ pythPriceInfoObjectId,
446
+ betCoin
447
+ }) => play2({
448
+ package: config.gamesPackageId.limbo,
449
+ typeArguments: [coinType],
450
+ arguments: [
451
+ config.sweetHousePackageId,
452
+ stake,
453
+ betCoin,
454
+ betCount,
455
+ BigInt(numerator),
456
+ BigInt(scale),
457
+ metadata.keys,
458
+ metadata.values,
459
+ pythPriceInfoObjectId
460
+ ]
461
+ })(tx)
462
+ });
463
+ }
464
+
465
+ // src/contracts/plinko/plinko.ts
466
+ function play3(options) {
467
+ const packageAddress = options.package ?? "0xd3dd2200883af10811724f0bed97591ad155a02efd6332d471ff8b346030dfb7";
468
+ const argumentsTypes = [
469
+ null,
470
+ "u64",
471
+ null,
472
+ "u64",
473
+ "u8",
474
+ "vector<0x1::string::String>",
475
+ "vector<vector<u8>>",
476
+ null,
477
+ "0x2::clock::Clock",
478
+ "0x2::random::Random"
479
+ ];
480
+ return (tx) => tx.moveCall({
481
+ package: packageAddress,
482
+ module: "plinko",
483
+ function: "play",
484
+ arguments: normalizeMoveArguments(options.arguments, argumentsTypes),
485
+ typeArguments: options.typeArguments
486
+ });
487
+ }
488
+
489
+ // src/transactions/plinko.ts
490
+ function buildPlinkoTransaction(options) {
491
+ const configId = toU8Number(options.configId, "configId");
492
+ return buildSharedStandardGameBetTransaction({
493
+ ...options,
494
+ game: "plinko",
495
+ buildRewardCoin: ({
496
+ tx,
497
+ config,
498
+ coinType,
499
+ stake,
500
+ betCount,
501
+ metadata,
502
+ pythPriceInfoObjectId,
503
+ betCoin
504
+ }) => play3({
505
+ package: config.gamesPackageId.plinko,
506
+ typeArguments: [coinType],
507
+ arguments: [
508
+ config.sweetHousePackageId,
509
+ stake,
510
+ betCoin,
511
+ betCount,
512
+ configId,
513
+ metadata.keys,
514
+ metadata.values,
515
+ pythPriceInfoObjectId
516
+ ]
517
+ })(tx)
518
+ });
519
+ }
520
+ var $moduleName = "0x0000000000000000000000000000000000000000000000000000000000000001::type_name";
521
+ var TypeName = new MoveStruct({ name: `${$moduleName}::TypeName`, fields: {
522
+ name: bcs.string()
523
+ } });
524
+
525
+ // src/contracts/pvp-coinflip/pvp_coinflip.ts
526
+ var $moduleName2 = "0xb43cf6583c0c15315c7e66f173af4be79ac40c38aad1fd92ec08638ab2026202::pvp_coinflip";
527
+ function GameCreatedEvent(...typeParameters) {
528
+ return new MoveStruct({ name: `${$moduleName2}::GameCreatedEvent<${typeParameters[0].name}>`, fields: {
529
+ game_id: bcs.Address,
530
+ creator: bcs.Address,
531
+ creator_is_tails: bcs.bool(),
532
+ is_private: bcs.bool(),
533
+ joiner_is_tails: bcs.bool(),
534
+ stake_per_player: bcs.u64(),
535
+ house_edge_bps: bcs.u64(),
536
+ coin_type: TypeName
537
+ } });
538
+ }
539
+ function GameResolvedEvent(...typeParameters) {
540
+ return new MoveStruct({ name: `${$moduleName2}::GameResolvedEvent<${typeParameters[0].name}>`, fields: {
541
+ game_id: bcs.Address,
542
+ creator: bcs.Address,
543
+ joiner: bcs.Address,
544
+ winner: bcs.Address,
545
+ creator_is_tails: bcs.bool(),
546
+ is_private: bcs.bool(),
547
+ joiner_is_tails: bcs.bool(),
548
+ stake_per_player: bcs.u64(),
549
+ total_pot: bcs.u64(),
550
+ house_edge_amount: bcs.u64(),
551
+ payout_amount: bcs.u64(),
552
+ coin_type: TypeName
553
+ } });
554
+ }
555
+ function GameCancelledEvent(...typeParameters) {
556
+ return new MoveStruct({ name: `${$moduleName2}::GameCancelledEvent<${typeParameters[0].name}>`, fields: {
557
+ game_id: bcs.Address,
558
+ creator: bcs.Address,
559
+ creator_is_tails: bcs.bool(),
560
+ is_private: bcs.bool(),
561
+ stake_per_player: bcs.u64(),
562
+ coin_type: TypeName
563
+ } });
564
+ }
565
+ function createGame(options) {
566
+ const packageAddress = options.package ?? "0xb43cf6583c0c15315c7e66f173af4be79ac40c38aad1fd92ec08638ab2026202";
567
+ const argumentsTypes = [
568
+ null,
569
+ null,
570
+ "bool",
571
+ "bool",
572
+ "vector<0x1::string::String>",
573
+ "vector<vector<u8>>"
574
+ ];
575
+ return (tx) => tx.moveCall({
576
+ package: packageAddress,
577
+ module: "pvp_coinflip",
578
+ function: "create_game",
579
+ arguments: normalizeMoveArguments(options.arguments, argumentsTypes),
580
+ typeArguments: options.typeArguments
581
+ });
582
+ }
583
+ function joinGame(options) {
584
+ const packageAddress = options.package ?? "0xb43cf6583c0c15315c7e66f173af4be79ac40c38aad1fd92ec08638ab2026202";
585
+ const argumentsTypes = [
586
+ "0x2::object::ID",
587
+ null,
588
+ null,
589
+ "vector<0x1::string::String>",
590
+ "vector<vector<u8>>",
591
+ null,
592
+ "0x2::clock::Clock",
593
+ "0x2::random::Random"
594
+ ];
595
+ return (tx) => tx.moveCall({
596
+ package: packageAddress,
597
+ module: "pvp_coinflip",
598
+ function: "join_game",
599
+ arguments: normalizeMoveArguments(options.arguments, argumentsTypes),
600
+ typeArguments: options.typeArguments
601
+ });
602
+ }
603
+ function cancelGame(options) {
604
+ const packageAddress = options.package ?? "0xb43cf6583c0c15315c7e66f173af4be79ac40c38aad1fd92ec08638ab2026202";
605
+ const argumentsTypes = [
606
+ "0x2::object::ID",
607
+ null
608
+ ];
609
+ return (tx) => tx.moveCall({
610
+ package: packageAddress,
611
+ module: "pvp_coinflip",
612
+ function: "cancel_game",
613
+ arguments: normalizeMoveArguments(options.arguments, argumentsTypes),
614
+ typeArguments: options.typeArguments
615
+ });
616
+ }
617
+
618
+ // src/transactions/pvp-coinflip.ts
619
+ function buildPvPCoinflipTransaction(action, options) {
620
+ const tx = createBaseGameTransaction({
621
+ ...options,
622
+ game: "pvp-coinflip"
623
+ });
624
+ const normalizedCoinType = normalizeStructTag(options.coinType);
625
+ const encodedMetadata = encodeBetMetadata(options.metadata);
626
+ switch (action) {
627
+ case "create": {
628
+ const createOptions = options;
629
+ const stake = toBigIntAmount(createOptions.stake, "stake");
630
+ const betCoin = tx.coin({
631
+ type: normalizedCoinType,
632
+ balance: stake,
633
+ useGasCoin: createOptions.allowGasCoinShortcut
634
+ });
635
+ tx.add(
636
+ createGame({
637
+ package: createOptions.config.gamesPackageId["pvp-coinflip"],
638
+ typeArguments: [normalizedCoinType],
639
+ arguments: [
640
+ createOptions.config.sweetHousePackageId,
641
+ betCoin,
642
+ createOptions.side === "tails",
643
+ Boolean(createOptions.isPrivate),
644
+ encodedMetadata.keys,
645
+ encodedMetadata.values
646
+ ]
647
+ })
648
+ );
649
+ return tx;
650
+ }
651
+ case "join": {
652
+ const joinOptions = options;
653
+ const stake = toBigIntAmount(joinOptions.stake, "stake");
654
+ const betCoin = tx.coin({
655
+ type: normalizedCoinType,
656
+ balance: stake,
657
+ useGasCoin: joinOptions.allowGasCoinShortcut
658
+ });
659
+ tx.add(
660
+ joinGame({
661
+ package: joinOptions.config.gamesPackageId["pvp-coinflip"],
662
+ typeArguments: [normalizedCoinType],
663
+ arguments: [
664
+ joinOptions.gameId,
665
+ joinOptions.config.sweetHousePackageId,
666
+ betCoin,
667
+ encodedMetadata.keys,
668
+ encodedMetadata.values,
669
+ joinOptions.extraObjectId
670
+ ]
671
+ })
672
+ );
673
+ return tx;
674
+ }
675
+ case "cancel": {
676
+ const cancelOptions = options;
677
+ tx.add(
678
+ cancelGame({
679
+ package: cancelOptions.config.gamesPackageId["pvp-coinflip"],
680
+ typeArguments: [normalizedCoinType],
681
+ arguments: [
682
+ cancelOptions.gameId,
683
+ cancelOptions.config.sweetHousePackageId
684
+ ]
685
+ })
686
+ );
687
+ return tx;
688
+ }
689
+ default:
690
+ throw new Error(`Unsupported PvP coinflip action: ${action}`);
691
+ }
692
+ }
693
+
694
+ // src/contracts/range/range.ts
695
+ function play4(options) {
696
+ const packageAddress = options.package ?? "0x096a4cf18b3661e76b2c62b90785418345d52f45b272448794f123a4cb6b6416";
697
+ const argumentsTypes = [
698
+ null,
699
+ "u64",
700
+ null,
701
+ "u64",
702
+ "u64",
703
+ "u64",
704
+ "bool",
705
+ "vector<0x1::string::String>",
706
+ "vector<vector<u8>>",
707
+ null,
708
+ "0x2::clock::Clock",
709
+ "0x2::random::Random"
710
+ ];
711
+ return (tx) => tx.moveCall({
712
+ package: packageAddress,
713
+ module: "range",
714
+ function: "play",
715
+ arguments: normalizeMoveArguments(options.arguments, argumentsTypes),
716
+ typeArguments: options.typeArguments
717
+ });
718
+ }
719
+
720
+ // src/transactions/range.ts
721
+ function buildRangeTransaction(options) {
722
+ const scale = options.scale ?? RANGE_FIXED_POINT_SCALE;
723
+ const leftPoint = Math.round(options.leftPoint * scale);
724
+ const rightPoint = Math.round(options.rightPoint * scale);
725
+ return buildSharedStandardGameBetTransaction({
726
+ ...options,
727
+ game: "range",
728
+ buildRewardCoin: ({
729
+ tx,
730
+ config,
731
+ coinType,
732
+ stake,
733
+ betCount,
734
+ metadata,
735
+ pythPriceInfoObjectId,
736
+ betCoin
737
+ }) => play4({
738
+ package: config.gamesPackageId.range,
739
+ typeArguments: [coinType],
740
+ arguments: [
741
+ config.sweetHousePackageId,
742
+ stake,
743
+ betCoin,
744
+ betCount,
745
+ BigInt(leftPoint),
746
+ BigInt(rightPoint),
747
+ Boolean(options.outOfRange),
748
+ metadata.keys,
749
+ metadata.values,
750
+ pythPriceInfoObjectId
751
+ ]
752
+ })(tx)
753
+ });
754
+ }
755
+
756
+ // src/contracts/wheel/wheel.ts
757
+ function play5(options) {
758
+ const packageAddress = options.package ?? "0x0997852ded7e13301c42317004bc49704a893aa82997c5706cebee59053a31b7";
759
+ const argumentsTypes = [
760
+ null,
761
+ "u64",
762
+ null,
763
+ "u64",
764
+ "u8",
765
+ "vector<0x1::string::String>",
766
+ "vector<vector<u8>>",
767
+ null,
768
+ "0x2::clock::Clock",
769
+ "0x2::random::Random"
770
+ ];
771
+ return (tx) => tx.moveCall({
772
+ package: packageAddress,
773
+ module: "wheel",
774
+ function: "play",
775
+ arguments: normalizeMoveArguments(options.arguments, argumentsTypes),
776
+ typeArguments: options.typeArguments
777
+ });
778
+ }
779
+
780
+ // src/transactions/wheel.ts
781
+ function buildWheelTransaction(options) {
782
+ const configId = toU8Number(options.configId, "configId");
783
+ return buildSharedStandardGameBetTransaction({
784
+ ...options,
785
+ game: "wheel",
786
+ buildRewardCoin: ({
787
+ tx,
788
+ config,
789
+ coinType,
790
+ stake,
791
+ betCount,
792
+ metadata,
793
+ pythPriceInfoObjectId,
794
+ betCoin
795
+ }) => play5({
796
+ package: config.gamesPackageId.wheel,
797
+ typeArguments: [coinType],
798
+ arguments: [
799
+ config.sweetHousePackageId,
800
+ stake,
801
+ betCoin,
802
+ betCount,
803
+ configId,
804
+ metadata.keys,
805
+ metadata.values,
806
+ pythPriceInfoObjectId
807
+ ]
808
+ })(tx)
809
+ });
810
+ }
811
+ var $moduleName3 = "0x0000000000000000000000000000000000000000000000000000000000000001::type_name";
812
+ var TypeName2 = new MoveStruct({ name: `${$moduleName3}::TypeName`, fields: {
813
+ name: bcs.string()
814
+ } });
815
+ var $moduleName4 = "0xf391858d2a08473e8d4defcc8df89976bd7b123d3865c6b9341b237f7853dbbc::i64";
816
+ var I64 = new MoveStruct({ name: `${$moduleName4}::I64`, fields: {
817
+ bits: bcs.u64()
818
+ } });
819
+
820
+ // src/contracts/core/float.ts
821
+ var $moduleName5 = "0xf391858d2a08473e8d4defcc8df89976bd7b123d3865c6b9341b237f7853dbbc::float";
822
+ var Float = new MoveStruct({ name: `${$moduleName5}::Float`, fields: {
823
+ is_negative: bcs.bool(),
824
+ exp: I64,
825
+ mant: bcs.u64()
826
+ } });
827
+ var $moduleName6 = "0x2::vec_map";
828
+ function Entry(...typeParameters) {
829
+ return new MoveStruct({ name: `${$moduleName6}::Entry<${typeParameters[0].name}, ${typeParameters[1].name}>`, fields: {
830
+ key: typeParameters[0],
831
+ value: typeParameters[1]
832
+ } });
833
+ }
834
+ function VecMap(...typeParameters) {
835
+ return new MoveStruct({ name: `${$moduleName6}::VecMap<${typeParameters[0].name}, ${typeParameters[1].name}>`, fields: {
836
+ contents: bcs.vector(Entry(typeParameters[0], typeParameters[1]))
837
+ } });
838
+ }
839
+
840
+ // src/contracts/core/core.ts
841
+ var $moduleName7 = "0xf391858d2a08473e8d4defcc8df89976bd7b123d3865c6b9341b237f7853dbbc::core";
842
+ function BetResultEvent(...typeParameters) {
843
+ return new MoveStruct({ name: `${$moduleName7}::BetResultEvent<${typeParameters[0].name}>`, fields: {
844
+ player: bcs.Address,
845
+ coin_type: TypeName2,
846
+ stake_amount: bcs.u64(),
847
+ unsafe_oracle_usd_coin_price: Float,
848
+ adjusted_oracle_usd_coin_price: Float,
849
+ outcome_amount: bcs.u64(),
850
+ game_details: VecMap(bcs.string(), bcs.vector(bcs.u8())),
851
+ metadata: VecMap(bcs.string(), bcs.vector(bcs.u8()))
852
+ } });
853
+ }
854
+
855
+ // src/client.ts
856
+ function suigar({
857
+ name = "suigar",
858
+ ...options
859
+ } = {}) {
860
+ return {
861
+ name,
862
+ register: (client) => {
863
+ return new SuigarClient({ client, options });
864
+ }
865
+ };
866
+ }
867
+ var SuigarClient = class {
868
+ #client;
869
+ #config;
870
+ constructor({
871
+ client,
872
+ options
873
+ }) {
874
+ this.#client = client;
875
+ this.#config = resolveSuigarConfig(options);
876
+ }
877
+ /**
878
+ * Builds a transaction with the configured Sui client and returns the BCS bytes as a base64 string.
879
+ *
880
+ * @param transaction Transaction block to serialize.
881
+ * @returns Base64-encoded transaction bytes ready to send over the wire.
882
+ */
883
+ async serializeTransactionToBase64(transaction) {
884
+ const bytes = await transaction.build({ client: this.#client });
885
+ return Buffer.from(bytes).toString("base64");
886
+ }
887
+ /**
888
+ * BCS struct constructors for decoding Suigar events emitted on-chain.
889
+ */
890
+ bcs = {
891
+ /**
892
+ * Event emitted at the end of a standard game (e.g., Coinflip, Limbo), containing the result and payout information.
893
+ */
894
+ BetResultEvent,
895
+ /**
896
+ * Event emitted when a PvP Coinflip game is created, containing the game configuration and initial state.
897
+ */
898
+ PvPCoinflipGameCreated: GameCreatedEvent,
899
+ /**
900
+ * Event emitted when a PvP Coinflip game is resolved, containing the final outcome.
901
+ */
902
+ PvPCoinflipGameResolved: GameResolvedEvent,
903
+ /**
904
+ * Event emitted when a PvP Coinflip game is cancelled.
905
+ */
906
+ PvPCoinflipGameCancelled: GameCancelledEvent
907
+ };
908
+ /**
909
+ * Transaction builders for Suigar games.
910
+ */
911
+ tx = {
912
+ /**
913
+ * Creates a standard game transaction for the provided game id.
914
+ *
915
+ * @param gameId Supported standard game identifier.
916
+ * @param options Transaction builder options for the selected game.
917
+ * @returns Prepared transaction for the selected game.
918
+ */
919
+ createBetTransaction: (gameId, options) => {
920
+ switch (gameId) {
921
+ case "coinflip":
922
+ return buildCoinflipTransaction({
923
+ ...options,
924
+ config: this.#config
925
+ });
926
+ case "limbo":
927
+ return buildLimboTransaction({
928
+ ...options,
929
+ config: this.#config
930
+ });
931
+ case "plinko":
932
+ return buildPlinkoTransaction({
933
+ ...options,
934
+ config: this.#config
935
+ });
936
+ case "range":
937
+ return buildRangeTransaction({
938
+ ...options,
939
+ config: this.#config
940
+ });
941
+ case "wheel":
942
+ return buildWheelTransaction({
943
+ ...options,
944
+ config: this.#config
945
+ });
946
+ default:
947
+ throw new Error(`Unsupported game: ${gameId}`);
948
+ }
949
+ },
950
+ /**
951
+ * Creates a PvP coinflip transaction for the requested action.
952
+ *
953
+ * @param action PvP coinflip action to perform.
954
+ * @param options Transaction builder options for the selected action.
955
+ * @returns Prepared PvP coinflip transaction.
956
+ */
957
+ createPvPCoinflipTransaction: (action, options) => {
958
+ return buildPvPCoinflipTransaction(action, {
959
+ ...options,
960
+ config: this.#config
961
+ });
962
+ }
963
+ };
964
+ };
965
+
966
+ export { SuigarClient, suigar };