@suigar/sdk 2.0.0-beta.0 → 2.0.0-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,289 +1,365 @@
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';
1
+ import { MoveStruct, Float, parseCoinType, toBigInt, toU8, DEFAULT_GAS_BUDGET_MIST, normalizeMoveArguments, DEFAULT_LIMBO_MULTIPLIER_SCALE, DEFAULT_RANGE_SCALE } from './chunk-PPUDLRHA.js';
2
+ import { toBase64, normalizeStructTag, normalizeSuiAddress, fromHex } from '@mysten/sui/utils';
3
+ import { bcs } from '@mysten/sui/bcs';
4
+ import { Transaction } from '@mysten/sui/transactions';
4
5
 
5
- // src/utils/config.ts
6
+ var $moduleName = "0x0000000000000000000000000000000000000000000000000000000000000001::type_name";
7
+ var TypeName = new MoveStruct({
8
+ name: `${$moduleName}::TypeName`,
9
+ fields: {
10
+ name: bcs.string()
11
+ }
12
+ });
13
+ var $moduleName2 = "0x2::vec_map";
14
+ function Entry(...typeParameters) {
15
+ return new MoveStruct({
16
+ name: `${$moduleName2}::Entry<${typeParameters[0].name}, ${typeParameters[1].name}>`,
17
+ fields: {
18
+ key: typeParameters[0],
19
+ value: typeParameters[1]
20
+ }
21
+ });
22
+ }
23
+ function VecMap(...typeParameters) {
24
+ return new MoveStruct({
25
+ name: `${$moduleName2}::VecMap<${typeParameters[0].name}, ${typeParameters[1].name}>`,
26
+ fields: {
27
+ contents: bcs.vector(Entry(typeParameters[0], typeParameters[1]))
28
+ }
29
+ });
30
+ }
6
31
 
