@suigar/sdk 2.0.0-beta.1 → 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 +276 -111
- 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 +649 -363
- package/dist/index.d.cts +185 -224
- package/dist/index.d.ts +185 -224
- package/dist/index.js +536 -461
- 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
|
@@ -5,31 +5,75 @@ 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
|
+
} from '@suigar/sdk/utils';
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Game-specific type exports are available from the dedicated `games` subpath:
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
import type {
|
|
58
|
+
BuildCoinflipTransactionOptions,
|
|
59
|
+
BuildCreatePvPCoinflipTransactionOptions,
|
|
60
|
+
CoinSide,
|
|
61
|
+
PvPCoinflipAction,
|
|
62
|
+
} from '@suigar/sdk/games';
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Current game-type subpath exports:
|
|
66
|
+
|
|
67
|
+
- `@suigar/sdk/games`: `CoinSide`, `PvPCoinflipAction`, `BuildCoinflipTransactionOptions`, `BuildLimboTransactionOptions`, `BuildPlinkoTransactionOptions`, `BuildRangeTransactionOptions`, `BuildWheelTransactionOptions`, `BuildCreatePvPCoinflipTransactionOptions`, `BuildJoinPvPCoinflipTransactionOptions`, `BuildCancelPvPCoinflipTransactionOptions`
|
|
26
68
|
|
|
27
69
|
What you actually use at runtime is the registered extension instance:
|
|
28
70
|
|
|
29
71
|
```ts
|
|
30
|
-
const client = new
|
|
72
|
+
const client = new SuiGrpcClient({ baseUrl, network }).$extend(suigar());
|
|
31
73
|
|
|
32
74
|
client.suigar.serializeTransactionToBase64(...);
|
|
75
|
+
client.suigar.getConfig();
|
|
76
|
+
client.suigar.getPvPCoinflipGames(...);
|
|
33
77
|
client.suigar.bcs;
|
|
34
78
|
client.suigar.tx;
|
|
35
79
|
```
|
|
@@ -37,22 +81,16 @@ client.suigar.tx;
|
|
|
37
81
|
## Quick Start
|
|
38
82
|
|
|
39
83
|
```ts
|
|
40
|
-
import {
|
|
84
|
+
import { SuiGrpcClient } from '@mysten/sui/grpc';
|
|
41
85
|
import { suigar } from '@suigar/sdk';
|
|
42
86
|
|
|
43
|
-
const client = new
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
pyth: {
|
|
48
|
-
suiPriceInfoObjectId: '0xPYTH_SUI_PRICE_INFO',
|
|
49
|
-
usdcPriceInfoObjectId: '0xPYTH_USDC_PRICE_INFO',
|
|
50
|
-
},
|
|
51
|
-
}),
|
|
52
|
-
);
|
|
87
|
+
const client = new SuiGrpcClient({
|
|
88
|
+
baseUrl: 'https://fullnode.testnet.sui.io:443',
|
|
89
|
+
network: 'testnet',
|
|
90
|
+
}).$extend(suigar());
|
|
53
91
|
|
|
54
92
|
const tx = client.suigar.tx.createBetTransaction('coinflip', {
|
|
55
|
-
|
|
93
|
+
playerAddress: '0x123',
|
|
56
94
|
coinType: '0x2::sui::SUI',
|
|
57
95
|
stake: 1_000_000_000n,
|
|
58
96
|
side: 'heads',
|
|
@@ -67,78 +105,83 @@ const base64 = await client.suigar.serializeTransactionToBase64(tx);
|
|
|
67
105
|
|
|
68
106
|
Creates a named Sui client extension. By default, it registers under `client.suigar`.
|
|
69
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
|
+
|
|
70
114
|
```ts
|
|
71
|
-
const client = new
|
|
115
|
+
const client = new SuiGrpcClient({ baseUrl, network }).$extend(
|
|
116
|
+
suigar({ partner: '0xpartner_wallet_address' }),
|
|
117
|
+
);
|
|
72
118
|
|
|
73
119
|
client.suigar;
|
|
74
120
|
```
|
|
75
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
|
+
|
|
76
125
|
You can rename the extension:
|
|
77
126
|
|
|
78
127
|
```ts
|
|
79
|
-
const client = new
|
|
128
|
+
const client = new SuiGrpcClient({ baseUrl, network }).$extend(
|
|
129
|
+
suigar({ name: 'games' }),
|
|
130
|
+
);
|
|
80
131
|
|
|
81
|
-
client.
|
|
82
|
-
client.
|
|
132
|
+
client.games.tx;
|
|
133
|
+
client.games.bcs;
|
|
83
134
|
```
|
|
84
135
|
|
|
85
136
|
## Config
|
|
86
137
|
|
|
87
138
|
`suigar(options?)` resolves config from:
|
|
88
139
|
|
|
89
|
-
-
|
|
90
|
-
- internal
|
|
91
|
-
- internal
|
|
92
|
-
-
|
|
93
|
-
-
|
|
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
|
|
94
145
|
|
|
95
146
|
Supported override areas:
|
|
96
147
|
|
|
97
148
|
- `name`
|
|
98
|
-
- `
|
|
99
|
-
- `coinTypes.sui`
|
|
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:
|
|
149
|
+
- `partner`
|
|
114
150
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
pyth: {
|
|
120
|
-
suiPriceInfoObjectId: '0xsui',
|
|
121
|
-
usdcPriceInfoObjectId: '0xusdc',
|
|
122
|
-
priceInfoObjectIds: {
|
|
123
|
-
'0x123::custom::TOKEN': '0xprice',
|
|
124
|
-
},
|
|
125
|
-
},
|
|
126
|
-
gamesPackageId: {
|
|
127
|
-
coinflip: '0xcoinflip',
|
|
128
|
-
wheel: '0xwheel',
|
|
129
|
-
},
|
|
130
|
-
}),
|
|
131
|
-
);
|
|
132
|
-
```
|
|
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.
|
|
133
155
|
|
|
134
156
|
## Runtime Surface
|
|
135
157
|
|
|
136
|
-
The registered extension instance exposes
|
|
158
|
+
The registered extension instance exposes the main runtime surface:
|
|
137
159
|
|
|
160
|
+
- `getConfig()`
|
|
138
161
|
- `serializeTransactionToBase64(transaction, options?)`
|
|
162
|
+
- `getPvPCoinflipGames(options?)`
|
|
139
163
|
- `bcs`
|
|
140
164
|
- `tx`
|
|
141
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
|
+
|
|
142
185
|
### `serializeTransactionToBase64(transaction, options?)`
|
|
143
186
|
|
|
144
187
|
Builds a transaction with the configured Sui client and returns base64-encoded transaction bytes.
|
|
@@ -149,6 +192,42 @@ Use this when you need a transport-safe payload for a wallet, API, or external s
|
|
|
149
192
|
const base64 = await client.suigar.serializeTransactionToBase64(tx);
|
|
150
193
|
```
|
|
151
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
|
+
|
|
152
231
|
## `tx`
|
|
153
232
|
|
|
154
233
|
Transaction builders live under `client.suigar.tx`.
|
|
@@ -165,7 +244,7 @@ Use `createBetTransaction(gameId, options)` for:
|
|
|
165
244
|
|
|
166
245
|
```ts
|
|
167
246
|
const tx = client.suigar.tx.createBetTransaction('coinflip', {
|
|
168
|
-
|
|
247
|
+
playerAddress: '0x123',
|
|
169
248
|
coinType: '0x2::sui::SUI',
|
|
170
249
|
stake: 1_000_000_000n,
|
|
171
250
|
side: 'tails',
|
|
@@ -174,14 +253,13 @@ const tx = client.suigar.tx.createBetTransaction('coinflip', {
|
|
|
174
253
|
|
|
175
254
|
Shared option shape:
|
|
176
255
|
|
|
177
|
-
- `
|
|
256
|
+
- `playerAddress: string`
|
|
178
257
|
- `coinType: string`
|
|
179
258
|
- `stake: number | bigint`
|
|
180
259
|
- `cashStake?: number | bigint`
|
|
181
260
|
- `betCount?: number | bigint`
|
|
182
261
|
- `metadata?: Record<string, string | number | boolean | bigint | Uint8Array | number[] | null | undefined>`
|
|
183
262
|
- `gasBudget?: number | bigint`
|
|
184
|
-
- `sender?: string`
|
|
185
263
|
- `allowGasCoinShortcut?: boolean`
|
|
186
264
|
|
|
187
265
|
Shared behavior:
|
|
@@ -189,10 +267,11 @@ Shared behavior:
|
|
|
189
267
|
- `stake` is the logical stake passed into the Move call
|
|
190
268
|
- `cashStake` controls the withdrawn balance and defaults to `stake`
|
|
191
269
|
- `betCount` defaults to `1`
|
|
192
|
-
- `sender` overrides the transaction sender
|
|
193
270
|
- `metadata` is encoded into `keys` and `values` byte arrays
|
|
194
|
-
-
|
|
195
|
-
-
|
|
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`
|
|
196
275
|
|
|
197
276
|
Per-game options:
|
|
198
277
|
|
|
@@ -206,27 +285,35 @@ Examples:
|
|
|
206
285
|
|
|
207
286
|
```ts
|
|
208
287
|
const limboTx = client.suigar.tx.createBetTransaction('limbo', {
|
|
209
|
-
|
|
288
|
+
playerAddress: '0x123',
|
|
210
289
|
coinType: '0x2::sui::SUI',
|
|
211
290
|
stake: 1_000_000_000n,
|
|
212
291
|
targetMultiplier: 2.5,
|
|
213
292
|
});
|
|
214
293
|
|
|
215
294
|
const rangeTx = client.suigar.tx.createBetTransaction('range', {
|
|
216
|
-
|
|
295
|
+
playerAddress: '0x123',
|
|
217
296
|
coinType: '0x2::sui::SUI',
|
|
218
297
|
stake: 1_000_000_000n,
|
|
219
|
-
leftPoint:
|
|
220
|
-
rightPoint:
|
|
298
|
+
leftPoint: 25,
|
|
299
|
+
rightPoint: 75,
|
|
221
300
|
outOfRange: false,
|
|
222
301
|
});
|
|
223
302
|
```
|
|
224
303
|
|
|
225
|
-
|
|
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`
|
|
226
312
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
-
|
|
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
|
|
230
317
|
|
|
231
318
|
### PvP Coinflip
|
|
232
319
|
|
|
@@ -240,7 +327,7 @@ Create:
|
|
|
240
327
|
|
|
241
328
|
```ts
|
|
242
329
|
const tx = client.suigar.tx.createPvPCoinflipTransaction('create', {
|
|
243
|
-
|
|
330
|
+
playerAddress: '0x123',
|
|
244
331
|
coinType: '0x2::sui::SUI',
|
|
245
332
|
stake: 1_000_000_000n,
|
|
246
333
|
side: 'heads',
|
|
@@ -252,11 +339,9 @@ Join:
|
|
|
252
339
|
|
|
253
340
|
```ts
|
|
254
341
|
const tx = client.suigar.tx.createPvPCoinflipTransaction('join', {
|
|
255
|
-
|
|
342
|
+
playerAddress: '0x123',
|
|
256
343
|
coinType: '0x2::sui::SUI',
|
|
257
344
|
gameId: '0xGAME_ID',
|
|
258
|
-
extraObjectId: '0xEXTRA_OBJECT_ID',
|
|
259
|
-
stake: 1_000_000_000n,
|
|
260
345
|
});
|
|
261
346
|
```
|
|
262
347
|
|
|
@@ -264,25 +349,27 @@ Cancel:
|
|
|
264
349
|
|
|
265
350
|
```ts
|
|
266
351
|
const tx = client.suigar.tx.createPvPCoinflipTransaction('cancel', {
|
|
267
|
-
|
|
352
|
+
playerAddress: '0x123',
|
|
268
353
|
coinType: '0x2::sui::SUI',
|
|
269
354
|
gameId: '0xGAME_ID',
|
|
270
355
|
});
|
|
271
356
|
```
|
|
272
357
|
|
|
358
|
+
Join derives the stake from `gameId` and uses the configured price info object
|
|
359
|
+
id for `coinType`.
|
|
360
|
+
|
|
273
361
|
PvP shared options:
|
|
274
362
|
|
|
275
|
-
- `
|
|
363
|
+
- `playerAddress: string`
|
|
276
364
|
- `coinType: string`
|
|
277
|
-
- `metadata?:
|
|
365
|
+
- `metadata?: Record<string, string | number | boolean | bigint | Uint8Array | number[] | null | undefined>`
|
|
278
366
|
- `gasBudget?: number | bigint`
|
|
279
|
-
- `sender?: string`
|
|
280
367
|
- `allowGasCoinShortcut?: boolean`
|
|
281
368
|
|
|
282
369
|
Action-specific options:
|
|
283
370
|
|
|
284
371
|
- `create`: `stake`, `side`, `isPrivate?`
|
|
285
|
-
- `join`: `gameId
|
|
372
|
+
- `join`: `gameId`
|
|
286
373
|
- `cancel`: `gameId`
|
|
287
374
|
|
|
288
375
|
## `bcs`
|
|
@@ -291,24 +378,70 @@ BCS helpers live under `client.suigar.bcs`.
|
|
|
291
378
|
|
|
292
379
|
Current exposed helpers:
|
|
293
380
|
|
|
381
|
+
- `PvPCoinflipGame`
|
|
294
382
|
- `BetResultEvent`
|
|
295
|
-
- `
|
|
296
|
-
- `
|
|
297
|
-
- `
|
|
383
|
+
- `PvPCoinflipGameCreatedEvent`
|
|
384
|
+
- `PvPCoinflipGameResolvedEvent`
|
|
385
|
+
- `PvPCoinflipGameCancelledEvent`
|
|
298
386
|
|
|
299
|
-
These are generated Move
|
|
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:
|
|
388
|
+
|
|
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
|
|
394
|
+
|
|
395
|
+
### Parse PvP Coinflip Game Object Data
|
|
396
|
+
|
|
397
|
+
Use the generated BCS helper when you want to fetch and parse a game object:
|
|
398
|
+
|
|
399
|
+
```ts
|
|
400
|
+
const game = await client.suigar.bcs.PvPCoinflipGame.get({
|
|
401
|
+
client,
|
|
402
|
+
objectId: '0xGAME_ID',
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
console.log(game.json);
|
|
406
|
+
```
|
|
300
407
|
|
|
301
408
|
### Parse Standard Bet Result Data
|
|
302
409
|
|
|
303
410
|
```ts
|
|
304
|
-
const
|
|
305
|
-
|
|
411
|
+
const executeResult = await client.core.executeTransaction({
|
|
412
|
+
transaction: transactionBytes,
|
|
413
|
+
signatures: [signature],
|
|
306
414
|
include: {
|
|
307
|
-
|
|
415
|
+
events: true,
|
|
308
416
|
},
|
|
309
417
|
});
|
|
310
418
|
|
|
311
|
-
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
|
+
}
|
|
312
445
|
```
|
|
313
446
|
|
|
314
447
|
Parsed fields include:
|
|
@@ -322,36 +455,68 @@ Parsed fields include:
|
|
|
322
455
|
- `game_details`
|
|
323
456
|
- `metadata`
|
|
324
457
|
|
|
325
|
-
`game_details` and `metadata` decode as `VecMap<string, vector<u8>>`-shaped data, so values come back as byte arrays.
|
|
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.
|
|
326
459
|
|
|
327
460
|
```ts
|
|
328
|
-
|
|
461
|
+
import { parseGameDetails } from '@suigar/sdk/utils';
|
|
329
462
|
|
|
330
|
-
const
|
|
331
|
-
|
|
332
|
-
key,
|
|
333
|
-
textDecoder.decode(new Uint8Array(value)),
|
|
334
|
-
]),
|
|
335
|
-
);
|
|
463
|
+
const decoded = client.suigar.bcs.BetResultEvent.parse(event.bcs);
|
|
464
|
+
const gameDetails = parseGameDetails(decoded.game_details);
|
|
336
465
|
```
|
|
337
466
|
|
|
338
|
-
|
|
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`.
|
|
468
|
+
|
|
469
|
+
When the extension is configured with `partner`, decoded event `metadata` will
|
|
470
|
+
contain that partner wallet address under the `partner` entry.
|
|
339
471
|
|
|
340
|
-
|
|
341
|
-
|
|
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
|
|
479
|
+
|
|
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
|
|
342
484
|
|
|
343
485
|
### Parse PvP Coinflip Event Data
|
|
344
486
|
|
|
345
|
-
Use the matching helper for
|
|
487
|
+
Use the matching helper for each PvP coinflip event payload found in `transactionResult.events`:
|
|
346
488
|
|
|
347
|
-
- `client.suigar.bcs.
|
|
348
|
-
- `client.suigar.bcs.
|
|
349
|
-
- `client.suigar.bcs.
|
|
489
|
+
- `client.suigar.bcs.PvPCoinflipGameCreatedEvent`
|
|
490
|
+
- `client.suigar.bcs.PvPCoinflipGameResolvedEvent`
|
|
491
|
+
- `client.suigar.bcs.PvPCoinflipGameCancelledEvent`
|
|
350
492
|
|
|
351
493
|
## Development
|
|
352
494
|
|
|
353
495
|
```bash
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
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'
|
|
357
522
|
```
|