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