7
- // src/configs/package-id.ts
8
- var DEFAULT_SWEETHOUSE_PACKAGE_ID = "0xb7f64e5a273aba1ede00caa0a6f8027cc7490c279d17eab12e7100ed20660603";
9
- var DEFAULT_GAMES_PACKAGE_ID = {
32
+ // src/contracts/core/core.ts
33
+ var $moduleName3 = "0xf391858d2a08473e8d4defcc8df89976bd7b123d3865c6b9341b237f7853dbbc::core";
34
+ var BetResultEvent = new MoveStruct({
35
+ name: `${$moduleName3}::BetResultEvent<phantom T0>`,
36
+ fields: {
37
+ player: bcs.Address,
38
+ coin_type: TypeName,
39
+ stake_amount: bcs.u64(),
40
+ unsafe_oracle_usd_coin_price: Float,
41
+ adjusted_oracle_usd_coin_price: Float,
42
+ outcome_amount: bcs.u64(),
43
+ game_details: VecMap(bcs.string(), bcs.vector(bcs.u8())),
44
+ metadata: VecMap(bcs.string(), bcs.vector(bcs.u8()))
45
+ }
46
+ });
47
+ var $moduleName4 = "0x0000000000000000000000000000000000000000000000000000000000000001::type_name";
48
+ var TypeName2 = new MoveStruct({
49
+ name: `${$moduleName4}::TypeName`,
50
+ fields: {
51
+ name: bcs.string()
52
+ }
53
+ });
54
+ var $moduleName5 = "0x2::balance";
55
+ var Balance = new MoveStruct({
56
+ name: `${$moduleName5}::Balance<phantom T0>`,
57
+ fields: {
58
+ value: bcs.u64()
59
+ }
60
+ });
61
+ var $moduleName6 = "0x2::vec_map";
62
+ function Entry2(...typeParameters) {
63
+ return new MoveStruct({
64
+ name: `${$moduleName6}::Entry<${typeParameters[0].name}, ${typeParameters[1].name}>`,
65
+ fields: {
66
+ key: typeParameters[0],
67
+ value: typeParameters[1]
68
+ }
69
+ });
70
+ }
71
+ function VecMap2(...typeParameters) {
72
+ return new MoveStruct({
73
+ name: `${$moduleName6}::VecMap<${typeParameters[0].name}, ${typeParameters[1].name}>`,
74
+ fields: {
75
+ contents: bcs.vector(Entry2(typeParameters[0], typeParameters[1]))
76
+ }
77
+ });
78
+ }
79
+
80
+ // src/contracts/pvp-coinflip/pvp_coinflip.ts
81
+ var $moduleName7 = "0xb43cf6583c0c15315c7e66f173af4be79ac40c38aad1fd92ec08638ab2026202::pvp_coinflip";
82
+ var Game = new MoveStruct({
83
+ name: `${$moduleName7}::Game<phantom T0>`,
84
+ fields: {
85
+ id: bcs.Address,
86
+ creator: bcs.Address,
87
+ creator_is_tails: bcs.bool(),
88
+ is_private: bcs.bool(),
89
+ creator_metadata: VecMap2(bcs.string(), bcs.vector(bcs.u8())),
90
+ joiner: bcs.Address,
91
+ winner: bcs.Address,
92
+ stake_per_player: bcs.u64(),
93
+ house_edge_bps: bcs.u64(),
94
+ stake_pot: Balance
95
+ }
96
+ });
97
+ var GameCreatedEvent = new MoveStruct({
98
+ name: `${$moduleName7}::GameCreatedEvent<phantom T0>`,
99
+ fields: {
100
+ game_id: bcs.Address,
101
+ creator: bcs.Address,
102
+ creator_is_tails: bcs.bool(),
103
+ is_private: bcs.bool(),
104
+ joiner_is_tails: bcs.bool(),
105
+ stake_per_player: bcs.u64(),
106
+ house_edge_bps: bcs.u64(),
107
+ coin_type: TypeName2
108
+ }
109
+ });
110
+ var GameResolvedEvent = new MoveStruct({
111
+ name: `${$moduleName7}::GameResolvedEvent<phantom T0>`,
112
+ fields: {
113
+ game_id: bcs.Address,
114
+ creator: bcs.Address,
115
+ joiner: bcs.Address,
116
+ winner: bcs.Address,
117
+ creator_is_tails: bcs.bool(),
118
+ is_private: bcs.bool(),
119
+ joiner_is_tails: bcs.bool(),
120
+ stake_per_player: bcs.u64(),
121
+ total_pot: bcs.u64(),
122
+ house_edge_amount: bcs.u64(),
123
+ payout_amount: bcs.u64(),
124
+ coin_type: TypeName2
125
+ }
126
+ });
127
+ var GameCancelledEvent = new MoveStruct({
128
+ name: `${$moduleName7}::GameCancelledEvent<phantom T0>`,
129
+ fields: {
130
+ game_id: bcs.Address,
131
+ creator: bcs.Address,
132
+ creator_is_tails: bcs.bool(),
133
+ is_private: bcs.bool(),
134
+ stake_per_player: bcs.u64(),
135
+ coin_type: TypeName2
136
+ }
137
+ });
138
+ function createGame(options) {
139
+ const packageAddress = options.package ?? "0xb43cf6583c0c15315c7e66f173af4be79ac40c38aad1fd92ec08638ab2026202";
140
+ const argumentsTypes = [
141
+ null,
142
+ null,
143
+ "bool",
144
+ "bool",
145
+ "vector<0x1::string::String>",
146
+ "vector<vector<u8>>"
147
+ ];
148
+ return (tx) => tx.moveCall({
149
+ package: packageAddress,
150
+ module: "pvp_coinflip",
151
+ function: "create_game",
152
+ arguments: normalizeMoveArguments(options.arguments, argumentsTypes),
153
+ typeArguments: options.typeArguments
154
+ });
155
+ }
156
+ function joinGame(options) {
157
+ const packageAddress = options.package ?? "0xb43cf6583c0c15315c7e66f173af4be79ac40c38aad1fd92ec08638ab2026202";
158
+ const argumentsTypes = [
159
+ "0x2::object::ID",
160
+ null,
161
+ null,
162
+ "vector<0x1::string::String>",
163
+ "vector<vector<u8>>",
164
+ null,
165
+ "0x2::clock::Clock",
166
+ "0x2::random::Random"
167
+ ];
168
+ return (tx) => tx.moveCall({
169
+ package: packageAddress,
170
+ module: "pvp_coinflip",
171
+ function: "join_game",
172
+ arguments: normalizeMoveArguments(options.arguments, argumentsTypes),
173
+ typeArguments: options.typeArguments
174
+ });
175
+ }
176
+ function cancelGame(options) {
177
+ const packageAddress = options.package ?? "0xb43cf6583c0c15315c7e66f173af4be79ac40c38aad1fd92ec08638ab2026202";
178
+ const argumentsTypes = ["0x2::object::ID", null];
179
+ return (tx) => tx.moveCall({
180
+ package: packageAddress,
181
+ module: "pvp_coinflip",
182
+ function: "cancel_game",
183
+ arguments: normalizeMoveArguments(options.arguments, argumentsTypes),
184
+ typeArguments: options.typeArguments
185
+ });
186
+ }
187
+
188
+ // src/configs/package.mainnet.ts
189
+ var MAINNET_PACKAGE_IDS = {
190
+ sweetHouse: "0xa1549d73230118716bc08865b8d62454f360ddaf40eee2158e458e52125d4ef1",
191
+ core: "0xcbb0929f21450013ebe5e86e7139f2409da2e3ed212c51126a7e6448b795a43f",
192
+ coinflip: "0xca96885371150f55653f7fab9e9b146f5a19698b1002bdff42159ea9d2ba7d7e",
193
+ limbo: "0x89db6a55ad4e650cad641b6f9fd90b391b22b1d9adbb2cabbfeb94a9eeda7026",
194
+ plinko: "0x74a73daff11c11ed05299c93ed770c62ec4dc6756fa99e271e251c2399f49fef",
195
+ pvpCoinflip: "0x29162faf01a8135630e0a32bbe4ce47f69607b24dbb1edea3800861f91d0030a",
196
+ range: "0xd19e32b0f2a5e541fbd345b4602f8a93a2eee25c16029595b6fef0b1e0461a54",
197
+ wheel: "0x6791eac73fe7bf463b7f3b1ea391df265fbc1b96201270664a5a11e2441e9955"
198
+ };
199
+ var MAINNET_COIN_TYPES = {
200
+ sui: "0x2::sui::SUI",
201
+ usdc: "0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC"
202
+ };
203
+ var MAINNET_PRICE_INFO_OBJECT_IDS = {
204
+ sui: "0x801dbc2f0053d34734814b2d6df491ce7807a725fe9a01ad74a07e9c51396c37",
205
+ usdc: "0x5dec622733a204ca27f5a90d8c2fad453cc6665186fd5dff13a83d0b6c9027ab"
206
+ };
207
+
208
+ // src/configs/package.testnet.ts
209
+ var TESTNET_PACKAGE_IDS = {
210
+ sweetHouse: "0xb7f64e5a273aba1ede00caa0a6f8027cc7490c279d17eab12e7100ed20660603",
211
+ core: "0xf391858d2a08473e8d4defcc8df89976bd7b123d3865c6b9341b237f7853dbbc",
10
212
  coinflip: "0xb35c5f286c443752afc8ccb40125a578a4f32df35617170ccfa17fe180ab80ea",
11
213
  limbo: "0x96c7841b9b32c59a219760fd656f1c3aceb53cc74a68ec9844a3a696374309f4",
12
214
  plinko: "0xd3dd2200883af10811724f0bed97591ad155a02efd6332d471ff8b346030dfb7",
13
- pvp_coinflip: "0xb43cf6583c0c15315c7e66f173af4be79ac40c38aad1fd92ec08638ab2026202",
215
+ pvpCoinflip: "0xb43cf6583c0c15315c7e66f173af4be79ac40c38aad1fd92ec08638ab2026202",
14
216
  range: "0x096a4cf18b3661e76b2c62b90785418345d52f45b272448794f123a4cb6b6416",
15
217
  wheel: "0x0997852ded7e13301c42317004bc49704a893aa82997c5706cebee59053a31b7"
16
218
  };
219
+ var TESTNET_COIN_TYPES = {
220
+ sui: "0x47c67b9594069c32caa7a6e875ddf31d7fa52602dd22ccb9ebd8d3482aed76dc::test_sui::TEST_SUI",
221
+ usdc: "0x47c67b9594069c32caa7a6e875ddf31d7fa52602dd22ccb9ebd8d3482aed76dc::test_usdc::TEST_USDC"
222
+ };
223
+ var TESTNET_PRICE_INFO_OBJECT_IDS = {
224
+ sui: "0x1ebb295c789cc42b3b2a1606482cd1c7124076a0f5676718501fda8c7fd075a0",
225
+ usdc: "0x9c4dd4008297ffa5e480684b8100ec21cc934405ed9a25d4e4d7b6259aad9c81"
226
+ };
227
+
228
+ // src/configs/package.ts
229
+ var PACKAGE_IDS = {
230
+ mainnet: { ...MAINNET_PACKAGE_IDS },
231
+ testnet: { ...TESTNET_PACKAGE_IDS }
232
+ };
233
+ var COIN_TYPES = {
234
+ mainnet: { ...MAINNET_COIN_TYPES },
235
+ testnet: { ...TESTNET_COIN_TYPES }
236
+ };
237
+ var PRICE_INFO_OBJECT_IDS = {
238
+ mainnet: { ...MAINNET_PRICE_INFO_OBJECT_IDS },
239
+ testnet: { ...TESTNET_PRICE_INFO_OBJECT_IDS }
240
+ };
241
+
242
+ // src/configs/registry.mainnet.ts
243
+ var PVP_COINFLIP_REGISTRY_ID = "0x3d73568546c539c1da3eb2b8fe917faef3c0acdbec78a67fe6d52800a0729349";
244
+
245
+ // src/configs/registry.testnet.ts
246
+ var PVP_COINFLIP_REGISTRY_ID2 = "0x99f20d8e4be012ea14a681144ae72ac349d0a1a1585205880183eb167f075bad";
17
247
 
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";
248
+ // src/configs/registry.ts
249
+ var REGISTRY_IDS = {
250
+ mainnet: {
251
+ pvpCoinflip: PVP_COINFLIP_REGISTRY_ID
252
+ },
253
+ testnet: {
254
+ pvpCoinflip: PVP_COINFLIP_REGISTRY_ID2
255
+ }
256
+ };
21
257
 
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
- );
258
+ // src/helpers/config.ts
259
+ function resolveSuigarConfig(network) {
260
+ const packageIds = PACKAGE_IDS[network];
261
+ const registryIds = REGISTRY_IDS[network];
262
+ const coinTypes = COIN_TYPES[network];
263
+ const priceInfoObjectIds = PRICE_INFO_OBJECT_IDS[network];
39
264
  return {
40
- sweetHousePackageId: trim(options.sweetHousePackageId) || trim(DEFAULT_SWEETHOUSE_PACKAGE_ID),
265
+ packageIds: { ...packageIds },
266
+ registryIds: { ...registryIds },
41
267
  coinTypes: {
42
- sui: suiCoinType,
43
- usdc: usdcCoinType,
44
- usdcFlowx: usdcFlowxCoinType
268
+ sui: normalizeStructTag(coinTypes.sui),
269
+ usdc: normalizeStructTag(coinTypes.usdc)
45
270
  },
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
271
+ priceInfoObjectIds: {
272
+ sui: priceInfoObjectIds.sui,
273
+ usdc: priceInfoObjectIds.usdc
59
274
  }
60
275
  };
61
276
  }
