@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/dist/index.js
CHANGED
|
@@ -1,289 +1,365 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { MoveStruct, Float, parseCoinType, toBigInt, toU8, DEFAULT_GAS_BUDGET_MIST, normalizeMoveArguments, DEFAULT_LIMBO_MULTIPLIER_SCALE, DEFAULT_RANGE_SCALE } from './chunk-PPUDLRHA.js';
|
|
2
|
+
import { toBase64, normalizeStructTag, normalizeSuiAddress, fromHex } from '@mysten/sui/utils';
|
|
3
|
+
import { bcs } from '@mysten/sui/bcs';
|
|
4
|
+
import { Transaction } from '@mysten/sui/transactions';
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
var $moduleName = "0x0000000000000000000000000000000000000000000000000000000000000001::type_name";
|
|
7
|
+
var TypeName = new MoveStruct({
|
|
8
|
+
name: `${$moduleName}::TypeName`,
|
|
9
|
+
fields: {
|
|
10
|
+
name: bcs.string()
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
var $moduleName2 = "0x2::vec_map";
|
|
14
|
+
function Entry(...typeParameters) {
|
|
15
|
+
return new MoveStruct({
|
|
16
|
+
name: `${$moduleName2}::Entry<${typeParameters[0].name}, ${typeParameters[1].name}>`,
|
|
17
|
+
fields: {
|
|
18
|
+
key: typeParameters[0],
|
|
19
|
+
value: typeParameters[1]
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
function VecMap(...typeParameters) {
|
|
24
|
+
return new MoveStruct({
|
|
25
|
+
name: `${$moduleName2}::VecMap<${typeParameters[0].name}, ${typeParameters[1].name}>`,
|
|
26
|
+
fields: {
|
|
27
|
+
contents: bcs.vector(Entry(typeParameters[0], typeParameters[1]))
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// src/contracts/core/core.ts
|
|
33
|
+
var $moduleName3 = "0xf391858d2a08473e8d4defcc8df89976bd7b123d3865c6b9341b237f7853dbbc::core";
|
|
34
|
+
var BetResultEvent = new MoveStruct({
|
|
35
|
+
name: `${$moduleName3}::BetResultEvent<phantom T0>`,
|
|
36
|
+
fields: {
|
|
37
|
+
player: bcs.Address,
|
|
38
|
+
coin_type: TypeName,
|
|
39
|
+
stake_amount: bcs.u64(),
|
|
40
|
+
unsafe_oracle_usd_coin_price: Float,
|
|
41
|
+
adjusted_oracle_usd_coin_price: Float,
|
|
42
|
+
outcome_amount: bcs.u64(),
|
|
43
|
+
game_details: VecMap(bcs.string(), bcs.vector(bcs.u8())),
|
|
44
|
+
metadata: VecMap(bcs.string(), bcs.vector(bcs.u8()))
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
var $moduleName4 = "0x0000000000000000000000000000000000000000000000000000000000000001::type_name";
|
|
48
|
+
var TypeName2 = new MoveStruct({
|
|
49
|
+
name: `${$moduleName4}::TypeName`,
|
|
50
|
+
fields: {
|
|
51
|
+
name: bcs.string()
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
var $moduleName5 = "0x2::balance";
|
|
55
|
+
var Balance = new MoveStruct({
|
|
56
|
+
name: `${$moduleName5}::Balance<phantom T0>`,
|
|
57
|
+
fields: {
|
|
58
|
+
value: bcs.u64()
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
var $moduleName6 = "0x2::vec_map";
|
|
62
|
+
function Entry2(...typeParameters) {
|
|
63
|
+
return new MoveStruct({
|
|
64
|
+
name: `${$moduleName6}::Entry<${typeParameters[0].name}, ${typeParameters[1].name}>`,
|
|
65
|
+
fields: {
|
|
66
|
+
key: typeParameters[0],
|
|
67
|
+
value: typeParameters[1]
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
function VecMap2(...typeParameters) {
|
|
72
|
+
return new MoveStruct({
|
|
73
|
+
name: `${$moduleName6}::VecMap<${typeParameters[0].name}, ${typeParameters[1].name}>`,
|
|
74
|
+
fields: {
|
|
75
|
+
contents: bcs.vector(Entry2(typeParameters[0], typeParameters[1]))
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// src/contracts/pvp-coinflip/pvp_coinflip.ts
|
|
81
|
+
var $moduleName7 = "0xb43cf6583c0c15315c7e66f173af4be79ac40c38aad1fd92ec08638ab2026202::pvp_coinflip";
|
|
82
|
+
var Game = new MoveStruct({
|
|
83
|
+
name: `${$moduleName7}::Game<phantom T0>`,
|
|
84
|
+
fields: {
|
|
85
|
+
id: bcs.Address,
|
|
86
|
+
creator: bcs.Address,
|
|
87
|
+
creator_is_tails: bcs.bool(),
|
|
88
|
+
is_private: bcs.bool(),
|
|
89
|
+
creator_metadata: VecMap2(bcs.string(), bcs.vector(bcs.u8())),
|
|
90
|
+
joiner: bcs.Address,
|
|
91
|
+
winner: bcs.Address,
|
|
92
|
+
stake_per_player: bcs.u64(),
|
|
93
|
+
house_edge_bps: bcs.u64(),
|
|
94
|
+
stake_pot: Balance
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
var GameCreatedEvent = new MoveStruct({
|
|
98
|
+
name: `${$moduleName7}::GameCreatedEvent<phantom T0>`,
|
|
99
|
+
fields: {
|
|
100
|
+
game_id: bcs.Address,
|
|
101
|
+
creator: bcs.Address,
|
|
102
|
+
creator_is_tails: bcs.bool(),
|
|
103
|
+
is_private: bcs.bool(),
|
|
104
|
+
joiner_is_tails: bcs.bool(),
|
|
105
|
+
stake_per_player: bcs.u64(),
|
|
106
|
+
house_edge_bps: bcs.u64(),
|
|
107
|
+
coin_type: TypeName2
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
var GameResolvedEvent = new MoveStruct({
|
|
111
|
+
name: `${$moduleName7}::GameResolvedEvent<phantom T0>`,
|
|
112
|
+
fields: {
|
|
113
|
+
game_id: bcs.Address,
|
|
114
|
+
creator: bcs.Address,
|
|
115
|
+
joiner: bcs.Address,
|
|
116
|
+
winner: bcs.Address,
|
|
117
|
+
creator_is_tails: bcs.bool(),
|
|
118
|
+
is_private: bcs.bool(),
|
|
119
|
+
joiner_is_tails: bcs.bool(),
|
|
120
|
+
stake_per_player: bcs.u64(),
|
|
121
|
+
total_pot: bcs.u64(),
|
|
122
|
+
house_edge_amount: bcs.u64(),
|
|
123
|
+
payout_amount: bcs.u64(),
|
|
124
|
+
coin_type: TypeName2
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
var GameCancelledEvent = new MoveStruct({
|
|
128
|
+
name: `${$moduleName7}::GameCancelledEvent<phantom T0>`,
|
|
129
|
+
fields: {
|
|
130
|
+
game_id: bcs.Address,
|
|
131
|
+
creator: bcs.Address,
|
|
132
|
+
creator_is_tails: bcs.bool(),
|
|
133
|
+
is_private: bcs.bool(),
|
|
134
|
+
stake_per_player: bcs.u64(),
|
|
135
|
+
coin_type: TypeName2
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
function createGame(options) {
|
|
139
|
+
const packageAddress = options.package ?? "0xb43cf6583c0c15315c7e66f173af4be79ac40c38aad1fd92ec08638ab2026202";
|
|
140
|
+
const argumentsTypes = [
|
|
141
|
+
null,
|
|
142
|
+
null,
|
|
143
|
+
"bool",
|
|
144
|
+
"bool",
|
|
145
|
+
"vector<0x1::string::String>",
|
|
146
|
+
"vector<vector<u8>>"
|
|
147
|
+
];
|
|
148
|
+
return (tx) => tx.moveCall({
|
|
149
|
+
package: packageAddress,
|
|
150
|
+
module: "pvp_coinflip",
|
|
151
|
+
function: "create_game",
|
|
152
|
+
arguments: normalizeMoveArguments(options.arguments, argumentsTypes),
|
|
153
|
+
typeArguments: options.typeArguments
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
function joinGame(options) {
|
|
157
|
+
const packageAddress = options.package ?? "0xb43cf6583c0c15315c7e66f173af4be79ac40c38aad1fd92ec08638ab2026202";
|
|
158
|
+
const argumentsTypes = [
|
|
159
|
+
"0x2::object::ID",
|
|
160
|
+
null,
|
|
161
|
+
null,
|
|
162
|
+
"vector<0x1::string::String>",
|
|
163
|
+
"vector<vector<u8>>",
|
|
164
|
+
null,
|
|
165
|
+
"0x2::clock::Clock",
|
|
166
|
+
"0x2::random::Random"
|
|
167
|
+
];
|
|
168
|
+
return (tx) => tx.moveCall({
|
|
169
|
+
package: packageAddress,
|
|
170
|
+
module: "pvp_coinflip",
|
|
171
|
+
function: "join_game",
|
|
172
|
+
arguments: normalizeMoveArguments(options.arguments, argumentsTypes),
|
|
173
|
+
typeArguments: options.typeArguments
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
function cancelGame(options) {
|
|
177
|
+
const packageAddress = options.package ?? "0xb43cf6583c0c15315c7e66f173af4be79ac40c38aad1fd92ec08638ab2026202";
|
|
178
|
+
const argumentsTypes = ["0x2::object::ID", null];
|
|
179
|
+
return (tx) => tx.moveCall({
|
|
180
|
+
package: packageAddress,
|
|
181
|
+
module: "pvp_coinflip",
|
|
182
|
+
function: "cancel_game",
|
|
183
|
+
arguments: normalizeMoveArguments(options.arguments, argumentsTypes),
|
|
184
|
+
typeArguments: options.typeArguments
|
|
185
|
+
});
|
|
186
|
+
}
|
|
6
187
|
|
|
7
|
-
// src/configs/package
|
|
8
|
-
var
|
|
9
|
-
|
|
188
|
+
// src/configs/package.mainnet.ts
|
|
189
|
+
var MAINNET_PACKAGE_IDS = {
|
|
190
|
+
sweetHouse: "0xa1549d73230118716bc08865b8d62454f360ddaf40eee2158e458e52125d4ef1",
|
|
191
|
+
core: "0xcbb0929f21450013ebe5e86e7139f2409da2e3ed212c51126a7e6448b795a43f",
|
|
192
|
+
coinflip: "0xca96885371150f55653f7fab9e9b146f5a19698b1002bdff42159ea9d2ba7d7e",
|
|
193
|
+
limbo: "0x89db6a55ad4e650cad641b6f9fd90b391b22b1d9adbb2cabbfeb94a9eeda7026",
|
|
194
|
+
plinko: "0x74a73daff11c11ed05299c93ed770c62ec4dc6756fa99e271e251c2399f49fef",
|
|
195
|
+
pvpCoinflip: "0x29162faf01a8135630e0a32bbe4ce47f69607b24dbb1edea3800861f91d0030a",
|
|
196
|
+
range: "0xd19e32b0f2a5e541fbd345b4602f8a93a2eee25c16029595b6fef0b1e0461a54",
|
|
197
|
+
wheel: "0x6791eac73fe7bf463b7f3b1ea391df265fbc1b96201270664a5a11e2441e9955"
|
|
198
|
+
};
|
|
199
|
+
var MAINNET_COIN_TYPES = {
|
|
200
|
+
sui: "0x2::sui::SUI",
|
|
201
|
+
usdc: "0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC"
|
|
202
|
+
};
|
|
203
|
+
var MAINNET_PRICE_INFO_OBJECT_IDS = {
|
|
204
|
+
sui: "0x801dbc2f0053d34734814b2d6df491ce7807a725fe9a01ad74a07e9c51396c37",
|
|
205
|
+
usdc: "0x5dec622733a204ca27f5a90d8c2fad453cc6665186fd5dff13a83d0b6c9027ab"
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
// src/configs/package.testnet.ts
|
|
209
|
+
var TESTNET_PACKAGE_IDS = {
|
|
210
|
+
sweetHouse: "0xb7f64e5a273aba1ede00caa0a6f8027cc7490c279d17eab12e7100ed20660603",
|
|
211
|
+
core: "0xf391858d2a08473e8d4defcc8df89976bd7b123d3865c6b9341b237f7853dbbc",
|
|
10
212
|
coinflip: "0xb35c5f286c443752afc8ccb40125a578a4f32df35617170ccfa17fe180ab80ea",
|
|
11
213
|
limbo: "0x96c7841b9b32c59a219760fd656f1c3aceb53cc74a68ec9844a3a696374309f4",
|
|
12
214
|
plinko: "0xd3dd2200883af10811724f0bed97591ad155a02efd6332d471ff8b346030dfb7",
|
|
13
|
-
|
|
215
|
+
pvpCoinflip: "0xb43cf6583c0c15315c7e66f173af4be79ac40c38aad1fd92ec08638ab2026202",
|
|
14
216
|
range: "0x096a4cf18b3661e76b2c62b90785418345d52f45b272448794f123a4cb6b6416",
|
|
15
217
|
wheel: "0x0997852ded7e13301c42317004bc49704a893aa82997c5706cebee59053a31b7"
|
|
16
218
|
};
|
|
219
|
+
var TESTNET_COIN_TYPES = {
|
|
220
|
+
sui: "0x47c67b9594069c32caa7a6e875ddf31d7fa52602dd22ccb9ebd8d3482aed76dc::test_sui::TEST_SUI",
|
|
221
|
+
usdc: "0x47c67b9594069c32caa7a6e875ddf31d7fa52602dd22ccb9ebd8d3482aed76dc::test_usdc::TEST_USDC"
|
|
222
|
+
};
|
|
223
|
+
var TESTNET_PRICE_INFO_OBJECT_IDS = {
|
|
224
|
+
sui: "0x1ebb295c789cc42b3b2a1606482cd1c7124076a0f5676718501fda8c7fd075a0",
|
|
225
|
+
usdc: "0x9c4dd4008297ffa5e480684b8100ec21cc934405ed9a25d4e4d7b6259aad9c81"
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
// src/configs/package.ts
|
|
229
|
+
var PACKAGE_IDS = {
|
|
230
|
+
mainnet: { ...MAINNET_PACKAGE_IDS },
|
|
231
|
+
testnet: { ...TESTNET_PACKAGE_IDS }
|
|
232
|
+
};
|
|
233
|
+
var COIN_TYPES = {
|
|
234
|
+
mainnet: { ...MAINNET_COIN_TYPES },
|
|
235
|
+
testnet: { ...TESTNET_COIN_TYPES }
|
|
236
|
+
};
|
|
237
|
+
var PRICE_INFO_OBJECT_IDS = {
|
|
238
|
+
mainnet: { ...MAINNET_PRICE_INFO_OBJECT_IDS },
|
|
239
|
+
testnet: { ...TESTNET_PRICE_INFO_OBJECT_IDS }
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
// src/configs/registry.mainnet.ts
|
|
243
|
+
var PVP_COINFLIP_REGISTRY_ID = "0x3d73568546c539c1da3eb2b8fe917faef3c0acdbec78a67fe6d52800a0729349";
|
|
17
244
|
|
|
18
|
-
// src/configs/
|
|
19
|
-
var
|
|
20
|
-
|
|
245
|
+
// src/configs/registry.testnet.ts
|
|
246
|
+
var PVP_COINFLIP_REGISTRY_ID2 = "0x99f20d8e4be012ea14a681144ae72ac349d0a1a1585205880183eb167f075bad";
|
|
247
|
+
|
|
248
|
+
// src/configs/registry.ts
|
|
249
|
+
var REGISTRY_IDS = {
|
|
250
|
+
mainnet: {
|
|
251
|
+
pvpCoinflip: PVP_COINFLIP_REGISTRY_ID
|
|
252
|
+
},
|
|
253
|
+
testnet: {
|
|
254
|
+
pvpCoinflip: PVP_COINFLIP_REGISTRY_ID2
|
|
255
|
+
}
|
|
256
|
+
};
|
|
21
257
|
|
|
22
|
-
// src/
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
const usdcCoinType = normalizeStructTag(
|
|
29
|
-
options.coinTypes?.usdc ?? DEFAULT_USDC_COIN_TYPE
|
|
30
|
-
);
|
|
31
|
-
const usdcFlowxCoinType = normalizeStructTag(
|
|
32
|
-
options.coinTypes?.usdcFlowx ?? DEFAULT_USDC_FLOWX_COIN_TYPE
|
|
33
|
-
);
|
|
34
|
-
const explicitPriceInfoObjectIds = Object.fromEntries(
|
|
35
|
-
Object.entries(options.pyth?.priceInfoObjectIds ?? {}).map(
|
|
36
|
-
([coinType, objectId]) => [normalizeStructTag(coinType), objectId]
|
|
37
|
-
)
|
|
38
|
-
);
|
|
258
|
+
// src/helpers/config.ts
|
|
259
|
+
function resolveSuigarConfig(network) {
|
|
260
|
+
const packageIds = PACKAGE_IDS[network];
|
|
261
|
+
const registryIds = REGISTRY_IDS[network];
|
|
262
|
+
const coinTypes = COIN_TYPES[network];
|
|
263
|
+
const priceInfoObjectIds = PRICE_INFO_OBJECT_IDS[network];
|
|
39
264
|
return {
|
|
40
|
-
|
|
265
|
+
packageIds: { ...packageIds },
|
|
266
|
+
registryIds: { ...registryIds },
|
|
41
267
|
coinTypes: {
|
|
42
|
-
sui:
|
|
43
|
-
usdc:
|
|
44
|
-
usdcFlowx: usdcFlowxCoinType
|
|
45
|
-
},
|
|
46
|
-
gamesPackageId: {
|
|
47
|
-
coinflip: trim(options.gamesPackageId?.coinflip) || DEFAULT_GAMES_PACKAGE_ID.coinflip,
|
|
48
|
-
limbo: trim(options.gamesPackageId?.limbo) || DEFAULT_GAMES_PACKAGE_ID.limbo,
|
|
49
|
-
plinko: trim(options.gamesPackageId?.plinko) || DEFAULT_GAMES_PACKAGE_ID.plinko,
|
|
50
|
-
"pvp-coinflip": trim(options.gamesPackageId?.["pvp-coinflip"]) || DEFAULT_GAMES_PACKAGE_ID.pvp_coinflip,
|
|
51
|
-
range: trim(options.gamesPackageId?.range) || DEFAULT_GAMES_PACKAGE_ID.range,
|
|
52
|
-
wheel: trim(options.gamesPackageId?.wheel) || DEFAULT_GAMES_PACKAGE_ID.wheel
|
|
268
|
+
sui: normalizeStructTag(coinTypes.sui),
|
|
269
|
+
usdc: normalizeStructTag(coinTypes.usdc)
|
|
53
270
|
},
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
usdcPriceInfoObjectId: trim(options.pyth?.usdcPriceInfoObjectId),
|
|
58
|
-
priceInfoObjectIds: explicitPriceInfoObjectIds
|
|
271
|
+
priceInfoObjectIds: {
|
|
272
|
+
sui: priceInfoObjectIds.sui,
|
|
273
|
+
usdc: priceInfoObjectIds.usdc
|
|
59
274
|
}
|
|
60
275
|
};
|
|
61
276
|
}
|
|
62
|
-
function
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
if (explicitObjectId) {
|
|
66
|
-
return explicitObjectId;
|
|
277
|
+
function assertConfiguredBetGame(config, game) {
|
|
278
|
+
if (!resolveGamePackageId(config, game)) {
|
|
279
|
+
throw new Error(`Missing required config for ${game}: packageIds.${game}`);
|
|
67
280
|
}
|
|
68
|
-
|
|
69
|
-
|
|
281
|
+
}
|
|
282
|
+
function resolveGamePackageId(config, game) {
|
|
283
|
+
switch (game) {
|
|
284
|
+
case "coinflip":
|
|
285
|
+
return config.packageIds.coinflip;
|
|
286
|
+
case "limbo":
|
|
287
|
+
return config.packageIds.limbo;
|
|
288
|
+
case "plinko":
|
|
289
|
+
return config.packageIds.plinko;
|
|
290
|
+
case "pvp-coinflip":
|
|
291
|
+
return config.packageIds.pvpCoinflip;
|
|
292
|
+
case "range":
|
|
293
|
+
return config.packageIds.range;
|
|
294
|
+
case "wheel":
|
|
295
|
+
return config.packageIds.wheel;
|
|
70
296
|
}
|
|
71
|
-
|
|
72
|
-
|
|
297
|
+
}
|
|
298
|
+
function resolvePriceInfoObjectId(config, coinType) {
|
|
299
|
+
const normalizedCoinType = normalizeStructTag(coinType);
|
|
300
|
+
const supportedCoin = resolveSupportedCoin(config, normalizedCoinType);
|
|
301
|
+
const objectId = config.priceInfoObjectIds[supportedCoin];
|
|
302
|
+
if (!objectId) {
|
|
303
|
+
throw new Error(
|
|
304
|
+
`Missing price info object configuration for coin type ${coinType}`
|
|
305
|
+
);
|
|
73
306
|
}
|
|
74
|
-
|
|
75
|
-
`Missing Pyth price object configuration for coin type ${coinType}`
|
|
76
|
-
);
|
|
307
|
+
return objectId;
|
|
77
308
|
}
|
|
78
|
-
function
|
|
79
|
-
|
|
309
|
+
function resolveSupportedCoin(config, coinType) {
|
|
310
|
+
const [supportedCoin] = Object.entries(config.coinTypes).find(([_, value]) => value === coinType) ?? [];
|
|
311
|
+
if (!supportedCoin) {
|
|
80
312
|
throw new Error(
|
|
81
|
-
`
|
|
313
|
+
`Unsupported coin type ${coinType}. Supported coin types: ${Object.values(
|
|
314
|
+
config.coinTypes
|
|
315
|
+
).join(", ")}`
|
|
82
316
|
);
|
|
83
317
|
}
|
|
318
|
+
return supportedCoin;
|
|
84
319
|
}
|
|
85
|
-
var
|
|
320
|
+
var PARTNER_METADATA_KEY = "partner";
|
|
321
|
+
var RESERVED_METADATA_KEYS = /* @__PURE__ */ new Set([PARTNER_METADATA_KEY, "referrer"]);
|
|
86
322
|
var textEncoder = new TextEncoder();
|
|
87
|
-
|
|
88
|
-
const trimmed = value.trim();
|
|
89
|
-
if (!trimmed) return null;
|
|
323
|
+
function encodeString(value) {
|
|
90
324
|
try {
|
|
91
|
-
|
|
92
|
-
const bytes = new Uint8Array(normalized.length / 2);
|
|
93
|
-
for (let index = 0; index < normalized.length; index += 2) {
|
|
94
|
-
bytes[index / 2] = Number.parseInt(
|
|
95
|
-
normalized.slice(index, index + 2),
|
|
96
|
-
16
|
|
97
|
-
);
|
|
98
|
-
}
|
|
99
|
-
return bytes;
|
|
325
|
+
return fromHex(value);
|
|
100
326
|
} catch {
|
|
101
|
-
return
|
|
102
|
-
}
|
|
103
|
-
};
|
|
104
|
-
function encodeBetMetadata(metadata) {
|
|
105
|
-
const keys = [];
|
|
106
|
-
const values = [];
|
|
107
|
-
for (const [key, value] of Object.entries(metadata ?? {})) {
|
|
108
|
-
if (value === void 0 || value === null) {
|
|
109
|
-
continue;
|
|
110
|
-
}
|
|
111
|
-
let encodedValue;
|
|
112
|
-
if (value instanceof Uint8Array) {
|
|
113
|
-
encodedValue = Array.from(value);
|
|
114
|
-
} else if (Array.isArray(value)) {
|
|
115
|
-
encodedValue = value;
|
|
116
|
-
} else if (typeof value === "string" && ADDRESS_METADATA_KEYS.has(key)) {
|
|
117
|
-
encodedValue = Array.from(
|
|
118
|
-
parseHexAddress(value) ?? textEncoder.encode(value)
|
|
119
|
-
);
|
|
120
|
-
} else {
|
|
121
|
-
encodedValue = Array.from(textEncoder.encode(String(value)));
|
|
122
|
-
}
|
|
123
|
-
keys.push(key);
|
|
124
|
-
values.push(encodedValue);
|
|
327
|
+
return textEncoder.encode(value);
|
|
125
328
|
}
|
|
126
|
-
return { keys, values };
|
|
127
329
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
var RANGE_FIXED_POINT_SCALE = 1e6;
|
|
132
|
-
var LIMBO_MULTIPLIER_SCALE = 100;
|
|
133
|
-
function toBigIntAmount(value, fieldName) {
|
|
134
|
-
if (typeof value === "bigint") {
|
|
135
|
-
if (value < 0n) {
|
|
136
|
-
throw new Error(`${fieldName} must be non-negative`);
|
|
137
|
-
}
|
|
138
|
-
return value;
|
|
139
|
-
}
|
|
140
|
-
if (!Number.isFinite(value) || value < 0) {
|
|
141
|
-
throw new Error(`${fieldName} must be a finite non-negative number`);
|
|
330
|
+
function encodeMetadataValue(value) {
|
|
331
|
+
if (value instanceof Uint8Array) {
|
|
332
|
+
return Array.from(value);
|
|
142
333
|
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
function toU8Number(value, fieldName) {
|
|
146
|
-
if (!Number.isInteger(value) || value < 0 || value > 255) {
|
|
147
|
-
throw new Error(`${fieldName} must be an integer between 0 and 255`);
|
|
148
|
-
}
|
|
149
|
-
return value;
|
|
150
|
-
}
|
|
151
|
-
var MOVE_STDLIB_ADDRESS = normalizeSuiAddress("0x1");
|
|
152
|
-
var SUI_FRAMEWORK_ADDRESS = normalizeSuiAddress("0x2");
|
|
153
|
-
function getPureBcsSchema(typeTag) {
|
|
154
|
-
const parsedTag = typeof typeTag === "string" ? TypeTagSerializer.parseFromStr(typeTag) : typeTag;
|
|
155
|
-
if ("u8" in parsedTag) {
|
|
156
|
-
return bcs.U8;
|
|
157
|
-
} else if ("u16" in parsedTag) {
|
|
158
|
-
return bcs.U16;
|
|
159
|
-
} else if ("u32" in parsedTag) {
|
|
160
|
-
return bcs.U32;
|
|
161
|
-
} else if ("u64" in parsedTag) {
|
|
162
|
-
return bcs.U64;
|
|
163
|
-
} else if ("u128" in parsedTag) {
|
|
164
|
-
return bcs.U128;
|
|
165
|
-
} else if ("u256" in parsedTag) {
|
|
166
|
-
return bcs.U256;
|
|
167
|
-
} else if ("address" in parsedTag) {
|
|
168
|
-
return bcs.Address;
|
|
169
|
-
} else if ("bool" in parsedTag) {
|
|
170
|
-
return bcs.Bool;
|
|
171
|
-
} else if ("vector" in parsedTag) {
|
|
172
|
-
const type = getPureBcsSchema(parsedTag.vector);
|
|
173
|
-
return type ? bcs.vector(type) : null;
|
|
174
|
-
} else if ("struct" in parsedTag) {
|
|
175
|
-
const structTag = parsedTag.struct;
|
|
176
|
-
const pkg = normalizeSuiAddress(structTag.address);
|
|
177
|
-
if (pkg === MOVE_STDLIB_ADDRESS) {
|
|
178
|
-
if ((structTag.module === "ascii" || structTag.module === "string") && structTag.name === "String") {
|
|
179
|
-
return bcs.String;
|
|
180
|
-
}
|
|
181
|
-
if (structTag.module === "option" && structTag.name === "Option") {
|
|
182
|
-
const type = getPureBcsSchema(structTag.typeParams[0]);
|
|
183
|
-
return type ? bcs.option(type) : null;
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
if (pkg === SUI_FRAMEWORK_ADDRESS && structTag.module === "object" && (structTag.name === "ID" || structTag.name === "UID")) {
|
|
187
|
-
return bcs.Address;
|
|
188
|
-
}
|
|
334
|
+
if (Array.isArray(value)) {
|
|
335
|
+
return value;
|
|
189
336
|
}
|
|
190
|
-
return
|
|
337
|
+
return Array.from(encodeString(String(value)));
|
|
191
338
|
}
|
|
192
|
-
function
|
|
193
|
-
|
|
194
|
-
const
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
}
|
|
201
|
-
if (argType === "0x2::random::Random") {
|
|
202
|
-
normalizedArgs.push((tx) => tx.object.random());
|
|
203
|
-
continue;
|
|
204
|
-
}
|
|
205
|
-
if (argType === "0x2::deny_list::DenyList") {
|
|
206
|
-
normalizedArgs.push((tx) => tx.object.denyList());
|
|
207
|
-
continue;
|
|
208
|
-
}
|
|
209
|
-
if (argType === "0x3::sui_system::SuiSystemState") {
|
|
210
|
-
normalizedArgs.push((tx) => tx.object.system());
|
|
211
|
-
continue;
|
|
212
|
-
}
|
|
213
|
-
let arg;
|
|
214
|
-
if (Array.isArray(args)) {
|
|
215
|
-
if (index >= args.length) {
|
|
216
|
-
throw new Error(
|
|
217
|
-
`Invalid number of arguments, expected at least ${index + 1}, got ${args.length}`
|
|
218
|
-
);
|
|
219
|
-
}
|
|
220
|
-
arg = args[index];
|
|
221
|
-
} else {
|
|
222
|
-
{
|
|
223
|
-
throw new Error(`Expected arguments to be passed as an array`);
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
index += 1;
|
|
227
|
-
if (typeof arg === "function" || isArgument(arg)) {
|
|
228
|
-
normalizedArgs.push(arg);
|
|
229
|
-
continue;
|
|
230
|
-
}
|
|
231
|
-
const type = argTypes[i];
|
|
232
|
-
const bcsType = type === null ? null : getPureBcsSchema(type);
|
|
233
|
-
if (bcsType) {
|
|
234
|
-
const bytes = bcsType.serialize(arg);
|
|
235
|
-
normalizedArgs.push((tx) => tx.pure(bytes));
|
|
339
|
+
function encodeBetMetadata(metadata, partner) {
|
|
340
|
+
const keys = [];
|
|
341
|
+
const values = [];
|
|
342
|
+
for (const [key, value] of Object.entries(metadata ?? {})) {
|
|
343
|
+
if (RESERVED_METADATA_KEYS.has(key)) {
|
|
344
|
+
console.warn(
|
|
345
|
+
`Metadata key "${key}" is reserved and will be ignored when parsing metadata.`
|
|
346
|
+
);
|
|
236
347
|
continue;
|
|
237
348
|
}
|
|
238
|
-
if (
|
|
239
|
-
normalizedArgs.push((tx) => tx.object(arg));
|
|
349
|
+
if (value == null) {
|
|
240
350
|
continue;
|
|
241
351
|
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
return normalizedArgs;
|
|
245
|
-
}
|
|
246
|
-
var MoveStruct = class extends BcsStruct {
|
|
247
|
-
async get({
|
|
248
|
-
objectId,
|
|
249
|
-
...options
|
|
250
|
-
}) {
|
|
251
|
-
const [res] = await this.getMany({
|
|
252
|
-
...options,
|
|
253
|
-
objectIds: [objectId]
|
|
254
|
-
});
|
|
255
|
-
return res;
|
|
256
|
-
}
|
|
257
|
-
async getMany({
|
|
258
|
-
client,
|
|
259
|
-
...options
|
|
260
|
-
}) {
|
|
261
|
-
const response = await client.core.getObjects({
|
|
262
|
-
...options,
|
|
263
|
-
include: {
|
|
264
|
-
...options.include,
|
|
265
|
-
content: true
|
|
266
|
-
}
|
|
267
|
-
});
|
|
268
|
-
return response.objects.map((obj) => {
|
|
269
|
-
if (obj instanceof Error) {
|
|
270
|
-
throw obj;
|
|
271
|
-
}
|
|
272
|
-
return {
|
|
273
|
-
...obj,
|
|
274
|
-
json: this.parse(obj.content)
|
|
275
|
-
};
|
|
276
|
-
});
|
|
277
|
-
}
|
|
278
|
-
};
|
|
279
|
-
function stringify(val) {
|
|
280
|
-
if (typeof val === "object") {
|
|
281
|
-
return JSON.stringify(val, (val2) => val2);
|
|
352
|
+
keys.push(key);
|
|
353
|
+
values.push(encodeMetadataValue(value));
|
|
282
354
|
}
|
|
283
|
-
if (
|
|
284
|
-
|
|
355
|
+
if (partner?.trim()) {
|
|
356
|
+
keys.unshift(PARTNER_METADATA_KEY);
|
|
357
|
+
values.unshift(encodeMetadataValue(partner));
|
|
285
358
|
}
|
|
286
|
-
return
|
|
359
|
+
return {
|
|
360
|
+
keys,
|
|
361
|
+
values
|
|
362
|
+
};
|
|
287
363
|
}
|
|
288
364
|
|
|
289
365
|
// src/contracts/coinflip/coinflip.ts
|
|
@@ -309,39 +385,46 @@ function play(options) {
|
|
|
309
385
|
typeArguments: options.typeArguments
|
|
310
386
|
});
|
|
311
387
|
}
|
|
388
|
+
|
|
389
|
+
// src/types/network.type.ts
|
|
390
|
+
var SUPPORTED_SUI_NETWORKS = [
|
|
391
|
+
"mainnet",
|
|
392
|
+
"testnet"
|
|
393
|
+
];
|
|
394
|
+
|
|
395
|
+
// src/transactions/shared.ts
|
|
312
396
|
function createBaseGameTransaction({
|
|
313
397
|
config,
|
|
314
398
|
game,
|
|
315
|
-
|
|
316
|
-
sender,
|
|
399
|
+
playerAddress,
|
|
317
400
|
gasBudget
|
|
318
401
|
}) {
|
|
319
402
|
assertConfiguredBetGame(config, game);
|
|
320
403
|
const tx = new Transaction();
|
|
321
|
-
tx.setSenderIfNotSet(normalizeSuiAddress(
|
|
404
|
+
tx.setSenderIfNotSet(normalizeSuiAddress(playerAddress));
|
|
322
405
|
tx.setGasBudgetIfNotSet(gasBudget ?? DEFAULT_GAS_BUDGET_MIST);
|
|
323
406
|
return tx;
|
|
324
407
|
}
|
|
325
408
|
function buildSharedStandardGameBetCall({
|
|
326
409
|
config,
|
|
327
|
-
|
|
328
|
-
sender,
|
|
410
|
+
playerAddress,
|
|
329
411
|
coinType,
|
|
330
412
|
stake,
|
|
331
413
|
cashStake,
|
|
332
414
|
betCount,
|
|
333
415
|
metadata,
|
|
416
|
+
partner,
|
|
334
417
|
allowGasCoinShortcut = true,
|
|
335
418
|
buildRewardCoin
|
|
336
419
|
}) {
|
|
337
420
|
return (tx) => {
|
|
338
|
-
const
|
|
421
|
+
const normalizedPlayerAddress = normalizeSuiAddress(playerAddress);
|
|
339
422
|
const normalizedCoinType = normalizeStructTag(coinType);
|
|
340
|
-
const resolvedStake =
|
|
341
|
-
const resolvedCashStake =
|
|
342
|
-
const resolvedBetCount =
|
|
343
|
-
const encodedMetadata = encodeBetMetadata(metadata);
|
|
344
|
-
const
|
|
423
|
+
const resolvedStake = toBigInt(stake);
|
|
424
|
+
const resolvedCashStake = toBigInt(cashStake ?? stake);
|
|
425
|
+
const resolvedBetCount = toBigInt(betCount ?? 1);
|
|
426
|
+
const encodedMetadata = encodeBetMetadata(metadata, partner);
|
|
427
|
+
const priceInfoObjectId = resolvePriceInfoObjectId(
|
|
345
428
|
config,
|
|
346
429
|
normalizedCoinType
|
|
347
430
|
);
|
|
@@ -353,16 +436,16 @@ function buildSharedStandardGameBetCall({
|
|
|
353
436
|
const rewardCoin = buildRewardCoin({
|
|
354
437
|
tx,
|
|
355
438
|
config,
|
|
356
|
-
|
|
439
|
+
playerAddress: normalizedPlayerAddress,
|
|
357
440
|
coinType: normalizedCoinType,
|
|
358
441
|
stake: resolvedStake,
|
|
359
442
|
cashStake: resolvedCashStake,
|
|
360
443
|
betCount: resolvedBetCount,
|
|
361
444
|
metadata: encodedMetadata,
|
|
362
|
-
|
|
445
|
+
priceInfoObjectId,
|
|
363
446
|
betCoin
|
|
364
447
|
});
|
|
365
|
-
tx.transferObjects([rewardCoin], tx.pure.address(
|
|
448
|
+
tx.transferObjects([rewardCoin], tx.pure.address(normalizedPlayerAddress));
|
|
366
449
|
return rewardCoin;
|
|
367
450
|
};
|
|
368
451
|
}
|
|
@@ -384,20 +467,20 @@ function buildCoinflipTransaction(options) {
|
|
|
384
467
|
stake,
|
|
385
468
|
betCount,
|
|
386
469
|
metadata,
|
|
387
|
-
|
|
470
|
+
priceInfoObjectId,
|
|
388
471
|
betCoin
|
|
389
472
|
}) => play({
|
|
390
|
-
package: config.
|
|
473
|
+
package: config.packageIds.coinflip,
|
|
391
474
|
typeArguments: [coinType],
|
|
392
475
|
arguments: [
|
|
393
|
-
config.
|
|
476
|
+
config.packageIds.sweetHouse,
|
|
394
477
|
stake,
|
|
395
478
|
betCoin,
|
|
396
479
|
betCount,
|
|
397
480
|
options.side === "tails",
|
|
398
481
|
metadata.keys,
|
|
399
482
|
metadata.values,
|
|
400
|
-
|
|
483
|
+
priceInfoObjectId
|
|
401
484
|
]
|
|
402
485
|
})(tx)
|
|
403
486
|
});
|
|
@@ -430,7 +513,7 @@ function play2(options) {
|
|
|
430
513
|
|
|
431
514
|
// src/transactions/limbo.ts
|
|
432
515
|
function buildLimboTransaction(options) {
|
|
433
|
-
const scale = options.scale ??
|
|
516
|
+
const scale = options.scale ?? DEFAULT_LIMBO_MULTIPLIER_SCALE;
|
|
434
517
|
const numerator = Math.round(options.targetMultiplier * scale);
|
|
435
518
|
return buildSharedStandardGameBetTransaction({
|
|
436
519
|
...options,
|
|
@@ -442,13 +525,13 @@ function buildLimboTransaction(options) {
|
|
|
442
525
|
stake,
|
|
443
526
|
betCount,
|
|
444
527
|
metadata,
|
|
445
|
-
|
|
528
|
+
priceInfoObjectId,
|
|
446
529
|
betCoin
|
|
447
530
|
}) => play2({
|
|
448
|
-
package: config.
|
|
531
|
+
package: config.packageIds.limbo,
|
|
449
532
|
typeArguments: [coinType],
|
|
450
533
|
arguments: [
|
|
451
|
-
config.
|
|
534
|
+
config.packageIds.sweetHouse,
|
|
452
535
|
stake,
|
|
453
536
|
betCoin,
|
|
454
537
|
betCount,
|
|
@@ -456,7 +539,7 @@ function buildLimboTransaction(options) {
|
|
|
456
539
|
BigInt(scale),
|
|
457
540
|
metadata.keys,
|
|
458
541
|
metadata.values,
|
|
459
|
-
|
|
542
|
+
priceInfoObjectId
|
|
460
543
|
]
|
|
461
544
|
})(tx)
|
|
462
545
|
});
|
|
@@ -488,7 +571,7 @@ function play3(options) {
|
|
|
488
571
|
|
|
489
572
|
// src/transactions/plinko.ts
|
|
490
573
|
function buildPlinkoTransaction(options) {
|
|
491
|
-
const configId =
|
|
574
|
+
const configId = toU8(options.configId);
|
|
492
575
|
return buildSharedStandardGameBetTransaction({
|
|
493
576
|
...options,
|
|
494
577
|
game: "plinko",
|
|
@@ -499,134 +582,35 @@ function buildPlinkoTransaction(options) {
|
|
|
499
582
|
stake,
|
|
500
583
|
betCount,
|
|
501
584
|
metadata,
|
|
502
|
-
|
|
585
|
+
priceInfoObjectId,
|
|
503
586
|
betCoin
|
|
504
587
|
}) => play3({
|
|
505
|
-
package: config.
|
|
588
|
+
package: config.packageIds.plinko,
|
|
506
589
|
typeArguments: [coinType],
|
|
507
590
|
arguments: [
|
|
508
|
-
config.
|
|
591
|
+
config.packageIds.sweetHouse,
|
|
509
592
|
stake,
|
|
510
593
|
betCoin,
|
|
511
594
|
betCount,
|
|
512
595
|
configId,
|
|
513
596
|
metadata.keys,
|
|
514
597
|
metadata.values,
|
|
515
|
-
|
|
598
|
+
priceInfoObjectId
|
|
516
599
|
]
|
|
517
600
|
})(tx)
|
|
518
601
|
});
|
|
519
602
|
}
|
|
520
|
-
var $moduleName = "0x0000000000000000000000000000000000000000000000000000000000000001::type_name";
|
|
521
|
-
var TypeName = new MoveStruct({ name: `${$moduleName}::TypeName`, fields: {
|
|
522
|
-
name: bcs.string()
|
|
523
|
-
} });
|
|
524
|
-
|
|
525
|
-
// src/contracts/pvp-coinflip/pvp_coinflip.ts
|
|
526
|
-
var $moduleName2 = "0xb43cf6583c0c15315c7e66f173af4be79ac40c38aad1fd92ec08638ab2026202::pvp_coinflip";
|
|
527
|
-
function GameCreatedEvent(...typeParameters) {
|
|
528
|
-
return new MoveStruct({ name: `${$moduleName2}::GameCreatedEvent<${typeParameters[0].name}>`, fields: {
|
|
529
|
-
game_id: bcs.Address,
|
|
530
|
-
creator: bcs.Address,
|
|
531
|
-
creator_is_tails: bcs.bool(),
|
|
532
|
-
is_private: bcs.bool(),
|
|
533
|
-
joiner_is_tails: bcs.bool(),
|
|
534
|
-
stake_per_player: bcs.u64(),
|
|
535
|
-
house_edge_bps: bcs.u64(),
|
|
536
|
-
coin_type: TypeName
|
|
537
|
-
} });
|
|
538
|
-
}
|
|
539
|
-
function GameResolvedEvent(...typeParameters) {
|
|
540
|
-
return new MoveStruct({ name: `${$moduleName2}::GameResolvedEvent<${typeParameters[0].name}>`, fields: {
|
|
541
|
-
game_id: bcs.Address,
|
|
542
|
-
creator: bcs.Address,
|
|
543
|
-
joiner: bcs.Address,
|
|
544
|
-
winner: bcs.Address,
|
|
545
|
-
creator_is_tails: bcs.bool(),
|
|
546
|
-
is_private: bcs.bool(),
|
|
547
|
-
joiner_is_tails: bcs.bool(),
|
|
548
|
-
stake_per_player: bcs.u64(),
|
|
549
|
-
total_pot: bcs.u64(),
|
|
550
|
-
house_edge_amount: bcs.u64(),
|
|
551
|
-
payout_amount: bcs.u64(),
|
|
552
|
-
coin_type: TypeName
|
|
553
|
-
} });
|
|
554
|
-
}
|
|
555
|
-
function GameCancelledEvent(...typeParameters) {
|
|
556
|
-
return new MoveStruct({ name: `${$moduleName2}::GameCancelledEvent<${typeParameters[0].name}>`, fields: {
|
|
557
|
-
game_id: bcs.Address,
|
|
558
|
-
creator: bcs.Address,
|
|
559
|
-
creator_is_tails: bcs.bool(),
|
|
560
|
-
is_private: bcs.bool(),
|
|
561
|
-
stake_per_player: bcs.u64(),
|
|
562
|
-
coin_type: TypeName
|
|
563
|
-
} });
|
|
564
|
-
}
|
|
565
|
-
function createGame(options) {
|
|
566
|
-
const packageAddress = options.package ?? "0xb43cf6583c0c15315c7e66f173af4be79ac40c38aad1fd92ec08638ab2026202";
|
|
567
|
-
const argumentsTypes = [
|
|
568
|
-
null,
|
|
569
|
-
null,
|
|
570
|
-
"bool",
|
|
571
|
-
"bool",
|
|
572
|
-
"vector<0x1::string::String>",
|
|
573
|
-
"vector<vector<u8>>"
|
|
574
|
-
];
|
|
575
|
-
return (tx) => tx.moveCall({
|
|
576
|
-
package: packageAddress,
|
|
577
|
-
module: "pvp_coinflip",
|
|
578
|
-
function: "create_game",
|
|
579
|
-
arguments: normalizeMoveArguments(options.arguments, argumentsTypes),
|
|
580
|
-
typeArguments: options.typeArguments
|
|
581
|
-
});
|
|
582
|
-
}
|
|
583
|
-
function joinGame(options) {
|
|
584
|
-
const packageAddress = options.package ?? "0xb43cf6583c0c15315c7e66f173af4be79ac40c38aad1fd92ec08638ab2026202";
|
|
585
|
-
const argumentsTypes = [
|
|
586
|
-
"0x2::object::ID",
|
|
587
|
-
null,
|
|
588
|
-
null,
|
|
589
|
-
"vector<0x1::string::String>",
|
|
590
|
-
"vector<vector<u8>>",
|
|
591
|
-
null,
|
|
592
|
-
"0x2::clock::Clock",
|
|
593
|
-
"0x2::random::Random"
|
|
594
|
-
];
|
|
595
|
-
return (tx) => tx.moveCall({
|
|
596
|
-
package: packageAddress,
|
|
597
|
-
module: "pvp_coinflip",
|
|
598
|
-
function: "join_game",
|
|
599
|
-
arguments: normalizeMoveArguments(options.arguments, argumentsTypes),
|
|
600
|
-
typeArguments: options.typeArguments
|
|
601
|
-
});
|
|
602
|
-
}
|
|
603
|
-
function cancelGame(options) {
|
|
604
|
-
const packageAddress = options.package ?? "0xb43cf6583c0c15315c7e66f173af4be79ac40c38aad1fd92ec08638ab2026202";
|
|
605
|
-
const argumentsTypes = [
|
|
606
|
-
"0x2::object::ID",
|
|
607
|
-
null
|
|
608
|
-
];
|
|
609
|
-
return (tx) => tx.moveCall({
|
|
610
|
-
package: packageAddress,
|
|
611
|
-
module: "pvp_coinflip",
|
|
612
|
-
function: "cancel_game",
|
|
613
|
-
arguments: normalizeMoveArguments(options.arguments, argumentsTypes),
|
|
614
|
-
typeArguments: options.typeArguments
|
|
615
|
-
});
|
|
616
|
-
}
|
|
617
|
-
|
|
618
|
-
// src/transactions/pvp-coinflip.ts
|
|
619
603
|
function buildPvPCoinflipTransaction(action, options) {
|
|
620
604
|
const tx = createBaseGameTransaction({
|
|
621
605
|
...options,
|
|
622
606
|
game: "pvp-coinflip"
|
|
623
607
|
});
|
|
624
608
|
const normalizedCoinType = normalizeStructTag(options.coinType);
|
|
625
|
-
const encodedMetadata = encodeBetMetadata(options.metadata);
|
|
609
|
+
const encodedMetadata = encodeBetMetadata(options.metadata, options.partner);
|
|
626
610
|
switch (action) {
|
|
627
611
|
case "create": {
|
|
628
612
|
const createOptions = options;
|
|
629
|
-
const stake =
|
|
613
|
+
const stake = toBigInt(createOptions.stake);
|
|
630
614
|
const betCoin = tx.coin({
|
|
631
615
|
type: normalizedCoinType,
|
|
632
616
|
balance: stake,
|
|
@@ -634,10 +618,10 @@ function buildPvPCoinflipTransaction(action, options) {
|
|
|
634
618
|
});
|
|
635
619
|
tx.add(
|
|
636
620
|
createGame({
|
|
637
|
-
package: createOptions.config.
|
|
621
|
+
package: createOptions.config.packageIds.pvpCoinflip,
|
|
638
622
|
typeArguments: [normalizedCoinType],
|
|
639
623
|
arguments: [
|
|
640
|
-
createOptions.config.
|
|
624
|
+
createOptions.config.packageIds.sweetHouse,
|
|
641
625
|
betCoin,
|
|
642
626
|
createOptions.side === "tails",
|
|
643
627
|
Boolean(createOptions.isPrivate),
|
|
@@ -650,23 +634,21 @@ function buildPvPCoinflipTransaction(action, options) {
|
|
|
650
634
|
}
|
|
651
635
|
case "join": {
|
|
652
636
|
const joinOptions = options;
|
|
653
|
-
const
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
useGasCoin: joinOptions.allowGasCoinShortcut
|
|
658
|
-
});
|
|
637
|
+
const priceInfoObjectId = resolvePriceInfoObjectId(
|
|
638
|
+
joinOptions.config,
|
|
639
|
+
normalizedCoinType
|
|
640
|
+
);
|
|
659
641
|
tx.add(
|
|
660
642
|
joinGame({
|
|
661
|
-
package: joinOptions.config.
|
|
643
|
+
package: joinOptions.config.packageIds.pvpCoinflip,
|
|
662
644
|
typeArguments: [normalizedCoinType],
|
|
663
645
|
arguments: [
|
|
664
646
|
joinOptions.gameId,
|
|
665
|
-
joinOptions.config.
|
|
666
|
-
betCoin,
|
|
647
|
+
joinOptions.config.packageIds.sweetHouse,
|
|
648
|
+
tx.add(joinOptions.betCoin),
|
|
667
649
|
encodedMetadata.keys,
|
|
668
650
|
encodedMetadata.values,
|
|
669
|
-
|
|
651
|
+
priceInfoObjectId
|
|
670
652
|
]
|
|
671
653
|
})
|
|
672
654
|
);
|
|
@@ -676,11 +658,11 @@ function buildPvPCoinflipTransaction(action, options) {
|
|
|
676
658
|
const cancelOptions = options;
|
|
677
659
|
tx.add(
|
|
678
660
|
cancelGame({
|
|
679
|
-
package: cancelOptions.config.
|
|
661
|
+
package: cancelOptions.config.packageIds.pvpCoinflip,
|
|
680
662
|
typeArguments: [normalizedCoinType],
|
|
681
663
|
arguments: [
|
|
682
664
|
cancelOptions.gameId,
|
|
683
|
-
cancelOptions.config.
|
|
665
|
+
cancelOptions.config.packageIds.sweetHouse
|
|
684
666
|
]
|
|
685
667
|
})
|
|
686
668
|
);
|
|
@@ -719,7 +701,7 @@ function play4(options) {
|
|
|
719
701
|
|
|
720
702
|
// src/transactions/range.ts
|
|
721
703
|
function buildRangeTransaction(options) {
|
|
722
|
-
const scale = options.scale ??
|
|
704
|
+
const scale = options.scale ?? DEFAULT_RANGE_SCALE;
|
|
723
705
|
const leftPoint = Math.round(options.leftPoint * scale);
|
|
724
706
|
const rightPoint = Math.round(options.rightPoint * scale);
|
|
725
707
|
return buildSharedStandardGameBetTransaction({
|
|
@@ -732,13 +714,13 @@ function buildRangeTransaction(options) {
|
|
|
732
714
|
stake,
|
|
733
715
|
betCount,
|
|
734
716
|
metadata,
|
|
735
|
-
|
|
717
|
+
priceInfoObjectId,
|
|
736
718
|
betCoin
|
|
737
719
|
}) => play4({
|
|
738
|
-
package: config.
|
|
720
|
+
package: config.packageIds.range,
|
|
739
721
|
typeArguments: [coinType],
|
|
740
722
|
arguments: [
|
|
741
|
-
config.
|
|
723
|
+
config.packageIds.sweetHouse,
|
|
742
724
|
stake,
|
|
743
725
|
betCoin,
|
|
744
726
|
betCount,
|
|
@@ -747,7 +729,7 @@ function buildRangeTransaction(options) {
|
|
|
747
729
|
Boolean(options.outOfRange),
|
|
748
730
|
metadata.keys,
|
|
749
731
|
metadata.values,
|
|
750
|
-
|
|
732
|
+
priceInfoObjectId
|
|
751
733
|
]
|
|
752
734
|
})(tx)
|
|
753
735
|
});
|
|
@@ -779,7 +761,7 @@ function play5(options) {
|
|
|
779
761
|
|
|
780
762
|
// src/transactions/wheel.ts
|
|
781
763
|
function buildWheelTransaction(options) {
|
|
782
|
-
const configId =
|
|
764
|
+
const configId = toU8(options.configId);
|
|
783
765
|
return buildSharedStandardGameBetTransaction({
|
|
784
766
|
...options,
|
|
785
767
|
game: "wheel",
|
|
@@ -790,87 +772,64 @@ function buildWheelTransaction(options) {
|
|
|
790
772
|
stake,
|
|
791
773
|
betCount,
|
|
792
774
|
metadata,
|
|
793
|
-
|
|
775
|
+
priceInfoObjectId,
|
|
794
776
|
betCoin
|
|
795
777
|
}) => play5({
|
|
796
|
-
package: config.
|
|
778
|
+
package: config.packageIds.wheel,
|
|
797
779
|
typeArguments: [coinType],
|
|
798
780
|
arguments: [
|
|
799
|
-
config.
|
|
781
|
+
config.packageIds.sweetHouse,
|
|
800
782
|
stake,
|
|
801
783
|
betCoin,
|
|
802
784
|
betCount,
|
|
803
785
|
configId,
|
|
804
786
|
metadata.keys,
|
|
805
787
|
metadata.values,
|
|
806
|
-
|
|
788
|
+
priceInfoObjectId
|
|
807
789
|
]
|
|
808
790
|
})(tx)
|
|
809
791
|
});
|
|
810
792
|
}
|
|
811
|
-
var $moduleName3 = "0x0000000000000000000000000000000000000000000000000000000000000001::type_name";
|
|
812
|
-
var TypeName2 = new MoveStruct({ name: `${$moduleName3}::TypeName`, fields: {
|
|
813
|
-
name: bcs.string()
|
|
814
|
-
} });
|
|
815
|
-
var $moduleName4 = "0xf391858d2a08473e8d4defcc8df89976bd7b123d3865c6b9341b237f7853dbbc::i64";
|
|
816
|
-
var I64 = new MoveStruct({ name: `${$moduleName4}::I64`, fields: {
|
|
817
|
-
bits: bcs.u64()
|
|
818
|
-
} });
|
|
819
793
|
|
|
820
|
-
// src/
|
|
821
|
-
var $moduleName5 = "0xf391858d2a08473e8d4defcc8df89976bd7b123d3865c6b9341b237f7853dbbc::float";
|
|
822
|
-
var Float = new MoveStruct({ name: `${$moduleName5}::Float`, fields: {
|
|
823
|
-
is_negative: bcs.bool(),
|
|
824
|
-
exp: I64,
|
|
825
|
-
mant: bcs.u64()
|
|
826
|
-
} });
|
|
827
|
-
var $moduleName6 = "0x2::vec_map";
|
|
828
|
-
function Entry(...typeParameters) {
|
|
829
|
-
return new MoveStruct({ name: `${$moduleName6}::Entry<${typeParameters[0].name}, ${typeParameters[1].name}>`, fields: {
|
|
830
|
-
key: typeParameters[0],
|
|
831
|
-
value: typeParameters[1]
|
|
832
|
-
} });
|
|
833
|
-
}
|
|
834
|
-
function VecMap(...typeParameters) {
|
|
835
|
-
return new MoveStruct({ name: `${$moduleName6}::VecMap<${typeParameters[0].name}, ${typeParameters[1].name}>`, fields: {
|
|
836
|
-
contents: bcs.vector(Entry(typeParameters[0], typeParameters[1]))
|
|
837
|
-
} });
|
|
838
|
-
}
|
|
839
|
-
|
|
840
|
-
// src/contracts/core/core.ts
|
|
841
|
-
var $moduleName7 = "0xf391858d2a08473e8d4defcc8df89976bd7b123d3865c6b9341b237f7853dbbc::core";
|
|
842
|
-
function BetResultEvent(...typeParameters) {
|
|
843
|
-
return new MoveStruct({ name: `${$moduleName7}::BetResultEvent<${typeParameters[0].name}>`, fields: {
|
|
844
|
-
player: bcs.Address,
|
|
845
|
-
coin_type: TypeName2,
|
|
846
|
-
stake_amount: bcs.u64(),
|
|
847
|
-
unsafe_oracle_usd_coin_price: Float,
|
|
848
|
-
adjusted_oracle_usd_coin_price: Float,
|
|
849
|
-
outcome_amount: bcs.u64(),
|
|
850
|
-
game_details: VecMap(bcs.string(), bcs.vector(bcs.u8())),
|
|
851
|
-
metadata: VecMap(bcs.string(), bcs.vector(bcs.u8()))
|
|
852
|
-
} });
|
|
853
|
-
}
|
|
794
|
+
// src/client.ts
|
|
854
795
|
function suigar({
|
|
855
796
|
name = "suigar",
|
|
856
|
-
|
|
797
|
+
partner
|
|
857
798
|
} = {}) {
|
|
858
799
|
return {
|
|
859
800
|
name,
|
|
860
801
|
register: (client) => {
|
|
861
|
-
return new SuigarClient({ client,
|
|
802
|
+
return new SuigarClient({ client, partner });
|
|
862
803
|
}
|
|
863
804
|
};
|
|
864
805
|
}
|
|
865
806
|
var SuigarClient = class {
|
|
866
807
|
#client;
|
|
867
808
|
#config;
|
|
809
|
+
#partner;
|
|
868
810
|
constructor({
|
|
869
811
|
client,
|
|
870
|
-
|
|
812
|
+
partner
|
|
871
813
|
}) {
|
|
872
814
|
this.#client = client;
|
|
873
|
-
this.#
|
|
815
|
+
this.#partner = partner;
|
|
816
|
+
const network = this.#client.network;
|
|
817
|
+
if (!SUPPORTED_SUI_NETWORKS.includes(network)) {
|
|
818
|
+
throw new Error(`Unsupported network: ${network}`);
|
|
819
|
+
}
|
|
820
|
+
this.#config = resolveSuigarConfig(network);
|
|
821
|
+
}
|
|
822
|
+
/**
|
|
823
|
+
* Returns the resolved SDK configuration for the connected network.
|
|
824
|
+
*
|
|
825
|
+
* This is primarily useful for debugging or inspecting which package ids,
|
|
826
|
+
* supported coin types, and price info object ids the SDK resolved for the
|
|
827
|
+
* current client network.
|
|
828
|
+
*
|
|
829
|
+
* @returns Network-resolved Suigar configuration.
|
|
830
|
+
*/
|
|
831
|
+
getConfig() {
|
|
832
|
+
return this.#config;
|
|
874
833
|
}
|
|
875
834
|
/**
|
|
876
835
|
* Builds a transaction with the configured Sui client and encodes the resulting BCS bytes as base64.
|
|
@@ -888,9 +847,86 @@ var SuigarClient = class {
|
|
|
888
847
|
return toBase64(bytes);
|
|
889
848
|
}
|
|
890
849
|
/**
|
|
891
|
-
*
|
|
850
|
+
* Lists unresolved PvP coinflip games from the configured registry and resolves
|
|
851
|
+
* each entry into parsed onchain game state.
|
|
852
|
+
*
|
|
853
|
+
* This fetches dynamic fields from the PvP coinflip registry object, then bulk
|
|
854
|
+
* loads the referenced game objects through `client.core.getObjects()`. Registry
|
|
855
|
+
* membership is the unresolved-state signal: when a game is joined and resolved,
|
|
856
|
+
* the Move flow removes it from the registry and deletes the live `Game` object.
|
|
857
|
+
* Use this when a product needs the current set of open PvP coinflip matches for
|
|
858
|
+
* browsing or lobby views.
|
|
859
|
+
*
|
|
860
|
+
* @param options Optional dynamic field pagination forwarded to `listDynamicFields()`, excluding `parentId`.
|
|
861
|
+
* Supported options such as `limit`, `cursor`, and `signal` are forwarded to the
|
|
862
|
+
* underlying lookup calls. Pass `throwOnError: true` to fail the whole lookup
|
|
863
|
+
* when any referenced game object cannot be fetched or parsed. By default,
|
|
864
|
+
* failed per-object lookups are skipped and only successfully parsed unresolved
|
|
865
|
+
* games are returned.
|
|
866
|
+
* @returns Parsed unresolved PvP coinflip game objects for the requested
|
|
867
|
+
* registry page. When `throwOnError` is `false`, entries that fail object fetch
|
|
868
|
+
* or parse are omitted from the returned array.
|
|
869
|
+
*/
|
|
870
|
+
async getPvPCoinflipGames(options = {
|
|
871
|
+
limit: 50
|
|
872
|
+
}) {
|
|
873
|
+
const { throwOnError = false, ...listOptions } = options;
|
|
874
|
+
const { dynamicFields } = await this.#client.core.listDynamicFields({
|
|
875
|
+
...listOptions,
|
|
876
|
+
parentId: this.#config.registryIds.pvpCoinflip
|
|
877
|
+
});
|
|
878
|
+
const { objects } = await this.#client.core.getObjects({
|
|
879
|
+
objectIds: dynamicFields.map(({ childId }) => childId),
|
|
880
|
+
signal: listOptions.signal,
|
|
881
|
+
include: {
|
|
882
|
+
content: true
|
|
883
|
+
}
|
|
884
|
+
});
|
|
885
|
+
const resolvedGames = objects.map((object) => {
|
|
886
|
+
try {
|
|
887
|
+
if (object instanceof Error) {
|
|
888
|
+
throw object;
|
|
889
|
+
}
|
|
890
|
+
if (!object.content) {
|
|
891
|
+
throw new Error(
|
|
892
|
+
"Unable to resolve PvP coinflip game from retrieved object"
|
|
893
|
+
);
|
|
894
|
+
}
|
|
895
|
+
return {
|
|
896
|
+
...Game.parse(object.content),
|
|
897
|
+
coinType: parseCoinType(object.type)
|
|
898
|
+
};
|
|
899
|
+
} catch (error) {
|
|
900
|
+
return error instanceof Error ? error : new Error(String(error));
|
|
901
|
+
}
|
|
902
|
+
});
|
|
903
|
+
if (throwOnError) {
|
|
904
|
+
const firstError = resolvedGames.find((game) => game instanceof Error);
|
|
905
|
+
if (firstError) {
|
|
906
|
+
throw firstError;
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
return resolvedGames.flatMap(
|
|
910
|
+
(game) => game instanceof Error ? [] : [game]
|
|
911
|
+
);
|
|
912
|
+
}
|
|
913
|
+
/**
|
|
914
|
+
* BCS struct constructors for decoding on-chain objects and events related to Suigar games.
|
|
915
|
+
*
|
|
916
|
+
* These can be used to parse the `content` field of on-chain objects and events into structured data with the
|
|
917
|
+
* expected types. For example, use `client.suigar.bcs.PvPCoinflipGame.parse(object.content)` to decode a PvP
|
|
918
|
+
* coinflip game object.
|
|
919
|
+
*
|
|
920
|
+
* Note that these constructors are not meant for encoding transaction arguments, as the SDK's transaction
|
|
921
|
+
* builders handle argument serialization internally. Use these primarily for decoding and parsing on-chain data.
|
|
892
922
|
*/
|
|
893
923
|
bcs = {
|
|
924
|
+
// Objects
|
|
925
|
+
/**
|
|
926
|
+
* Object representing the state of a PvP coinflip game, as stored on-chain.
|
|
927
|
+
*/
|
|
928
|
+
PvPCoinflipGame: Game,
|
|
929
|
+
// Events
|
|
894
930
|
/**
|
|
895
931
|
* Event emitted at the end of a standard game (e.g., Coinflip, Limbo), containing the result and payout information.
|
|
896
932
|
*/
|
|
@@ -898,15 +934,15 @@ var SuigarClient = class {
|
|
|
898
934
|
/**
|
|
899
935
|
* Event emitted when a PvP Coinflip game is created, containing the game configuration and initial state.
|
|
900
936
|
*/
|
|
901
|
-
|
|
937
|
+
PvPCoinflipGameCreatedEvent: GameCreatedEvent,
|
|
902
938
|
/**
|
|
903
939
|
* Event emitted when a PvP Coinflip game is resolved, containing the final outcome.
|
|
904
940
|
*/
|
|
905
|
-
|
|
941
|
+
PvPCoinflipGameResolvedEvent: GameResolvedEvent,
|
|
906
942
|
/**
|
|
907
943
|
* Event emitted when a PvP Coinflip game is cancelled.
|
|
908
944
|
*/
|
|
909
|
-
|
|
945
|
+
PvPCoinflipGameCancelledEvent: GameCancelledEvent
|
|
910
946
|
};
|
|
911
947
|
/**
|
|
912
948
|
* Transaction builders for Suigar games.
|
|
@@ -924,27 +960,32 @@ var SuigarClient = class {
|
|
|
924
960
|
case "coinflip":
|
|
925
961
|
return buildCoinflipTransaction({
|
|
926
962
|
...options,
|
|
927
|
-
config: this.#config
|
|
963
|
+
config: this.#config,
|
|
964
|
+
partner: this.#partner
|
|
928
965
|
});
|
|
929
966
|
case "limbo":
|
|
930
967
|
return buildLimboTransaction({
|
|
931
968
|
...options,
|
|
932
|
-
config: this.#config
|
|
969
|
+
config: this.#config,
|
|
970
|
+
partner: this.#partner
|
|
933
971
|
});
|
|
934
972
|
case "plinko":
|
|
935
973
|
return buildPlinkoTransaction({
|
|
936
974
|
...options,
|
|
937
|
-
config: this.#config
|
|
975
|
+
config: this.#config,
|
|
976
|
+
partner: this.#partner
|
|
938
977
|
});
|
|
939
978
|
case "range":
|
|
940
979
|
return buildRangeTransaction({
|
|
941
980
|
...options,
|
|
942
|
-
config: this.#config
|
|
981
|
+
config: this.#config,
|
|
982
|
+
partner: this.#partner
|
|
943
983
|
});
|
|
944
984
|
case "wheel":
|
|
945
985
|
return buildWheelTransaction({
|
|
946
986
|
...options,
|
|
947
|
-
config: this.#config
|
|
987
|
+
config: this.#config,
|
|
988
|
+
partner: this.#partner
|
|
948
989
|
});
|
|
949
990
|
default:
|
|
950
991
|
throw new Error(`Unsupported game: ${gameId}`);
|
|
@@ -958,12 +999,46 @@ var SuigarClient = class {
|
|
|
958
999
|
* @returns Prepared PvP coinflip transaction.
|
|
959
1000
|
*/
|
|
960
1001
|
createPvPCoinflipTransaction: (action, options) => {
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
1002
|
+
switch (action) {
|
|
1003
|
+
case "create":
|
|
1004
|
+
return buildPvPCoinflipTransaction("create", {
|
|
1005
|
+
...options,
|
|
1006
|
+
config: this.#config,
|
|
1007
|
+
partner: this.#partner
|
|
1008
|
+
});
|
|
1009
|
+
case "join": {
|
|
1010
|
+
const joinOptions = options;
|
|
1011
|
+
return buildPvPCoinflipTransaction("join", {
|
|
1012
|
+
...joinOptions,
|
|
1013
|
+
betCoin: this.#createPvPCoinflipBetCoin(joinOptions),
|
|
1014
|
+
config: this.#config,
|
|
1015
|
+
partner: this.#partner
|
|
1016
|
+
});
|
|
1017
|
+
}
|
|
1018
|
+
case "cancel":
|
|
1019
|
+
return buildPvPCoinflipTransaction("cancel", {
|
|
1020
|
+
...options,
|
|
1021
|
+
config: this.#config,
|
|
1022
|
+
partner: this.#partner
|
|
1023
|
+
});
|
|
1024
|
+
default:
|
|
1025
|
+
throw new Error(`Unsupported PvP coinflip action: ${action}`);
|
|
1026
|
+
}
|
|
965
1027
|
}
|
|
966
1028
|
};
|
|
1029
|
+
#createPvPCoinflipBetCoin(options) {
|
|
1030
|
+
return async (tx) => {
|
|
1031
|
+
const { json } = await Game.get({
|
|
1032
|
+
client: this.#client,
|
|
1033
|
+
objectId: options.gameId
|
|
1034
|
+
});
|
|
1035
|
+
return tx.coin({
|
|
1036
|
+
type: options.coinType,
|
|
1037
|
+
balance: BigInt(json.stake_per_player),
|
|
1038
|
+
useGasCoin: options.allowGasCoinShortcut
|
|
1039
|
+
});
|
|
1040
|
+
};
|
|
1041
|
+
}
|
|
967
1042
|
};
|
|
968
1043
|
|
|
969
|
-
export { suigar };
|
|
1044
|
+
export { SuigarClient, suigar };
|