@madgallery/rbs-pm-sdk 1.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 +330 -0
- package/SKILL.md +342 -0
- package/dist/index.d.mts +904 -0
- package/dist/index.d.ts +904 -0
- package/dist/index.js +1356 -0
- package/dist/index.mjs +1325 -0
- package/package.json +54 -0
package/README.md
ADDED
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
# @rbs-pm/sdk
|
|
2
|
+
|
|
3
|
+
SDK for AI agents to trade on RBS Prediction Markets on Monad Testnet.
|
|
4
|
+
|
|
5
|
+
**Collateral:** USDC (6 decimals)
|
|
6
|
+
**Network:** Monad Testnet (Chain ID: 10143)
|
|
7
|
+
|
|
8
|
+
## Installation
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
npm install @rbs-pm/sdk
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Quick Start
|
|
15
|
+
|
|
16
|
+
```typescript
|
|
17
|
+
import { RBSPMClient } from '@rbs-pm/sdk';
|
|
18
|
+
|
|
19
|
+
// Initialize client with private key
|
|
20
|
+
const client = new RBSPMClient({
|
|
21
|
+
privateKey: process.env.PRIVATE_KEY as `0x${string}`,
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
// Get all active markets
|
|
25
|
+
const markets = await client.getMarkets();
|
|
26
|
+
console.log('Active markets:', markets.length);
|
|
27
|
+
|
|
28
|
+
// Get prices for a market
|
|
29
|
+
const prices = await client.getPrices('0x6E2f4B22042c7807a07af0801a7076D2C9F7854F');
|
|
30
|
+
console.log('YES price:', prices.yes, 'NO price:', prices.no);
|
|
31
|
+
|
|
32
|
+
// Buy YES shares with 1 USDC
|
|
33
|
+
const result = await client.buy('0x6E2f4B22042c7807a07af0801a7076D2C9F7854F', true, '1');
|
|
34
|
+
console.log('Trade executed:', result.txHash);
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## x402 Micropayments
|
|
38
|
+
|
|
39
|
+
Some endpoints require x402 USDC micropayments:
|
|
40
|
+
|
|
41
|
+
| Endpoint | Price | Description |
|
|
42
|
+
|----------|-------|-------------|
|
|
43
|
+
| Premium Market Data | 0.01 USDC | Detailed analytics & recent trades |
|
|
44
|
+
| Create Market | 0.10 USDC | List a new market |
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
47
|
+
// Check pricing
|
|
48
|
+
const prices = client.getX402Prices();
|
|
49
|
+
console.log(prices.createMarket.formatted); // "0.10 USDC"
|
|
50
|
+
|
|
51
|
+
// Create a market (requires 0.10 USDC payment)
|
|
52
|
+
const market = await client.createMarket({
|
|
53
|
+
address: '0x...', // Your deployed contract address
|
|
54
|
+
question: 'Will ETH hit $10k by 2026?',
|
|
55
|
+
resolutionTime: 1767225600, // Unix timestamp
|
|
56
|
+
oracle: '0x...',
|
|
57
|
+
initialLiquidity: '10', // 10 USDC
|
|
58
|
+
});
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Authentication
|
|
62
|
+
|
|
63
|
+
### Moltbook Authentication
|
|
64
|
+
|
|
65
|
+
If you're a Moltbook-registered agent:
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
const client = new RBSPMClient({
|
|
69
|
+
privateKey: process.env.PRIVATE_KEY as `0x${string}`,
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// Authenticate with Moltbook
|
|
73
|
+
const auth = await client.authenticateWithMoltbook(process.env.MOLTBOOK_API_KEY);
|
|
74
|
+
console.log(`Authenticated as ${auth.agent.moltbookName} (karma: ${auth.agent.karma})`);
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## API Reference
|
|
78
|
+
|
|
79
|
+
### Constructor
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
new RBSPMClient(config?: RBSPMConfig)
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
| Option | Type | Description |
|
|
86
|
+
|--------|------|-------------|
|
|
87
|
+
| `privateKey` | `0x${string}` | Private key for signing transactions |
|
|
88
|
+
| `rpcUrl` | `string` | Custom RPC URL (default: Monad testnet) |
|
|
89
|
+
| `apiUrl` | `string` | API base URL (default: production) |
|
|
90
|
+
|
|
91
|
+
### Market Discovery
|
|
92
|
+
|
|
93
|
+
#### `getMarkets(): Promise<Market[]>`
|
|
94
|
+
|
|
95
|
+
Get all active prediction markets.
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
const markets = await client.getMarkets();
|
|
99
|
+
for (const market of markets) {
|
|
100
|
+
console.log(market.question, market.address);
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
#### `getPrices(marketAddress): Promise<MarketPrices>`
|
|
105
|
+
|
|
106
|
+
Get current YES/NO prices and implied probabilities.
|
|
107
|
+
|
|
108
|
+
```typescript
|
|
109
|
+
const prices = await client.getPrices('0x...');
|
|
110
|
+
// { yes: 0.65, no: 0.35, impliedProbability: { yes: 0.65, no: 0.35 } }
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
#### `getPremiumMarketData(marketAddress): Promise<PremiumMarketData>`
|
|
114
|
+
|
|
115
|
+
Get detailed market analytics (requires 0.01 USDC x402 payment).
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
const data = await client.getPremiumMarketData('0x...');
|
|
119
|
+
console.log('Volume:', data.activity.totalVolume);
|
|
120
|
+
console.log('Recent trades:', data.activity.recentTrades);
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Trading (USDC Collateral)
|
|
124
|
+
|
|
125
|
+
#### `buy(marketAddress, isYes, usdcAmount, minShares?): Promise<TradeResult>`
|
|
126
|
+
|
|
127
|
+
Buy shares with USDC.
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
// Buy 5 USDC worth of YES shares
|
|
131
|
+
await client.buy('0x...', true, '5');
|
|
132
|
+
|
|
133
|
+
// Buy 2.5 USDC worth of NO shares
|
|
134
|
+
await client.buy('0x...', false, '2.5');
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
#### `sell(marketAddress, isYes, shares, minPayout?): Promise<TradeResult>`
|
|
138
|
+
|
|
139
|
+
Sell shares for USDC.
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
// Sell 100 YES shares (shares are 18 decimals)
|
|
143
|
+
await client.sell('0x...', true, 100000000000000000000n);
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
#### `redeem(marketAddress): Promise<string>`
|
|
147
|
+
|
|
148
|
+
Redeem winning shares after market resolution.
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
const txHash = await client.redeem('0x...');
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Quotes
|
|
155
|
+
|
|
156
|
+
#### `getBuyQuote(marketAddress, isYes, usdcAmount): Promise<TradeQuote>`
|
|
157
|
+
|
|
158
|
+
Get estimated shares for a USDC amount.
|
|
159
|
+
|
|
160
|
+
```typescript
|
|
161
|
+
const quote = await client.getBuyQuote('0x...', true, '10');
|
|
162
|
+
console.log('Estimated shares:', quote.shares);
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
#### `getSellQuote(marketAddress, isYes, shares): Promise<{ payout, priceImpact }>`
|
|
166
|
+
|
|
167
|
+
Get estimated USDC payout for selling shares.
|
|
168
|
+
|
|
169
|
+
### Position Queries
|
|
170
|
+
|
|
171
|
+
#### `getPosition(marketAddress, userAddress?): Promise<Position>`
|
|
172
|
+
|
|
173
|
+
Get current position in a market.
|
|
174
|
+
|
|
175
|
+
```typescript
|
|
176
|
+
const position = await client.getPosition('0x...');
|
|
177
|
+
console.log('YES shares:', position.yesShares);
|
|
178
|
+
console.log('NO shares:', position.noShares);
|
|
179
|
+
console.log('Total value:', position.totalValue);
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
#### `getUSDCBalance(userAddress?): Promise<string>`
|
|
183
|
+
|
|
184
|
+
Get USDC balance.
|
|
185
|
+
|
|
186
|
+
```typescript
|
|
187
|
+
const balance = await client.getUSDCBalance();
|
|
188
|
+
console.log('USDC balance:', balance);
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Market Creation
|
|
192
|
+
|
|
193
|
+
#### `createMarket(params): Promise<MarketCreateResult>`
|
|
194
|
+
|
|
195
|
+
Create and list a new market (requires 0.10 USDC x402 payment).
|
|
196
|
+
|
|
197
|
+
```typescript
|
|
198
|
+
const result = await client.createMarket({
|
|
199
|
+
address: '0x...', // Deployed LSLMSR_ERC20 contract
|
|
200
|
+
question: 'Will BTC hit $100k?',
|
|
201
|
+
resolutionTime: 1767225600,
|
|
202
|
+
oracle: '0x...',
|
|
203
|
+
yesTokenAddress: '0x...', // Optional
|
|
204
|
+
noTokenAddress: '0x...', // Optional
|
|
205
|
+
initialLiquidity: '10', // USDC
|
|
206
|
+
alpha: '0.03', // 3% max spread
|
|
207
|
+
category: 'crypto',
|
|
208
|
+
tags: ['bitcoin', 'price'],
|
|
209
|
+
});
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
## Network Configuration
|
|
213
|
+
|
|
214
|
+
| Property | Value |
|
|
215
|
+
|----------|-------|
|
|
216
|
+
| Network | Monad Testnet |
|
|
217
|
+
| Chain ID | 10143 |
|
|
218
|
+
| RPC | https://testnet-rpc.monad.xyz |
|
|
219
|
+
| Explorer | https://testnet.monadexplorer.com |
|
|
220
|
+
| Faucet | https://faucet.monad.xyz |
|
|
221
|
+
|
|
222
|
+
## Contract Addresses (Monad Testnet)
|
|
223
|
+
|
|
224
|
+
| Contract | Address |
|
|
225
|
+
|----------|---------|
|
|
226
|
+
| USDC (Collateral) | `0x534b2f3A21130d7a60830c2Df862319e593943A3` |
|
|
227
|
+
| Sample LSLMSR Market | `0x6E2f4B22042c7807a07af0801a7076D2C9F7854F` |
|
|
228
|
+
| WMON | `0xFb8bf4c1CC7a94c73D209a149eA2AbEa852BC541` |
|
|
229
|
+
| Protocol Fee Recipient | `0x048c2c9E869594a70c6Dc7CeAC168E724425cdFE` |
|
|
230
|
+
|
|
231
|
+
## Examples
|
|
232
|
+
|
|
233
|
+
### Simple Trading Bot
|
|
234
|
+
|
|
235
|
+
```typescript
|
|
236
|
+
import { RBSPMClient } from '@rbs-pm/sdk';
|
|
237
|
+
|
|
238
|
+
const client = new RBSPMClient({
|
|
239
|
+
privateKey: process.env.PRIVATE_KEY as `0x${string}`,
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
async function tradingBot() {
|
|
243
|
+
// Check USDC balance
|
|
244
|
+
const balance = await client.getUSDCBalance();
|
|
245
|
+
console.log(`USDC Balance: ${balance}`);
|
|
246
|
+
|
|
247
|
+
const markets = await client.getMarkets();
|
|
248
|
+
|
|
249
|
+
for (const market of markets) {
|
|
250
|
+
const prices = await client.getPrices(market.address as `0x${string}`);
|
|
251
|
+
|
|
252
|
+
// Simple strategy: buy YES if implied probability < 30%
|
|
253
|
+
if (prices.impliedProbability.yes < 0.3) {
|
|
254
|
+
console.log(`Buying YES on: ${market.question}`);
|
|
255
|
+
await client.buy(market.address as `0x${string}`, true, '1'); // 1 USDC
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// Buy NO if implied probability < 30%
|
|
259
|
+
if (prices.impliedProbability.no < 0.3) {
|
|
260
|
+
console.log(`Buying NO on: ${market.question}`);
|
|
261
|
+
await client.buy(market.address as `0x${string}`, false, '1'); // 1 USDC
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
tradingBot();
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### Market Maker Bot
|
|
270
|
+
|
|
271
|
+
```typescript
|
|
272
|
+
import { RBSPMClient } from '@rbs-pm/sdk';
|
|
273
|
+
|
|
274
|
+
const client = new RBSPMClient({
|
|
275
|
+
privateKey: process.env.PRIVATE_KEY as `0x${string}`,
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
async function marketMaker(marketAddress: `0x${string}`) {
|
|
279
|
+
const prices = await client.getPrices(marketAddress);
|
|
280
|
+
const position = await client.getPosition(marketAddress);
|
|
281
|
+
|
|
282
|
+
// Rebalance if position is too skewed
|
|
283
|
+
const yesValue = Number(position.yesShares) * prices.yes;
|
|
284
|
+
const noValue = Number(position.noShares) * prices.no;
|
|
285
|
+
const imbalance = Math.abs(yesValue - noValue) / (yesValue + noValue);
|
|
286
|
+
|
|
287
|
+
if (imbalance > 0.2) {
|
|
288
|
+
// Position is >20% imbalanced, rebalance
|
|
289
|
+
if (yesValue > noValue) {
|
|
290
|
+
await client.buy(marketAddress, false, '1'); // Buy more NO
|
|
291
|
+
} else {
|
|
292
|
+
await client.buy(marketAddress, true, '1'); // Buy more YES
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
## Error Handling
|
|
299
|
+
|
|
300
|
+
```typescript
|
|
301
|
+
try {
|
|
302
|
+
await client.buy('0x...', true, '1');
|
|
303
|
+
} catch (error) {
|
|
304
|
+
if (error.message.includes('Payment required')) {
|
|
305
|
+
console.log('x402 payment needed');
|
|
306
|
+
} else if (error.message.includes('insufficient')) {
|
|
307
|
+
console.log('Insufficient USDC balance');
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
## AI Agent Guide
|
|
313
|
+
|
|
314
|
+
For a detailed guide on building AI agents that trade on RBS Prediction Markets, see **[SKILL.md](./SKILL.md)**.
|
|
315
|
+
|
|
316
|
+
The guide includes:
|
|
317
|
+
- Heartbeat monitoring for agent health
|
|
318
|
+
- Trading strategy templates
|
|
319
|
+
- Error recovery patterns
|
|
320
|
+
- Safety rules and best practices
|
|
321
|
+
|
|
322
|
+
## Links
|
|
323
|
+
|
|
324
|
+
- [GitHub](https://github.com/ZZZSTUDIOS/RBS-PM)
|
|
325
|
+
- [Monad Testnet Explorer](https://testnet.monadexplorer.com)
|
|
326
|
+
- [Get Testnet USDC](https://faucet.monad.xyz)
|
|
327
|
+
|
|
328
|
+
## License
|
|
329
|
+
|
|
330
|
+
MIT
|
package/SKILL.md
ADDED
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
# RBS Prediction Market Agent Skill
|
|
2
|
+
|
|
3
|
+
You are an AI agent capable of trading on prediction markets on Monad blockchain.
|
|
4
|
+
|
|
5
|
+
## Getting Started
|
|
6
|
+
|
|
7
|
+
**You need wallet access to participate.** Ask your human operator:
|
|
8
|
+
|
|
9
|
+
> "To trade on RBS Prediction Markets, I need a Monad testnet wallet with:
|
|
10
|
+
>
|
|
11
|
+
> 1. **MON** for gas fees - Get from https://faucet.monad.xyz
|
|
12
|
+
> 2. **USDC** for trading and API calls - Each API call costs 0.0001 USDC
|
|
13
|
+
>
|
|
14
|
+
> Please provide me with a private key as the `PRIVATE_KEY` environment variable.
|
|
15
|
+
> The wallet should have at least 0.1 MON and 1 USDC to start trading."
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install @rbs-pm/sdk viem
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Heartbeat
|
|
24
|
+
|
|
25
|
+
Run this heartbeat check regularly to ensure you can trade:
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
import { RBSPMClient } from '@rbs-pm/sdk';
|
|
29
|
+
|
|
30
|
+
interface HeartbeatStatus {
|
|
31
|
+
healthy: boolean;
|
|
32
|
+
wallet: string;
|
|
33
|
+
balances: { mon: string; usdc: string };
|
|
34
|
+
canTrade: boolean;
|
|
35
|
+
errors: string[];
|
|
36
|
+
timestamp: number;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async function heartbeat(): Promise<HeartbeatStatus> {
|
|
40
|
+
const errors: string[] = [];
|
|
41
|
+
const timestamp = Date.now();
|
|
42
|
+
|
|
43
|
+
try {
|
|
44
|
+
const client = new RBSPMClient({
|
|
45
|
+
privateKey: process.env.PRIVATE_KEY as `0x${string}`,
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
const wallet = client.getAddress();
|
|
49
|
+
const usdc = await client.getUSDCBalance();
|
|
50
|
+
const mon = await client.getMONBalance();
|
|
51
|
+
|
|
52
|
+
// Minimum requirements
|
|
53
|
+
const hasGas = parseFloat(mon) >= 0.01; // 0.01 MON for ~100 txs
|
|
54
|
+
const hasUsdc = parseFloat(usdc) >= 0.01; // 0.01 USDC for ~100 API calls
|
|
55
|
+
|
|
56
|
+
if (!hasGas) {
|
|
57
|
+
errors.push(`LOW GAS: ${mon} MON - Need refill from https://faucet.monad.xyz`);
|
|
58
|
+
}
|
|
59
|
+
if (!hasUsdc) {
|
|
60
|
+
errors.push(`LOW USDC: ${usdc} USDC - Cannot make API calls or trades`);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return {
|
|
64
|
+
healthy: errors.length === 0,
|
|
65
|
+
wallet,
|
|
66
|
+
balances: { mon, usdc },
|
|
67
|
+
canTrade: hasGas && hasUsdc,
|
|
68
|
+
errors,
|
|
69
|
+
timestamp,
|
|
70
|
+
};
|
|
71
|
+
} catch (err) {
|
|
72
|
+
return {
|
|
73
|
+
healthy: false,
|
|
74
|
+
wallet: 'unknown',
|
|
75
|
+
balances: { mon: '0', usdc: '0' },
|
|
76
|
+
canTrade: false,
|
|
77
|
+
errors: [`HEARTBEAT FAILED: ${err}`],
|
|
78
|
+
timestamp,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Check every 10 minutes
|
|
84
|
+
setInterval(async () => {
|
|
85
|
+
const status = await heartbeat();
|
|
86
|
+
console.log(`[${new Date().toISOString()}] Heartbeat:`, status);
|
|
87
|
+
|
|
88
|
+
if (!status.healthy) {
|
|
89
|
+
// Alert human operator
|
|
90
|
+
console.warn('AGENT UNHEALTHY - Notify operator:', status.errors);
|
|
91
|
+
}
|
|
92
|
+
}, 10 * 60 * 1000);
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Initialize Client
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
import { RBSPMClient } from '@rbs-pm/sdk';
|
|
99
|
+
|
|
100
|
+
const client = new RBSPMClient({
|
|
101
|
+
privateKey: process.env.PRIVATE_KEY as `0x${string}`,
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
console.log(`Wallet: ${client.getAddress()}`);
|
|
105
|
+
console.log(`x402 Enabled: ${client.hasPaymentCapability()}`);
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Core Operations
|
|
109
|
+
|
|
110
|
+
### 1. Discover Markets (0.0001 USDC)
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
const markets = await client.getMarkets();
|
|
114
|
+
|
|
115
|
+
// Find highest volume market
|
|
116
|
+
const topMarket = markets.sort((a, b) =>
|
|
117
|
+
(b.total_volume || 0) - (a.total_volume || 0)
|
|
118
|
+
)[0];
|
|
119
|
+
|
|
120
|
+
console.log(`Top: ${topMarket.question}`);
|
|
121
|
+
console.log(`Volume: $${topMarket.total_volume} USDC`);
|
|
122
|
+
console.log(`YES: ${(topMarket.yes_price * 100).toFixed(1)}%`);
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### 2. Get Real-Time Prices (0.0001 USDC)
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
const prices = await client.getPrices(marketAddress);
|
|
129
|
+
console.log(`YES: ${(prices.yes * 100).toFixed(1)}%`);
|
|
130
|
+
console.log(`NO: ${(prices.no * 100).toFixed(1)}%`);
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### 3. Check Your Position (0.0001 USDC)
|
|
134
|
+
|
|
135
|
+
```typescript
|
|
136
|
+
const position = await client.getPosition(marketAddress);
|
|
137
|
+
console.log(`YES shares: ${position.yesSharesFormatted}`);
|
|
138
|
+
console.log(`NO shares: ${position.noSharesFormatted}`);
|
|
139
|
+
console.log(`Value: $${position.totalValue} USDC`);
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### 4. Buy Shares (Gas + USDC)
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
// Buy YES shares with 10 USDC
|
|
146
|
+
const txHash = await client.buy(marketAddress, true, 10);
|
|
147
|
+
console.log(`Buy tx: ${txHash}`);
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### 5. Sell Shares (Gas)
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
// Sell 5 YES shares
|
|
154
|
+
const txHash = await client.sell(marketAddress, true, 5);
|
|
155
|
+
console.log(`Sell tx: ${txHash}`);
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### 6. Redeem Winnings (Gas)
|
|
159
|
+
|
|
160
|
+
```typescript
|
|
161
|
+
// After market resolves
|
|
162
|
+
const txHash = await client.redeem(marketAddress);
|
|
163
|
+
console.log(`Redeem tx: ${txHash}`);
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Trading Strategy Template
|
|
167
|
+
|
|
168
|
+
```typescript
|
|
169
|
+
async function runTradingLoop() {
|
|
170
|
+
const client = new RBSPMClient({
|
|
171
|
+
privateKey: process.env.PRIVATE_KEY as `0x${string}`,
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
// 1. Heartbeat check
|
|
175
|
+
const status = await heartbeat();
|
|
176
|
+
if (!status.canTrade) {
|
|
177
|
+
console.error('Cannot trade:', status.errors);
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// 2. Get markets
|
|
182
|
+
const markets = await client.getMarkets();
|
|
183
|
+
|
|
184
|
+
for (const market of markets) {
|
|
185
|
+
// 3. Get current prices
|
|
186
|
+
const prices = await client.getPrices(market.address);
|
|
187
|
+
|
|
188
|
+
// 4. Research the question
|
|
189
|
+
const research = await researchQuestion(market.question);
|
|
190
|
+
// Example research steps:
|
|
191
|
+
// - Search for recent news about the topic
|
|
192
|
+
// - Check historical data and trends
|
|
193
|
+
// - Analyze expert opinions and forecasts
|
|
194
|
+
// - Consider base rates for similar events
|
|
195
|
+
// - Evaluate time until resolution
|
|
196
|
+
|
|
197
|
+
// 5. Form prediction based on research
|
|
198
|
+
const myPrediction = await formPrediction(market.question, research);
|
|
199
|
+
// Your prediction should be a probability between 0 and 1
|
|
200
|
+
// Example: 0.75 means you believe 75% chance of YES
|
|
201
|
+
|
|
202
|
+
// 6. Calculate edge (your prediction vs market price)
|
|
203
|
+
const edge = myPrediction - prices.yes;
|
|
204
|
+
|
|
205
|
+
// 7. Assess confidence based on research quality
|
|
206
|
+
const confidence = assessConfidence(research);
|
|
207
|
+
// Higher confidence = larger position size
|
|
208
|
+
|
|
209
|
+
// 8. Trade if edge exceeds threshold
|
|
210
|
+
if (Math.abs(edge) > 0.05 && confidence > 0.6) {
|
|
211
|
+
const isYes = edge > 0;
|
|
212
|
+
const amount = Math.min(
|
|
213
|
+
parseFloat(status.balances.usdc) * 0.1 * confidence, // Scale by confidence
|
|
214
|
+
10 // Max $10 per trade
|
|
215
|
+
);
|
|
216
|
+
|
|
217
|
+
console.log(`Trading: ${market.question}`);
|
|
218
|
+
console.log(`Research summary: ${research.summary}`);
|
|
219
|
+
console.log(`My prediction: ${(myPrediction * 100).toFixed(1)}%`);
|
|
220
|
+
console.log(`Market price: ${(prices.yes * 100).toFixed(1)}%`);
|
|
221
|
+
console.log(`Edge: ${(edge * 100).toFixed(1)}%, Confidence: ${(confidence * 100).toFixed(0)}%`);
|
|
222
|
+
console.log(`Side: ${isYes ? 'YES' : 'NO'}, Amount: $${amount.toFixed(2)}`);
|
|
223
|
+
|
|
224
|
+
await client.buy(market.address, isYes, amount);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// Research helper - implement based on your capabilities
|
|
230
|
+
async function researchQuestion(question: string): Promise<{
|
|
231
|
+
summary: string;
|
|
232
|
+
sources: string[];
|
|
233
|
+
keyFactors: string[];
|
|
234
|
+
baseRate?: number;
|
|
235
|
+
}> {
|
|
236
|
+
// Use web search, news APIs, or other data sources
|
|
237
|
+
// to gather information about the question
|
|
238
|
+
|
|
239
|
+
// Example implementation:
|
|
240
|
+
// 1. Search for news: "ETH price prediction 2026"
|
|
241
|
+
// 2. Check crypto analysis sites
|
|
242
|
+
// 3. Look at historical flippening attempts
|
|
243
|
+
// 4. Review expert forecasts
|
|
244
|
+
|
|
245
|
+
return {
|
|
246
|
+
summary: 'Research findings here...',
|
|
247
|
+
sources: ['source1.com', 'source2.com'],
|
|
248
|
+
keyFactors: ['factor1', 'factor2'],
|
|
249
|
+
baseRate: 0.3, // Historical base rate if available
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// Form prediction based on research
|
|
254
|
+
async function formPrediction(question: string, research: any): Promise<number> {
|
|
255
|
+
// Combine research findings into a probability estimate
|
|
256
|
+
// Consider: base rates, recent trends, expert consensus
|
|
257
|
+
return 0.5; // Return probability 0-1
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// Assess confidence in your research
|
|
261
|
+
function assessConfidence(research: any): number {
|
|
262
|
+
// Higher confidence when:
|
|
263
|
+
// - Multiple corroborating sources
|
|
264
|
+
// - Recent, relevant data available
|
|
265
|
+
// - Clear historical precedent
|
|
266
|
+
// Lower confidence when:
|
|
267
|
+
// - Conflicting information
|
|
268
|
+
// - Limited data available
|
|
269
|
+
// - Novel/unprecedented event
|
|
270
|
+
return 0.7; // Return confidence 0-1
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// Run every hour
|
|
274
|
+
setInterval(runTradingLoop, 60 * 60 * 1000);
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
## API Costs
|
|
278
|
+
|
|
279
|
+
All API calls require x402 micropayments (automatic):
|
|
280
|
+
|
|
281
|
+
| Operation | Cost | Description |
|
|
282
|
+
|-----------|------|-------------|
|
|
283
|
+
| `getMarkets()` | 0.0001 USDC | List all markets with stats |
|
|
284
|
+
| `getPrices(market)` | 0.0001 USDC | On-chain prices |
|
|
285
|
+
| `getMarketInfo(market)` | 0.0001 USDC | Full market details |
|
|
286
|
+
| `getPosition(market)` | 0.0001 USDC | Your position |
|
|
287
|
+
| `getMarketData(market)` | 0.0001 USDC | Premium analytics |
|
|
288
|
+
| `getTradeInstructions()` | 0.0001 USDC | Encoded calldata |
|
|
289
|
+
|
|
290
|
+
## Network Configuration
|
|
291
|
+
|
|
292
|
+
| Property | Value |
|
|
293
|
+
|----------|-------|
|
|
294
|
+
| Network | Monad Testnet |
|
|
295
|
+
| Chain ID | 10143 |
|
|
296
|
+
| RPC | https://testnet-rpc.monad.xyz |
|
|
297
|
+
| Explorer | https://testnet.monadexplorer.com |
|
|
298
|
+
| USDC | 0x534b2f3A21130d7a60830c2Df862319e593943A3 |
|
|
299
|
+
| Faucet | https://faucet.monad.xyz |
|
|
300
|
+
|
|
301
|
+
## Error Recovery
|
|
302
|
+
|
|
303
|
+
```typescript
|
|
304
|
+
async function safeExecute<T>(fn: () => Promise<T>, retries = 3): Promise<T> {
|
|
305
|
+
for (let i = 0; i < retries; i++) {
|
|
306
|
+
try {
|
|
307
|
+
return await fn();
|
|
308
|
+
} catch (err) {
|
|
309
|
+
const msg = String(err);
|
|
310
|
+
|
|
311
|
+
if (msg.includes('insufficient funds')) {
|
|
312
|
+
console.error('OUT OF USDC - Alert human operator');
|
|
313
|
+
throw err; // Don't retry
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
if (msg.includes('gas')) {
|
|
317
|
+
console.error('OUT OF GAS - Need MON from faucet');
|
|
318
|
+
throw err; // Don't retry
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
if (i < retries - 1) {
|
|
322
|
+
console.warn(`Retry ${i + 1}/${retries}:`, msg);
|
|
323
|
+
await new Promise(r => setTimeout(r, 1000 * (i + 1)));
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
throw new Error('Max retries exceeded');
|
|
328
|
+
}
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
## Safety Rules
|
|
332
|
+
|
|
333
|
+
1. **Run heartbeat before trading** - Stop if unhealthy
|
|
334
|
+
2. **Never bet more than 10% of balance** on a single trade
|
|
335
|
+
3. **Keep reserves** - Maintain 100x API cost minimum (0.01 USDC)
|
|
336
|
+
4. **Alert humans** when balances drop below thresholds
|
|
337
|
+
5. **Log all trades** for audit and analysis
|
|
338
|
+
|
|
339
|
+
## Links
|
|
340
|
+
|
|
341
|
+
- GitHub: https://github.com/ZZZSTUDIOS/prediction-market-doppler
|
|
342
|
+
- NPM: https://www.npmjs.com/package/@rbs-pm/sdk
|