62
- function resolvePythPriceInfoObjectId(config, coinType) {
63
- const normalizedCoinType = normalizeStructTag(coinType);
64
- const explicitObjectId = config.pyth.priceInfoObjectIds[normalizedCoinType];
65
- if (explicitObjectId) {
66
- return explicitObjectId;
277
+ function assertConfiguredBetGame(config, game) {
278
+ if (!resolveGamePackageId(config, game)) {
279
+ throw new Error(`Missing required config for ${game}: packageIds.${game}`);
67
280
  }
68
- if (normalizedCoinType === config.coinTypes.sui && config.pyth.suiPriceInfoObjectId) {
69
- return config.pyth.suiPriceInfoObjectId;
281
+ }
282
+ function resolveGamePackageId(config, game) {
283
+ switch (game) {
284
+ case "coinflip":
285
+ return config.packageIds.coinflip;
286
+ case "limbo":
287
+ return config.packageIds.limbo;
288
+ case "plinko":
289
+ return config.packageIds.plinko;
290
+ case "pvp-coinflip":
291
+ return config.packageIds.pvpCoinflip;
292
+ case "range":
293
+ return config.packageIds.range;
294
+ case "wheel":
295
+ return config.packageIds.wheel;
70
296
  }
71
- if ((normalizedCoinType === config.coinTypes.usdc || normalizedCoinType === config.coinTypes.usdcFlowx) && config.pyth.usdcPriceInfoObjectId) {
72
- return config.pyth.usdcPriceInfoObjectId;
297
+ }
298
+ function resolvePriceInfoObjectId(config, coinType) {
299
+ const normalizedCoinType = normalizeStructTag(coinType);
300
+ const supportedCoin = resolveSupportedCoin(config, normalizedCoinType);
301
+ const objectId = config.priceInfoObjectIds[supportedCoin];
302
+ if (!objectId) {
303
+ throw new Error(
304
+ `Missing price info object configuration for coin type ${coinType}`
305
+ );
73
306
  }
74
- throw new Error(
75
- `Missing Pyth price object configuration for coin type ${coinType}`
76
- );
307
+ return objectId;
77
308
  }
78
- function assertConfiguredBetGame(config, game) {
79
- if (!config.gamesPackageId[game]) {
309
+ function resolveSupportedCoin(config, coinType) {
310
+ const [supportedCoin] = Object.entries(config.coinTypes).find(([_, value]) => value === coinType) ?? [];
311
+ if (!supportedCoin) {
80
312
  throw new Error(
81
- `Missing required config for ${game}: gamesPackageId.${game}`
313
+ `Unsupported coin type ${coinType}. Supported coin types: ${Object.values(
314
+ config.coinTypes
315
+ ).join(", ")}`
82
316
  );
83
317
  }
318
+ return supportedCoin;
84
319
  }
85
- var ADDRESS_METADATA_KEYS = /* @__PURE__ */ new Set(["referrer", "partner"]);
320
+ var PARTNER_METADATA_KEY = "partner";
321
+ var RESERVED_METADATA_KEYS = /* @__PURE__ */ new Set([PARTNER_METADATA_KEY, "referrer"]);
86
322
  var textEncoder = new TextEncoder();
87
- var parseHexAddress = (value) => {
88
- const trimmed = value.trim();
89
- if (!trimmed) return null;
323
+ function encodeString(value) {
90
324
  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;
325
+ return fromHex(value);
100
326
  } 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);
327
+ return textEncoder.encode(value);
125
328
  }
126
- return { keys, values };
127
329
  }
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`);
330
+ function encodeMetadataValue(value) {
331
+ if (value instanceof Uint8Array) {
332
+ return Array.from(value);
148
333
  }
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
- }
334
+ if (Array.isArray(value)) {
335
+ return value;
189
336
  }
190
- return null;
337
+ return Array.from(encodeString(String(value)));
191
338
  }
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));
339
+ function encodeBetMetadata(metadata, partner) {
340
+ const keys = [];
341
+ const values = [];
342
+ for (const [key, value] of Object.entries(metadata ?? {})) {
343
+ if (RESERVED_METADATA_KEYS.has(key)) {
344
+ console.warn(
345
+ `Metadata key "${key}" is reserved and will be ignored when parsing metadata.`
346
+ );
236
347
  continue;
237
348
  }
238
- if (typeof arg === "string") {
239
- normalizedArgs.push((tx) => tx.object(arg));
349
+ if (value == null) {
240
350
  continue;
241
351
  }
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);
352
+ keys.push(key);
353
+ values.push(encodeMetadataValue(value));
282
354
  }
283
- if (typeof val === "bigint") {
284
- return val.toString();
355
+ if (partner?.trim()) {
356
+ keys.unshift(PARTNER_METADATA_KEY);
357
+ values.unshift(encodeMetadataValue(partner));
285
358
  }
286
- return val;
359
+ return {
360
+ keys,
361
+ values
362
+ };
287
363
  }
288
364
 
289
365
  // src/contracts/coinflip/coinflip.ts
@@ -309,39 +385,46 @@ function play(options) {
309
385
  typeArguments: options.typeArguments
310
386
  });
311
387
  }
388
+
389
+ // src/types/network.type.ts
390
+ var SUPPORTED_SUI_NETWORKS = [
391
+ "mainnet",
392
+ "testnet"
393
+ ];
394
+
395
+ // src/transactions/shared.ts
312
396
  function createBaseGameTransaction({
313
397
  config,
314
398
  game,
315
- owner,
316
- sender,
399
+ playerAddress,
317
400
  gasBudget
318
401
  }) {
319
402
  assertConfiguredBetGame(config, game);
320
403
  const tx = new Transaction();
321
- tx.setSenderIfNotSet(normalizeSuiAddress(sender ?? owner));
404
+ tx.setSenderIfNotSet(normalizeSuiAddress(playerAddress));
322
405
  tx.setGasBudgetIfNotSet(gasBudget ?? DEFAULT_GAS_BUDGET_MIST);
323
406
  return tx;
324
407
  }
325
408
  function buildSharedStandardGameBetCall({
326
409
  config,
327
- owner,
328
- sender,
410
+ playerAddress,
329
411
  coinType,
330
412
  stake,
331
413
  cashStake,
332
414
  betCount,
333
415
  metadata,
416
+ partner,
334
417
  allowGasCoinShortcut = true,
335
418
  buildRewardCoin
336
419
  }) {
337
420
  return (tx) => {
338
- const normalizedOwner = normalizeSuiAddress(sender ?? owner);
421
+ const normalizedPlayerAddress = normalizeSuiAddress(playerAddress);
339
422
  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(
423
+ const resolvedStake = toBigInt(stake);
424
+ const resolvedCashStake = toBigInt(cashStake ?? stake);
425
+ const resolvedBetCount = toBigInt(betCount ?? 1);
426
+ const encodedMetadata = encodeBetMetadata(metadata, partner);
427
+ const priceInfoObjectId = resolvePriceInfoObjectId(
345
428
  config,
346
429
  normalizedCoinType
347
430
  );
@@ -353,16 +436,16 @@ function buildSharedStandardGameBetCall({
353
436
  const rewardCoin = buildRewardCoin({
354
437
  tx,
355
438
  config,
356
- owner: normalizedOwner,
439
+ playerAddress: normalizedPlayerAddress,
357
440
  coinType: normalizedCoinType,
358
441
  stake: resolvedStake,
359
442
  cashStake: resolvedCashStake,
360
443
  betCount: resolvedBetCount,
361
444
  metadata: encodedMetadata,
362
- pythPriceInfoObjectId,
445
+ priceInfoObjectId,
363
446
  betCoin
364
447
  });
365
- tx.transferObjects([rewardCoin], tx.pure.address(normalizedOwner));
448
+ tx.transferObjects([rewardCoin], tx.pure.address(normalizedPlayerAddress));
366
449
  return rewardCoin;
367
450
  };
368
451
  }
@@ -384,20 +467,20 @@ function buildCoinflipTransaction(options) {
384
467
  stake,
385
468
  betCount,
386
469
  metadata,
387
- pythPriceInfoObjectId,
470
+ priceInfoObjectId,
388
471
  betCoin
389
472
  }) => play({
390
- package: config.gamesPackageId.coinflip,
473
+ package: config.packageIds.coinflip,
391
474
  typeArguments: [coinType],
392
475
  arguments: [
393
- config.sweetHousePackageId,
476
+ config.packageIds.sweetHouse,
394
477
  stake,
395
478
  betCoin,
396
479
  betCount,
397
480
  options.side === "tails",
398
481
  metadata.keys,
399
482
  metadata.values,
400
- pythPriceInfoObjectId
483
+ priceInfoObjectId
401
484
  ]
402
485
  })(tx)
403
486
  });
@@ -430,7 +513,7 @@ function play2(options) {
430
513
 
431
514
  // src/transactions/limbo.ts
432
515
  function buildLimboTransaction(options) {
433
- const scale = options.scale ?? LIMBO_MULTIPLIER_SCALE;
516
+ const scale = options.scale ?? DEFAULT_LIMBO_MULTIPLIER_SCALE;
434
517
  const numerator = Math.round(options.targetMultiplier * scale);
435
518
  return buildSharedStandardGameBetTransaction({
436
519
  ...options,
@@ -442,13 +525,13 @@ function buildLimboTransaction(options) {
442
525
  stake,
443
526
  betCount,
444
527
  metadata,
445
- pythPriceInfoObjectId,
528
+ priceInfoObjectId,
446
529
  betCoin
447
530
  }) => play2({
448
- package: config.gamesPackageId.limbo,
531
+ package: config.packageIds.limbo,
449
532
  typeArguments: [coinType],
450
533
  arguments: [
451
- config.sweetHousePackageId,
534
+ config.packageIds.sweetHouse,
452
535
  stake,
453
536
  betCoin,
454
537
  betCount,
@@ -456,7 +539,7 @@ function buildLimboTransaction(options) {
456
539
  BigInt(scale),
457
540
  metadata.keys,
458
541
  metadata.values,
459
- pythPriceInfoObjectId
542
+ priceInfoObjectId
460
543
  ]
461
544
  })(tx)
462
545
  });
@@ -488,7 +571,7 @@ function play3(options) {
488
571
 
489
572
  // src/transactions/plinko.ts
490
573
  function buildPlinkoTransaction(options) {
491
- const configId = toU8Number(options.configId, "configId");
574
+ const configId = toU8(options.configId);
492
575
  return buildSharedStandardGameBetTransaction({
493
576
  ...options,
494
577
  game: "plinko",
@@ -499,134 +582,35 @@ function buildPlinkoTransaction(options) {
499
582
  stake,
500
583
  betCount,
501
584
  metadata,
502
- pythPriceInfoObjectId,
585
+ priceInfoObjectId,
503
586
  betCoin
504
587
  }) => play3({
505
- package: config.gamesPackageId.plinko,
588
+ package: config.packageIds.plinko,
506
589
  typeArguments: [coinType],
507
590
  arguments: [
508
- config.sweetHousePackageId,
591
+ config.packageIds.sweetHouse,
509
592
  stake,
510
593
  betCoin,
511
594
  betCount,
512
595
  configId,
513
596
  metadata.keys,
514
597
  metadata.values,
515
- pythPriceInfoObjectId
598
+ priceInfoObjectId
516
599
  ]
517
600
  })(tx)
518
601
  });
519
602
  }
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
603
  function buildPvPCoinflipTransaction(action, options) {
620
604
  const tx = createBaseGameTransaction({
621
605
  ...options,
622
606
  game: "pvp-coinflip"
623
607
  });
624
608
  const normalizedCoinType = normalizeStructTag(options.coinType);
625
- const encodedMetadata = encodeBetMetadata(options.metadata);
609
+ const encodedMetadata = encodeBetMetadata(options.metadata, options.partner);
626
610
  switch (action) {
627
611
  case "create": {
628
612
  const createOptions = options;
629
- const stake = toBigIntAmount(createOptions.stake, "stake");
613
+ const stake = toBigInt(createOptions.stake);
630
614
  const betCoin = tx.coin({
631
615
  type: normalizedCoinType,
632
616
  balance: stake,
@@ -634,10 +618,10 @@ function buildPvPCoinflipTransaction(action, options) {
634
618
  });
635
619
  tx.add(
636
620
  createGame({
637
- package: createOptions.config.gamesPackageId["pvp-coinflip"],
621
+ package: createOptions.config.packageIds.pvpCoinflip,
638
622
  typeArguments: [normalizedCoinType],
639
623
  arguments: [
640
- createOptions.config.sweetHousePackageId,
624
+ createOptions.config.packageIds.sweetHouse,
641
625
  betCoin,
642
626
  createOptions.side === "tails",
643
627
  Boolean(createOptions.isPrivate),
@@ -650,23 +634,21 @@ function buildPvPCoinflipTransaction(action, options) {
650
634
  }
651
635
  case "join": {
652
636
  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
- });
637
+ const priceInfoObjectId = resolvePriceInfoObjectId(
638
+ joinOptions.config,
639
+ normalizedCoinType
640
+ );
659
641
  tx.add(
660
642
  joinGame({
661
- package: joinOptions.config.gamesPackageId["pvp-coinflip"],
643
+ package: joinOptions.config.packageIds.pvpCoinflip,
662
644
  typeArguments: [normalizedCoinType],
663
645
  arguments: [
664
646
  joinOptions.gameId,
665
- joinOptions.config.sweetHousePackageId,
666
- betCoin,
647
+ joinOptions.config.packageIds.sweetHouse,
648
+ tx.add(joinOptions.betCoin),
667
649
  encodedMetadata.keys,
668
650
  encodedMetadata.values,
669
- joinOptions.extraObjectId
651
+ priceInfoObjectId
670
652
  ]
671
653
  })
672
654
  );
@@ -676,11 +658,11 @@ function buildPvPCoinflipTransaction(action, options) {
676
658
  const cancelOptions = options;
677
659
  tx.add(
678
660
  cancelGame({
679
- package: cancelOptions.config.gamesPackageId["pvp-coinflip"],
661
+ package: cancelOptions.config.packageIds.pvpCoinflip,
680
662
  typeArguments: [normalizedCoinType],
681
663
  arguments: [
682
664
  cancelOptions.gameId,
683
- cancelOptions.config.sweetHousePackageId
665
+ cancelOptions.config.packageIds.sweetHouse
684
666
  ]
685
667
  })
686
668
  );
@@ -719,7 +701,7 @@ function play4(options) {
719
701
 
720
702
  // src/transactions/range.ts
721
703
  function buildRangeTransaction(options) {
722
- const scale = options.scale ?? RANGE_FIXED_POINT_SCALE;
704
+ const scale = options.scale ?? DEFAULT_RANGE_SCALE;
723
705
  const leftPoint = Math.round(options.leftPoint * scale);
724
706
  const rightPoint = Math.round(options.rightPoint * scale);
725
707
  return buildSharedStandardGameBetTransaction({
@@ -732,13 +714,13 @@ function buildRangeTransaction(options) {
732
714
  stake,
733
715
  betCount,
734
716
  metadata,
735
- pythPriceInfoObjectId,
717
+ priceInfoObjectId,
736
718
  betCoin
737
719
  }) => play4({
738
- package: config.gamesPackageId.range,
720
+ package: config.packageIds.range,
739
721
  typeArguments: [coinType],
740
722
  arguments: [
741
- config.sweetHousePackageId,
723
+ config.packageIds.sweetHouse,
742
724
  stake,
743
725
  betCoin,
744
726
  betCount,
@@ -747,7 +729,7 @@ function buildRangeTransaction(options) {
747
729
  Boolean(options.outOfRange),
748
730
  metadata.keys,
749
731
  metadata.values,
750
- pythPriceInfoObjectId
732
+ priceInfoObjectId
751
733
  ]
752
734
  })(tx)
753
735
  });
@@ -779,7 +761,7 @@ function play5(options) {
779
761
 
780
762
  // src/transactions/wheel.ts
781
763
  function buildWheelTransaction(options) {
782
- const configId = toU8Number(options.configId, "configId");
764
+ const configId = toU8(options.configId);
783
765
  return buildSharedStandardGameBetTransaction({
784
766
  ...options,
785
767
  game: "wheel",
@@ -790,104 +772,161 @@ function buildWheelTransaction(options) {
790
772
  stake,
791
773
  betCount,
792
774
  metadata,
793
- pythPriceInfoObjectId,
775
+ priceInfoObjectId,
794
776
  betCoin
795
777
  }) => play5({
796
- package: config.gamesPackageId.wheel,
778
+ package: config.packageIds.wheel,
797
779
  typeArguments: [coinType],
798
780
  arguments: [
799
- config.sweetHousePackageId,
781
+ config.packageIds.sweetHouse,
800
782
  stake,
801
783
  betCoin,
802
784
  betCount,
803
785
  configId,
804
786
  metadata.keys,
805
787
  metadata.values,
806
- pythPriceInfoObjectId
788
+ priceInfoObjectId
807
789
  ]
808
790
  })(tx)
809
791
  });
810
792
  }
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
793
 
855
794
  // src/client.ts
856
795
  function suigar({
857
796
  name = "suigar",
858
- ...options
797
+ partner
859
798
  } = {}) {
860
799
  return {
861
800
  name,
862
801
  register: (client) => {
863
- return new SuigarClient({ client, options });
802
+ return new SuigarClient({ client, partner });
864
803
  }
865
804
  };
866
805
  }
867
806
  var SuigarClient = class {
868
807
  #client;
869
808
  #config;
809
+ #partner;
870
810
  constructor({
871
811
  client,
872
- options
812
+ partner
873
813
  }) {
874
814
  this.#client = client;
875
- this.#config = resolveSuigarConfig(options);
815
+ this.#partner = partner;
816
+ const network = this.#client.network;
817
+ if (!SUPPORTED_SUI_NETWORKS.includes(network)) {
818
+ throw new Error(`Unsupported network: ${network}`);
819
+ }
820
+ this.#config = resolveSuigarConfig(network);
876
821
  }
877
822
  /**
878
- * Builds a transaction with the configured Sui client and returns the BCS bytes as a base64 string.
823
+ * Returns the resolved SDK configuration for the connected network.
824
+ *
825
+ * This is primarily useful for debugging or inspecting which package ids,
826
+ * supported coin types, and price info object ids the SDK resolved for the
827
+ * current client network.
828
+ *
829
+ * @returns Network-resolved Suigar configuration.
830
+ */
831
+ getConfig() {
832
+ return this.#config;
833
+ }
834
+ /**
835
+ * Builds a transaction with the configured Sui client and encodes the resulting BCS bytes as base64.
836
+ *
837
+ * Use this when an external wallet, API, or transport expects the built transaction payload as a base64 string
838
+ * instead of raw bytes. The SDK always injects the configured Sui client, so `options` accepts the standard
839
+ * transaction build options except for `client`.
879
840
  *
880
- * @param transaction Transaction block to serialize.
841
+ * @param transaction Transaction to build and serialize.
842
+ * @param options Optional transaction build options forwarded to `transaction.build()`, excluding `client`.
881
843
  * @returns Base64-encoded transaction bytes ready to send over the wire.
882
844
  */
883
- async serializeTransactionToBase64(transaction) {
884
- const bytes = await transaction.build({ client: this.#client });
885
- return Buffer.from(bytes).toString("base64");
845
+ async serializeTransactionToBase64(transaction, options) {
846
+ const bytes = await transaction.build({ ...options, client: this.#client });
847
+ return toBase64(bytes);
848
+ }
849
+ /**
850
+ * Lists unresolved PvP coinflip games from the configured registry and resolves
851
+ * each entry into parsed onchain game state.
852
+ *
853
+ * This fetches dynamic fields from the PvP coinflip registry object, then bulk
854
+ * loads the referenced game objects through `client.core.getObjects()`. Registry
855
+ * membership is the unresolved-state signal: when a game is joined and resolved,
856
+ * the Move flow removes it from the registry and deletes the live `Game` object.
857
+ * Use this when a product needs the current set of open PvP coinflip matches for
858
+ * browsing or lobby views.
859
+ *
860
+ * @param options Optional dynamic field pagination forwarded to `listDynamicFields()`, excluding `parentId`.
861
+ * Supported options such as `limit`, `cursor`, and `signal` are forwarded to the
862
+ * underlying lookup calls. Pass `throwOnError: true` to fail the whole lookup
863
+ * when any referenced game object cannot be fetched or parsed. By default,
864
+ * failed per-object lookups are skipped and only successfully parsed unresolved
865
+ * games are returned.
866
+ * @returns Parsed unresolved PvP coinflip game objects for the requested
867
+ * registry page. When `throwOnError` is `false`, entries that fail object fetch
868
+ * or parse are omitted from the returned array.
869
+ */
870
+ async getPvPCoinflipGames(options = {
871
+ limit: 50
872
+ }) {
873
+ const { throwOnError = false, ...listOptions } = options;
874
+ const { dynamicFields } = await this.#client.core.listDynamicFields({
875
+ ...listOptions,
876
+ parentId: this.#config.registryIds.pvpCoinflip
877
+ });
878
+ const { objects } = await this.#client.core.getObjects({
879
+ objectIds: dynamicFields.map(({ childId }) => childId),
880
+ signal: listOptions.signal,
881
+ include: {
882
+ content: true
883
+ }
884
+ });
885
+ const resolvedGames = objects.map((object) => {
886
+ try {
887
+ if (object instanceof Error) {
888
+ throw object;
889
+ }
890
+ if (!object.content) {
891
+ throw new Error(
892
+ "Unable to resolve PvP coinflip game from retrieved object"
893
+ );
894
+ }
895
+ return {
896
+ ...Game.parse(object.content),
897
+ coinType: parseCoinType(object.type)
898
+ };
899
+ } catch (error) {
900
+ return error instanceof Error ? error : new Error(String(error));
901
+ }
902
+ });
903
+ if (throwOnError) {
904
+ const firstError = resolvedGames.find((game) => game instanceof Error);
905
+ if (firstError) {
906
+ throw firstError;
907
+ }
908
+ }
909
+ return resolvedGames.flatMap(
910
+ (game) => game instanceof Error ? [] : [game]
911
+ );
886
912
  }
887
913
  /**
888
- * BCS struct constructors for decoding Suigar events emitted on-chain.
914
+ * BCS struct constructors for decoding on-chain objects and events related to Suigar games.
915
+ *
916
+ * These can be used to parse the `content` field of on-chain objects and events into structured data with the
917
+ * expected types. For example, use `client.suigar.bcs.PvPCoinflipGame.parse(object.content)` to decode a PvP
918
+ * coinflip game object.
919
+ *
920
+ * Note that these constructors are not meant for encoding transaction arguments, as the SDK's transaction
921
+ * builders handle argument serialization internally. Use these primarily for decoding and parsing on-chain data.
889
922
  */
890
923
  bcs = {
924
+ // Objects
925
+ /**
926
+ * Object representing the state of a PvP coinflip game, as stored on-chain.
927
+ */
928
+ PvPCoinflipGame: Game,
929
+ // Events
891
930
  /**
892
931
  * Event emitted at the end of a standard game (e.g., Coinflip, Limbo), containing the result and payout information.
893
932
  */
@@ -895,15 +934,15 @@ var SuigarClient = class {
895
934
  /**
896
935
  * Event emitted when a PvP Coinflip game is created, containing the game configuration and initial state.
897
936
  */
898
- PvPCoinflipGameCreated: GameCreatedEvent,
937
+ PvPCoinflipGameCreatedEvent: GameCreatedEvent,
899
938
  /**
900
939
  * Event emitted when a PvP Coinflip game is resolved, containing the final outcome.
901
940
  */
902
- PvPCoinflipGameResolved: GameResolvedEvent,
941
+ PvPCoinflipGameResolvedEvent: GameResolvedEvent,
903
942
  /**
904
943
  * Event emitted when a PvP Coinflip game is cancelled.
905
944
  */
906
- PvPCoinflipGameCancelled: GameCancelledEvent
945
+ PvPCoinflipGameCancelledEvent: GameCancelledEvent
907
946
  };
908
947
  /**
909
948
  * Transaction builders for Suigar games.
@@ -921,27 +960,32 @@ var SuigarClient = class {
921
960
  case "coinflip":
922
961
  return buildCoinflipTransaction({
923
962
  ...options,
924
- config: this.#config
963
+ config: this.#config,
964
+ partner: this.#partner
925
965
  });
926
966
  case "limbo":
927
967
  return buildLimboTransaction({
928
968
  ...options,
929
- config: this.#config
969
+ config: this.#config,
970
+ partner: this.#partner
930
971
  });
931
972
  case "plinko":
932
973
  return buildPlinkoTransaction({
933
974
  ...options,
934
- config: this.#config
975
+ config: this.#config,
976
+ partner: this.#partner
935
977
  });
936
978
  case "range":
937
979
  return buildRangeTransaction({
938
980
  ...options,
939
- config: this.#config
981
+ config: this.#config,
982
+ partner: this.#partner
940
983
  });
941
984
  case "wheel":
942
985
  return buildWheelTransaction({
943
986
  ...options,
944
- config: this.#config
987
+ config: this.#config,
988
+ partner: this.#partner
945
989
  });
946
990
  default:
947
991
  throw new Error(`Unsupported game: ${gameId}`);
@@ -955,12 +999,46 @@ var SuigarClient = class {
955
999
  * @returns Prepared PvP coinflip transaction.
956
1000
  */
957
1001
  createPvPCoinflipTransaction: (action, options) => {
958
- return buildPvPCoinflipTransaction(action, {
959
- ...options,
960
- config: this.#config
961
- });
1002
+ switch (action) {
1003
+ case "create":
1004
+ return buildPvPCoinflipTransaction("create", {
1005
+ ...options,
1006
+ config: this.#config,
1007
+ partner: this.#partner
1008
+ });
1009
+ case "join": {
1010
+ const joinOptions = options;
1011
+ return buildPvPCoinflipTransaction("join", {
1012
+ ...joinOptions,
1013
+ betCoin: this.#createPvPCoinflipBetCoin(joinOptions),
1014
+ config: this.#config,
1015
+ partner: this.#partner
1016
+ });
1017
+ }
1018
+ case "cancel":
1019
+ return buildPvPCoinflipTransaction("cancel", {
1020
+ ...options,
1021
+ config: this.#config,
1022
+ partner: this.#partner
1023
+ });
1024
+ default:
1025
+ throw new Error(`Unsupported PvP coinflip action: ${action}`);
1026
+ }
962
1027
  }
963
1028
  };
1029
+ #createPvPCoinflipBetCoin(options) {
1030
+ return async (tx) => {
1031
+ const { json } = await Game.get({
1032
+ client: this.#client,
1033
+ objectId: options.gameId
1034
+ });
1035
+ return tx.coin({
1036
+ type: options.coinType,
1037
+ balance: BigInt(json.stake_per_player),
1038
+ useGasCoin: options.allowGasCoinShortcut
1039
+ });
1040
+ };
1041
+ }
964
1042
  };
965
1043
 
966
1044
  export { SuigarClient, suigar };