@suigar/sdk 2.0.0-beta.7 → 2.0.0-beta.9
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 +23 -0
- package/README.md +29 -20
- package/dist/{chunk-YGYMLRE4.js → chunk-FEQY5O43.js} +8 -16
- package/dist/{games--Haw_z7M.d.cts → games-BccpPyWd.d.cts} +19 -20
- package/dist/{games--Haw_z7M.d.ts → games-BccpPyWd.d.ts} +19 -20
- package/dist/games.d.cts +2 -1
- package/dist/games.d.ts +2 -1
- package/dist/{index-jwSXA8q3.d.ts → index-3P_LBbDM.d.cts} +4 -4
- package/dist/{index-jwSXA8q3.d.cts → index-3P_LBbDM.d.ts} +4 -4
- package/dist/index.cjs +83 -70
- package/dist/index.d.cts +15 -10
- package/dist/index.d.ts +15 -10
- package/dist/index.js +85 -72
- package/dist/utils.cjs +8 -16
- package/dist/utils.d.cts +58 -1
- package/dist/utils.d.ts +58 -1
- package/dist/utils.js +1 -1
- package/package.json +6 -7
package/dist/index.cjs
CHANGED
|
@@ -126,56 +126,44 @@ function resolvePriceInfoObjectId(config, coinType) {
|
|
|
126
126
|
const normalizedCoinType = utils.normalizeStructTag(coinType);
|
|
127
127
|
const supportedCoin = resolveSupportedCoin(config, normalizedCoinType);
|
|
128
128
|
const objectId = config.priceInfoObjectIds[supportedCoin];
|
|
129
|
-
if (objectId) {
|
|
130
|
-
|
|
129
|
+
if (!objectId) {
|
|
130
|
+
throw new Error(
|
|
131
|
+
`Missing price info object configuration for coin type ${coinType}`
|
|
132
|
+
);
|
|
131
133
|
}
|
|
132
|
-
|
|
133
|
-
`Missing price info object configuration for coin type ${coinType}`
|
|
134
|
-
);
|
|
134
|
+
return objectId;
|
|
135
135
|
}
|
|
136
136
|
function resolveSupportedCoin(config, coinType) {
|
|
137
|
-
const
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
137
|
+
const [supportedCoin] = Object.entries(config.coinTypes).find(([_, value]) => value === coinType) ?? [];
|
|
138
|
+
if (!supportedCoin) {
|
|
139
|
+
throw new Error(
|
|
140
|
+
`Unsupported coin type ${coinType}. Supported coin types: ${Object.values(
|
|
141
|
+
config.coinTypes
|
|
142
|
+
).join(", ")}`
|
|
143
|
+
);
|
|
143
144
|
}
|
|
144
|
-
|
|
145
|
-
`Unsupported coin type ${coinType}. Supported coin types: ${entries.map(([, configuredCoinType]) => configuredCoinType).join(", ")}`
|
|
146
|
-
);
|
|
145
|
+
return supportedCoin;
|
|
147
146
|
}
|
|
148
|
-
var
|
|
149
|
-
var RESERVED_METADATA_KEYS = /* @__PURE__ */ new Set([
|
|
147
|
+
var PARTNER_METADATA_KEY = "partner";
|
|
148
|
+
var RESERVED_METADATA_KEYS = /* @__PURE__ */ new Set([PARTNER_METADATA_KEY, "referrer"]);
|
|
150
149
|
var textEncoder = new TextEncoder();
|
|
151
150
|
function parseHexAddress(value) {
|
|
152
|
-
const trimmed = value.trim();
|
|
153
|
-
if (!trimmed || !utils.isValidSuiAddress(trimmed)) return null;
|
|
154
151
|
try {
|
|
155
|
-
|
|
156
|
-
const bytes = new Uint8Array(normalized.length / 2);
|
|
157
|
-
for (let index = 0; index < normalized.length; index += 2) {
|
|
158
|
-
bytes[index / 2] = Number.parseInt(
|
|
159
|
-
normalized.slice(index, index + 2),
|
|
160
|
-
16
|
|
161
|
-
);
|
|
162
|
-
}
|
|
163
|
-
return bytes;
|
|
152
|
+
return utils.fromHex(value);
|
|
164
153
|
} catch {
|
|
165
154
|
return null;
|
|
166
155
|
}
|
|
167
156
|
}
|
|
168
|
-
function encodeMetadataValue(
|
|
157
|
+
function encodeMetadataValue(value) {
|
|
169
158
|
if (value instanceof Uint8Array) {
|
|
170
159
|
return Array.from(value);
|
|
171
160
|
}
|
|
172
161
|
if (Array.isArray(value)) {
|
|
173
162
|
return value;
|
|
174
163
|
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
return Array.from(textEncoder.encode(String(value)));
|
|
164
|
+
return Array.from(
|
|
165
|
+
parseHexAddress(String(value)) ?? textEncoder.encode(String(value))
|
|
166
|
+
);
|
|
179
167
|
}
|
|
180
168
|
function encodeBetMetadata(metadata, partner) {
|
|
181
169
|
const keys = [];
|
|
@@ -191,14 +179,15 @@ function encodeBetMetadata(metadata, partner) {
|
|
|
191
179
|
continue;
|
|
192
180
|
}
|
|
193
181
|
keys.push(key);
|
|
194
|
-
values.push(encodeMetadataValue(
|
|
182
|
+
values.push(encodeMetadataValue(value));
|
|
195
183
|
}
|
|
196
|
-
if (
|
|
197
|
-
|
|
184
|
+
if (partner?.trim()) {
|
|
185
|
+
keys.unshift(PARTNER_METADATA_KEY);
|
|
186
|
+
values.unshift(encodeMetadataValue(partner));
|
|
198
187
|
}
|
|
199
188
|
return {
|
|
200
|
-
keys
|
|
201
|
-
values
|
|
189
|
+
keys,
|
|
190
|
+
values
|
|
202
191
|
};
|
|
203
192
|
}
|
|
204
193
|
var MOVE_STDLIB_ADDRESS = utils.normalizeSuiAddress("0x1");
|
|
@@ -413,20 +402,18 @@ var Float = new MoveStruct({ name: `${$moduleName2}::Float`, fields: {
|
|
|
413
402
|
function createBaseGameTransaction({
|
|
414
403
|
config,
|
|
415
404
|
game,
|
|
416
|
-
|
|
417
|
-
sender,
|
|
405
|
+
playerAddress,
|
|
418
406
|
gasBudget
|
|
419
407
|
}) {
|
|
420
408
|
assertConfiguredBetGame(config, game);
|
|
421
409
|
const tx = new transactions.Transaction();
|
|
422
|
-
tx.setSenderIfNotSet(utils.normalizeSuiAddress(
|
|
410
|
+
tx.setSenderIfNotSet(utils.normalizeSuiAddress(playerAddress));
|
|
423
411
|
tx.setGasBudgetIfNotSet(gasBudget ?? DEFAULT_GAS_BUDGET_MIST);
|
|
424
412
|
return tx;
|
|
425
413
|
}
|
|
426
414
|
function buildSharedStandardGameBetCall({
|
|
427
415
|
config,
|
|
428
|
-
|
|
429
|
-
sender,
|
|
416
|
+
playerAddress,
|
|
430
417
|
coinType,
|
|
431
418
|
stake,
|
|
432
419
|
cashStake,
|
|
@@ -437,7 +424,7 @@ function buildSharedStandardGameBetCall({
|
|
|
437
424
|
buildRewardCoin
|
|
438
425
|
}) {
|
|
439
426
|
return (tx) => {
|
|
440
|
-
const
|
|
427
|
+
const normalizedPlayerAddress = utils.normalizeSuiAddress(playerAddress);
|
|
441
428
|
const normalizedCoinType = utils.normalizeStructTag(coinType);
|
|
442
429
|
const resolvedStake = toBigInt(stake);
|
|
443
430
|
const resolvedCashStake = toBigInt(cashStake ?? stake);
|
|
@@ -455,7 +442,7 @@ function buildSharedStandardGameBetCall({
|
|
|
455
442
|
const rewardCoin = buildRewardCoin({
|
|
456
443
|
tx,
|
|
457
444
|
config,
|
|
458
|
-
|
|
445
|
+
playerAddress: normalizedPlayerAddress,
|
|
459
446
|
coinType: normalizedCoinType,
|
|
460
447
|
stake: resolvedStake,
|
|
461
448
|
cashStake: resolvedCashStake,
|
|
@@ -464,7 +451,7 @@ function buildSharedStandardGameBetCall({
|
|
|
464
451
|
priceInfoObjectId,
|
|
465
452
|
betCoin
|
|
466
453
|
});
|
|
467
|
-
tx.transferObjects([rewardCoin], tx.pure.address(
|
|
454
|
+
tx.transferObjects([rewardCoin], tx.pure.address(normalizedPlayerAddress));
|
|
468
455
|
return rewardCoin;
|
|
469
456
|
};
|
|
470
457
|
}
|
|
@@ -1019,39 +1006,53 @@ var SuigarClient = class {
|
|
|
1019
1006
|
* Lists unresolved PvP coinflip games from the configured registry and resolves
|
|
1020
1007
|
* each entry into parsed onchain game state.
|
|
1021
1008
|
*
|
|
1022
|
-
* This fetches dynamic fields from the PvP coinflip registry object, then
|
|
1023
|
-
*
|
|
1009
|
+
* This fetches dynamic fields from the PvP coinflip registry object, then bulk
|
|
1010
|
+
* loads the referenced game objects through `client.core.getObjects()`. Registry
|
|
1024
1011
|
* membership is the unresolved-state signal: when a game is joined and resolved,
|
|
1025
1012
|
* the Move flow removes it from the registry and deletes the live `Game` object.
|
|
1026
1013
|
* Use this when a product needs the current set of open PvP coinflip matches for
|
|
1027
1014
|
* browsing or lobby views.
|
|
1028
1015
|
*
|
|
1029
1016
|
* @param options Optional dynamic field pagination forwarded to `listDynamicFields()`, excluding `parentId`.
|
|
1030
|
-
*
|
|
1031
|
-
*
|
|
1032
|
-
*
|
|
1017
|
+
* Supported options such as `limit`, `cursor`, and `signal` are forwarded to the
|
|
1018
|
+
* underlying lookup calls. Pass `throwOnError: true` to fail the whole lookup
|
|
1019
|
+
* when any referenced game object cannot be fetched or parsed. By default,
|
|
1020
|
+
* failed per-object lookups are skipped and only successfully parsed unresolved
|
|
1021
|
+
* games are returned.
|
|
1033
1022
|
* @returns Parsed unresolved PvP coinflip game objects for the requested
|
|
1034
|
-
* registry page. When `throwOnError` is `false`, entries that fail
|
|
1035
|
-
*
|
|
1023
|
+
* registry page. When `throwOnError` is `false`, entries that fail object fetch
|
|
1024
|
+
* or parse are omitted from the returned array.
|
|
1036
1025
|
*/
|
|
1037
1026
|
async getPvPCoinflipGames(options = {
|
|
1038
1027
|
limit: 50
|
|
1039
1028
|
}) {
|
|
1040
1029
|
const { throwOnError = false, ...listOptions } = options;
|
|
1041
1030
|
const { dynamicFields } = await this.#client.core.listDynamicFields({
|
|
1042
|
-
|
|
1043
|
-
|
|
1031
|
+
...listOptions,
|
|
1032
|
+
parentId: this.#config.registryIds.pvpCoinflip
|
|
1033
|
+
});
|
|
1034
|
+
const { objects } = await this.#client.core.getObjects({
|
|
1035
|
+
objectIds: dynamicFields.map(({ childId }) => childId),
|
|
1036
|
+
signal: listOptions.signal,
|
|
1037
|
+
include: {
|
|
1038
|
+
content: true
|
|
1039
|
+
}
|
|
1040
|
+
});
|
|
1041
|
+
const resolvedGames = objects.map((object) => {
|
|
1042
|
+
try {
|
|
1043
|
+
return this.#resolvePvPCoinflipGameObject(object);
|
|
1044
|
+
} catch (error) {
|
|
1045
|
+
return error instanceof Error ? error : new Error(String(error));
|
|
1046
|
+
}
|
|
1044
1047
|
});
|
|
1045
1048
|
if (throwOnError) {
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
+
const firstError = resolvedGames.find((game) => game instanceof Error);
|
|
1050
|
+
if (firstError) {
|
|
1051
|
+
throw firstError;
|
|
1052
|
+
}
|
|
1049
1053
|
}
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
);
|
|
1053
|
-
return settledGames.flatMap(
|
|
1054
|
-
(result) => result.status === "fulfilled" ? [result.value] : []
|
|
1054
|
+
return resolvedGames.flatMap(
|
|
1055
|
+
(game) => game instanceof Error ? [] : [game]
|
|
1055
1056
|
);
|
|
1056
1057
|
}
|
|
1057
1058
|
/**
|
|
@@ -1065,21 +1066,19 @@ var SuigarClient = class {
|
|
|
1065
1066
|
* of a specific PvP coinflip match before rendering join, cancel, or result UI.
|
|
1066
1067
|
*
|
|
1067
1068
|
* @param gameId On-chain object id of the PvP coinflip game.
|
|
1069
|
+
* @param options Optional `getObject()` options forwarded to the underlying
|
|
1070
|
+
* client lookup, excluding `objectId` and `include`. Supported options include
|
|
1071
|
+
* `signal`.
|
|
1068
1072
|
* @returns Parsed PvP coinflip game state with a normalized `coinType`.
|
|
1069
1073
|
* @throws Error If the object cannot be decoded because no content was returned.
|
|
1070
1074
|
*/
|
|
1071
|
-
async resolvePvPConflipGame(gameId) {
|
|
1075
|
+
async resolvePvPConflipGame(gameId, options = {}) {
|
|
1072
1076
|
const { object } = await this.#client.core.getObject({
|
|
1077
|
+
...options,
|
|
1073
1078
|
objectId: gameId,
|
|
1074
1079
|
include: { content: true }
|
|
1075
1080
|
});
|
|
1076
|
-
|
|
1077
|
-
throw new Error("Unable to resolve PvP coinflip from game object");
|
|
1078
|
-
}
|
|
1079
|
-
return {
|
|
1080
|
-
...Game.parse(object.content),
|
|
1081
|
-
coinType: utils.normalizeStructTag(utils.parseStructTag(object.type).typeParams[0])
|
|
1082
|
-
};
|
|
1081
|
+
return this.#resolvePvPCoinflipGameObject(object);
|
|
1083
1082
|
}
|
|
1084
1083
|
/**
|
|
1085
1084
|
* BCS struct constructors for decoding on-chain objects and events related to Suigar games.
|
|
@@ -1209,6 +1208,20 @@ var SuigarClient = class {
|
|
|
1209
1208
|
});
|
|
1210
1209
|
};
|
|
1211
1210
|
}
|
|
1211
|
+
#resolvePvPCoinflipGameObject(object) {
|
|
1212
|
+
if (object instanceof Error) {
|
|
1213
|
+
throw object;
|
|
1214
|
+
}
|
|
1215
|
+
if (!object.content) {
|
|
1216
|
+
throw new Error(
|
|
1217
|
+
"Unable to resolve PvP coinflip game from retrieved object"
|
|
1218
|
+
);
|
|
1219
|
+
}
|
|
1220
|
+
return {
|
|
1221
|
+
...Game.parse(object.content),
|
|
1222
|
+
coinType: utils.normalizeStructTag(utils.parseStructTag(object.type).typeParams[0])
|
|
1223
|
+
};
|
|
1224
|
+
}
|
|
1212
1225
|
};
|
|
1213
1226
|
|
|
1214
1227
|
exports.SuigarClient = SuigarClient;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { M as MoveStruct } from './index-
|
|
1
|
+
import { M as MoveStruct } from './index-3P_LBbDM.cjs';
|
|
2
2
|
import * as _mysten_bcs from '@mysten/bcs';
|
|
3
3
|
import { ClientWithCoreApi, SuiClientTypes } from '@mysten/sui/client';
|
|
4
4
|
import { Transaction, BuildTransactionOptions } from '@mysten/sui/transactions';
|
|
5
|
-
import { S as StandardGame, B as BuildCoinflipTransactionOptions, a as BuildWheelTransactionOptions, b as BuildLimboTransactionOptions, c as BuildPlinkoTransactionOptions, d as BuildRangeTransactionOptions, e as SuigarConfig, W as WithThrowOnError, P as PvPCoinflipAction, f as BuildPvPCoinflipTransactionOptions, g as SuigarExtensionOptions } from './games
|
|
5
|
+
import { S as StandardGame, B as BuildCoinflipTransactionOptions, a as BuildWheelTransactionOptions, b as BuildLimboTransactionOptions, c as BuildPlinkoTransactionOptions, d as BuildRangeTransactionOptions, e as SuigarConfig, W as WithThrowOnError, P as PvPCoinflipAction, f as BuildPvPCoinflipTransactionOptions, g as SuigarExtensionOptions } from './games-BccpPyWd.cjs';
|
|
6
6
|
import '@mysten/sui/bcs';
|
|
7
7
|
|
|
8
8
|
type WithoutConfig<T> = Omit<T, 'config'>;
|
|
@@ -44,20 +44,22 @@ declare class SuigarClient {
|
|
|
44
44
|
* Lists unresolved PvP coinflip games from the configured registry and resolves
|
|
45
45
|
* each entry into parsed onchain game state.
|
|
46
46
|
*
|
|
47
|
-
* This fetches dynamic fields from the PvP coinflip registry object, then
|
|
48
|
-
*
|
|
47
|
+
* This fetches dynamic fields from the PvP coinflip registry object, then bulk
|
|
48
|
+
* loads the referenced game objects through `client.core.getObjects()`. Registry
|
|
49
49
|
* membership is the unresolved-state signal: when a game is joined and resolved,
|
|
50
50
|
* the Move flow removes it from the registry and deletes the live `Game` object.
|
|
51
51
|
* Use this when a product needs the current set of open PvP coinflip matches for
|
|
52
52
|
* browsing or lobby views.
|
|
53
53
|
*
|
|
54
54
|
* @param options Optional dynamic field pagination forwarded to `listDynamicFields()`, excluding `parentId`.
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
55
|
+
* Supported options such as `limit`, `cursor`, and `signal` are forwarded to the
|
|
56
|
+
* underlying lookup calls. Pass `throwOnError: true` to fail the whole lookup
|
|
57
|
+
* when any referenced game object cannot be fetched or parsed. By default,
|
|
58
|
+
* failed per-object lookups are skipped and only successfully parsed unresolved
|
|
59
|
+
* games are returned.
|
|
58
60
|
* @returns Parsed unresolved PvP coinflip game objects for the requested
|
|
59
|
-
* registry page. When `throwOnError` is `false`, entries that fail
|
|
60
|
-
*
|
|
61
|
+
* registry page. When `throwOnError` is `false`, entries that fail object fetch
|
|
62
|
+
* or parse are omitted from the returned array.
|
|
61
63
|
*/
|
|
62
64
|
getPvPCoinflipGames(options?: WithThrowOnError<Omit<SuiClientTypes.ListDynamicFieldsOptions, 'parentId'>>): Promise<{
|
|
63
65
|
coinType: string;
|
|
@@ -90,10 +92,13 @@ declare class SuigarClient {
|
|
|
90
92
|
* of a specific PvP coinflip match before rendering join, cancel, or result UI.
|
|
91
93
|
*
|
|
92
94
|
* @param gameId On-chain object id of the PvP coinflip game.
|
|
95
|
+
* @param options Optional `getObject()` options forwarded to the underlying
|
|
96
|
+
* client lookup, excluding `objectId` and `include`. Supported options include
|
|
97
|
+
* `signal`.
|
|
93
98
|
* @returns Parsed PvP coinflip game state with a normalized `coinType`.
|
|
94
99
|
* @throws Error If the object cannot be decoded because no content was returned.
|
|
95
100
|
*/
|
|
96
|
-
resolvePvPConflipGame(gameId: string): Promise<{
|
|
101
|
+
resolvePvPConflipGame(gameId: string, options?: Omit<SuiClientTypes.GetObjectOptions, 'objectId' | 'include'>): Promise<{
|
|
97
102
|
coinType: string;
|
|
98
103
|
id: string;
|
|
99
104
|
creator: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { M as MoveStruct } from './index-
|
|
1
|
+
import { M as MoveStruct } from './index-3P_LBbDM.js';
|
|
2
2
|
import * as _mysten_bcs from '@mysten/bcs';
|
|
3
3
|
import { ClientWithCoreApi, SuiClientTypes } from '@mysten/sui/client';
|
|
4
4
|
import { Transaction, BuildTransactionOptions } from '@mysten/sui/transactions';
|
|
5
|
-
import { S as StandardGame, B as BuildCoinflipTransactionOptions, a as BuildWheelTransactionOptions, b as BuildLimboTransactionOptions, c as BuildPlinkoTransactionOptions, d as BuildRangeTransactionOptions, e as SuigarConfig, W as WithThrowOnError, P as PvPCoinflipAction, f as BuildPvPCoinflipTransactionOptions, g as SuigarExtensionOptions } from './games
|
|
5
|
+
import { S as StandardGame, B as BuildCoinflipTransactionOptions, a as BuildWheelTransactionOptions, b as BuildLimboTransactionOptions, c as BuildPlinkoTransactionOptions, d as BuildRangeTransactionOptions, e as SuigarConfig, W as WithThrowOnError, P as PvPCoinflipAction, f as BuildPvPCoinflipTransactionOptions, g as SuigarExtensionOptions } from './games-BccpPyWd.js';
|
|
6
6
|
import '@mysten/sui/bcs';
|
|
7
7
|
|
|
8
8
|
type WithoutConfig<T> = Omit<T, 'config'>;
|
|
@@ -44,20 +44,22 @@ declare class SuigarClient {
|
|
|
44
44
|
* Lists unresolved PvP coinflip games from the configured registry and resolves
|
|
45
45
|
* each entry into parsed onchain game state.
|
|
46
46
|
*
|
|
47
|
-
* This fetches dynamic fields from the PvP coinflip registry object, then
|
|
48
|
-
*
|
|
47
|
+
* This fetches dynamic fields from the PvP coinflip registry object, then bulk
|
|
48
|
+
* loads the referenced game objects through `client.core.getObjects()`. Registry
|
|
49
49
|
* membership is the unresolved-state signal: when a game is joined and resolved,
|
|
50
50
|
* the Move flow removes it from the registry and deletes the live `Game` object.
|
|
51
51
|
* Use this when a product needs the current set of open PvP coinflip matches for
|
|
52
52
|
* browsing or lobby views.
|
|
53
53
|
*
|
|
54
54
|
* @param options Optional dynamic field pagination forwarded to `listDynamicFields()`, excluding `parentId`.
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
55
|
+
* Supported options such as `limit`, `cursor`, and `signal` are forwarded to the
|
|
56
|
+
* underlying lookup calls. Pass `throwOnError: true` to fail the whole lookup
|
|
57
|
+
* when any referenced game object cannot be fetched or parsed. By default,
|
|
58
|
+
* failed per-object lookups are skipped and only successfully parsed unresolved
|
|
59
|
+
* games are returned.
|
|
58
60
|
* @returns Parsed unresolved PvP coinflip game objects for the requested
|
|
59
|
-
* registry page. When `throwOnError` is `false`, entries that fail
|
|
60
|
-
*
|
|
61
|
+
* registry page. When `throwOnError` is `false`, entries that fail object fetch
|
|
62
|
+
* or parse are omitted from the returned array.
|
|
61
63
|
*/
|
|
62
64
|
getPvPCoinflipGames(options?: WithThrowOnError<Omit<SuiClientTypes.ListDynamicFieldsOptions, 'parentId'>>): Promise<{
|
|
63
65
|
coinType: string;
|
|
@@ -90,10 +92,13 @@ declare class SuigarClient {
|
|
|
90
92
|
* of a specific PvP coinflip match before rendering join, cancel, or result UI.
|
|
91
93
|
*
|
|
92
94
|
* @param gameId On-chain object id of the PvP coinflip game.
|
|
95
|
+
* @param options Optional `getObject()` options forwarded to the underlying
|
|
96
|
+
* client lookup, excluding `objectId` and `include`. Supported options include
|
|
97
|
+
* `signal`.
|
|
93
98
|
* @returns Parsed PvP coinflip game state with a normalized `coinType`.
|
|
94
99
|
* @throws Error If the object cannot be decoded because no content was returned.
|
|
95
100
|
*/
|
|
96
|
-
resolvePvPConflipGame(gameId: string): Promise<{
|
|
101
|
+
resolvePvPConflipGame(gameId: string, options?: Omit<SuiClientTypes.GetObjectOptions, 'objectId' | 'include'>): Promise<{
|
|
97
102
|
coinType: string;
|
|
98
103
|
id: string;
|
|
99
104
|
creator: string;
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { MoveStruct, Float, toBigInt, toU8, DEFAULT_GAS_BUDGET_MIST, normalizeMoveArguments, DEFAULT_LIMBO_MULTIPLIER_SCALE, DEFAULT_RANGE_SCALE } from './chunk-
|
|
2
|
-
import { toBase64, normalizeStructTag, parseStructTag, normalizeSuiAddress,
|
|
1
|
+
import { MoveStruct, Float, toBigInt, toU8, DEFAULT_GAS_BUDGET_MIST, normalizeMoveArguments, DEFAULT_LIMBO_MULTIPLIER_SCALE, DEFAULT_RANGE_SCALE } from './chunk-FEQY5O43.js';
|
|
2
|
+
import { toBase64, normalizeStructTag, parseStructTag, normalizeSuiAddress, fromHex } from '@mysten/sui/utils';
|
|
3
3
|
import { Transaction } from '@mysten/sui/transactions';
|
|
4
4
|
import { bcs } from '@mysten/sui/bcs';
|
|
5
5
|
|
|
@@ -123,56 +123,44 @@ function resolvePriceInfoObjectId(config, coinType) {
|
|
|
123
123
|
const normalizedCoinType = normalizeStructTag(coinType);
|
|
124
124
|
const supportedCoin = resolveSupportedCoin(config, normalizedCoinType);
|
|
125
125
|
const objectId = config.priceInfoObjectIds[supportedCoin];
|
|
126
|
-
if (objectId) {
|
|
127
|
-
|
|
126
|
+
if (!objectId) {
|
|
127
|
+
throw new Error(
|
|
128
|
+
`Missing price info object configuration for coin type ${coinType}`
|
|
129
|
+
);
|
|
128
130
|
}
|
|
129
|
-
|
|
130
|
-
`Missing price info object configuration for coin type ${coinType}`
|
|
131
|
-
);
|
|
131
|
+
return objectId;
|
|
132
132
|
}
|
|
133
133
|
function resolveSupportedCoin(config, coinType) {
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
134
|
+
const [supportedCoin] = Object.entries(config.coinTypes).find(([_, value]) => value === coinType) ?? [];
|
|
135
|
+
if (!supportedCoin) {
|
|
136
|
+
throw new Error(
|
|
137
|
+
`Unsupported coin type ${coinType}. Supported coin types: ${Object.values(
|
|
138
|
+
config.coinTypes
|
|
139
|
+
).join(", ")}`
|
|
140
|
+
);
|
|
140
141
|
}
|
|
141
|
-
|
|
142
|
-
`Unsupported coin type ${coinType}. Supported coin types: ${entries.map(([, configuredCoinType]) => configuredCoinType).join(", ")}`
|
|
143
|
-
);
|
|
142
|
+
return supportedCoin;
|
|
144
143
|
}
|
|
145
|
-
var
|
|
146
|
-
var RESERVED_METADATA_KEYS = /* @__PURE__ */ new Set([
|
|
144
|
+
var PARTNER_METADATA_KEY = "partner";
|
|
145
|
+
var RESERVED_METADATA_KEYS = /* @__PURE__ */ new Set([PARTNER_METADATA_KEY, "referrer"]);
|
|
147
146
|
var textEncoder = new TextEncoder();
|
|
148
147
|
function parseHexAddress(value) {
|
|
149
|
-
const trimmed = value.trim();
|
|
150
|
-
if (!trimmed || !isValidSuiAddress(trimmed)) return null;
|
|
151
148
|
try {
|
|
152
|
-
|
|
153
|
-
const bytes = new Uint8Array(normalized.length / 2);
|
|
154
|
-
for (let index = 0; index < normalized.length; index += 2) {
|
|
155
|
-
bytes[index / 2] = Number.parseInt(
|
|
156
|
-
normalized.slice(index, index + 2),
|
|
157
|
-
16
|
|
158
|
-
);
|
|
159
|
-
}
|
|
160
|
-
return bytes;
|
|
149
|
+
return fromHex(value);
|
|
161
150
|
} catch {
|
|
162
151
|
return null;
|
|
163
152
|
}
|
|
164
153
|
}
|
|
165
|
-
function encodeMetadataValue(
|
|
154
|
+
function encodeMetadataValue(value) {
|
|
166
155
|
if (value instanceof Uint8Array) {
|
|
167
156
|
return Array.from(value);
|
|
168
157
|
}
|
|
169
158
|
if (Array.isArray(value)) {
|
|
170
159
|
return value;
|
|
171
160
|
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
return Array.from(textEncoder.encode(String(value)));
|
|
161
|
+
return Array.from(
|
|
162
|
+
parseHexAddress(String(value)) ?? textEncoder.encode(String(value))
|
|
163
|
+
);
|
|
176
164
|
}
|
|
177
165
|
function encodeBetMetadata(metadata, partner) {
|
|
178
166
|
const keys = [];
|
|
@@ -188,14 +176,15 @@ function encodeBetMetadata(metadata, partner) {
|
|
|
188
176
|
continue;
|
|
189
177
|
}
|
|
190
178
|
keys.push(key);
|
|
191
|
-
values.push(encodeMetadataValue(
|
|
179
|
+
values.push(encodeMetadataValue(value));
|
|
192
180
|
}
|
|
193
|
-
if (
|
|
194
|
-
|
|
181
|
+
if (partner?.trim()) {
|
|
182
|
+
keys.unshift(PARTNER_METADATA_KEY);
|
|
183
|
+
values.unshift(encodeMetadataValue(partner));
|
|
195
184
|
}
|
|
196
185
|
return {
|
|
197
|
-
keys
|
|
198
|
-
values
|
|
186
|
+
keys,
|
|
187
|
+
values
|
|
199
188
|
};
|
|
200
189
|
}
|
|
201
190
|
|
|
@@ -225,20 +214,18 @@ function play(options) {
|
|
|
225
214
|
function createBaseGameTransaction({
|
|
226
215
|
config,
|
|
227
216
|
game,
|
|
228
|
-
|
|
229
|
-
sender,
|
|
217
|
+
playerAddress,
|
|
230
218
|
gasBudget
|
|
231
219
|
}) {
|
|
232
220
|
assertConfiguredBetGame(config, game);
|
|
233
221
|
const tx = new Transaction();
|
|
234
|
-
tx.setSenderIfNotSet(normalizeSuiAddress(
|
|
222
|
+
tx.setSenderIfNotSet(normalizeSuiAddress(playerAddress));
|
|
235
223
|
tx.setGasBudgetIfNotSet(gasBudget ?? DEFAULT_GAS_BUDGET_MIST);
|
|
236
224
|
return tx;
|
|
237
225
|
}
|
|
238
226
|
function buildSharedStandardGameBetCall({
|
|
239
227
|
config,
|
|
240
|
-
|
|
241
|
-
sender,
|
|
228
|
+
playerAddress,
|
|
242
229
|
coinType,
|
|
243
230
|
stake,
|
|
244
231
|
cashStake,
|
|
@@ -249,7 +236,7 @@ function buildSharedStandardGameBetCall({
|
|
|
249
236
|
buildRewardCoin
|
|
250
237
|
}) {
|
|
251
238
|
return (tx) => {
|
|
252
|
-
const
|
|
239
|
+
const normalizedPlayerAddress = normalizeSuiAddress(playerAddress);
|
|
253
240
|
const normalizedCoinType = normalizeStructTag(coinType);
|
|
254
241
|
const resolvedStake = toBigInt(stake);
|
|
255
242
|
const resolvedCashStake = toBigInt(cashStake ?? stake);
|
|
@@ -267,7 +254,7 @@ function buildSharedStandardGameBetCall({
|
|
|
267
254
|
const rewardCoin = buildRewardCoin({
|
|
268
255
|
tx,
|
|
269
256
|
config,
|
|
270
|
-
|
|
257
|
+
playerAddress: normalizedPlayerAddress,
|
|
271
258
|
coinType: normalizedCoinType,
|
|
272
259
|
stake: resolvedStake,
|
|
273
260
|
cashStake: resolvedCashStake,
|
|
@@ -276,7 +263,7 @@ function buildSharedStandardGameBetCall({
|
|
|
276
263
|
priceInfoObjectId,
|
|
277
264
|
betCoin
|
|
278
265
|
});
|
|
279
|
-
tx.transferObjects([rewardCoin], tx.pure.address(
|
|
266
|
+
tx.transferObjects([rewardCoin], tx.pure.address(normalizedPlayerAddress));
|
|
280
267
|
return rewardCoin;
|
|
281
268
|
};
|
|
282
269
|
}
|
|
@@ -831,39 +818,53 @@ var SuigarClient = class {
|
|
|
831
818
|
* Lists unresolved PvP coinflip games from the configured registry and resolves
|
|
832
819
|
* each entry into parsed onchain game state.
|
|
833
820
|
*
|
|
834
|
-
* This fetches dynamic fields from the PvP coinflip registry object, then
|
|
835
|
-
*
|
|
821
|
+
* This fetches dynamic fields from the PvP coinflip registry object, then bulk
|
|
822
|
+
* loads the referenced game objects through `client.core.getObjects()`. Registry
|
|
836
823
|
* membership is the unresolved-state signal: when a game is joined and resolved,
|
|
837
824
|
* the Move flow removes it from the registry and deletes the live `Game` object.
|
|
838
825
|
* Use this when a product needs the current set of open PvP coinflip matches for
|
|
839
826
|
* browsing or lobby views.
|
|
840
827
|
*
|
|
841
828
|
* @param options Optional dynamic field pagination forwarded to `listDynamicFields()`, excluding `parentId`.
|
|
842
|
-
*
|
|
843
|
-
*
|
|
844
|
-
*
|
|
829
|
+
* Supported options such as `limit`, `cursor`, and `signal` are forwarded to the
|
|
830
|
+
* underlying lookup calls. Pass `throwOnError: true` to fail the whole lookup
|
|
831
|
+
* when any referenced game object cannot be fetched or parsed. By default,
|
|
832
|
+
* failed per-object lookups are skipped and only successfully parsed unresolved
|
|
833
|
+
* games are returned.
|
|
845
834
|
* @returns Parsed unresolved PvP coinflip game objects for the requested
|
|
846
|
-
* registry page. When `throwOnError` is `false`, entries that fail
|
|
847
|
-
*
|
|
835
|
+
* registry page. When `throwOnError` is `false`, entries that fail object fetch
|
|
836
|
+
* or parse are omitted from the returned array.
|
|
848
837
|
*/
|
|
849
838
|
async getPvPCoinflipGames(options = {
|
|
850
839
|
limit: 50
|
|
851
840
|
}) {
|
|
852
841
|
const { throwOnError = false, ...listOptions } = options;
|
|
853
842
|
const { dynamicFields } = await this.#client.core.listDynamicFields({
|
|
854
|
-
|
|
855
|
-
|
|
843
|
+
...listOptions,
|
|
844
|
+
parentId: this.#config.registryIds.pvpCoinflip
|
|
845
|
+
});
|
|
846
|
+
const { objects } = await this.#client.core.getObjects({
|
|
847
|
+
objectIds: dynamicFields.map(({ childId }) => childId),
|
|
848
|
+
signal: listOptions.signal,
|
|
849
|
+
include: {
|
|
850
|
+
content: true
|
|
851
|
+
}
|
|
852
|
+
});
|
|
853
|
+
const resolvedGames = objects.map((object) => {
|
|
854
|
+
try {
|
|
855
|
+
return this.#resolvePvPCoinflipGameObject(object);
|
|
856
|
+
} catch (error) {
|
|
857
|
+
return error instanceof Error ? error : new Error(String(error));
|
|
858
|
+
}
|
|
856
859
|
});
|
|
857
860
|
if (throwOnError) {
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
+
const firstError = resolvedGames.find((game) => game instanceof Error);
|
|
862
|
+
if (firstError) {
|
|
863
|
+
throw firstError;
|
|
864
|
+
}
|
|
861
865
|
}
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
);
|
|
865
|
-
return settledGames.flatMap(
|
|
866
|
-
(result) => result.status === "fulfilled" ? [result.value] : []
|
|
866
|
+
return resolvedGames.flatMap(
|
|
867
|
+
(game) => game instanceof Error ? [] : [game]
|
|
867
868
|
);
|
|
868
869
|
}
|
|
869
870
|
/**
|
|
@@ -877,21 +878,19 @@ var SuigarClient = class {
|
|
|
877
878
|
* of a specific PvP coinflip match before rendering join, cancel, or result UI.
|
|
878
879
|
*
|
|
879
880
|
* @param gameId On-chain object id of the PvP coinflip game.
|
|
881
|
+
* @param options Optional `getObject()` options forwarded to the underlying
|
|
882
|
+
* client lookup, excluding `objectId` and `include`. Supported options include
|
|
883
|
+
* `signal`.
|
|
880
884
|
* @returns Parsed PvP coinflip game state with a normalized `coinType`.
|
|
881
885
|
* @throws Error If the object cannot be decoded because no content was returned.
|
|
882
886
|
*/
|
|
883
|
-
async resolvePvPConflipGame(gameId) {
|
|
887
|
+
async resolvePvPConflipGame(gameId, options = {}) {
|
|
884
888
|
const { object } = await this.#client.core.getObject({
|
|
889
|
+
...options,
|
|
885
890
|
objectId: gameId,
|
|
886
891
|
include: { content: true }
|
|
887
892
|
});
|
|
888
|
-
|
|
889
|
-
throw new Error("Unable to resolve PvP coinflip from game object");
|
|
890
|
-
}
|
|
891
|
-
return {
|
|
892
|
-
...Game.parse(object.content),
|
|
893
|
-
coinType: normalizeStructTag(parseStructTag(object.type).typeParams[0])
|
|
894
|
-
};
|
|
893
|
+
return this.#resolvePvPCoinflipGameObject(object);
|
|
895
894
|
}
|
|
896
895
|
/**
|
|
897
896
|
* BCS struct constructors for decoding on-chain objects and events related to Suigar games.
|
|
@@ -1021,6 +1020,20 @@ var SuigarClient = class {
|
|
|
1021
1020
|
});
|
|
1022
1021
|
};
|
|
1023
1022
|
}
|
|
1023
|
+
#resolvePvPCoinflipGameObject(object) {
|
|
1024
|
+
if (object instanceof Error) {
|
|
1025
|
+
throw object;
|
|
1026
|
+
}
|
|
1027
|
+
if (!object.content) {
|
|
1028
|
+
throw new Error(
|
|
1029
|
+
"Unable to resolve PvP coinflip game from retrieved object"
|
|
1030
|
+
);
|
|
1031
|
+
}
|
|
1032
|
+
return {
|
|
1033
|
+
...Game.parse(object.content),
|
|
1034
|
+
coinType: normalizeStructTag(parseStructTag(object.type).typeParams[0])
|
|
1035
|
+
};
|
|
1036
|
+
}
|
|
1024
1037
|
};
|
|
1025
1038
|
|
|
1026
1039
|
export { SuigarClient, suigar };
|