@suigar/sdk 2.0.0-beta.2 → 2.0.0-beta.20

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.
Files changed (147) hide show
  1. package/CHANGELOG.md +165 -1
  2. package/README.md +300 -59
  3. package/dist/client.d.mts +257 -0
  4. package/dist/client.d.mts.map +1 -0
  5. package/dist/client.mjs +278 -0
  6. package/dist/client.mjs.map +1 -0
  7. package/dist/configs/package.mainnet.mjs +23 -0
  8. package/dist/configs/package.mainnet.mjs.map +1 -0
  9. package/dist/configs/package.mjs +19 -0
  10. package/dist/configs/package.mjs.map +1 -0
  11. package/dist/configs/package.testnet.mjs +23 -0
  12. package/dist/configs/package.testnet.mjs.map +1 -0
  13. package/dist/configs/registry.mainnet.mjs +6 -0
  14. package/dist/configs/registry.mainnet.mjs.map +1 -0
  15. package/dist/configs/registry.mjs +11 -0
  16. package/dist/configs/registry.mjs.map +1 -0
  17. package/dist/configs/registry.testnet.mjs +6 -0
  18. package/dist/configs/registry.testnet.mjs.map +1 -0
  19. package/dist/contracts/coinflip/coinflip.mjs +46 -0
  20. package/dist/contracts/coinflip/coinflip.mjs.map +1 -0
  21. package/dist/contracts/core/core.d.mts +54 -0
  22. package/dist/contracts/core/core.d.mts.map +1 -0
  23. package/dist/contracts/core/core.mjs +22 -0
  24. package/dist/contracts/core/core.mjs.map +1 -0
  25. package/dist/contracts/core/deps/0x0000000000000000000000000000000000000000000000000000000000000001/type_name.mjs +10 -0
  26. package/dist/contracts/core/deps/0x0000000000000000000000000000000000000000000000000000000000000001/type_name.mjs.map +1 -0
  27. package/dist/contracts/core/deps/0x0000000000000000000000000000000000000000000000000000000000000002/vec_map.mjs +26 -0
  28. package/dist/contracts/core/deps/0x0000000000000000000000000000000000000000000000000000000000000002/vec_map.mjs.map +1 -0
  29. package/dist/contracts/core/float.d.mts +13 -0
  30. package/dist/contracts/core/float.d.mts.map +1 -0
  31. package/dist/contracts/core/float.mjs +15 -0
  32. package/dist/contracts/core/float.mjs.map +1 -0
  33. package/dist/contracts/core/i64.mjs +10 -0
  34. package/dist/contracts/core/i64.mjs.map +1 -0
  35. package/dist/contracts/limbo/deps/0xf391858d2a08473e8d4defcc8df89976bd7b123d3865c6b9341b237f7853dbbc/float.mjs +15 -0
  36. package/dist/contracts/limbo/deps/0xf391858d2a08473e8d4defcc8df89976bd7b123d3865c6b9341b237f7853dbbc/float.mjs.map +1 -0
  37. package/dist/contracts/limbo/deps/0xf391858d2a08473e8d4defcc8df89976bd7b123d3865c6b9341b237f7853dbbc/i64.mjs +10 -0
  38. package/dist/contracts/limbo/deps/0xf391858d2a08473e8d4defcc8df89976bd7b123d3865c6b9341b237f7853dbbc/i64.mjs.map +1 -0
  39. package/dist/contracts/limbo/limbo.mjs +53 -0
  40. package/dist/contracts/limbo/limbo.mjs.map +1 -0
  41. package/dist/contracts/plinko/deps/0x0000000000000000000000000000000000000000000000000000000000000002/vec_map.mjs +26 -0
  42. package/dist/contracts/plinko/deps/0x0000000000000000000000000000000000000000000000000000000000000002/vec_map.mjs.map +1 -0
  43. package/dist/contracts/plinko/deps/0xf391858d2a08473e8d4defcc8df89976bd7b123d3865c6b9341b237f7853dbbc/float.mjs +15 -0
  44. package/dist/contracts/plinko/deps/0xf391858d2a08473e8d4defcc8df89976bd7b123d3865c6b9341b237f7853dbbc/float.mjs.map +1 -0
  45. package/dist/contracts/plinko/deps/0xf391858d2a08473e8d4defcc8df89976bd7b123d3865c6b9341b237f7853dbbc/i64.mjs +10 -0
  46. package/dist/contracts/plinko/deps/0xf391858d2a08473e8d4defcc8df89976bd7b123d3865c6b9341b237f7853dbbc/i64.mjs.map +1 -0
  47. package/dist/contracts/plinko/plinko.mjs +59 -0
  48. package/dist/contracts/plinko/plinko.mjs.map +1 -0
  49. package/dist/contracts/pvp-coinflip/deps/0x0000000000000000000000000000000000000000000000000000000000000001/type_name.mjs +10 -0
  50. package/dist/contracts/pvp-coinflip/deps/0x0000000000000000000000000000000000000000000000000000000000000001/type_name.mjs.map +1 -0
  51. package/dist/contracts/pvp-coinflip/deps/0x0000000000000000000000000000000000000000000000000000000000000002/balance.mjs +10 -0
  52. package/dist/contracts/pvp-coinflip/deps/0x0000000000000000000000000000000000000000000000000000000000000002/balance.mjs.map +1 -0
  53. package/dist/contracts/pvp-coinflip/deps/0x0000000000000000000000000000000000000000000000000000000000000002/vec_map.mjs +26 -0
  54. package/dist/contracts/pvp-coinflip/deps/0x0000000000000000000000000000000000000000000000000000000000000002/vec_map.mjs.map +1 -0
  55. package/dist/contracts/pvp-coinflip/pvp_coinflip.d.mts +33 -0
  56. package/dist/contracts/pvp-coinflip/pvp_coinflip.d.mts.map +1 -0
  57. package/dist/contracts/pvp-coinflip/pvp_coinflip.mjs +131 -0
  58. package/dist/contracts/pvp-coinflip/pvp_coinflip.mjs.map +1 -0
  59. package/dist/contracts/range/deps/0xf391858d2a08473e8d4defcc8df89976bd7b123d3865c6b9341b237f7853dbbc/float.mjs +15 -0
  60. package/dist/contracts/range/deps/0xf391858d2a08473e8d4defcc8df89976bd7b123d3865c6b9341b237f7853dbbc/float.mjs.map +1 -0
  61. package/dist/contracts/range/deps/0xf391858d2a08473e8d4defcc8df89976bd7b123d3865c6b9341b237f7853dbbc/i64.mjs +10 -0
  62. package/dist/contracts/range/deps/0xf391858d2a08473e8d4defcc8df89976bd7b123d3865c6b9341b237f7853dbbc/i64.mjs.map +1 -0
  63. package/dist/contracts/range/range.mjs +53 -0
  64. package/dist/contracts/range/range.mjs.map +1 -0
  65. package/dist/contracts/utils/index.d.mts +68 -0
  66. package/dist/contracts/utils/index.d.mts.map +1 -0
  67. package/dist/contracts/utils/index.mjs +185 -0
  68. package/dist/contracts/utils/index.mjs.map +1 -0
  69. package/dist/contracts/wheel/deps/0x0000000000000000000000000000000000000000000000000000000000000002/vec_map.mjs +26 -0
  70. package/dist/contracts/wheel/deps/0x0000000000000000000000000000000000000000000000000000000000000002/vec_map.mjs.map +1 -0
  71. package/dist/contracts/wheel/deps/0xf391858d2a08473e8d4defcc8df89976bd7b123d3865c6b9341b237f7853dbbc/float.mjs +15 -0
  72. package/dist/contracts/wheel/deps/0xf391858d2a08473e8d4defcc8df89976bd7b123d3865c6b9341b237f7853dbbc/float.mjs.map +1 -0
  73. package/dist/contracts/wheel/deps/0xf391858d2a08473e8d4defcc8df89976bd7b123d3865c6b9341b237f7853dbbc/i64.mjs +10 -0
  74. package/dist/contracts/wheel/deps/0xf391858d2a08473e8d4defcc8df89976bd7b123d3865c6b9341b237f7853dbbc/i64.mjs.map +1 -0
  75. package/dist/contracts/wheel/wheel.mjs +59 -0
  76. package/dist/contracts/wheel/wheel.mjs.map +1 -0
  77. package/dist/games.d.mts +3 -0
  78. package/dist/games.mjs +1 -0
  79. package/dist/helpers/config.mjs +51 -0
  80. package/dist/helpers/config.mjs.map +1 -0
  81. package/dist/helpers/game-settings.mjs +19 -0
  82. package/dist/helpers/game-settings.mjs.map +1 -0
  83. package/dist/helpers/metadata.mjs +42 -0
  84. package/dist/helpers/metadata.mjs.map +1 -0
  85. package/dist/index.d.mts +2 -0
  86. package/dist/index.mjs +2 -0
  87. package/dist/transactions/coinflip.mjs +27 -0
  88. package/dist/transactions/coinflip.mjs.map +1 -0
  89. package/dist/transactions/limbo.mjs +31 -0
  90. package/dist/transactions/limbo.mjs.map +1 -0
  91. package/dist/transactions/plinko.mjs +29 -0
  92. package/dist/transactions/plinko.mjs.map +1 -0
  93. package/dist/transactions/pvp-coinflip.mjs +70 -0
  94. package/dist/transactions/pvp-coinflip.mjs.map +1 -0
  95. package/dist/transactions/range.mjs +33 -0
  96. package/dist/transactions/range.mjs.map +1 -0
  97. package/dist/transactions/shared.mjs +49 -0
  98. package/dist/transactions/shared.mjs.map +1 -0
  99. package/dist/transactions/wheel.mjs +29 -0
  100. package/dist/transactions/wheel.mjs.map +1 -0
  101. package/dist/ttl-cache.mjs +60 -0
  102. package/dist/ttl-cache.mjs.map +1 -0
  103. package/dist/types/bet-metadata.type.d.mts +7 -0
  104. package/dist/types/bet-metadata.type.d.mts.map +1 -0
  105. package/dist/types/build-game-transaction-options.type.d.mts +9 -0
  106. package/dist/types/build-game-transaction-options.type.d.mts.map +1 -0
  107. package/dist/types/game-details.type.d.mts +72 -0
  108. package/dist/types/game-details.type.d.mts.map +1 -0
  109. package/dist/types/game-details.type.mjs +59 -0
  110. package/dist/types/game-details.type.mjs.map +1 -0
  111. package/dist/types/game-settings.type.d.mts +200 -0
  112. package/dist/types/game-settings.type.d.mts.map +1 -0
  113. package/dist/types/game-settings.type.mjs +37 -0
  114. package/dist/types/game-settings.type.mjs.map +1 -0
  115. package/dist/types/game.type.d.mts +15 -0
  116. package/dist/types/game.type.d.mts.map +1 -0
  117. package/dist/types/game.type.mjs +19 -0
  118. package/dist/types/game.type.mjs.map +1 -0
  119. package/dist/types/index.d.mts +7 -0
  120. package/dist/types/move-float.type.d.mts +7 -0
  121. package/dist/types/move-float.type.d.mts.map +1 -0
  122. package/dist/types/network.type.d.mts +1 -0
  123. package/dist/types/network.type.mjs +6 -0
  124. package/dist/types/network.type.mjs.map +1 -0
  125. package/dist/types/suigar-config.type.d.mts +33 -0
  126. package/dist/types/suigar-config.type.d.mts.map +1 -0
  127. package/dist/types/transaction-options.type.d.mts +63 -0
  128. package/dist/types/transaction-options.type.d.mts.map +1 -0
  129. package/dist/utils/constants.d.mts +8 -0
  130. package/dist/utils/constants.d.mts.map +1 -0
  131. package/dist/utils/constants.mjs +10 -0
  132. package/dist/utils/constants.mjs.map +1 -0
  133. package/dist/utils/numeric.d.mts +86 -0
  134. package/dist/utils/numeric.d.mts.map +1 -0
  135. package/dist/utils/numeric.mjs +148 -0
  136. package/dist/utils/numeric.mjs.map +1 -0
  137. package/dist/utils/parser.d.mts +54 -0
  138. package/dist/utils/parser.d.mts.map +1 -0
  139. package/dist/utils/parser.mjs +94 -0
  140. package/dist/utils/parser.mjs.map +1 -0
  141. package/dist/utils.d.mts +4 -0
  142. package/dist/utils.mjs +4 -0
  143. package/package.json +80 -82
  144. package/dist/index.cjs +0 -1016
  145. package/dist/index.d.cts +0 -267
  146. package/dist/index.d.ts +0 -267
  147. package/dist/index.js +0 -1014
