@suigar/sdk 2.0.0-beta.1 → 2.0.0-beta.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +123 -0
- package/README.md +324 -111
- package/dist/chunk-TBJ5TYYE.js +341 -0
- package/dist/games-BHYRg31e.d.cts +98 -0
- package/dist/games-BHYRg31e.d.ts +98 -0
- package/dist/games.cjs +2 -0
- package/dist/games.d.cts +2 -0
- package/dist/games.d.ts +2 -0
- package/dist/games.js +1 -0
- package/dist/index-3P_LBbDM.d.cts +25 -0
- package/dist/index-3P_LBbDM.d.ts +25 -0
- package/dist/index.cjs +1082 -363
- package/dist/index.d.cts +390 -218
- package/dist/index.d.ts +390 -218
- package/dist/index.js +962 -461
- package/dist/utils.cjs +241 -0
- package/dist/utils.d.cts +180 -0
- package/dist/utils.d.ts +180 -0
- package/dist/utils.js +1 -0
- package/package.json +81 -79
package/README.md
CHANGED
|
@@ -5,31 +5,92 @@ 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
13
|
- Node.js `>=22`
|
|
14
|
-
-
|
|
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
|
|
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
|
-
|
|
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
|
+
- `toU8(value)` accepts a finite integer `number` or plain integer `string` in
|
|
60
|
+
the inclusive `0..255` range and rejects booleans or fractional values
|
|
61
|
+
- `toU16(value)` accepts a finite integer `number` or plain integer `string`
|
|
62
|
+
in the inclusive `0..65535` range and rejects booleans or fractional values
|
|
63
|
+
- `fromMoveI64(value)` converts a generated Move `i64` wrapper into a
|
|
64
|
+
JavaScript `number`
|
|
65
|
+
- `fromMoveFloat(value)` converts a generated Move float struct into a
|
|
66
|
+
JavaScript `number`
|
|
67
|
+
- `parseGameDetails(gameDetails)` decodes standard `BetResultEvent.game_details`
|
|
68
|
+
byte arrays into the expected string, number, and boolean values while
|
|
69
|
+
preserving the original onchain keys
|
|
70
|
+
|
|
71
|
+
Game-specific type exports are available from the dedicated `games` subpath:
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
import type {
|
|
75
|
+
BuildCoinflipTransactionOptions,
|
|
76
|
+
BuildCreatePvPCoinflipTransactionOptions,
|
|
77
|
+
CoinSide,
|
|
78
|
+
PvPCoinflipAction,
|
|
79
|
+
} from '@suigar/sdk/games';
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Current game-type subpath exports:
|
|
83
|
+
|
|
84
|
+
- `@suigar/sdk/games`: `CoinSide`, `PvPCoinflipAction`, `BuildCoinflipTransactionOptions`, `BuildLimboTransactionOptions`, `BuildPlinkoTransactionOptions`, `BuildRangeTransactionOptions`, `BuildWheelTransactionOptions`, `BuildCreatePvPCoinflipTransactionOptions`, `BuildJoinPvPCoinflipTransactionOptions`, `BuildCancelPvPCoinflipTransactionOptions`
|
|
26
85
|
|
|
27
86
|
What you actually use at runtime is the registered extension instance:
|
|
28
87
|
|
|
29
88
|
```ts
|
|
30
|
-
const client = new
|
|
89
|
+
const client = new SuiGrpcClient({ baseUrl, network }).$extend(suigar());
|
|
31
90
|
|
|
32
91
|
client.suigar.serializeTransactionToBase64(...);
|
|
92
|
+
client.suigar.getConfig();
|
|
93
|
+
client.suigar.getPvPCoinflipGames(...);
|
|
33
94
|
client.suigar.bcs;
|
|
34
95
|
client.suigar.tx;
|
|
35
96
|
```
|
|
@@ -37,22 +98,16 @@ client.suigar.tx;
|
|
|
37
98
|
## Quick Start
|
|
38
99
|
|
|
39
100
|
```ts
|
|
40
|
-
import {
|
|
101
|
+
import { SuiGrpcClient } from '@mysten/sui/grpc';
|
|
41
102
|
import { suigar } from '@suigar/sdk';
|
|
42
103
|
|
|
43
|
-
const client = new
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
pyth: {
|
|
48
|
-
suiPriceInfoObjectId: '0xPYTH_SUI_PRICE_INFO',
|
|
49
|
-
usdcPriceInfoObjectId: '0xPYTH_USDC_PRICE_INFO',
|
|
50
|
-
},
|
|
51
|
-
}),
|
|
52
|
-
);
|
|
104
|
+
const client = new SuiGrpcClient({
|
|
105
|
+
baseUrl: 'https://fullnode.testnet.sui.io:443',
|
|
106
|
+
network: 'testnet',
|
|
107
|
+
}).$extend(suigar());
|
|
53
108
|
|
|
54
109
|
const tx = client.suigar.tx.createBetTransaction('coinflip', {
|
|
55
|
-
|
|
110
|
+
playerAddress: '0x123',
|
|
56
111
|
coinType: '0x2::sui::SUI',
|
|
57
112
|
stake: 1_000_000_000n,
|
|
58
113
|
side: 'heads',
|
|
@@ -67,78 +122,114 @@ const base64 = await client.suigar.serializeTransactionToBase64(tx);
|
|
|
67
122
|
|
|
68
123
|
Creates a named Sui client extension. By default, it registers under `client.suigar`.
|
|
69
124
|
|
|
125
|
+
### Partner Setup
|
|
126
|
+
|
|
127
|
+
> **Important:** `partner` is the partner wallet address. Configure it once
|
|
128
|
+
> when you register the extension so the SDK can prepend that wallet address to
|
|
129
|
+
> supported bet metadata automatically.
|
|
130
|
+
|
|
70
131
|
```ts
|
|
71
|
-
const client = new
|
|
132
|
+
const client = new SuiGrpcClient({ baseUrl, network }).$extend(
|
|
133
|
+
suigar({ partner: '0xpartner_wallet_address' }),
|
|
134
|
+
);
|
|
72
135
|
|
|
73
136
|
client.suigar;
|
|
74
137
|
```
|
|
75
138
|
|
|
139
|
+
Do not pass a partner slug, label, or display name here. Use the wallet
|
|
140
|
+
address that should receive partner attribution onchain.
|
|
141
|
+
|
|
76
142
|
You can rename the extension:
|
|
77
143
|
|
|
78
144
|
```ts
|
|
79
|
-
const client = new
|
|
145
|
+
const client = new SuiGrpcClient({ baseUrl, network }).$extend(
|
|
146
|
+
suigar({ name: 'games' }),
|
|
147
|
+
);
|
|
80
148
|
|
|
81
|
-
client.
|
|
82
|
-
client.
|
|
149
|
+
client.games.tx;
|
|
150
|
+
client.games.bcs;
|
|
83
151
|
```
|
|
84
152
|
|
|
85
153
|
## Config
|
|
86
154
|
|
|
87
155
|
`suigar(options?)` resolves config from:
|
|
88
156
|
|
|
89
|
-
-
|
|
90
|
-
- internal
|
|
91
|
-
- internal
|
|
92
|
-
-
|
|
93
|
-
-
|
|
157
|
+
- internal package ids by network
|
|
158
|
+
- internal supported coin types by network
|
|
159
|
+
- internal price info object ids by network
|
|
160
|
+
- the connected client network
|
|
161
|
+
- the extension name
|
|
94
162
|
|
|
95
163
|
Supported override areas:
|
|
96
164
|
|
|
97
165
|
- `name`
|
|
98
|
-
- `
|
|
99
|
-
- `
|
|
100
|
-
- `coinTypes.usdc`
|
|
101
|
-
- `coinTypes.usdcFlowx`
|
|
102
|
-
- `gamesPackageId.coinflip`
|
|
103
|
-
- `gamesPackageId.limbo`
|
|
104
|
-
- `gamesPackageId.plinko`
|
|
105
|
-
- `gamesPackageId['pvp-coinflip']`
|
|
106
|
-
- `gamesPackageId.range`
|
|
107
|
-
- `gamesPackageId.wheel`
|
|
108
|
-
- `pyth.packageId`
|
|
109
|
-
- `pyth.suiPriceInfoObjectId`
|
|
110
|
-
- `pyth.usdcPriceInfoObjectId`
|
|
111
|
-
- `pyth.priceInfoObjectIds[coinType]`
|
|
112
|
-
|
|
113
|
-
Example:
|
|
166
|
+
- `partner`
|
|
167
|
+
- `cacheTtl`
|
|
114
168
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
priceInfoObjectIds: {
|
|
123
|
-
'0x123::custom::TOKEN': '0xprice',
|
|
124
|
-
},
|
|
125
|
-
},
|
|
126
|
-
gamesPackageId: {
|
|
127
|
-
coinflip: '0xcoinflip',
|
|
128
|
-
wheel: '0xwheel',
|
|
129
|
-
},
|
|
130
|
-
}),
|
|
131
|
-
);
|
|
132
|
-
```
|
|
169
|
+
If `partner` is configured, the SDK automatically writes that partner wallet
|
|
170
|
+
address into the onchain metadata vec-map. Transaction builder options may also
|
|
171
|
+
include `metadata`, but reserved keys such as `partner` and `referrer` are
|
|
172
|
+
ignored with a warning when provided manually.
|
|
173
|
+
|
|
174
|
+
`cacheTtl` controls the SDK cache for onchain reads such as parsed game
|
|
175
|
+
parameters. It is expressed in milliseconds and defaults to 30 minutes.
|
|
133
176
|
|
|
134
177
|
## Runtime Surface
|
|
135
178
|
|
|
136
|
-
The registered extension instance exposes
|
|
179
|
+
The registered extension instance exposes the main runtime surface:
|
|
137
180
|
|
|
181
|
+
- `getConfig()`
|
|
182
|
+
- `getGameParameters(game, options?)`
|
|
138
183
|
- `serializeTransactionToBase64(transaction, options?)`
|
|
184
|
+
- `getPvPCoinflipGames(options?)`
|
|
139
185
|
- `bcs`
|
|
140
186
|
- `tx`
|
|
141
187
|
|
|
188
|
+
### `getConfig()`
|
|
189
|
+
|
|
190
|
+
Returns the resolved SDK configuration for the connected network.
|
|
191
|
+
|
|
192
|
+
This is intended mainly for debugging and inspection, for example to verify the
|
|
193
|
+
resolved package ids or supported coin mappings for the active client network.
|
|
194
|
+
|
|
195
|
+
It includes:
|
|
196
|
+
|
|
197
|
+
- `packageIds`
|
|
198
|
+
- `registryIds`
|
|
199
|
+
- `coinTypes`
|
|
200
|
+
- `priceInfoObjectIds`
|
|
201
|
+
|
|
202
|
+
```ts
|
|
203
|
+
const config = client.suigar.getConfig();
|
|
204
|
+
console.log(config.packageIds);
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### `getGameParameters(game, options?)`
|
|
208
|
+
|
|
209
|
+
Returns the onchain `Parameters<T>` object for any supported game and coin type.
|
|
210
|
+
The return type is inferred from `game`.
|
|
211
|
+
|
|
212
|
+
The SDK first reads the selected game's settings object from the configured
|
|
213
|
+
SweetHouse object, then reads that game's coin-specific `Parameters<T>` object.
|
|
214
|
+
This is useful for displaying or validating current limits such as min/max
|
|
215
|
+
stake, house edge, or game-specific config bounds. The parsed result is cached
|
|
216
|
+
using the extension `cacheTtl`.
|
|
217
|
+
|
|
218
|
+
When a parameter field is a generated Move float struct, such as
|
|
219
|
+
`min_target_multiplier`, `max_target_multiplier`, `min_rtp`, or `max_rtp`, use
|
|
220
|
+
`fromMoveFloat()` before treating it as a normal JavaScript number.
|
|
221
|
+
|
|
222
|
+
```ts
|
|
223
|
+
const parameters = await client.suigar.getGameParameters('coinflip', {
|
|
224
|
+
coinType: '0x2::sui::SUI',
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
console.log(parameters.min_stake);
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
Pass `ignoreCache: true` to refresh the onchain read and replace the cached
|
|
231
|
+
value.
|
|
232
|
+
|
|
142
233
|
### `serializeTransactionToBase64(transaction, options?)`
|
|
143
234
|
|
|
144
235
|
Builds a transaction with the configured Sui client and returns base64-encoded transaction bytes.
|
|
@@ -149,6 +240,42 @@ Use this when you need a transport-safe payload for a wallet, API, or external s
|
|
|
149
240
|
const base64 = await client.suigar.serializeTransactionToBase64(tx);
|
|
150
241
|
```
|
|
151
242
|
|
|
243
|
+
### `getPvPCoinflipGames(options?)`
|
|
244
|
+
|
|
245
|
+
Lists unresolved PvP coinflip games from the configured PvP registry.
|
|
246
|
+
|
|
247
|
+
This reads the registry dynamic fields for the active network and resolves each
|
|
248
|
+
entry into parsed game state through a bulk `client.core.getObjects()` lookup.
|
|
249
|
+
Registry membership is the unresolved-state signal: once a match is joined and
|
|
250
|
+
resolved, the Move flow removes it from the registry and deletes the live
|
|
251
|
+
`Game` object.
|
|
252
|
+
|
|
253
|
+
Use this when a product needs the current set of open PvP coinflip matches for
|
|
254
|
+
browsing or lobby views.
|
|
255
|
+
|
|
256
|
+
By default, per-object fetch or parse failures are skipped so one broken or
|
|
257
|
+
already-deleted registry entry does not reject the full lookup. Pass
|
|
258
|
+
`throwOnError: true` if you want the call to reject instead.
|
|
259
|
+
|
|
260
|
+
Any supported `listDynamicFields()` options such as `limit`, `cursor`, or
|
|
261
|
+
`signal` can be passed through `options`.
|
|
262
|
+
|
|
263
|
+
```ts
|
|
264
|
+
const games = await client.suigar.getPvPCoinflipGames({ limit: 20 });
|
|
265
|
+
|
|
266
|
+
for (const game of games) {
|
|
267
|
+
console.log(game.id);
|
|
268
|
+
console.log(game.coinType);
|
|
269
|
+
}
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
```ts
|
|
273
|
+
const games = await client.suigar.getPvPCoinflipGames({
|
|
274
|
+
limit: 20,
|
|
275
|
+
throwOnError: true,
|
|
276
|
+
});
|
|
277
|
+
```
|
|
278
|
+
|
|
152
279
|
## `tx`
|
|
153
280
|
|
|
154
281
|
Transaction builders live under `client.suigar.tx`.
|
|
@@ -165,7 +292,7 @@ Use `createBetTransaction(gameId, options)` for:
|
|
|
165
292
|
|
|
166
293
|
```ts
|
|
167
294
|
const tx = client.suigar.tx.createBetTransaction('coinflip', {
|
|
168
|
-
|
|
295
|
+
playerAddress: '0x123',
|
|
169
296
|
coinType: '0x2::sui::SUI',
|
|
170
297
|
stake: 1_000_000_000n,
|
|
171
298
|
side: 'tails',
|
|
@@ -174,14 +301,13 @@ const tx = client.suigar.tx.createBetTransaction('coinflip', {
|
|
|
174
301
|
|
|
175
302
|
Shared option shape:
|
|
176
303
|
|
|
177
|
-
- `
|
|
304
|
+
- `playerAddress: string`
|
|
178
305
|
- `coinType: string`
|
|
179
306
|
- `stake: number | bigint`
|
|
180
307
|
- `cashStake?: number | bigint`
|
|
181
308
|
- `betCount?: number | bigint`
|
|
182
309
|
- `metadata?: Record<string, string | number | boolean | bigint | Uint8Array | number[] | null | undefined>`
|
|
183
310
|
- `gasBudget?: number | bigint`
|
|
184
|
-
- `sender?: string`
|
|
185
311
|
- `allowGasCoinShortcut?: boolean`
|
|
186
312
|
|
|
187
313
|
Shared behavior:
|
|
@@ -189,10 +315,11 @@ Shared behavior:
|
|
|
189
315
|
- `stake` is the logical stake passed into the Move call
|
|
190
316
|
- `cashStake` controls the withdrawn balance and defaults to `stake`
|
|
191
317
|
- `betCount` defaults to `1`
|
|
192
|
-
- `sender` overrides the transaction sender
|
|
193
318
|
- `metadata` is encoded into `keys` and `values` byte arrays
|
|
194
|
-
-
|
|
195
|
-
-
|
|
319
|
+
- `partner` configured via `suigar({ partner })` is prepended automatically to metadata as the partner wallet address
|
|
320
|
+
- `metadata.partner` and `metadata.referrer` are reserved and ignored with a warning
|
|
321
|
+
- the SDK resolves the price info object from the configured supported-coin mapping
|
|
322
|
+
- the reward object is transferred back to `playerAddress`
|
|
196
323
|
|
|
197
324
|
Per-game options:
|
|
198
325
|
|
|
@@ -206,27 +333,35 @@ Examples:
|
|
|
206
333
|
|
|
207
334
|
```ts
|
|
208
335
|
const limboTx = client.suigar.tx.createBetTransaction('limbo', {
|
|
209
|
-
|
|
336
|
+
playerAddress: '0x123',
|
|
210
337
|
coinType: '0x2::sui::SUI',
|
|
211
338
|
stake: 1_000_000_000n,
|
|
212
339
|
targetMultiplier: 2.5,
|
|
213
340
|
});
|
|
214
341
|
|
|
215
342
|
const rangeTx = client.suigar.tx.createBetTransaction('range', {
|
|
216
|
-
|
|
343
|
+
playerAddress: '0x123',
|
|
217
344
|
coinType: '0x2::sui::SUI',
|
|
218
345
|
stake: 1_000_000_000n,
|
|
219
|
-
leftPoint:
|
|
220
|
-
rightPoint:
|
|
346
|
+
leftPoint: 25,
|
|
347
|
+
rightPoint: 75,
|
|
221
348
|
outOfRange: false,
|
|
222
349
|
});
|
|
223
350
|
```
|
|
224
351
|
|
|
225
|
-
|
|
352
|
+
> **Note:**
|
|
353
|
+
>
|
|
354
|
+
> - limbo converts `targetMultiplier` with `Math.round(targetMultiplier * scale)`
|
|
355
|
+
> - with the default limbo scale `100`, exposed as `DEFAULT_LIMBO_MULTIPLIER_SCALE`, a target multiplier of `2.5` becomes `250` onchain
|
|
356
|
+
> - range converts each point with `Math.round(value * scale)`
|
|
357
|
+
> - range points are bounded by the contract limit exposed as `RANGE_POINT_LIMIT`
|
|
358
|
+
> - with the default range scale `1_000_000`, exposed as `DEFAULT_RANGE_SCALE`, valid UI values are `0` to `100`
|
|
359
|
+
> - plinko and wheel `configId` must fit in `u8`
|
|
226
360
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
-
|
|
361
|
+
> **Tip:**
|
|
362
|
+
>
|
|
363
|
+
> - if you set `scale` to `10_000_000`, valid UI values become `0` to `10`
|
|
364
|
+
> - do not pre-scale range points before passing them to the SDK; pass the human value and let the SDK scale it once
|
|
230
365
|
|
|
231
366
|
### PvP Coinflip
|
|
232
367
|
|
|
@@ -240,7 +375,7 @@ Create:
|
|
|
240
375
|
|
|
241
376
|
```ts
|
|
242
377
|
const tx = client.suigar.tx.createPvPCoinflipTransaction('create', {
|
|
243
|
-
|
|
378
|
+
playerAddress: '0x123',
|
|
244
379
|
coinType: '0x2::sui::SUI',
|
|
245
380
|
stake: 1_000_000_000n,
|
|
246
381
|
side: 'heads',
|
|
@@ -252,11 +387,9 @@ Join:
|
|
|
252
387
|
|
|
253
388
|
```ts
|
|
254
389
|
const tx = client.suigar.tx.createPvPCoinflipTransaction('join', {
|
|
255
|
-
|
|
390
|
+
playerAddress: '0x123',
|
|
256
391
|
coinType: '0x2::sui::SUI',
|
|
257
392
|
gameId: '0xGAME_ID',
|
|
258
|
-
extraObjectId: '0xEXTRA_OBJECT_ID',
|
|
259
|
-
stake: 1_000_000_000n,
|
|
260
393
|
});
|
|
261
394
|
```
|
|
262
395
|
|
|
@@ -264,25 +397,27 @@ Cancel:
|
|
|
264
397
|
|
|
265
398
|
```ts
|
|
266
399
|
const tx = client.suigar.tx.createPvPCoinflipTransaction('cancel', {
|
|
267
|
-
|
|
400
|
+
playerAddress: '0x123',
|
|
268
401
|
coinType: '0x2::sui::SUI',
|
|
269
402
|
gameId: '0xGAME_ID',
|
|
270
403
|
});
|
|
271
404
|
```
|
|
272
405
|
|
|
406
|
+
Join derives the stake from `gameId` and uses the configured price info object
|
|
407
|
+
id for `coinType`.
|
|
408
|
+
|
|
273
409
|
PvP shared options:
|
|
274
410
|
|
|
275
|
-
- `
|
|
411
|
+
- `playerAddress: string`
|
|
276
412
|
- `coinType: string`
|
|
277
|
-
- `metadata?:
|
|
413
|
+
- `metadata?: Record<string, string | number | boolean | bigint | Uint8Array | number[] | null | undefined>`
|
|
278
414
|
- `gasBudget?: number | bigint`
|
|
279
|
-
- `sender?: string`
|
|
280
415
|
- `allowGasCoinShortcut?: boolean`
|
|
281
416
|
|
|
282
417
|
Action-specific options:
|
|
283
418
|
|
|
284
419
|
- `create`: `stake`, `side`, `isPrivate?`
|
|
285
|
-
- `join`: `gameId
|
|
420
|
+
- `join`: `gameId`
|
|
286
421
|
- `cancel`: `gameId`
|
|
287
422
|
|
|
288
423
|
## `bcs`
|
|
@@ -291,24 +426,70 @@ BCS helpers live under `client.suigar.bcs`.
|
|
|
291
426
|
|
|
292
427
|
Current exposed helpers:
|
|
293
428
|
|
|
429
|
+
- `PvPCoinflipGame`
|
|
294
430
|
- `BetResultEvent`
|
|
295
|
-
- `
|
|
296
|
-
- `
|
|
297
|
-
- `
|
|
431
|
+
- `PvPCoinflipGameCreatedEvent`
|
|
432
|
+
- `PvPCoinflipGameResolvedEvent`
|
|
433
|
+
- `PvPCoinflipGameCancelledEvent`
|
|
434
|
+
|
|
435
|
+
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:
|
|
436
|
+
|
|
437
|
+
- `PvPCoinflipGame` parses a PvP coinflip game object's `content`
|
|
438
|
+
- `fromMoveI64(float.exp)` converts a generated Move `i64` exponent to a JavaScript number
|
|
439
|
+
- `fromMoveFloat(float)` converts a generated Move `Float` struct to a JavaScript number
|
|
440
|
+
- `parseCoinType(type)` extracts the normalized coin type from generic Move object type strings such as PvP coinflip `Game<T>`
|
|
441
|
+
- `parseGameDetails(game_details)` decodes `BetResultEvent.game_details` entries into the expected string, number, and boolean values
|
|
442
|
+
|
|
443
|
+
### Parse PvP Coinflip Game Object Data
|
|
444
|
+
|
|
445
|
+
Use the generated BCS helper when you want to fetch and parse a game object:
|
|
446
|
+
|
|
447
|
+
```ts
|
|
448
|
+
const game = await client.suigar.bcs.PvPCoinflipGame.get({
|
|
449
|
+
client,
|
|
450
|
+
objectId: '0xGAME_ID',
|
|
451
|
+
});
|
|
298
452
|
|
|
299
|
-
|
|
453
|
+
console.log(game.json);
|
|
454
|
+
```
|
|
300
455
|
|
|
301
456
|
### Parse Standard Bet Result Data
|
|
302
457
|
|
|
303
458
|
```ts
|
|
304
|
-
const
|
|
305
|
-
|
|
459
|
+
const executeResult = await client.core.executeTransaction({
|
|
460
|
+
transaction: transactionBytes,
|
|
461
|
+
signatures: [signature],
|
|
306
462
|
include: {
|
|
307
|
-
|
|
463
|
+
events: true,
|
|
308
464
|
},
|
|
309
465
|
});
|
|
310
466
|
|
|
311
|
-
const
|
|
467
|
+
const finalResult = await client.core.waitForTransaction({
|
|
468
|
+
result: executeResult,
|
|
469
|
+
include: {
|
|
470
|
+
effects: true,
|
|
471
|
+
events: true,
|
|
472
|
+
},
|
|
473
|
+
});
|
|
474
|
+
|
|
475
|
+
if (finalResult.$kind === 'FailedTransaction') {
|
|
476
|
+
throw new Error(finalResult.FailedTransaction.status.error?.message);
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
console.log(finalResult.Transaction.digest);
|
|
480
|
+
|
|
481
|
+
const transactionResult = finalResult.Transaction;
|
|
482
|
+
|
|
483
|
+
const betResults = [];
|
|
484
|
+
|
|
485
|
+
for (const event of transactionResult.events ?? []) {
|
|
486
|
+
try {
|
|
487
|
+
const decoded = client.suigar.bcs.BetResultEvent.parse(event.bcs);
|
|
488
|
+
betResults.push(decoded);
|
|
489
|
+
} catch {
|
|
490
|
+
// Ignore non-BetResultEvent payloads.
|
|
491
|
+
}
|
|
492
|
+
}
|
|
312
493
|
```
|
|
313
494
|
|
|
314
495
|
Parsed fields include:
|
|
@@ -322,36 +503,68 @@ Parsed fields include:
|
|
|
322
503
|
- `game_details`
|
|
323
504
|
- `metadata`
|
|
324
505
|
|
|
325
|
-
`game_details` and `metadata` decode as `VecMap<string, vector<u8>>`-shaped data, so values come back as byte arrays.
|
|
506
|
+
`game_details` and `metadata` decode as `VecMap<string, vector<u8>>`-shaped data, so values come back as byte arrays. Use `parseGameDetails` from `@suigar/sdk/utils` to decode `game_details` with the SDK's known game-detail schemas.
|
|
326
507
|
|
|
327
508
|
```ts
|
|
328
|
-
|
|
509
|
+
import { parseGameDetails } from '@suigar/sdk/utils';
|
|
329
510
|
|
|
330
|
-
const
|
|
331
|
-
|
|
332
|
-
key,
|
|
333
|
-
textDecoder.decode(new Uint8Array(value)),
|
|
334
|
-
]),
|
|
335
|
-
);
|
|
511
|
+
const decoded = client.suigar.bcs.BetResultEvent.parse(event.bcs);
|
|
512
|
+
const gameDetails = parseGameDetails(decoded.game_details);
|
|
336
513
|
```
|
|
337
514
|
|
|
338
|
-
|
|
515
|
+
`parseGameDetails` preserves the onchain 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`.
|
|
516
|
+
|
|
517
|
+
When the extension is configured with `partner`, decoded event `metadata` will
|
|
518
|
+
contain that partner wallet address under the `partner` entry.
|
|
519
|
+
|
|
520
|
+
> **Important:**
|
|
521
|
+
>
|
|
522
|
+
> - execute or wait for the transaction with `include: { events: true }`
|
|
523
|
+
> - unwrap the core API union with `result.$kind`, `result.Transaction`, and `result.FailedTransaction`
|
|
524
|
+
> - parse emitted events from the unwrapped transaction result
|
|
525
|
+
> - use `event.bcs` for consistent decoding across transports
|
|
526
|
+
> - use `parseGameDetails(decoded.game_details)` instead of hand-decoding standard game detail byte arrays
|
|
339
527
|
|
|
340
|
-
|
|
341
|
-
|
|
528
|
+
> **Tip:**
|
|
529
|
+
>
|
|
530
|
+
> - `waitForTransaction({ result, include: { effects: true, events: true } })` is useful when you want the finalized transaction result before decoding
|
|
531
|
+
> - these helpers decode the event payload itself, not a full transaction response
|
|
342
532
|
|
|
343
533
|
### Parse PvP Coinflip Event Data
|
|
344
534
|
|
|
345
|
-
Use the matching helper for
|
|
535
|
+
Use the matching helper for each PvP coinflip event payload found in `transactionResult.events`:
|
|
346
536
|
|
|
347
|
-
- `client.suigar.bcs.
|
|
348
|
-
- `client.suigar.bcs.
|
|
349
|
-
- `client.suigar.bcs.
|
|
537
|
+
- `client.suigar.bcs.PvPCoinflipGameCreatedEvent`
|
|
538
|
+
- `client.suigar.bcs.PvPCoinflipGameResolvedEvent`
|
|
539
|
+
- `client.suigar.bcs.PvPCoinflipGameCancelledEvent`
|
|
350
540
|
|
|
351
541
|
## Development
|
|
352
542
|
|
|
353
543
|
```bash
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
544
|
+
pnpm --dir packages/sdk build
|
|
545
|
+
pnpm --dir packages/sdk typecheck
|
|
546
|
+
pnpm --dir packages/sdk test
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
## Example App
|
|
550
|
+
|
|
551
|
+
This repository includes a Next.js integration playground in [apps/playground](../../apps/playground).
|
|
552
|
+
|
|
553
|
+
It demonstrates:
|
|
554
|
+
|
|
555
|
+
- standard game transactions through `client.suigar.tx.createBetTransaction(...)`
|
|
556
|
+
- PvP coinflip create, join, and cancel flows through `client.suigar.tx.createPvPCoinflipTransaction(...)`, exposed in the example through a PvP coinflip action selector
|
|
557
|
+
- 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
|
|
558
|
+
- wallet connection and execution with `@mysten/dapp-kit-core` and `@mysten/dapp-kit-react`
|
|
559
|
+
- supported coin selection from `client.suigar.getConfig()`
|
|
560
|
+
- connected-wallet balance display for each supported coin in the example app
|
|
561
|
+
- privacy badges and copyable PvP game ids in the lobby UI
|
|
562
|
+
- decoding `BetResultEvent` and PvP events into a persistent event log
|
|
563
|
+
- parsing `BetResultEvent.game_details` with `parseGameDetails`
|
|
564
|
+
|
|
565
|
+
Run it from the repo root with:
|
|
566
|
+
|
|
567
|
+
```bash
|
|
568
|
+
pnpm install
|
|
569
|
+
pnpm turbo run dev --filter='./apps/playground'
|
|
357
570
|
```
|