@baozi.bet/mcp-server 4.0.0
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/README.md +294 -0
- package/dist/__tests__/full-test.d.ts +1 -0
- package/dist/__tests__/full-test.js +291 -0
- package/dist/builders/affiliate-transaction.d.ts +41 -0
- package/dist/builders/affiliate-transaction.js +123 -0
- package/dist/builders/bet-transaction.d.ts +70 -0
- package/dist/builders/bet-transaction.js +323 -0
- package/dist/builders/claim-transaction.d.ts +57 -0
- package/dist/builders/claim-transaction.js +196 -0
- package/dist/builders/creator-transaction.d.ts +49 -0
- package/dist/builders/creator-transaction.js +177 -0
- package/dist/builders/dispute-transaction.d.ts +81 -0
- package/dist/builders/dispute-transaction.js +215 -0
- package/dist/builders/index.d.ts +14 -0
- package/dist/builders/index.js +15 -0
- package/dist/builders/market-creation-tx.d.ts +65 -0
- package/dist/builders/market-creation-tx.js +362 -0
- package/dist/builders/market-management-transaction.d.ts +85 -0
- package/dist/builders/market-management-transaction.js +239 -0
- package/dist/builders/race-transaction.d.ts +67 -0
- package/dist/builders/race-transaction.js +242 -0
- package/dist/builders/resolution-transaction.d.ts +108 -0
- package/dist/builders/resolution-transaction.js +250 -0
- package/dist/builders/whitelist-transaction.d.ts +72 -0
- package/dist/builders/whitelist-transaction.js +179 -0
- package/dist/config.d.ts +138 -0
- package/dist/config.js +307 -0
- package/dist/handlers/agent-network.d.ts +81 -0
- package/dist/handlers/agent-network.js +332 -0
- package/dist/handlers/claims.d.ts +47 -0
- package/dist/handlers/claims.js +218 -0
- package/dist/handlers/market-creation.d.ts +154 -0
- package/dist/handlers/market-creation.js +290 -0
- package/dist/handlers/markets.d.ts +41 -0
- package/dist/handlers/markets.js +319 -0
- package/dist/handlers/positions.d.ts +40 -0
- package/dist/handlers/positions.js +244 -0
- package/dist/handlers/quote.d.ts +33 -0
- package/dist/handlers/quote.js +144 -0
- package/dist/handlers/race-markets.d.ts +54 -0
- package/dist/handlers/race-markets.js +308 -0
- package/dist/handlers/resolution.d.ts +43 -0
- package/dist/handlers/resolution.js +194 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +109 -0
- package/dist/resources.d.ts +13 -0
- package/dist/resources.js +336 -0
- package/dist/tools.d.ts +3109 -0
- package/dist/tools.js +1956 -0
- package/dist/validation/bet-rules.d.ts +82 -0
- package/dist/validation/bet-rules.js +276 -0
- package/dist/validation/creation-rules.d.ts +69 -0
- package/dist/validation/creation-rules.js +302 -0
- package/dist/validation/index.d.ts +6 -0
- package/dist/validation/index.js +7 -0
- package/dist/validation/market-rules.d.ts +60 -0
- package/dist/validation/market-rules.js +237 -0
- package/dist/validation/parimutuel-rules.d.ts +117 -0
- package/dist/validation/parimutuel-rules.js +270 -0
- package/package.json +52 -0
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Positions handler for MCP server
|
|
3
|
+
* Fetches user positions from Solana V4.7.6 program (Mainnet)
|
|
4
|
+
*/
|
|
5
|
+
import { Connection, PublicKey } from '@solana/web3.js';
|
|
6
|
+
import bs58 from 'bs58';
|
|
7
|
+
import { PROGRAM_ID, RPC_ENDPOINT, DISCRIMINATORS, lamportsToSol, } from '../config.js';
|
|
8
|
+
import { getMarket } from './markets.js';
|
|
9
|
+
// =============================================================================
|
|
10
|
+
// POSITION DECODER
|
|
11
|
+
// =============================================================================
|
|
12
|
+
/**
|
|
13
|
+
* Decode UserPosition account data from V4.7.6 struct
|
|
14
|
+
*
|
|
15
|
+
* UserPosition struct layout (from IDL):
|
|
16
|
+
* - discriminator (8)
|
|
17
|
+
* - user (Pubkey, 32)
|
|
18
|
+
* - market_id (u64, 8)
|
|
19
|
+
* - yes_amount (u64, 8)
|
|
20
|
+
* - no_amount (u64, 8)
|
|
21
|
+
* - claimed (bool, 1)
|
|
22
|
+
* - bump (u8, 1)
|
|
23
|
+
* - referred_by (Option<Pubkey>: 1 + 0/32)
|
|
24
|
+
* - affiliate_fee_paid (u64, 8)
|
|
25
|
+
* - reserved ([u8; 16], 16)
|
|
26
|
+
*/
|
|
27
|
+
function decodePosition(data, pubkey) {
|
|
28
|
+
try {
|
|
29
|
+
let offset = 8; // Skip discriminator
|
|
30
|
+
// user (Pubkey, 32 bytes)
|
|
31
|
+
const user = new PublicKey(data.slice(offset, offset + 32));
|
|
32
|
+
offset += 32;
|
|
33
|
+
// market_id (u64, 8 bytes)
|
|
34
|
+
const marketId = data.readBigUInt64LE(offset);
|
|
35
|
+
offset += 8;
|
|
36
|
+
// yes_amount (u64, 8 bytes)
|
|
37
|
+
const yesAmount = data.readBigUInt64LE(offset);
|
|
38
|
+
offset += 8;
|
|
39
|
+
// no_amount (u64, 8 bytes)
|
|
40
|
+
const noAmount = data.readBigUInt64LE(offset);
|
|
41
|
+
offset += 8;
|
|
42
|
+
// claimed (bool, 1 byte)
|
|
43
|
+
const claimed = data.readUInt8(offset) === 1;
|
|
44
|
+
offset += 1;
|
|
45
|
+
// bump (u8, 1 byte)
|
|
46
|
+
offset += 1;
|
|
47
|
+
// referred_by (Option<Pubkey>: 1 byte discriminant + optional 32 bytes)
|
|
48
|
+
const hasReferrer = data.readUInt8(offset) === 1;
|
|
49
|
+
offset += 1;
|
|
50
|
+
let referredBy = null;
|
|
51
|
+
if (hasReferrer) {
|
|
52
|
+
referredBy = new PublicKey(data.slice(offset, offset + 32)).toBase58();
|
|
53
|
+
offset += 32;
|
|
54
|
+
}
|
|
55
|
+
// affiliate_fee_paid (u64, 8 bytes)
|
|
56
|
+
const affiliateFeePaid = data.readBigUInt64LE(offset);
|
|
57
|
+
// Derived fields
|
|
58
|
+
const yesAmountSol = round4(lamportsToSol(yesAmount));
|
|
59
|
+
const noAmountSol = round4(lamportsToSol(noAmount));
|
|
60
|
+
const totalAmountSol = round4(yesAmountSol + noAmountSol);
|
|
61
|
+
// Determine primary side
|
|
62
|
+
let side;
|
|
63
|
+
if (yesAmount > 0n && noAmount > 0n) {
|
|
64
|
+
side = 'Both';
|
|
65
|
+
}
|
|
66
|
+
else if (yesAmount > 0n) {
|
|
67
|
+
side = 'Yes';
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
side = 'No';
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
publicKey: pubkey.toBase58(),
|
|
74
|
+
user: user.toBase58(),
|
|
75
|
+
marketId: marketId.toString(),
|
|
76
|
+
yesAmountSol,
|
|
77
|
+
noAmountSol,
|
|
78
|
+
totalAmountSol,
|
|
79
|
+
side,
|
|
80
|
+
claimed,
|
|
81
|
+
referredBy,
|
|
82
|
+
affiliateFeePaidSol: round4(lamportsToSol(affiliateFeePaid)),
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
catch (err) {
|
|
86
|
+
console.error('Error decoding position:', err);
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
// =============================================================================
|
|
91
|
+
// PUBLIC API
|
|
92
|
+
// =============================================================================
|
|
93
|
+
/**
|
|
94
|
+
* Get all positions for a wallet
|
|
95
|
+
*/
|
|
96
|
+
export async function getPositions(walletAddress) {
|
|
97
|
+
const connection = new Connection(RPC_ENDPOINT, 'confirmed');
|
|
98
|
+
try {
|
|
99
|
+
const wallet = new PublicKey(walletAddress);
|
|
100
|
+
// Get all position accounts for this user
|
|
101
|
+
// Note: Solana RPC expects base58 encoding for memcmp bytes
|
|
102
|
+
const accounts = await connection.getProgramAccounts(PROGRAM_ID, {
|
|
103
|
+
filters: [
|
|
104
|
+
{
|
|
105
|
+
memcmp: {
|
|
106
|
+
offset: 0,
|
|
107
|
+
bytes: bs58.encode(DISCRIMINATORS.USER_POSITION),
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
memcmp: {
|
|
112
|
+
offset: 8, // After discriminator
|
|
113
|
+
bytes: wallet.toBase58(),
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
],
|
|
117
|
+
});
|
|
118
|
+
const positions = [];
|
|
119
|
+
for (const { account, pubkey } of accounts) {
|
|
120
|
+
const position = decodePosition(account.data, pubkey);
|
|
121
|
+
if (position) {
|
|
122
|
+
positions.push(position);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
// Sort by market ID (newest markets first)
|
|
126
|
+
positions.sort((a, b) => Number(BigInt(b.marketId) - BigInt(a.marketId)));
|
|
127
|
+
return positions;
|
|
128
|
+
}
|
|
129
|
+
catch (err) {
|
|
130
|
+
console.error('Error fetching positions:', err);
|
|
131
|
+
return [];
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Derive market PDA from market_id
|
|
136
|
+
*/
|
|
137
|
+
function deriveMarketPda(marketId) {
|
|
138
|
+
const marketIdBigInt = BigInt(marketId);
|
|
139
|
+
const marketIdBuffer = Buffer.alloc(8);
|
|
140
|
+
marketIdBuffer.writeBigUInt64LE(marketIdBigInt);
|
|
141
|
+
const [pda] = PublicKey.findProgramAddressSync([Buffer.from('market'), marketIdBuffer], PROGRAM_ID);
|
|
142
|
+
return pda.toBase58();
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Get positions with enriched market data
|
|
146
|
+
*/
|
|
147
|
+
export async function getPositionsEnriched(walletAddress) {
|
|
148
|
+
const positions = await getPositions(walletAddress);
|
|
149
|
+
// Derive market PDAs from market_id
|
|
150
|
+
const positionsWithPda = positions.map(p => ({
|
|
151
|
+
...p,
|
|
152
|
+
marketPda: deriveMarketPda(p.marketId),
|
|
153
|
+
}));
|
|
154
|
+
// Batch fetch market data for unique markets
|
|
155
|
+
const uniqueMarkets = [...new Set(positionsWithPda.map(p => p.marketPda))];
|
|
156
|
+
const marketData = new Map();
|
|
157
|
+
await Promise.all(uniqueMarkets.map(async (marketPda) => {
|
|
158
|
+
if (marketPda) {
|
|
159
|
+
const market = await getMarket(marketPda);
|
|
160
|
+
if (market) {
|
|
161
|
+
marketData.set(marketPda, market);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}));
|
|
165
|
+
// Enrich positions with market data
|
|
166
|
+
return positionsWithPda.map(position => {
|
|
167
|
+
const market = position.marketPda ? marketData.get(position.marketPda) : null;
|
|
168
|
+
if (!market)
|
|
169
|
+
return position;
|
|
170
|
+
// Calculate potential payout if position is winning
|
|
171
|
+
let potentialPayout;
|
|
172
|
+
const positionAmount = position.side === 'Yes' ? position.yesAmountSol : position.noAmountSol;
|
|
173
|
+
if (market.status === 'Resolved' && market.winningOutcome === position.side) {
|
|
174
|
+
const totalPool = market.yesPoolSol + market.noPoolSol;
|
|
175
|
+
const winningPool = position.side === 'Yes' ? market.yesPoolSol : market.noPoolSol;
|
|
176
|
+
if (winningPool > 0) {
|
|
177
|
+
const share = positionAmount / winningPool;
|
|
178
|
+
const grossPayout = share * totalPool;
|
|
179
|
+
const profit = grossPayout - positionAmount;
|
|
180
|
+
const fee = profit > 0 ? (profit * market.platformFeeBps) / 10000 : 0;
|
|
181
|
+
potentialPayout = round4(grossPayout - fee);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return {
|
|
185
|
+
...position,
|
|
186
|
+
marketQuestion: market.question,
|
|
187
|
+
marketStatus: market.status,
|
|
188
|
+
marketOutcome: market.winningOutcome,
|
|
189
|
+
potentialPayout,
|
|
190
|
+
};
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Get position summary with statistics
|
|
195
|
+
*/
|
|
196
|
+
export async function getPositionsSummary(walletAddress) {
|
|
197
|
+
const positions = await getPositionsEnriched(walletAddress);
|
|
198
|
+
const totalBetSol = positions.reduce((sum, p) => sum + p.totalAmountSol, 0);
|
|
199
|
+
const activePositions = positions.filter(p => !p.claimed).length;
|
|
200
|
+
const claimedPositions = positions.filter(p => p.claimed).length;
|
|
201
|
+
// Count winning/losing/pending based on market status and outcome
|
|
202
|
+
let winningPositions = 0;
|
|
203
|
+
let losingPositions = 0;
|
|
204
|
+
let pendingPositions = 0;
|
|
205
|
+
for (const position of positions) {
|
|
206
|
+
if (!position.marketStatus || position.marketStatus === 'Active' || position.marketStatus === 'Closed') {
|
|
207
|
+
pendingPositions++;
|
|
208
|
+
}
|
|
209
|
+
else if (position.marketStatus === 'Resolved') {
|
|
210
|
+
if (position.marketOutcome === position.side) {
|
|
211
|
+
winningPositions++;
|
|
212
|
+
}
|
|
213
|
+
else if (position.marketOutcome === 'Invalid') {
|
|
214
|
+
// Refund case
|
|
215
|
+
pendingPositions++;
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
losingPositions++;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
else if (position.marketStatus === 'Cancelled') {
|
|
222
|
+
// Refund case
|
|
223
|
+
pendingPositions++;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
return {
|
|
227
|
+
wallet: walletAddress,
|
|
228
|
+
totalPositions: positions.length,
|
|
229
|
+
totalBetSol: round4(totalBetSol),
|
|
230
|
+
activePositions,
|
|
231
|
+
claimedPositions,
|
|
232
|
+
winningPositions,
|
|
233
|
+
losingPositions,
|
|
234
|
+
pendingPositions,
|
|
235
|
+
positions,
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
// =============================================================================
|
|
239
|
+
// HELPERS
|
|
240
|
+
// =============================================================================
|
|
241
|
+
function round4(n) {
|
|
242
|
+
return Math.round(n * 10000) / 10000;
|
|
243
|
+
}
|
|
244
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicG9zaXRpb25zLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2hhbmRsZXJzL3Bvc2l0aW9ucy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7O0dBR0c7QUFDSCxPQUFPLEVBQUUsVUFBVSxFQUFFLFNBQVMsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ3hELE9BQU8sSUFBSSxNQUFNLE1BQU0sQ0FBQztBQUN4QixPQUFPLEVBQ0wsVUFBVSxFQUNWLFlBQVksRUFDWixjQUFjLEVBQ2QsYUFBYSxHQUNkLE1BQU0sY0FBYyxDQUFDO0FBQ3RCLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFxQ3pDLGdGQUFnRjtBQUNoRixtQkFBbUI7QUFDbkIsZ0ZBQWdGO0FBRWhGOzs7Ozs7Ozs7Ozs7OztHQWNHO0FBQ0gsU0FBUyxjQUFjLENBQUMsSUFBWSxFQUFFLE1BQWlCO0lBQ3JELElBQUksQ0FBQztRQUNILElBQUksTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDLHFCQUFxQjtRQUVyQywwQkFBMEI7UUFDMUIsTUFBTSxJQUFJLEdBQUcsSUFBSSxTQUFTLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsTUFBTSxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDNUQsTUFBTSxJQUFJLEVBQUUsQ0FBQztRQUViLDJCQUEyQjtRQUMzQixNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQzlDLE1BQU0sSUFBSSxDQUFDLENBQUM7UUFFWiw0QkFBNEI7UUFDNUIsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUMvQyxNQUFNLElBQUksQ0FBQyxDQUFDO1FBRVosMkJBQTJCO1FBQzNCLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDOUMsTUFBTSxJQUFJLENBQUMsQ0FB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LEVBQUUsQ0FBQztZQUNoRCxJQUFJLFFBQVEsQ0FBQyxhQUFhLEtBQUssUUFBUSxDQUFDLElBQUksRUFBRSxDQUFDO2dCQUM3QyxnQkFBZ0IsRUFBRSxDQUFDO1lBQ3JCLENBQUM7aUJBQU0sSUFBSSxRQUFRLENBQUMsYUFBYSxLQUFLLFNBQVMsRUFBRSxDQUFDO2dCQUNoRCxjQUFjO2dCQUNkLGdCQUFnQixFQUFFLENBQUM7WUFDckIsQ0FBQztpQkFBTSxDQUFDO2dCQUNOLGVBQWUsRUFBRSxDQUFDO1lBQ3BCLENBQUM7UUFDSCxDQUFDO2FBQU0sSUFBSSxRQUFRLENBQUMsWUFBWSxLQUFLLFdBQVcsRUFBRSxDQUFDO1lBQ2pELGNBQWM7WUFDZCxnQkFBZ0IsRUFBRSxDQUFDO1FBQ3JCLENBQUM7SUFDSCxDQUFDO0lBRUQsT0FBTztRQUNMLE1BQU0sRUFBRSxhQUFhO1FBQ3JCLGNBQWMsRUFBRSxTQUFTLENBQUMsTUFBTTtRQUNoQyxXQUFXLEVBQUUsTUFBTSxDQUFDLFdBQVcsQ0FBQztRQUNoQyxlQUFlO1FBQ2YsZ0JBQWdCO1FBQ2hCLGdCQUFnQjtRQUNoQixlQUFlO1FBQ2YsZ0JBQWdCO1FBQ2hCLFNBQVM7S0FDVixDQUFDO0FBQ0osQ0FBQztBQUVELGdGQUFnRjtBQUNoRixVQUFVO0FBQ1YsZ0ZBQWdGO0FBRWhGLFNBQVMsTUFBTSxDQUFDLENBQVM7SUFDdkIsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsR0FBRyxLQUFLLENBQUMsR0FBRyxLQUFLLENBQUM7QUFDdkMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogUG9zaXRpb25zIGhhbmRsZXIgZm9yIE1DUCBzZXJ2ZXJcbiAqIEZldGNoZXMgdXNlciBwb3NpdGlvbnMgZnJvbSBTb2xhbmEgVjQuNy42IHByb2dyYW0gKE1haW5uZXQpXG4gKi9cbmltcG9ydCB7IENvbm5lY3Rpb24sIFB1YmxpY0tleSB9IGZyb20gJ0Bzb2xhbmEvd2ViMy5qcyc7XG5pbXBvcnQgYnM1OCBmcm9tICdiczU4JztcbmltcG9ydCB7XG4gIFBST0dSQU1fSUQsXG4gIFJQQ19FTkRQT0lOVCxcbiAgRElTQ1JJTUlOQVRPUlMsXG4gIGxhbXBvcnRzVG9Tb2wsXG59IGZyb20gJy4uL2NvbmZpZy5qcyc7XG5pbXBvcnQgeyBnZXRNYXJrZXQgfSBmcm9tICcuL21hcmtldHMuanMnO1xuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gVFlQRVNcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbmV4cG9ydCBpbnRlcmZhY2UgUG9zaXRpb24ge1xuICBwdWJsaWNLZXk6IHN0cmluZztcbiAgdXNlcjogc3RyaW5nO1xuICBtYXJrZXRJZDogc3RyaW5nO1xuICB5ZXNBbW91bnRTb2w6IG51bWJlcjtcbiAgbm9BbW91bnRTb2w6IG51bWJlcjtcbiAgdG90YWxBbW91bnRTb2w6IG51bWJlcjtcbiAgc2lkZTogJ1llcycgfCAnTm8nIHwgJ0JvdGgnOyAvLyBEZXJpdmVkOiB3aGljaCBzaWRlIGhhcyBtb3JlXG4gIGNsYWltZWQ6IGJvb2xlYW47XG4gIHJlZmVycmVkQnk6IHN0cmluZyB8IG51bGw7XG4gIGFmZmlsaWF0ZUZlZVBhaWRTb2w6IG51bWJlcjtcbiAgLy8gRW5yaWNoZWQgZmllbGRzIChvcHRpb25hbCwgZnJvbSBtYXJrZXQgbG9va3VwKVxuICBtYXJrZXRQZGE/OiBzdHJpbmc7XG4gIG1hcmtldFF1ZXN0aW9uPzogc3RyaW5nO1xuICBtYXJrZXRTdGF0dXM/OiBzdHJpbmc7XG4gIG1hcmtldE91dGNvbWU/OiBzdHJpbmcgfCBudWxsO1xuICBwb3RlbnRpYWxQYXlvdXQ/OiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUG9zaXRpb25TdW1tYXJ5IHtcbiAgd2FsbGV0OiBzdHJpbmc7XG4gIHRvdGFsUG9zaXRpb25zOiBudW1iZXI7XG4gIHRvdGFsQmV0U29sOiBudW1iZXI7XG4gIGFjdGl2ZVBvc2l0aW9uczogbnVtYmVyO1xuICBjbGFpbWVkUG9zaXRpb25zOiBudW1iZXI7XG4gIHdpbm5pbmdQb3NpdGlvbnM6IG51bWJlcjtcbiAgbG9zaW5nUG9zaXRpb25zOiBudW1iZXI7XG4gIHBlbmRpbmdQb3NpdGlvbnM6IG51bWJlcjtcbiAgcG9zaXRpb25zOiBQb3NpdGlvbltdO1xufVxuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gUE9TSVRJT04gREVDT0RFUlxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuLyoqXG4gKiBEZWNvZGUgVXNlclBvc2l0aW9uIGFjY291bnQgZGF0YSBmcm9tIFY0LjcuNiBzdHJ1Y3RcbiAqXG4gKiBVc2VyUG9zaXRpb24gc3RydWN0IGxheW91dCAoZnJvbSBJREwpOlxuICogLSBkaXNjcmltaW5hdG9yICg4KVxuICogLSB1c2VyIChQdWJrZXksIDMyKVxuICogLSBtYXJrZXRfaWQgKHU2NCwgOClcbiAqIC0geWVzX2Ftb3VudCAodTY0LCA4KVxuICogLSBub19hbW91bnQgKHU2NCwgOClcbiAqIC0gY2xhaW1lZCAoYm9vbCwgMSlcbiAqIC0gYnVtcCAodTgsIDEpXG4gKiAtIHJlZmVycmVkX2J5IChPcHRpb248UHVia2V5PjogMSArIDAvMzIpXG4gKiAtIGFmZmlsaWF0ZV9mZWVfcGFpZCAodTY0LCA4KVxuICogLSByZXNlcnZlZCAoW3U4OyAxNl0sIDE2KVxuICovXG5mdW5jdGlvbiBkZWNvZGVQb3NpdGlvbihkYXRhOiBCdWZmZXIsIHB1YmtleTogUHVibGljS2V5KTogUG9zaXRpb24gfCBudWxsIHtcbiAgdHJ5IHtcbiAgICBsZXQgb2Zmc2V0ID0gODsgLy8gU2tpcCBkaXNjcmltaW5hdG9yXG5cbiAgICAvLyB1c2VyIChQdWJrZXksIDMyIGJ5dGVzKVxuICAgIGNvbnN0IHVzZXIgPSBuZXcgUHVibGljS2V5KGRhdGEuc2xpY2Uob2Zmc2V0LCBvZmZzZXQgKyAzMikpO1xuICAgIG9mZnNldCArPSAzMjtcblxuICAgIC8vIG1hcmtldF9pZCAodTY0LCA4IGJ5dGVzKVxuICAgIGNvbnN0IG1hcmtldElkID0gZGF0YS5yZWFkQmlnVUludDY0TEUob2Zmc2V0KTtcbiAgICBvZmZzZXQgKz0gODtcblxuICAgIC8vIHllc19hbW91bnQgKHU2NCwgOCBieXRlcylcbiAgICBjb25zdCB5ZXNBbW91bnQgPSBkYXRhLnJlYWRCaWdVSW50NjRMRShvZmZzZXQpO1xuICAgIG9mZnNldCArPSA4O1xuXG4gICAgLy8gbm9fYW1vdW50ICh1NjQsIDggYnl0ZXMpXG4gICAgY29uc3Qgbm9BbW91bnQgPSBkYXRhLnJlYWRCaWdVSW50NjRMRShvZmZzZXQpO1xuICAgIG9mZnNldCArPSA4O1xuXG4gICAgLy8gY2xhaW1lZCAoYm9vbCwgMSBieXRlKVxuICAgIGNvbnN0IGNsYWltZWQgPSBkYXRhLnJlYWRVSW50OChvZmZzZXQpID09PSAxO1xuICAgIG9mZnNldCArPSAxO1xuXG4gICAgLy8gYnVtcCAodTgsIDEgYnl0ZSlcbiAgICBvZmZzZXQgKz0gMTtcblxuICAgIC8vIHJlZmVycmVkX2J5IChPcHRpb248UHVia2V5PjogMSBieXRlIGRpc2NyaW1pbmFudCArIG9wdGlvbmFsIDMyIGJ5dGVzKVxuICAgIGNvbnN0IGhhc1JlZmVycmVyID0gZGF0YS5yZWFkVUludDgob2Zmc2V0KSA9PT0gMTtcbiAgICBvZmZzZXQgKz0gMTtcbiAgICBsZXQgcmVmZXJyZWRCeTogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gICAgaWYgKGhhc1JlZmVycmVyKSB7XG4gICAgICByZWZlcnJlZEJ5ID0gbmV3IFB1YmxpY0tleShkYXRhLnNsaWNlKG9mZnNldCwgb2Zmc2V0ICsgMzIpKS50b0Jhc2U1OCgpO1xuICAgICAgb2Zmc2V0ICs9IDMyO1xuICAgIH1cblxuICAgIC8vIGFmZmlsaWF0ZV9mZWVfcGFpZCAodTY0LCA4IGJ5dGVzKVxuICAgIGNvbnN0IGFmZmlsaWF0ZUZlZVBhaWQgPSBkYXRhLnJlYWRCaWdVSW50NjRMRShvZmZzZXQpO1xuXG4gICAgLy8gRGVyaXZlZCBmaWVsZHNcbiAgICBjb25zdCB5ZXNBbW91bnRTb2wgPSByb3VuZDQobGFtcG9ydHNUb1NvbCh5ZXNBbW91bnQpKTtcbiAgICBjb25zdCBub0Ftb3VudFNvbCA9IHJvdW5kNChsYW1wb3J0c1RvU29sKG5vQW1vdW50KSk7XG4gICAgY29uc3QgdG90YWxBbW91bnRTb2wgPSByb3VuZDQoeWVzQW1vdW50U29sICsgbm9BbW91bnRTb2wpO1xuXG4gICAgLy8gRGV0ZXJtaW5lIHByaW1hcnkgc2lkZVxuICAgIGxldCBzaWRlOiAnWWVzJyB8ICdObycgfCAnQm90aCc7XG4gICAgaWYgKHllc0Ftb3VudCA+IDBuICYmIG5vQW1vdW50ID4gMG4pIHtcbiAgICAgIHNpZGUgPSAnQm90aCc7XG4gICAgfSBlbHNlIGlmICh5ZXNBbW91bnQgPiAwbikge1xuICAgICAgc2lkZSA9ICdZZXMnO1xuICAgIH0gZWxzZSB7XG4gICAgICBzaWRlID0gJ05vJztcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgcHVibGljS2V5OiBwdWJrZXkudG9CYXNlNTgoKSxcbiAgICAgIHVzZXI6IHVzZXIudG9CYXNlNTgoKSxcbiAgICAgIG1hcmtldElkOiBtYXJrZXRJZC50b1N0cmluZygpLFxuICAgICAgeWVzQW1vdW50U29sLFxuICAgICAgbm9BbW91bnRTb2wsXG4gICAgICB0b3RhbEFtb3VudFNvbCxcbiAgICAgIHNpZGUsXG4gICAgICBjbGFpbWVkLFxuICAgICAgcmVmZXJyZWRCeSxcbiAgICAgIGFmZmlsaWF0ZUZlZVBhaWRTb2w6IHJvdW5kNChsYW1wb3J0c1RvU29sKGFmZmlsaWF0ZUZlZVBhaWQpKSxcbiAgICB9O1xuICB9IGNhdGNoIChlcnIpIHtcbiAgICBjb25zb2xlLmVycm9yKCdFcnJvciBkZWNvZGluZyBwb3NpdGlvbjonLCBlcnIpO1xuICAgIHJldHVybiBudWxsO1xuICB9XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBQVUJMSUMgQVBJXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4vKipcbiAqIEdldCBhbGwgcG9zaXRpb25zIGZvciBhIHdhbGxldFxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0UG9zaXRpb25zKHdhbGxldEFkZHJlc3M6IHN0cmluZyk6IFByb21pc2U8UG9zaXRpb25bXT4ge1xuICBjb25zdCBjb25uZWN0aW9uID0gbmV3IENvbm5lY3Rpb24oUlBDX0VORFBPSU5ULCAnY29uZmlybWVkJyk7XG5cbiAgdHJ5IHtcbiAgICBjb25zdCB3YWxsZXQgPSBuZXcgUHVibGljS2V5KHdhbGxldEFkZHJlc3MpO1xuXG4gICAgLy8gR2V0IGFsbCBwb3NpdGlvbiBhY2NvdW50cyBmb3IgdGhpcyB1c2VyXG4gICAgLy8gTm90ZTogU29sYW5hIFJQQyBleHBlY3RzIGJhc2U1OCBlbmNvZGluZyBmb3IgbWVtY21wIGJ5dGVzXG4gICAgY29uc3QgYWNjb3VudHMgPSBhd2FpdCBjb25uZWN0aW9uLmdldFByb2dyYW1BY2NvdW50cyhQUk9HUkFNX0lELCB7XG4gICAgICBmaWx0ZXJzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBtZW1jbXA6IHtcbiAgICAgICAgICAgIG9mZnNldDogMCxcbiAgICAgICAgICAgIGJ5dGVzOiBiczU4LmVuY29kZShESVNDUklNSU5BVE9SUy5VU0VSX1BPU0lUSU9OKSxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgbWVtY21wOiB7XG4gICAgICAgICAgICBvZmZzZXQ6IDgsIC8vIEFmdGVyIGRpc2NyaW1pbmF0b3JcbiAgICAgICAgICAgIGJ5dGVzOiB3YWxsZXQudG9CYXNlNTgoKSxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9KTtcblxuICAgIGNvbnN0IHBvc2l0aW9uczogUG9zaXRpb25bXSA9IFtdO1xuXG4gICAgZm9yIChjb25zdCB7IGFjY291bnQsIHB1YmtleSB9IG9mIGFjY291bnRzKSB7XG4gICAgICBjb25zdCBwb3NpdGlvbiA9IGRlY29kZVBvc2l0aW9uKGFjY291bnQuZGF0YSBhcyBCdWZmZXIsIHB1YmtleSk7XG4gICAgICBpZiAocG9zaXRpb24pIHtcbiAgICAgICAgcG9zaXRpb25zLnB1c2gocG9zaXRpb24pO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIFNvcnQgYnkgbWFya2V0IElEIChuZXdlc3QgbWFya2V0cyBmaXJzdClcbiAgICBwb3NpdGlvbnMuc29ydCgoYSwgYikgPT4gTnVtYmVyKEJpZ0ludChiLm1hcmtldElkKSAtIEJpZ0ludChhLm1hcmtldElkKSkpO1xuXG4gICAgcmV0dXJuIHBvc2l0aW9ucztcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgY29uc29sZS5lcnJvcignRXJyb3IgZmV0Y2hpbmcgcG9zaXRpb25zOicsIGVycik7XG4gICAgcmV0dXJuIFtdO1xuICB9XG59XG5cbi8qKlxuICogRGVyaXZlIG1hcmtldCBQREEgZnJvbSBtYXJrZXRfaWRcbiAqL1xuZnVuY3Rpb24gZGVyaXZlTWFya2V0UGRhKG1hcmtldElkOiBzdHJpbmcpOiBzdHJpbmcge1xuICBjb25zdCBtYXJrZXRJZEJpZ0ludCA9IEJpZ0ludChtYXJrZXRJZCk7XG4gIGNvbnN0IG1hcmtldElkQnVmZmVyID0gQnVmZmVyLmFsbG9jKDgpO1xuICBtYXJrZXRJZEJ1ZmZlci53cml0ZUJpZ1VJbnQ2NExFKG1hcmtldElkQmlnSW50KTtcbiAgY29uc3QgW3BkYV0gPSBQdWJsaWNLZXkuZmluZFByb2dyYW1BZGRyZXNzU3luYyhcbiAgICBbQnVmZmVyLmZyb20oJ21hcmtldCcpLCBtYXJrZXRJZEJ1ZmZlcl0sXG4gICAgUFJPR1JBTV9JRFxuICApO1xuICByZXR1cm4gcGRhLnRvQmFzZTU4KCk7XG59XG5cbi8qKlxuICogR2V0IHBvc2l0aW9ucyB3aXRoIGVucmljaGVkIG1hcmtldCBkYXRhXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRQb3NpdGlvbnNFbnJpY2hlZCh3YWxsZXRBZGRyZXNzOiBzdHJpbmcpOiBQcm9taXNlPFBvc2l0aW9uW10+IHtcbiAgY29uc3QgcG9zaXRpb25zID0gYXdhaXQgZ2V0UG9zaXRpb25zKHdhbGxldEFkZHJlc3MpO1xuXG4gIC8vIERlcml2ZSBtYXJrZXQgUERBcyBmcm9tIG1hcmtldF9pZFxuICBjb25zdCBwb3NpdGlvbnNXaXRoUGRhID0gcG9zaXRpb25zLm1hcChwID0+ICh7XG4gICAgLi4ucCxcbiAgICBtYXJrZXRQZGE6IGRlcml2ZU1hcmtldFBkYShwLm1hcmtldElkKSxcbiAgfSkpO1xuXG4gIC8vIEJhdGNoIGZldGNoIG1hcmtldCBkYXRhIGZvciB1bmlxdWUgbWFya2V0c1xuICBjb25zdCB1bmlxdWVNYXJrZXRzID0gWy4uLm5ldyBTZXQocG9zaXRpb25zV2l0aFBkYS5tYXAocCA9PiBwLm1hcmtldFBkYSkpXTtcbiAgY29uc3QgbWFya2V0RGF0YSA9IG5ldyBNYXA8c3RyaW5nLCBBd2FpdGVkPFJldHVyblR5cGU8dHlwZW9mIGdldE1hcmtldD4+PigpO1xuXG4gIGF3YWl0IFByb21pc2UuYWxsKFxuICAgIHVuaXF1ZU1hcmtldHMubWFwKGFzeW5jIChtYXJrZXRQZGEpID0+IHtcbiAgICAgIGlmIChtYXJrZXRQZGEpIHtcbiAgICAgICAgY29uc3QgbWFya2V0ID0gYXdhaXQgZ2V0TWFya2V0KG1hcmtldFBkYSk7XG4gICAgICAgIGlmIChtYXJrZXQpIHtcbiAgICAgICAgICBtYXJrZXREYXRhLnNldChtYXJrZXRQZGEsIG1hcmtldCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KVxuICApO1xuXG4gIC8vIEVucmljaCBwb3NpdGlvbnMgd2l0aCBtYXJrZXQgZGF0YVxuICByZXR1cm4gcG9zaXRpb25zV2l0aFBkYS5tYXAocG9zaXRpb24gPT4ge1xuICAgIGNvbnN0IG1hcmtldCA9IHBvc2l0aW9uLm1hcmtldFBkYSA/IG1hcmtldERhdGEuZ2V0KHBvc2l0aW9uLm1hcmtldFBkYSkgOiBudWxsO1xuICAgIGlmICghbWFya2V0KSByZXR1cm4gcG9zaXRpb247XG5cbiAgICAvLyBDYWxjdWxhdGUgcG90ZW50aWFsIHBheW91dCBpZiBwb3NpdGlvbiBpcyB3aW5uaW5nXG4gICAgbGV0IHBvdGVudGlhbFBheW91dDogbnVtYmVyIHwgdW5kZWZpbmVkO1xuICAgIGNvbnN0IHBvc2l0aW9uQW1vdW50ID0gcG9zaXRpb24uc2lkZSA9PT0gJ1llcycgPyBwb3NpdGlvbi55ZXNBbW91bnRTb2wgOiBwb3NpdGlvbi5ub0Ftb3VudFNvbDtcbiAgICBpZiAobWFya2V0LnN0YXR1cyA9PT0gJ1Jlc29sdmVkJyAmJiBtYXJrZXQud2lubmluZ091dGNvbWUgPT09IHBvc2l0aW9uLnNpZGUpIHtcbiAgICAgIGNvbnN0IHRvdGFsUG9vbCA9IG1hcmtldC55ZXNQb29sU29sICsgbWFya2V0Lm5vUG9vbFNvbDtcbiAgICAgIGNvbnN0IHdpbm5pbmdQb29sID0gcG9zaXRpb24uc2lkZSA9PT0gJ1llcycgPyBtYXJrZXQueWVzUG9vbFNvbCA6IG1hcmtldC5ub1Bvb2xTb2w7XG4gICAgICBpZiAod2lubmluZ1Bvb2wgPiAwKSB7XG4gICAgICAgIGNvbnN0IHNoYXJlID0gcG9zaXRpb25BbW91bnQgLyB3aW5uaW5nUG9vbDtcbiAgICAgICAgY29uc3QgZ3Jvc3NQYXlvdXQgPSBzaGFyZSAqIHRvdGFsUG9vbDtcbiAgICAgICAgY29uc3QgcHJvZml0ID0gZ3Jvc3NQYXlvdXQgLSBwb3NpdGlvbkFtb3VudDtcbiAgICAgICAgY29uc3QgZmVlID0gcHJvZml0ID4gMCA/IChwcm9maXQgKiBtYXJrZXQucGxhdGZvcm1GZWVCcHMpIC8gMTAwMDAgOiAwO1xuICAgICAgICBwb3RlbnRpYWxQYXlvdXQgPSByb3VuZDQoZ3Jvc3NQYXlvdXQgLSBmZWUpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICAuLi5wb3NpdGlvbixcbiAgICAgIG1hcmtldFF1ZXN0aW9uOiBtYXJrZXQucXVlc3Rpb24sXG4gICAgICBtYXJrZXRTdGF0dXM6IG1hcmtldC5zdGF0dXMsXG4gICAgICBtYXJrZXRPdXRjb21lOiBtYXJrZXQud2lubmluZ091dGNvbWUsXG4gICAgICBwb3RlbnRpYWxQYXlvdXQsXG4gICAgfTtcbiAgfSk7XG59XG5cbi8qKlxuICogR2V0IHBvc2l0aW9uIHN1bW1hcnkgd2l0aCBzdGF0aXN0aWNzXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRQb3NpdGlvbnNTdW1tYXJ5KHdhbGxldEFkZHJlc3M6IHN0cmluZyk6IFByb21pc2U8UG9zaXRpb25TdW1tYXJ5PiB7XG4gIGNvbnN0IHBvc2l0aW9ucyA9IGF3YWl0IGdldFBvc2l0aW9uc0VucmljaGVkKHdhbGxldEFkZHJlc3MpO1xuXG4gIGNvbnN0IHRvdGFsQmV0U29sID0gcG9zaXRpb25zLnJlZHVjZSgoc3VtLCBwKSA9PiBzdW0gKyBwLnRvdGFsQW1vdW50U29sLCAwKTtcbiAgY29uc3QgYWN0aXZlUG9zaXRpb25zID0gcG9zaXRpb25zLmZpbHRlcihwID0+ICFwLmNsYWltZWQpLmxlbmd0aDtcbiAgY29uc3QgY2xhaW1lZFBvc2l0aW9ucyA9IHBvc2l0aW9ucy5maWx0ZXIocCA9PiBwLmNsYWltZWQpLmxlbmd0aDtcblxuICAvLyBDb3VudCB3aW5uaW5nL2xvc2luZy9wZW5kaW5nIGJhc2VkIG9uIG1hcmtldCBzdGF0dXMgYW5kIG91dGNvbWVcbiAgbGV0IHdpbm5pbmdQb3NpdGlvbnMgPSAwO1xuICBsZXQgbG9zaW5nUG9zaXRpb25zID0gMDtcbiAgbGV0IHBlbmRpbmdQb3NpdGlvbnMgPSAwO1xuXG4gIGZvciAoY29uc3QgcG9zaXRpb24gb2YgcG9zaXRpb25zKSB7XG4gICAgaWYgKCFwb3NpdGlvbi5tYXJrZXRTdGF0dXMgfHwgcG9zaXRpb24ubWFya2V0U3RhdHVzID09PSAnQWN0aXZlJyB8fCBwb3NpdGlvbi5tYXJrZXRTdGF0dXMgPT09ICdDbG9zZWQnKSB7XG4gICAgICBwZW5kaW5nUG9zaXRpb25zKys7XG4gICAgfSBlbHNlIGlmIChwb3NpdGlvbi5tYXJrZXRTdGF0dXMgPT09ICdSZXNvbHZlZCcpIHtcbiAgICAgIGlmIChwb3NpdGlvbi5tYXJrZXRPdXRjb21lID09PSBwb3NpdGlvbi5zaWRlKSB7XG4gICAgICAgIHdpbm5pbmdQb3NpdGlvbnMrKztcbiAgICAgIH0gZWxzZSBpZiAocG9zaXRpb24ubWFya2V0T3V0Y29tZSA9PT0gJ0ludmFsaWQnKSB7XG4gICAgICAgIC8vIFJlZnVuZCBjYXNlXG4gICAgICAgIHBlbmRpbmdQb3NpdGlvbnMrKztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGxvc2luZ1Bvc2l0aW9ucysrO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAocG9zaXRpb24ubWFya2V0U3RhdHVzID09PSAnQ2FuY2VsbGVkJykge1xuICAgICAgLy8gUmVmdW5kIGNhc2VcbiAgICAgIHBlbmRpbmdQb3NpdGlvbnMrKztcbiAgICB9XG4gIH1cblxuICByZXR1cm4ge1xuICAgIHdhbGxldDogd2FsbGV0QWRkcmVzcyxcbiAgICB0b3RhbFBvc2l0aW9uczogcG9zaXRpb25zLmxlbmd0aCxcbiAgICB0b3RhbEJldFNvbDogcm91bmQ0KHRvdGFsQmV0U29sKSxcbiAgICBhY3RpdmVQb3NpdGlvbnMsXG4gICAgY2xhaW1lZFBvc2l0aW9ucyxcbiAgICB3aW5uaW5nUG9zaXRpb25zLFxuICAgIGxvc2luZ1Bvc2l0aW9ucyxcbiAgICBwZW5kaW5nUG9zaXRpb25zLFxuICAgIHBvc2l0aW9ucyxcbiAgfTtcbn1cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIEhFTFBFUlNcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbmZ1bmN0aW9uIHJvdW5kNChuOiBudW1iZXIpOiBudW1iZXIge1xuICByZXR1cm4gTWF0aC5yb3VuZChuICogMTAwMDApIC8gMTAwMDA7XG59XG4iXX0=
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export interface Quote {
|
|
2
|
+
valid: boolean;
|
|
3
|
+
error?: string;
|
|
4
|
+
warnings: string[];
|
|
5
|
+
market: string;
|
|
6
|
+
marketQuestion?: string;
|
|
7
|
+
side: 'Yes' | 'No';
|
|
8
|
+
betAmountSol: number;
|
|
9
|
+
expectedPayoutSol: number;
|
|
10
|
+
potentialProfitSol: number;
|
|
11
|
+
impliedOdds: number;
|
|
12
|
+
decimalOdds: number;
|
|
13
|
+
feeSol: number;
|
|
14
|
+
feeBps: number;
|
|
15
|
+
newYesPoolSol: number;
|
|
16
|
+
newNoPoolSol: number;
|
|
17
|
+
currentYesPercent: number;
|
|
18
|
+
currentNoPercent: number;
|
|
19
|
+
newYesPercent: number;
|
|
20
|
+
newNoPercent: number;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Calculate a quote for a potential bet
|
|
24
|
+
*/
|
|
25
|
+
export declare function getQuote(marketPubkey: string, side: 'Yes' | 'No', amountSol: number): Promise<Quote>;
|
|
26
|
+
/**
|
|
27
|
+
* Calculate quote with additional market data for transaction building
|
|
28
|
+
*/
|
|
29
|
+
export declare function getQuoteWithMarketData(marketPubkey: string, side: 'Yes' | 'No', amountSol: number): Promise<{
|
|
30
|
+
quote: Quote;
|
|
31
|
+
marketId?: bigint;
|
|
32
|
+
accessGate?: number;
|
|
33
|
+
}>;
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Quote handler for MCP server
|
|
3
|
+
* Calculates expected payouts for bets using pari-mutuel math
|
|
4
|
+
*/
|
|
5
|
+
import { getMarket, getMarketForBetting } from './markets.js';
|
|
6
|
+
import { validateBet } from '../validation/bet-rules.js';
|
|
7
|
+
// =============================================================================
|
|
8
|
+
// QUOTE CALCULATION
|
|
9
|
+
// =============================================================================
|
|
10
|
+
/**
|
|
11
|
+
* Calculate a quote for a potential bet
|
|
12
|
+
*/
|
|
13
|
+
export async function getQuote(marketPubkey, side, amountSol) {
|
|
14
|
+
const baseQuote = {
|
|
15
|
+
valid: false,
|
|
16
|
+
warnings: [],
|
|
17
|
+
market: marketPubkey,
|
|
18
|
+
side,
|
|
19
|
+
betAmountSol: amountSol,
|
|
20
|
+
expectedPayoutSol: 0,
|
|
21
|
+
potentialProfitSol: 0,
|
|
22
|
+
impliedOdds: 0,
|
|
23
|
+
decimalOdds: 0,
|
|
24
|
+
feeSol: 0,
|
|
25
|
+
feeBps: 0,
|
|
26
|
+
newYesPoolSol: 0,
|
|
27
|
+
newNoPoolSol: 0,
|
|
28
|
+
currentYesPercent: 50,
|
|
29
|
+
currentNoPercent: 50,
|
|
30
|
+
newYesPercent: 50,
|
|
31
|
+
newNoPercent: 50,
|
|
32
|
+
};
|
|
33
|
+
// Fetch market
|
|
34
|
+
const market = await getMarket(marketPubkey);
|
|
35
|
+
if (!market) {
|
|
36
|
+
return {
|
|
37
|
+
...baseQuote,
|
|
38
|
+
error: `Market ${marketPubkey} not found`,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
baseQuote.marketQuestion = market.question;
|
|
42
|
+
baseQuote.feeBps = market.platformFeeBps;
|
|
43
|
+
baseQuote.currentYesPercent = market.yesPercent;
|
|
44
|
+
baseQuote.currentNoPercent = market.noPercent;
|
|
45
|
+
// Validate bet parameters
|
|
46
|
+
const validation = validateBet({
|
|
47
|
+
amountSol,
|
|
48
|
+
marketStatus: market.statusCode,
|
|
49
|
+
closingTime: new Date(market.closingTime),
|
|
50
|
+
isPaused: false, // Not tracked in current Market type, assume not paused
|
|
51
|
+
accessGate: market.accessGate === 'Whitelist' ? 1 : 0,
|
|
52
|
+
userWhitelisted: true, // Can't check without user wallet, assume whitelisted
|
|
53
|
+
layer: market.layerCode,
|
|
54
|
+
});
|
|
55
|
+
if (!validation.valid) {
|
|
56
|
+
return {
|
|
57
|
+
...baseQuote,
|
|
58
|
+
error: validation.error,
|
|
59
|
+
warnings: validation.warnings,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
// Calculate new pools after bet
|
|
63
|
+
const newYesPoolSol = side === 'Yes'
|
|
64
|
+
? market.yesPoolSol + amountSol
|
|
65
|
+
: market.yesPoolSol;
|
|
66
|
+
const newNoPoolSol = side === 'No'
|
|
67
|
+
? market.noPoolSol + amountSol
|
|
68
|
+
: market.noPoolSol;
|
|
69
|
+
const newTotalPool = newYesPoolSol + newNoPoolSol;
|
|
70
|
+
// Calculate expected payout (pari-mutuel)
|
|
71
|
+
const sidePool = side === 'Yes' ? newYesPoolSol : newNoPoolSol;
|
|
72
|
+
const expectedPayoutSol = sidePool > 0
|
|
73
|
+
? (amountSol / sidePool) * newTotalPool
|
|
74
|
+
: 0;
|
|
75
|
+
// Calculate profit and fee
|
|
76
|
+
const grossProfit = expectedPayoutSol - amountSol;
|
|
77
|
+
const feeSol = grossProfit > 0
|
|
78
|
+
? (grossProfit * market.platformFeeBps) / 10000
|
|
79
|
+
: 0;
|
|
80
|
+
const potentialProfitSol = grossProfit - feeSol;
|
|
81
|
+
// Calculate odds
|
|
82
|
+
const impliedOdds = newTotalPool > 0
|
|
83
|
+
? (sidePool / newTotalPool) * 100
|
|
84
|
+
: 50;
|
|
85
|
+
const decimalOdds = sidePool > 0
|
|
86
|
+
? newTotalPool / sidePool
|
|
87
|
+
: 2;
|
|
88
|
+
// Calculate new percentages
|
|
89
|
+
const newYesPercent = newTotalPool > 0
|
|
90
|
+
? (newYesPoolSol / newTotalPool) * 100
|
|
91
|
+
: 50;
|
|
92
|
+
const newNoPercent = newTotalPool > 0
|
|
93
|
+
? (newNoPoolSol / newTotalPool) * 100
|
|
94
|
+
: 50;
|
|
95
|
+
return {
|
|
96
|
+
valid: true,
|
|
97
|
+
warnings: validation.warnings,
|
|
98
|
+
market: marketPubkey,
|
|
99
|
+
marketQuestion: market.question,
|
|
100
|
+
side,
|
|
101
|
+
betAmountSol: round4(amountSol),
|
|
102
|
+
expectedPayoutSol: round4(expectedPayoutSol),
|
|
103
|
+
potentialProfitSol: round4(potentialProfitSol),
|
|
104
|
+
impliedOdds: round2(impliedOdds),
|
|
105
|
+
decimalOdds: round2(decimalOdds),
|
|
106
|
+
feeSol: round4(feeSol),
|
|
107
|
+
feeBps: market.platformFeeBps,
|
|
108
|
+
newYesPoolSol: round4(newYesPoolSol),
|
|
109
|
+
newNoPoolSol: round4(newNoPoolSol),
|
|
110
|
+
currentYesPercent: market.yesPercent,
|
|
111
|
+
currentNoPercent: market.noPercent,
|
|
112
|
+
newYesPercent: round2(newYesPercent),
|
|
113
|
+
newNoPercent: round2(newNoPercent),
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Calculate quote with additional market data for transaction building
|
|
118
|
+
*/
|
|
119
|
+
export async function getQuoteWithMarketData(marketPubkey, side, amountSol) {
|
|
120
|
+
const quote = await getQuote(marketPubkey, side, amountSol);
|
|
121
|
+
if (!quote.valid) {
|
|
122
|
+
return { quote };
|
|
123
|
+
}
|
|
124
|
+
// Get additional market data for tx building
|
|
125
|
+
const marketData = await getMarketForBetting(marketPubkey);
|
|
126
|
+
if (!marketData) {
|
|
127
|
+
return { quote };
|
|
128
|
+
}
|
|
129
|
+
return {
|
|
130
|
+
quote,
|
|
131
|
+
marketId: marketData.marketId,
|
|
132
|
+
accessGate: marketData.accessGate,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
// =============================================================================
|
|
136
|
+
// HELPERS
|
|
137
|
+
// =============================================================================
|
|
138
|
+
function round2(n) {
|
|
139
|
+
return Math.round(n * 100) / 100;
|
|
140
|
+
}
|
|
141
|
+
function round4(n) {
|
|
142
|
+
return Math.round(n * 10000) / 10000;
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicXVvdGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaGFuZGxlcnMvcXVvdGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7OztHQUdHO0FBQ0gsT0FBTyxFQUFFLFNBQVMsRUFBRSxtQkFBbUIsRUFBVSxNQUFNLGNBQWMsQ0FBQztBQUN0RSxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUE2QnpELGdGQUFnRjtBQUNoRixvQkFBb0I7QUFDcEIsZ0ZBQWdGO0FBRWhGOztHQUVHO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSxRQUFRLENBQzVCLFlBQW9CLEVBQ3BCLElBQWtCLEVBQ2xCLFNBQWlCO0lBRWpCLE1BQU0sU0FBUyxHQUFVO1FBQ3ZCLEtBQUssRUFBRSxLQUFLO1FBQ1osUUFBUSxFQUFFLEVBQUU7UUFDWixNQUFNLEVBQUUsWUFBWTtRQUNwQixJQUFJO1FBQ0osWUFBWSxFQUFFLFNBQVM7UUFDdkIsaUJBQWlCLEVBQUUsQ0FBQztRQUNwQixrQkFBa0IsRUFBRSxDQUFDO1FBQ3JCLFdBQVcsRUFBRSxDQUFDO1FBQ2QsV0FBVyxFQUFFLENBQUM7UUFDZCxNQUFNLEVBQUUsQ0FBQztRQUNULE1BQU0sRUFBRSxDQUFDO1FBQ1QsYUFBYSxFQUFFLENBQUM7UUFDaEIsWUFBWSxFQUFFLENBQUM7UUFDZixpQkFBaUIsRUFBRSxFQUFFO1FBQ3JCLGdCQUFnQixFQUFFLEVBQUU7UUFDcEIsYUFBYSxFQUFFLEVBQUU7UUFDakIsWUFBWSxFQUFFLEVBQUU7S0FDakIsQ0FBQztJQUVGLGVBQWU7SUFDZixNQUFNLE1BQU0sR0FBRyxNQUFNLFNBQVMsQ0FBQyxZQUFZLENBQUMsQ0FBQztJQUU3QyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDWixPQUFPO1lBQ0wsR0FBRyxTQUFTO1lBQ1osS0FBSyxFQUFFLFVBQVUsWUFBWSxZQUFZO1NBQzFDLENBQUM7SUFDSixDQUFDO0lBRUQsU0FBUyxDQUFDLGNB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QyxZQUFZLENBQUMsQ0FBQztJQUUzRCxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDaEIsT0FBTyxFQUFFLEtBQUssRUFBRSxDQUFDO0lBQ25CLENBQUM7SUFFRCxPQUFPO1FBQ0wsS0FBSztRQUNMLFFBQVEsRUFBRSxVQUFVLENBQUMsUUFBUTtRQUM3QixVQUFVLEVBQUUsVUFBVSxDQUFDLFVBQVU7S0FDbEMsQ0FBQztBQUNKLENBQUM7QUFFRCxnRkFBZ0Y7QUFDaEYsVUFBVTtBQUNWLGdGQUFnRjtBQUVoRixTQUFTLE1BQU0sQ0FBQyxDQUFTO0lBQ3ZCLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLEdBQUcsR0FBRyxDQUFDLEdBQUcsR0FBRyxDQUFDO0FBQ25DLENBQUM7QUFFRCxTQUFTLE1BQU0sQ0FBQyxDQUFTO0lBQ3ZCLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLEdBQUcsS0FBSyxDQUFDLEdBQUcsS0FBSyxDQUFDO0FBQ3ZDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFF1b3RlIGhhbmRsZXIgZm9yIE1DUCBzZXJ2ZXJcbiAqIENhbGN1bGF0ZXMgZXhwZWN0ZWQgcGF5b3V0cyBmb3IgYmV0cyB1c2luZyBwYXJpLW11dHVlbCBtYXRoXG4gKi9cbmltcG9ydCB7IGdldE1hcmtldCwgZ2V0TWFya2V0Rm9yQmV0dGluZywgTWFya2V0IH0gZnJvbSAnLi9tYXJrZXRzLmpzJztcbmltcG9ydCB7IHZhbGlkYXRlQmV0IH0gZnJvbSAnLi4vdmFsaWRhdGlvbi9iZXQtcnVsZXMuanMnO1xuaW1wb3J0IHsgQkVUX0xJTUlUUyB9IGZyb20gJy4uL2NvbmZpZy5qcyc7XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBUWVBFU1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuZXhwb3J0IGludGVyZmFjZSBRdW90ZSB7XG4gIHZhbGlkOiBib29sZWFuO1xuICBlcnJvcj86IHN0cmluZztcbiAgd2FybmluZ3M6IHN0cmluZ1tdO1xuICBtYXJrZXQ6IHN0cmluZztcbiAgbWFya2V0UXVlc3Rpb24/OiBzdHJpbmc7XG4gIHNpZGU6ICdZZXMnIHwgJ05vJztcbiAgYmV0QW1vdW50U29sOiBudW1iZXI7XG4gIGV4cGVjdGVkUGF5b3V0U29sOiBudW1iZXI7XG4gIHBvdGVudGlhbFByb2ZpdFNvbDogbnVtYmVyO1xuICBpbXBsaWVkT2RkczogbnVtYmVyO1xuICBkZWNpbWFsT2RkczogbnVtYmVyO1xuICBmZWVTb2w6IG51bWJlcjtcbiAgZmVlQnBzOiBudW1iZXI7XG4gIG5ld1llc1Bvb2xTb2w6IG51bWJlcjtcbiAgbmV3Tm9Qb29sU29sOiBudW1iZXI7XG4gIGN1cnJlbnRZZXNQZXJjZW50OiBudW1iZXI7XG4gIGN1cnJlbnROb1BlcmNlbnQ6IG51bWJlcjtcbiAgbmV3WWVzUGVyY2VudDogbnVtYmVyO1xuICBuZXdOb1BlcmNlbnQ6IG51bWJlcjtcbn1cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIFFVT1RFIENBTENVTEFUSU9OXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4vKipcbiAqIENhbGN1bGF0ZSBhIHF1b3RlIGZvciBhIHBvdGVudGlhbCBiZXRcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdldFF1b3RlKFxuICBtYXJrZXRQdWJrZXk6IHN0cmluZyxcbiAgc2lkZTogJ1llcycgfCAnTm8nLFxuICBhbW91bnRTb2w6IG51bWJlclxuKTogUHJvbWlzZTxRdW90ZT4ge1xuICBjb25zdCBiYXNlUXVvdGU6IFF1b3RlID0ge1xuICAgIHZhbGlkOiBmYWxzZSxcbiAgICB3YXJuaW5nczogW10sXG4gICAgbWFya2V0OiBtYXJrZXRQdWJrZXksXG4gICAgc2lkZSxcbiAgICBiZXRBbW91bnRTb2w6IGFtb3VudFNvbCxcbiAgICBleHBlY3RlZFBheW91dFNvbDogMCxcbiAgICBwb3RlbnRpYWxQcm9maXRTb2w6IDAsXG4gICAgaW1wbGllZE9kZHM6IDAsXG4gICAgZGVjaW1hbE9kZHM6IDAsXG4gICAgZmVlU29sOiAwLFxuICAgIGZlZUJwczogMCxcbiAgICBuZXdZZXNQb29sU29sOiAwLFxuICAgIG5ld05vUG9vbFNvbDogMCxcbiAgICBjdXJyZW50WWVzUGVyY2VudDogNTAsXG4gICAgY3VycmVudE5vUGVyY2VudDogNTAsXG4gICAgbmV3WWVzUGVyY2VudDogNTAsXG4gICAgbmV3Tm9QZXJjZW50OiA1MCxcbiAgfTtcblxuICAvLyBGZXRjaCBtYXJrZXRcbiAgY29uc3QgbWFya2V0ID0gYXdhaXQgZ2V0TWFya2V0KG1hcmtldFB1YmtleSk7XG5cbiAgaWYgKCFtYXJrZXQpIHtcbiAgICByZXR1cm4ge1xuICAgICAgLi4uYmFzZVF1b3RlLFxuICAgICAgZXJyb3I6IGBNYXJrZXQgJHttYXJrZXRQdWJrZXl9IG5vdCBmb3VuZGAsXG4gICAgfTtcbiAgfVxuXG4gIGJhc2VRdW90ZS5tYXJrZXRRdWVzdGlvbiA9IG1hcmtldC5xdWVzdGlvbjtcbiAgYmFzZVF1b3RlLmZlZUJwcyA9IG1hcmtldC5wbGF0Zm9ybUZlZUJwcztcbiAgYmFzZVF1b3RlLmN1cnJlbnRZZXNQZXJjZW50ID0gbWFya2V0Lnllc1BlcmNlbnQ7XG4gIGJhc2VRdW90ZS5jdXJyZW50Tm9QZXJjZW50ID0gbWFya2V0Lm5vUGVyY2VudDtcblxuICAvLyBWYWxpZGF0ZSBiZXQgcGFyYW1ldGVyc1xuICBjb25zdCB2YWxpZGF0aW9uID0gdmFsaWRhdGVCZXQoe1xuICAgIGFtb3VudFNvbCxcbiAgICBtYXJrZXRTdGF0dXM6IG1hcmtldC5zdGF0dXNDb2RlLFxuICAgIGNsb3NpbmdUaW1lOiBuZXcgRGF0ZShtYXJrZXQuY2xvc2luZ1RpbWUpLFxuICAgIGlzUGF1c2VkOiBmYWxzZSwgLy8gTm90IHRyYWNrZWQgaW4gY3VycmVudCBNYXJrZXQgdHlwZSwgYXNzdW1lIG5vdCBwYXVzZWRcbiAgICBhY2Nlc3NHYXRlOiBtYXJrZXQuYWNjZXNzR2F0ZSA9PT0gJ1doaXRlbGlzdCcgPyAxIDogMCxcbiAgICB1c2VyV2hpdGVsaXN0ZWQ6IHRydWUsIC8vIENhbid0IGNoZWNrIHdpdGhvdXQgdXNlciB3YWxsZXQsIGFzc3VtZSB3aGl0ZWxpc3RlZFxuICAgIGxheWVyOiBtYXJrZXQubGF5ZXJDb2RlLFxuICB9KTtcblxuICBpZiAoIXZhbGlkYXRpb24udmFsaWQpIHtcbiAgICByZXR1cm4ge1xuICAgICAgLi4uYmFzZVF1b3RlLFxuICAgICAgZXJyb3I6IHZhbGlkYXRpb24uZXJyb3IsXG4gICAgICB3YXJuaW5nczogdmFsaWRhdGlvbi53YXJuaW5ncyxcbiAgICB9O1xuICB9XG5cbiAgLy8gQ2FsY3VsYXRlIG5ldyBwb29scyBhZnRlciBiZXRcbiAgY29uc3QgbmV3WWVzUG9vbFNvbCA9IHNpZGUgPT09ICdZZXMnXG4gICAgPyBtYXJrZXQueWVzUG9vbFNvbCArIGFtb3VudFNvbFxuICAgIDogbWFya2V0Lnllc1Bvb2xTb2w7XG4gIGNvbnN0IG5ld05vUG9vbFNvbCA9IHNpZGUgPT09ICdObydcbiAgICA/IG1hcmtldC5ub1Bvb2xTb2wgKyBhbW91bnRTb2xcbiAgICA6IG1hcmtldC5ub1Bvb2xTb2w7XG4gIGNvbnN0IG5ld1RvdGFsUG9vbCA9IG5ld1llc1Bvb2xTb2wgKyBuZXdOb1Bvb2xTb2w7XG5cbiAgLy8gQ2FsY3VsYXRlIGV4cGVjdGVkIHBheW91dCAocGFyaS1tdXR1ZWwpXG4gIGNvbnN0IHNpZGVQb29sID0gc2lkZSA9PT0gJ1llcycgPyBuZXdZZXNQb29sU29sIDogbmV3Tm9Qb29sU29sO1xuICBjb25zdCBleHBlY3RlZFBheW91dFNvbCA9IHNpZGVQb29sID4gMFxuICAgID8gKGFtb3VudFNvbCAvIHNpZGVQb29sKSAqIG5ld1RvdGFsUG9vbFxuICAgIDogMDtcblxuICAvLyBDYWxjdWxhdGUgcHJvZml0IGFuZCBmZWVcbiAgY29uc3QgZ3Jvc3NQcm9maXQgPSBleHBlY3RlZFBheW91dFNvbCAtIGFtb3VudFNvbDtcbiAgY29uc3QgZmVlU29sID0gZ3Jvc3NQcm9maXQgPiAwXG4gICAgPyAoZ3Jvc3NQcm9maXQgKiBtYXJrZXQucGxhdGZvcm1GZWVCcHMpIC8gMTAwMDBcbiAgICA6IDA7XG4gIGNvbnN0IHBvdGVudGlhbFByb2ZpdFNvbCA9IGdyb3NzUHJvZml0IC0gZmVlU29sO1xuXG4gIC8vIENhbGN1bGF0ZSBvZGRzXG4gIGNvbnN0IGltcGxpZWRPZGRzID0gbmV3VG90YWxQb29sID4gMFxuICAgID8gKHNpZGVQb29sIC8gbmV3VG90YWxQb29sKSAqIDEwMFxuICAgIDogNTA7XG4gIGNvbnN0IGRlY2ltYWxPZGRzID0gc2lkZVBvb2wgPiAwXG4gICAgPyBuZXdUb3RhbFBvb2wgLyBzaWRlUG9vbFxuICAgIDogMjtcblxuICAvLyBDYWxjdWxhdGUgbmV3IHBlcmNlbnRhZ2VzXG4gIGNvbnN0IG5ld1llc1BlcmNlbnQgPSBuZXdUb3RhbFBvb2wgPiAwXG4gICAgPyAobmV3WWVzUG9vbFNvbCAvIG5ld1RvdGFsUG9vbCkgKiAxMDBcbiAgICA6IDUwO1xuICBjb25zdCBuZXdOb1BlcmNlbnQgPSBuZXdUb3RhbFBvb2wgPiAwXG4gICAgPyAobmV3Tm9Qb29sU29sIC8gbmV3VG90YWxQb29sKSAqIDEwMFxuICAgIDogNTA7XG5cbiAgcmV0dXJuIHtcbiAgICB2YWxpZDogdHJ1ZSxcbiAgICB3YXJuaW5nczogdmFsaWRhdGlvbi53YXJuaW5ncyxcbiAgICBtYXJrZXQ6IG1hcmtldFB1YmtleSxcbiAgICBtYXJrZXRRdWVzdGlvbjogbWFya2V0LnF1ZXN0aW9uLFxuICAgIHNpZGUsXG4gICAgYmV0QW1vdW50U29sOiByb3VuZDQoYW1vdW50U29sKSxcbiAgICBleHBlY3RlZFBheW91dFNvbDogcm91bmQ0KGV4cGVjdGVkUGF5b3V0U29sKSxcbiAgICBwb3RlbnRpYWxQcm9maXRTb2w6IHJvdW5kNChwb3RlbnRpYWxQcm9maXRTb2wpLFxuICAgIGltcGxpZWRPZGRzOiByb3VuZDIoaW1wbGllZE9kZHMpLFxuICAgIGRlY2ltYWxPZGRzOiByb3VuZDIoZGVjaW1hbE9kZHMpLFxuICAgIGZlZVNvbDogcm91bmQ0KGZlZVNvbCksXG4gICAgZmVlQnBzOiBtYXJrZXQucGxhdGZvcm1GZWVCcHMsXG4gICAgbmV3WWVzUG9vbFNvbDogcm91bmQ0KG5ld1llc1Bvb2xTb2wpLFxuICAgIG5ld05vUG9vbFNvbDogcm91bmQ0KG5ld05vUG9vbFNvbCksXG4gICAgY3VycmVudFllc1BlcmNlbnQ6IG1hcmtldC55ZXNQZXJjZW50LFxuICAgIGN1cnJlbnROb1BlcmNlbnQ6IG1hcmtldC5ub1BlcmNlbnQsXG4gICAgbmV3WWVzUGVyY2VudDogcm91bmQyKG5ld1llc1BlcmNlbnQpLFxuICAgIG5ld05vUGVyY2VudDogcm91bmQyKG5ld05vUGVyY2VudCksXG4gIH07XG59XG5cbi8qKlxuICogQ2FsY3VsYXRlIHF1b3RlIHdpdGggYWRkaXRpb25hbCBtYXJrZXQgZGF0YSBmb3IgdHJhbnNhY3Rpb24gYnVpbGRpbmdcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdldFF1b3RlV2l0aE1hcmtldERhdGEoXG4gIG1hcmtldFB1YmtleTogc3RyaW5nLFxuICBzaWRlOiAnWWVzJyB8ICdObycsXG4gIGFtb3VudFNvbDogbnVtYmVyXG4pOiBQcm9taXNlPHtcbiAgcXVvdGU6IFF1b3RlO1xuICBtYXJrZXRJZD86IGJpZ2ludDtcbiAgYWNjZXNzR2F0ZT86IG51bWJlcjtcbn0+IHtcbiAgY29uc3QgcXVvdGUgPSBhd2FpdCBnZXRRdW90ZShtYXJrZXRQdWJrZXksIHNpZGUsIGFtb3VudFNvbCk7XG5cbiAgaWYgKCFxdW90ZS52YWxpZCkge1xuICAgIHJldHVybiB7IHF1b3RlIH07XG4gIH1cblxuICAvLyBHZXQgYWRkaXRpb25hbCBtYXJrZXQgZGF0YSBmb3IgdHggYnVpbGRpbmdcbiAgY29uc3QgbWFya2V0RGF0YSA9IGF3YWl0IGdldE1hcmtldEZvckJldHRpbmcobWFya2V0UHVia2V5KTtcblxuICBpZiAoIW1hcmtldERhdGEpIHtcbiAgICByZXR1cm4geyBxdW90ZSB9O1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBxdW90ZSxcbiAgICBtYXJrZXRJZDogbWFya2V0RGF0YS5tYXJrZXRJZCxcbiAgICBhY2Nlc3NHYXRlOiBtYXJrZXREYXRhLmFjY2Vzc0dhdGUsXG4gIH07XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBIRUxQRVJTXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG5mdW5jdGlvbiByb3VuZDIobjogbnVtYmVyKTogbnVtYmVyIHtcbiAgcmV0dXJuIE1hdGgucm91bmQobiAqIDEwMCkgLyAxMDA7XG59XG5cbmZ1bmN0aW9uIHJvdW5kNChuOiBudW1iZXIpOiBudW1iZXIge1xuICByZXR1cm4gTWF0aC5yb3VuZChuICogMTAwMDApIC8gMTAwMDA7XG59XG4iXX0=
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
export interface RaceOutcome {
|
|
2
|
+
index: number;
|
|
3
|
+
label: string;
|
|
4
|
+
poolSol: number;
|
|
5
|
+
percent: number;
|
|
6
|
+
}
|
|
7
|
+
export interface RaceMarket {
|
|
8
|
+
publicKey: string;
|
|
9
|
+
marketId: string;
|
|
10
|
+
question: string;
|
|
11
|
+
outcomes: RaceOutcome[];
|
|
12
|
+
closingTime: string;
|
|
13
|
+
resolutionTime: string;
|
|
14
|
+
status: string;
|
|
15
|
+
statusCode: number;
|
|
16
|
+
winningOutcomeIndex: number | null;
|
|
17
|
+
totalPoolSol: number;
|
|
18
|
+
layer: string;
|
|
19
|
+
layerCode: number;
|
|
20
|
+
accessGate: string;
|
|
21
|
+
creator: string;
|
|
22
|
+
platformFeeBps: number;
|
|
23
|
+
isBettingOpen: boolean;
|
|
24
|
+
}
|
|
25
|
+
export interface RacePosition {
|
|
26
|
+
publicKey: string;
|
|
27
|
+
user: string;
|
|
28
|
+
raceMarketPda: string;
|
|
29
|
+
marketId: string;
|
|
30
|
+
outcomeIndex: number;
|
|
31
|
+
amountSol: number;
|
|
32
|
+
claimed: boolean;
|
|
33
|
+
createdAt: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* List all race markets
|
|
37
|
+
*/
|
|
38
|
+
export declare function listRaceMarkets(status?: string): Promise<RaceMarket[]>;
|
|
39
|
+
/**
|
|
40
|
+
* Get a specific race market
|
|
41
|
+
*/
|
|
42
|
+
export declare function getRaceMarket(publicKey: string): Promise<RaceMarket | null>;
|
|
43
|
+
/**
|
|
44
|
+
* Get race quote for a potential bet
|
|
45
|
+
*/
|
|
46
|
+
export declare function getRaceQuote(market: RaceMarket, outcomeIndex: number, betAmountSol: number): {
|
|
47
|
+
valid: boolean;
|
|
48
|
+
error?: string;
|
|
49
|
+
outcomeLabel: string;
|
|
50
|
+
betAmountSol: number;
|
|
51
|
+
expectedPayoutSol: number;
|
|
52
|
+
impliedOdds: number;
|
|
53
|
+
newOutcomePercent: number;
|
|
54
|
+
};
|