package/README.md CHANGED
@@ -5,32 +5,99 @@ TypeScript SDK for building Suigar v2 game transactions on Sui.
5
5
  ## Installation
6
6
 
7
7
  ```bash
8
- npm install @suigar/sdk
8
+ npm install --save @suigar/sdk @mysten/sui @mysten/bcs
9
9
  ```
10
10
 
11
11
  Runtime requirements:
12
12
 
13
- - Node.js `>=22`
14
- - `@mysten/sui`
13
+ - Node.js `^22.18.0 || >=24`
14
+ - ESM project configuration (`"type": "module"`)
15
+ - `@mysten/sui` v2
16
+ - `@mysten/bcs` v2
17
+
18
+ This SDK targets Sui TypeScript SDK 2.0+ only. Follow the official [Sui 2.0 migration guide](https://sdk.mystenlabs.com/sui/migrations/sui-2.0) if your app still uses the pre-2.0 client API.
15
19
 
16
20
  ## What This Package Exposes
17
21
 
18
- The package root currently exposes the extension factory:
22
+ The package ships three public entrypoints:
23
+
24
+ - `@suigar/sdk` for the extension factory and runtime client class
25
+ - `@suigar/sdk/games` for game-specific public types
26
+ - `@suigar/sdk/utils` for public parser, constants, and numeric helpers
27
+
28
+ The package root exposes the extension factory and client class:
19
29
 
20
30
  ```ts
21
- import { suigar } from '@suigar/sdk';
31
+ import { suigar, SuigarClient } from '@suigar/sdk';
22
32
  ```
23
33
 
24
34
  It does not export the individual transaction builders from the package root.
25
- It also does not export `SuigarClient` as a public root symbol.
35
+ Those stay on the registered extension instance under `client.suigar.tx`.
36
+
37
+ Utility exports are available from the utils subpath:
38
+
39
+ ```ts
40
+ import {
41
+ DEFAULT_GAS_BUDGET_MIST,
42
+ DEFAULT_LIMBO_MULTIPLIER_SCALE,
43
+ DEFAULT_RANGE_SCALE,
44
+ fromMoveFloat,
45
+ fromMoveI64,
46
+ parseCoinType,
47
+ parseGameDetails,
48
+ RANGE_POINT_LIMIT,
49
+ toBigInt,
50
+ toU8,
51
+ toU16,
52
+ } from '@suigar/sdk/utils';
53
+ ```
54
+
55
+ Numeric helper behavior:
56
+
57
+ - `toBigInt(value)` accepts `bigint`, finite `number`, non-negative integer
58
+ `string`, and `boolean` inputs and returns a normalized non-negative `bigint`
59
+ while throwing `TypeError` for invalid input shapes and `RangeError` for
60
+ negative values
61
+ - `toU8(value)` accepts a finite integer `number` or plain integer `string` in
62
+ the inclusive `0..255` range, throwing `TypeError` for non-numeric input and
63
+ `RangeError` for booleans, fractional values, or out-of-range integers
64
+ - `toU16(value)` accepts a finite integer `number` or plain integer `string`
65
+ in the inclusive `0..65535` range, throwing `TypeError` for non-numeric
66
+ input and `RangeError` for booleans, fractional values, or out-of-range
67
+ integers
68
+ - `fromMoveI64(value)` converts a generated Move `i64` wrapper into a
69
+ JavaScript `number`
70
+ - `fromMoveFloat(value)` converts a generated Move float struct into a
71
+ JavaScript `number`
72
+ - `parseCoinType(type)` extracts the normalized first generic coin type from a
73
+ Move object type string and throws `TypeError` when no coin type can be parsed
74
+ - `parseGameDetails(gameId, gameDetails)` decodes standard `BetResultEvent.game_details`
75
+ byte arrays into the expected string, number, and boolean values while
76
+ preserving the original on-chain keys
77
+
78
+ Game-specific type exports are available from the dedicated `games` subpath:
79
+
80
+ ```ts
81
+ import type {
82
+ BuildCoinflipTransactionOptions,
83
+ BuildCreatePvPCoinflipTransactionOptions,
84
+ CoinSide,
85
+ PvPCoinflipAction,
86
+ } from '@suigar/sdk/games';
87
+ ```
88
+
89
+ Current game-type subpath exports:
90
+
91
+ - `@suigar/sdk/games`: `CoinSide`, `PvPCoinflipAction`, `BuildCoinflipTransactionOptions`, `BuildLimboTransactionOptions`, `BuildPlinkoTransactionOptions`, `BuildRangeTransactionOptions`, `BuildWheelTransactionOptions`, `BuildCreatePvPCoinflipTransactionOptions`, `BuildJoinPvPCoinflipTransactionOptions`, `BuildCancelPvPCoinflipTransactionOptions`
26
92
 
27
93
  What you actually use at runtime is the registered extension instance:
28
94
 
29
95
  ```ts
30
- const client = new SuiClient({ url }).$extend(suigar());
96
+ const client = new SuiGrpcClient({ baseUrl, network }).$extend(suigar());
31
97
 
32
98
  client.suigar.serializeTransactionToBase64(...);
33
99
  client.suigar.getConfig();
100
+ client.suigar.getPvPCoinflipGames(...);
34
101
  client.suigar.bcs;
35
102
  client.suigar.tx;
36
103
  ```
@@ -38,11 +105,12 @@ client.suigar.tx;
38
105
  ## Quick Start
39
106
 
40
107
  ```ts
41
- import { getFullnodeUrl, SuiClient } from '@mysten/sui/client';
108
+ import { SuiGrpcClient } from '@mysten/sui/grpc';
42
109
  import { suigar } from '@suigar/sdk';
43
110
 
44
- const client = new SuiClient({
45
- url: getFullnodeUrl('testnet'),
111
+ const client = new SuiGrpcClient({
112
+ baseUrl: 'https://fullnode.testnet.sui.io:443',
113
+ network: 'testnet',
46
114
  }).$extend(suigar());
47
115
 
48
116
  const tx = client.suigar.tx.createBetTransaction('coinflip', {
@@ -61,19 +129,35 @@ const base64 = await client.suigar.serializeTransactionToBase64(tx);
61
129
 
62
130
  Creates a named Sui client extension. By default, it registers under `client.suigar`.
63
131
 
132
+ The extension constructor throws `RangeError` when the connected client network
133
+ is not one of the SDK's supported Sui networks.
134
+
135
+ ### Partner Setup
136
+
137
+ > **Important:** `partner` is the partner wallet address. Configure it once
138
+ > when you register the extension so the SDK can prepend that wallet address to
139
+ > supported bet metadata automatically.
140
+
64
141
  ```ts
65
- const client = new SuiClient({ url }).$extend(suigar());
142
+ const client = new SuiGrpcClient({ baseUrl, network }).$extend(
143
+ suigar({ partner: '0xpartner_wallet_address' }),
144
+ );
66
145
 
67
146
  client.suigar;
68
147
  ```
69
148
 
149
+ Do not pass a partner slug, label, or display name here. Use the wallet
150
+ address that should receive partner attribution on-chain.
151
+
70
152
  You can rename the extension:
71
153
 
72
154
  ```ts
73
- const client = new SuiClient({ url }).$extend(suigar({ name: 'casino' }));
155
+ const client = new SuiGrpcClient({ baseUrl, network }).$extend(
156
+ suigar({ name: 'games' }),
157
+ );
74
158
 
75
- client.casino.tx;
76
- client.casino.bcs;
159
+ client.games.tx;
160
+ client.games.bcs;
77
161
  ```
78
162
 
79
163
  ## Config
@@ -83,19 +167,31 @@ client.casino.bcs;
83
167
  - internal package ids by network
84
168
  - internal supported coin types by network
85
169
  - internal price info object ids by network
86
- - the connected Sui client network
170
+ - the connected client network
87
171
  - the extension name
88
172
 
89
173
  Supported override areas:
90
174
 
91
175
  - `name`
176
+ - `partner`
177
+ - `cacheTtl`
178
+
179
+ If `partner` is configured, the SDK automatically writes that partner wallet
180
+ address into the on-chain metadata vec-map. Transaction builder options may also
181
+ include `metadata`, but reserved keys such as `partner` and `referrer` are
182
+ ignored with a warning when provided manually.
183
+
184
+ `cacheTtl` controls the SDK cache for on-chain reads such as parsed game
185
+ parameters. It is expressed in milliseconds and defaults to 30 minutes.
92
186
 
93
187
  ## Runtime Surface
94
188
 
95
- The registered extension instance exposes three main areas:
189
+ The registered extension instance exposes the main runtime surface:
96
190
 
97
191
  - `getConfig()`
192
+ - `getGameParameters(game, options?)`
98
193
  - `serializeTransactionToBase64(transaction, options?)`
194
+ - `getPvPCoinflipGames(options?)`
99
195
  - `bcs`
100
196
  - `tx`
101
197
 
@@ -109,6 +205,7 @@ resolved package ids or supported coin mappings for the active client network.
109
205
  It includes:
110
206
 
111
207
  - `packageIds`
208
+ - `registryIds`
112
209
  - `coinTypes`
113
210
  - `priceInfoObjectIds`
114
211
 
@@ -117,6 +214,32 @@ const config = client.suigar.getConfig();
117
214
  console.log(config.packageIds);
118
215
  ```
119
216
 
217
+ ### `getGameParameters(game, options?)`
218
+
219
+ Returns the on-chain `Parameters<T>` object for any supported game and coin type.
220
+ The return type is inferred from `game`.
221
+
222
+ The SDK first reads the selected game's settings object from the configured
223
+ SweetHouse object, then reads that game's coin-specific `Parameters<T>` object.
224
+ This is useful for displaying or validating current limits such as min/max
225
+ stake, house edge, or game-specific config bounds. The parsed result is cached
226
+ using the extension `cacheTtl`.
227
+
228
+ When a parameter field is a generated Move float struct, such as
229
+ `min_target_multiplier`, `max_target_multiplier`, `min_rtp`, or `max_rtp`, use
230
+ `fromMoveFloat()` before treating it as a normal JavaScript number.
231
+
232
+ ```ts
233
+ const parameters = await client.suigar.getGameParameters('coinflip', {
234
+ coinType: '0x2::sui::SUI',
235
+ });
236
+
237
+ console.log(parameters.min_stake);
238
+ ```
239
+
240
+ Pass `ignoreCache: true` to refresh the on-chain read and replace the cached
241
+ value.
242
+
120
243
  ### `serializeTransactionToBase64(transaction, options?)`
121
244
 
122
245
  Builds a transaction with the configured Sui client and returns base64-encoded transaction bytes.
@@ -127,6 +250,45 @@ Use this when you need a transport-safe payload for a wallet, API, or external s
127
250
  const base64 = await client.suigar.serializeTransactionToBase64(tx);
128
251
  ```
129
252
 
253
+ ### `getPvPCoinflipGames(options?)`
254
+
255
+ Lists unresolved PvP coinflip games from the configured PvP registry.
256
+
257
+ This reads the registry dynamic fields for the active network and resolves each
258
+ entry into parsed game state through a bulk `client.core.getObjects()` lookup.
259
+ Registry membership is the unresolved-state signal: once a match is joined and
260
+ resolved, the Move flow removes it from the registry and deletes the live
261
+ `Game` object.
262
+
263
+ Use this when a product needs the current set of open PvP coinflip matches for
264
+ browsing or lobby views.
265
+
266
+ By default, per-object fetch or parse failures are skipped so one broken or
267
+ already-deleted registry entry does not reject the full lookup. Pass
268
+ `throwOnError: true` if you want the call to reject instead.
269
+
270
+ Each returned entry includes the parsed game fields plus a derived
271
+ `coin_type` string from the underlying Move object type.
272
+
273
+ Any supported `listDynamicFields()` options such as `limit`, `cursor`, or
274
+ `signal` can be passed through `options`.
275
+
276
+ ```ts
277
+ const games = await client.suigar.getPvPCoinflipGames({ limit: 20 });
278
+
279
+ for (const game of games) {
280
+ console.log(game.id);
281
+ console.log(game.coin_type);
282
+ }
283
+ ```
284
+
285
+ ```ts
286
+ const games = await client.suigar.getPvPCoinflipGames({
287
+ limit: 20,
288
+ throwOnError: true,
289
+ });
290
+ ```
291
+
130
292
  ## `tx`
131
293
 
132
294
  Transaction builders live under `client.suigar.tx`.
@@ -159,7 +321,6 @@ Shared option shape:
159
321
  - `betCount?: number | bigint`
160
322
  - `metadata?: Record<string, string | number | boolean | bigint | Uint8Array | number[] | null | undefined>`
161
323
  - `gasBudget?: number | bigint`
162
- - `sender?: string`
163
324
  - `allowGasCoinShortcut?: boolean`
164
325
 
165
326
  Shared behavior:
@@ -167,11 +328,18 @@ Shared behavior:
167
328
  - `stake` is the logical stake passed into the Move call
168
329
  - `cashStake` controls the withdrawn balance and defaults to `stake`
169
330
  - `betCount` defaults to `1`
170
- - `sender` overrides the transaction sender
171
331
  - `metadata` is encoded into `keys` and `values` byte arrays
332
+ - `partner` configured via `suigar({ partner })` is prepended automatically to metadata as the partner wallet address
333
+ - `metadata.partner` and `metadata.referrer` are reserved and ignored with a warning
172
334
  - the SDK resolves the price info object from the configured supported-coin mapping
173
335
  - the reward object is transferred back to `owner`
174
336
 
337
+ Error behavior:
338
+
339
+ - `RangeError` when `gameId` is unsupported
340
+ - `RangeError` when `coinType` is not in the resolved supported-coin config for the active network
341
+ - `RangeError` from bounded numeric helpers such as `toU8()` when `plinko` or `wheel` `configId` is out of range or not an integer
342
+
175
343
  Per-game options:
176
344
 
177
345
  - `coinflip`: `side: 'heads' | 'tails'`
@@ -194,17 +362,25 @@ const rangeTx = client.suigar.tx.createBetTransaction('range', {
194
362
  owner: '0x123',
195
363
  coinType: '0x2::sui::SUI',
196
364
  stake: 1_000_000_000n,
197
- leftPoint: 0.95,
198
- rightPoint: 1.05,
365
+ leftPoint: 25,
366
+ rightPoint: 75,
199
367
  outOfRange: false,
200
368
  });
201
369
  ```
202
370
 
203
- Notes:
371
+ > **Note:**
372
+ >
373
+ > - limbo converts `targetMultiplier` with `Math.round(targetMultiplier * scale)`
374
+ > - with the default limbo scale `100`, exposed as `DEFAULT_LIMBO_MULTIPLIER_SCALE`, a target multiplier of `2.5` becomes `250` on-chain
375
+ > - range converts each point with `Math.round(value * scale)`
376
+ > - range points are bounded by the contract limit exposed as `RANGE_POINT_LIMIT`
377
+ > - with the default range scale `1_000_000`, exposed as `DEFAULT_RANGE_SCALE`, valid UI values are `0` to `100`
378
+ > - plinko and wheel `configId` must fit in `u8`
204
379
 
205
- - limbo converts `targetMultiplier` with `Math.round(targetMultiplier * scale)`
206
- - range converts each point with `Math.round(value * scale)`
207
- - plinko and wheel `configId` must fit in `u8`
380
+ > **Tip:**
381
+ >
382
+ > - if you set `scale` to `10_000_000`, valid UI values become `0` to `10`
383
+ > - do not pre-scale range points before passing them to the SDK; pass the human value and let the SDK scale it once
208
384
 
209
385
  ### PvP Coinflip
210
386
 
@@ -233,8 +409,6 @@ const tx = client.suigar.tx.createPvPCoinflipTransaction('join', {
233
409
  owner: '0x123',
234
410
  coinType: '0x2::sui::SUI',
235
411
  gameId: '0xGAME_ID',
236
- extraObjectId: '0xEXTRA_OBJECT_ID',
237
- stake: 1_000_000_000n,
238
412
  });
239
413
  ```
240
414
 
@@ -248,33 +422,61 @@ const tx = client.suigar.tx.createPvPCoinflipTransaction('cancel', {
248
422
  });
249
423
  ```
250
424
 
425
+ Join derives the stake from `gameId` and uses the configured price info object
426
+ id for `coinType`.
427
+
251
428
  PvP shared options:
252
429
 
253
430
  - `owner: string`
254
431
  - `coinType: string`
255
- - `metadata?: ...`
432
+ - `metadata?: Record<string, string | number | boolean | bigint | Uint8Array | number[] | null | undefined>`
256
433
  - `gasBudget?: number | bigint`
257
- - `sender?: string`
258
434
  - `allowGasCoinShortcut?: boolean`
259
435
 
260
436
  Action-specific options:
261
437
 
262
438
  - `create`: `stake`, `side`, `isPrivate?`
263
- - `join`: `gameId`, `extraObjectId`, `stake`
439
+ - `join`: `gameId`
264
440
  - `cancel`: `gameId`
265
441
 
442
+ Error behavior:
443
+
444
+ - `RangeError` when `action` is unsupported
445
+ - `RangeError` when `coinType` is not in the resolved supported-coin config for the active network
446
+
266
447
  ## `bcs`
267
448
 
268
449
  BCS helpers live under `client.suigar.bcs`.
269
450
 
270
451
  Current exposed helpers:
271
452
 
453
+ - `PvPCoinflipGame`
272
454
  - `BetResultEvent`
273
- - `PvPCoinflipGameCreated`
274
- - `PvPCoinflipGameResolved`
275
- - `PvPCoinflipGameCancelled`
455
+ - `PvPCoinflipGameCreatedEvent`
456
+ - `PvPCoinflipGameResolvedEvent`
457
+ - `PvPCoinflipGameCancelledEvent`
458
+
459
+ These are generated Move event decoders. Use them to parse Suigar event payloads from transaction results. The `@suigar/sdk/utils` subpath also exposes parser helpers for generated BCS values:
460
+
461
+ - `PvPCoinflipGame` parses a PvP coinflip game object's `content`
462
+ - `fromMoveI64(float.exp)` converts a generated Move `i64` exponent to a JavaScript number
463
+ - `fromMoveFloat(float)` converts a generated Move `Float` struct to a JavaScript number
464
+ - `parseCoinType(type)` extracts the normalized coin type from generic Move object type strings such as PvP coinflip `Game<T>`
465
+ and throws `TypeError` when the type string does not include a first generic coin type
466
+ - `parseGameDetails(gameId, game_details)` decodes `BetResultEvent.game_details` entries into the expected string, number, and boolean values
467
+
468
+ ### Parse PvP Coinflip Game Object Data
469
+
470
+ Use the generated BCS helper when you want to fetch and parse a game object:
276
471
 
277
- These are generated Move event decoders. Use them to parse Suigar event payloads from transaction results.
472
+ ```ts
473
+ const game = await client.suigar.bcs.PvPCoinflipGame.get({
474
+ client,
475
+ objectId: '0xGAME_ID',
476
+ });
477
+
478
+ console.log(game.json);
479
+ ```
278
480
 
279
481
  ### Parse Standard Bet Result Data
280
482
 
@@ -295,14 +497,13 @@ const finalResult = await client.core.waitForTransaction({
295
497
  },
296
498
  });
297
499
 
298
- if (finalResult.Transaction) {
299
- console.log(finalResult.Transaction.digest);
300
- } else if (finalResult.FailedTransaction) {
301
- throw new Error(finalResult.FailedTransaction.status.error.message);
500
+ if (finalResult.$kind === 'FailedTransaction') {
501
+ throw new Error(finalResult.FailedTransaction.status.error?.message);
302
502
  }
303
503
 
304
- const transactionResult =
305
- finalResult.Transaction ?? finalResult.FailedTransaction;
504
+ console.log(finalResult.Transaction.digest);
505
+
506
+ const transactionResult = finalResult.Transaction;
306
507
 
307
508
  const betResults = [];
308
509
 
@@ -327,39 +528,79 @@ Parsed fields include:
327
528
  - `game_details`
328
529
  - `metadata`
329
530
 
330
- `game_details` and `metadata` decode as `VecMap<string, vector<u8>>`-shaped data, so values come back as byte arrays.
531
+ `game_details` and `metadata` decode as `VecMap<string, vector<u8>>`-shaped data, so values come back as byte arrays. Use `parseGameEvent(event)` from `@suigar/sdk/utils` to retrieve the normalized `gameId` and `eventName`, then pass that `gameId` to `parseGameDetails(gameId, decoded.game_details)` for game-specific key and value typing.
331
532
 
332
533
  ```ts
333
- const textDecoder = new TextDecoder();
534
+ import { parseGameDetails, parseGameEvent } from '@suigar/sdk/utils';
334
535
 
335
- const metadata = new Map(
336
- decoded.metadata.contents.map(({ key, value }) => [
337
- key,
338
- textDecoder.decode(new Uint8Array(value)),
339
- ]),
340
- );
536
+ const { gameId, eventName } = parseGameEvent(event)!;
537
+ const decoded = client.suigar.bcs.BetResultEvent.parse(event.bcs);
538
+ const gameDetails = parseGameDetails(gameId, decoded.game_details);
341
539
  ```
342
540
 
343
- Important:
541
+ `parseGameDetails` preserves the on-chain keys and only changes the value representation. For example, coinflip details keep keys such as `player_bet` and `coin_outcome`; range details keep keys such as `roll_value`, `win`, and `payout_multiplier`.
542
+
543
+ `parseGameDetails(gameId, decoded.game_details)` narrows based on the parsed event game id. For example, when `gameId === 'coinflip'` it narrows to:
544
+
545
+ - `{ player_bet: string; coin_outcome: string }`
546
+
547
+ `parseGameEvent(event)` returns the normalized game id and raw Move event name for every supported Suigar event in `GAME_EVENTS`:
548
+
549
+ - `{ gameId: 'coinflip' | 'limbo' | 'plinko' | 'range' | 'wheel', eventName: 'BetResultEvent' }` for standard bet result events
550
+ - `{ gameId: 'pvp-coinflip', eventName: 'GameCreatedEvent' | 'GameResolvedEvent' | 'GameCancelledEvent' }` for PvP coinflip events
551
+ - `null` for unsupported event names or non-Suigar event payloads
344
552
 
345
- - execute or wait for the transaction with `include: { events: true }`
346
- - parse emitted events from `result.Transaction.events` or `result.FailedTransaction.events`
347
- - use `event.bcs` for consistent decoding across transports
348
- - `waitForTransaction({ result, include: { effects: true, events: true } })` is useful when you want the finalized transaction result before decoding
349
- - these helpers decode the event payload itself, not a full transaction response
553
+ When the extension is configured with `partner`, decoded event `metadata` will
554
+ contain that partner wallet address under the `partner` entry.
555
+
556
+ > **Important:**
557
+ >
558
+ > - execute or wait for the transaction with `include: { events: true }`
559
+ > - unwrap the core API union with `result.$kind`, `result.Transaction`, and `result.FailedTransaction`
560
+ > - parse emitted events from the unwrapped transaction result
561
+ > - use `event.bcs` for consistent decoding across transports
562
+ > - use `const { gameId } = parseGameEvent(event)!` and then `parseGameDetails(gameId, decoded.game_details)` instead of hand-decoding standard game detail byte arrays
563
+
564
+ > **Tip:**
565
+ >
566
+ > - `waitForTransaction({ result, include: { effects: true, events: true } })` is useful when you want the finalized transaction result before decoding
567
+ > - these helpers decode the event payload itself, not a full transaction response
350
568
 
351
569
  ### Parse PvP Coinflip Event Data
352
570
 
353
571
  Use the matching helper for each PvP coinflip event payload found in `transactionResult.events`:
354
572
 
355
- - `client.suigar.bcs.PvPCoinflipGameCreated`
356
- - `client.suigar.bcs.PvPCoinflipGameResolved`
357
- - `client.suigar.bcs.PvPCoinflipGameCancelled`
573
+ - `client.suigar.bcs.PvPCoinflipGameCreatedEvent`
574
+ - `client.suigar.bcs.PvPCoinflipGameResolvedEvent`
575
+ - `client.suigar.bcs.PvPCoinflipGameCancelledEvent`
358
576
 
359
577
  ## Development
360
578
 
361
579
  ```bash
362
- npm run build
363
- npm run typecheck
364
- npm test
580
+ pnpm --dir packages/sdk build
581
+ pnpm --dir packages/sdk typecheck
582
+ pnpm --dir packages/sdk test
583
+ ```
584
+
585
+ ## Example App
586
+
587
+ This repository includes a Next.js integration playground in [playground](../../playground).
588
+
589
+ It demonstrates:
590
+
591
+ - standard game transactions through `client.suigar.tx.createBetTransaction(...)`
592
+ - PvP coinflip create, join, and cancel flows through `client.suigar.tx.createPvPCoinflipTransaction(...)`, exposed in the example through a PvP coinflip action selector
593
+ - unresolved PvP lobby browsing through `client.suigar.getPvPCoinflipGames(...)`, including public join cards while disconnected, an optional private-lobby join toggle, and connected-wallet filtering for cancel
594
+ - wallet connection and execution with `@mysten/dapp-kit-core` and `@mysten/dapp-kit-react`
595
+ - supported coin selection from `client.suigar.getConfig()`
596
+ - connected-wallet balance display for each supported coin in the example app
597
+ - privacy badges and copyable PvP game ids in the lobby UI
598
+ - decoding `BetResultEvent` and PvP events into a persistent event log
599
+ - parsing `BetResultEvent.game_details` with `parseGameDetails`
600
+
601
+ Run it from the repo root with:
602
+
603
+ ```bash
604
+ pnpm install
605
+ pnpm turbo run dev --filter='./playground'
365
606
  ```