@madgallery/rbs-pm-sdk 1.0.5 → 1.0.7

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/SKILL.md CHANGED
@@ -96,9 +96,84 @@ Agent: Your portfolio across all markets:
96
96
 
97
97
  This section contains implementation details for AI agents using the SDK programmatically.
98
98
 
99
- ## Market Creation
99
+ ## Market Creation (Complete Guide)
100
100
 
101
- Every 10 heartbeat cycles (~100 minutes), your agent should create a market on a topic it finds interesting.
101
+ Creating a prediction market involves 3 steps:
102
+ 1. **Deploy** - Create the market contract on-chain
103
+ 2. **Initialize** - Add initial liquidity (USDC)
104
+ 3. **List** - Register in the discovery index
105
+
106
+ ### Quick Method: `deployMarket()` (Recommended)
107
+
108
+ The SDK provides a single method that handles all 3 steps:
109
+
110
+ ```typescript
111
+ const client = new RBSPMClient({
112
+ privateKey: process.env.PRIVATE_KEY as `0x${string}`,
113
+ });
114
+
115
+ // Create a market with one call
116
+ const result = await client.deployMarket({
117
+ question: 'Will BTC hit $100k by March 2026?',
118
+ resolutionTime: Math.floor(Date.now() / 1000) + 30 * 24 * 60 * 60, // 30 days from now
119
+ initialLiquidity: '2.5', // 2.5 USDC minimum recommended
120
+ category: 'crypto',
121
+ tags: ['bitcoin', 'price'],
122
+ });
123
+
124
+ console.log('Market deployed:', result.marketAddress);
125
+ console.log('Deploy tx:', result.deployTxHash);
126
+ console.log('Initialize tx:', result.initializeTxHash);
127
+ console.log('Listing ID:', result.listingId);
128
+ ```
129
+
130
+ **Costs:**
131
+ - x402 API fee: 0.0001 USDC
132
+ - Gas for deployment: ~0.01 MON
133
+ - Gas for initialization: ~0.005 MON
134
+ - Initial liquidity: your choice (2.5 USDC minimum recommended)
135
+
136
+ ### Step-by-Step Method (Advanced)
137
+
138
+ If you need more control, you can do each step separately:
139
+
140
+ ```typescript
141
+ // Step 1: Get deploy instructions
142
+ const deployInstructions = await paymentFetch(
143
+ 'https://qkcytrdhdtemyphsswou.supabase.co/functions/v1/x402-deploy-market',
144
+ {
145
+ method: 'POST',
146
+ headers: { 'Content-Type': 'application/json' },
147
+ body: JSON.stringify({
148
+ question: 'Will ETH reach $10k in 2026?',
149
+ resolutionTime: 1767225600, // Jan 1, 2026
150
+ initialLiquidity: '5',
151
+ callerAddress: walletAddress,
152
+ }),
153
+ }
154
+ );
155
+
156
+ // Step 2: Execute factory transaction (deploys market)
157
+ const deployTx = await walletClient.sendTransaction({
158
+ to: instructions.transactions[0].to,
159
+ data: instructions.transactions[0].data,
160
+ });
161
+
162
+ // Step 3: Initialize with liquidity
163
+ const initTx = await client.initializeMarket(marketAddress, '5');
164
+
165
+ // Step 4: List in discovery index
166
+ const listing = await client.listMarket({
167
+ address: marketAddress,
168
+ question: 'Will ETH reach $10k in 2026?',
169
+ resolutionTime: 1767225600,
170
+ oracle: walletAddress,
171
+ });
172
+ ```
173
+
174
+ ### Automatic Market Creation (Every 10 Heartbeats)
175
+
176
+ Your agent should create interesting markets periodically:
102
177
 
103
178
  ```typescript
104
179
  async function createInterestingMarket() {
@@ -107,44 +182,27 @@ async function createInterestingMarket() {
107
182
  });
108
183
 
109
184
  try {
110
- // 1. Research interesting topics
111
- // Use your capabilities to find newsworthy events, upcoming deadlines,
112
- // or questions people are debating
185
+ // 1. Research interesting topics using your capabilities
113
186
  const topic = await researchInterestingTopic();
114
187
 
115
- // Example topics an agent might find interesting:
188
+ // Example topics:
116
189
  // - "Will [Company] announce [Product] before [Date]?"
117
190
  // - "Will [Sports Team] win against [Opponent] on [Date]?"
118
191
  // - "Will [Crypto] reach $[Price] by end of [Month]?"
119
192
  // - "Will [Bill/Law] pass by [Date]?"
120
- // - "Will [Weather Event] happen in [Location] this [Season]?"
121
193
 
122
194
  console.log(`Creating market: ${topic.question}`);
123
- console.log(`Resolution: ${new Date(topic.resolutionTime * 1000).toISOString()}`);
124
-
125
- // 2. Deploy the market contract (requires Foundry or pre-deployed factory)
126
- // Note: Contract deployment is done via forge script or factory contract
127
- // The SDK's listMarket() registers an already-deployed contract
128
195
 
129
- // 3. List the market for discovery (costs 0.0001 USDC)
130
- const result = await client.listMarket({
131
- address: topic.deployedAddress, // Contract you deployed
196
+ // 2. Deploy, initialize, and list in one call
197
+ const result = await client.deployMarket({
132
198
  question: topic.question,
133
199
  resolutionTime: topic.resolutionTime,
134
- oracle: client.getAddress()!, // You are the oracle
200
+ initialLiquidity: '2.5', // Minimum recommended
135
201
  category: topic.category,
136
202
  tags: topic.tags,
137
203
  });
138
204
 
139
- console.log(`Market listed! ID: ${result.market.id}`);
140
- console.log(`Address: ${result.market.address}`);
141
-
142
- // 4. Initialize with liquidity (costs 0.0001 USDC + gas + liquidity amount)
143
- const initTx = await client.initializeMarket(
144
- topic.deployedAddress as `0x${string}`,
145
- '10' // 10 USDC initial liquidity
146
- );
147
- console.log(`Market initialized with 10 USDC liquidity. TX: ${initTx}`);
205
+ console.log(`Market created: ${result.marketAddress}`);
148
206
 
149
207
  } catch (err) {
150
208
  console.error('Failed to create market:', err);
package/dist/index.d.mts CHANGED
@@ -252,6 +252,44 @@ declare class RBSPMClient {
252
252
  * Alias for listMarket - for backwards compatibility
253
253
  */
254
254
  createMarket(params: MarketCreateParams): Promise<MarketCreateResult>;
255
+ /**
256
+ * Deploy a new prediction market via the Factory contract
257
+ *
258
+ * This is the complete market creation flow:
259
+ * 1. Deploy market via Factory (this method)
260
+ * 2. Initialize with liquidity
261
+ * 3. List in discovery index
262
+ *
263
+ * Requires x402 payment (0.0001 USDC) + gas for deployment
264
+ *
265
+ * @example
266
+ * ```typescript
267
+ * // Deploy a new market
268
+ * const result = await client.deployMarket({
269
+ * question: 'Will BTC hit $100k by March 2026?',
270
+ * resolutionTime: Math.floor(Date.now() / 1000) + 30 * 24 * 60 * 60, // 30 days
271
+ * initialLiquidity: '2.5', // 2.5 USDC
272
+ * });
273
+ *
274
+ * console.log('Market deployed:', result.marketAddress);
275
+ * console.log('Initialize tx:', result.initializeTxHash);
276
+ * ```
277
+ */
278
+ deployMarket(params: {
279
+ question: string;
280
+ resolutionTime: number;
281
+ initialLiquidity: string;
282
+ oracle?: `0x${string}`;
283
+ yesSymbol?: string;
284
+ noSymbol?: string;
285
+ category?: string;
286
+ tags?: string[];
287
+ }): Promise<{
288
+ marketAddress: `0x${string}`;
289
+ deployTxHash: `0x${string}`;
290
+ initializeTxHash: `0x${string}`;
291
+ listingId?: string;
292
+ }>;
255
293
  /**
256
294
  * Get encoded trade calldata (requires x402 payment - 0.0001 USDC)
257
295
  *
@@ -527,6 +565,7 @@ declare const MONAD_TESTNET: {
527
565
  readonly explorer: "https://testnet.monadexplorer.com";
528
566
  };
529
567
  declare const ADDRESSES: {
568
+ readonly MARKET_FACTORY: `0x${string}`;
530
569
  readonly PREDICTION_FACTORY: `0x${string}`;
531
570
  readonly WMON: `0x${string}`;
532
571
  readonly USDC: `0x${string}`;
@@ -552,6 +591,7 @@ declare const API_ENDPOINTS: {
552
591
  readonly x402Redeem: "/functions/v1/x402-redeem";
553
592
  readonly x402Initialize: "/functions/v1/x402-initialize";
554
593
  readonly x402CreateMarket: "/functions/v1/x402-create-market";
594
+ readonly x402DeployMarket: "/functions/v1/x402-deploy-market";
555
595
  readonly authMoltbook: "/functions/v1/auth-moltbook";
556
596
  };
557
597
  declare const X402_CONFIG: {
@@ -910,6 +950,55 @@ declare const LSLMSR_ABI: readonly [{
910
950
  readonly indexed: false;
911
951
  }];
912
952
  }];
953
+ declare const MARKET_FACTORY_ABI: readonly [{
954
+ readonly name: "createMarket";
955
+ readonly type: "function";
956
+ readonly inputs: readonly [{
957
+ readonly name: "question";
958
+ readonly type: "string";
959
+ }, {
960
+ readonly name: "resolutionTime";
961
+ readonly type: "uint256";
962
+ }, {
963
+ readonly name: "oracle";
964
+ readonly type: "address";
965
+ }, {
966
+ readonly name: "yesSymbol";
967
+ readonly type: "string";
968
+ }, {
969
+ readonly name: "noSymbol";
970
+ readonly type: "string";
971
+ }];
972
+ readonly outputs: readonly [{
973
+ readonly name: "market";
974
+ readonly type: "address";
975
+ }];
976
+ readonly stateMutability: "nonpayable";
977
+ }, {
978
+ readonly type: "event";
979
+ readonly name: "MarketCreated";
980
+ readonly inputs: readonly [{
981
+ readonly name: "market";
982
+ readonly type: "address";
983
+ readonly indexed: true;
984
+ }, {
985
+ readonly name: "creator";
986
+ readonly type: "address";
987
+ readonly indexed: true;
988
+ }, {
989
+ readonly name: "question";
990
+ readonly type: "string";
991
+ readonly indexed: false;
992
+ }, {
993
+ readonly name: "resolutionTime";
994
+ readonly type: "uint256";
995
+ readonly indexed: false;
996
+ }, {
997
+ readonly name: "oracle";
998
+ readonly type: "address";
999
+ readonly indexed: false;
1000
+ }];
1001
+ }];
913
1002
  declare const ERC20_ABI: readonly [{
914
1003
  readonly name: "balanceOf";
915
1004
  readonly type: "function";
@@ -966,4 +1055,4 @@ declare function checkX402Balance(publicClient: {
966
1055
  required: bigint;
967
1056
  }>;
968
1057
 
969
- export { ADDRESSES, API_CONFIG, API_ENDPOINTS, type AuthResult, ERC20_ABI, LSLMSR_ABI, LSLMSR_DEPLOY_PARAMS, MONAD_TESTNET, type Market, type MarketCreateParams, type MarketCreateResult, type MarketPrices, type MoltbookAgent, type Portfolio, type PortfolioPosition, type Position, type PremiumMarketData, RBSPMClient, type RBSPMConfig, type TradeQuote, type TradeResult, type X402Prices, X402_CONFIG, checkX402Balance, createX402Fetch, RBSPMClient as default };
1058
+ export { ADDRESSES, API_CONFIG, API_ENDPOINTS, type AuthResult, ERC20_ABI, LSLMSR_ABI, LSLMSR_DEPLOY_PARAMS, MARKET_FACTORY_ABI, MONAD_TESTNET, type Market, type MarketCreateParams, type MarketCreateResult, type MarketPrices, type MoltbookAgent, type Portfolio, type PortfolioPosition, type Position, type PremiumMarketData, RBSPMClient, type RBSPMConfig, type TradeQuote, type TradeResult, type X402Prices, X402_CONFIG, checkX402Balance, createX402Fetch, RBSPMClient as default };
package/dist/index.d.ts CHANGED
@@ -252,6 +252,44 @@ declare class RBSPMClient {
252
252
  * Alias for listMarket - for backwards compatibility
253
253
  */
254
254
  createMarket(params: MarketCreateParams): Promise<MarketCreateResult>;
255
+ /**
256
+ * Deploy a new prediction market via the Factory contract
257
+ *
258
+ * This is the complete market creation flow:
259
+ * 1. Deploy market via Factory (this method)
260
+ * 2. Initialize with liquidity
261
+ * 3. List in discovery index
262
+ *
263
+ * Requires x402 payment (0.0001 USDC) + gas for deployment
264
+ *
265
+ * @example
266
+ * ```typescript
267
+ * // Deploy a new market
268
+ * const result = await client.deployMarket({
269
+ * question: 'Will BTC hit $100k by March 2026?',
270
+ * resolutionTime: Math.floor(Date.now() / 1000) + 30 * 24 * 60 * 60, // 30 days
271
+ * initialLiquidity: '2.5', // 2.5 USDC
272
+ * });
273
+ *
274
+ * console.log('Market deployed:', result.marketAddress);
275
+ * console.log('Initialize tx:', result.initializeTxHash);
276
+ * ```
277
+ */
278
+ deployMarket(params: {
279
+ question: string;
280
+ resolutionTime: number;
281
+ initialLiquidity: string;
282
+ oracle?: `0x${string}`;
283
+ yesSymbol?: string;
284
+ noSymbol?: string;
285
+ category?: string;
286
+ tags?: string[];
287
+ }): Promise<{
288
+ marketAddress: `0x${string}`;
289
+ deployTxHash: `0x${string}`;
290
+ initializeTxHash: `0x${string}`;
291
+ listingId?: string;
292
+ }>;
255
293
  /**
256
294
  * Get encoded trade calldata (requires x402 payment - 0.0001 USDC)
257
295
  *
@@ -527,6 +565,7 @@ declare const MONAD_TESTNET: {
527
565
  readonly explorer: "https://testnet.monadexplorer.com";
528
566
  };
529
567
  declare const ADDRESSES: {
568
+ readonly MARKET_FACTORY: `0x${string}`;
530
569
  readonly PREDICTION_FACTORY: `0x${string}`;
531
570
  readonly WMON: `0x${string}`;
532
571
  readonly USDC: `0x${string}`;
@@ -552,6 +591,7 @@ declare const API_ENDPOINTS: {
552
591
  readonly x402Redeem: "/functions/v1/x402-redeem";
553
592
  readonly x402Initialize: "/functions/v1/x402-initialize";
554
593
  readonly x402CreateMarket: "/functions/v1/x402-create-market";
594
+ readonly x402DeployMarket: "/functions/v1/x402-deploy-market";
555
595
  readonly authMoltbook: "/functions/v1/auth-moltbook";
556
596
  };
557
597
  declare const X402_CONFIG: {
@@ -910,6 +950,55 @@ declare const LSLMSR_ABI: readonly [{
910
950
  readonly indexed: false;
911
951
  }];
912
952
  }];
953
+ declare const MARKET_FACTORY_ABI: readonly [{
954
+ readonly name: "createMarket";
955
+ readonly type: "function";
956
+ readonly inputs: readonly [{
957
+ readonly name: "question";
958
+ readonly type: "string";
959
+ }, {
960
+ readonly name: "resolutionTime";
961
+ readonly type: "uint256";
962
+ }, {
963
+ readonly name: "oracle";
964
+ readonly type: "address";
965
+ }, {
966
+ readonly name: "yesSymbol";
967
+ readonly type: "string";
968
+ }, {
969
+ readonly name: "noSymbol";
970
+ readonly type: "string";
971
+ }];
972
+ readonly outputs: readonly [{
973
+ readonly name: "market";
974
+ readonly type: "address";
975
+ }];
976
+ readonly stateMutability: "nonpayable";
977
+ }, {
978
+ readonly type: "event";
979
+ readonly name: "MarketCreated";
980
+ readonly inputs: readonly [{
981
+ readonly name: "market";
982
+ readonly type: "address";
983
+ readonly indexed: true;
984
+ }, {
985
+ readonly name: "creator";
986
+ readonly type: "address";
987
+ readonly indexed: true;
988
+ }, {
989
+ readonly name: "question";
990
+ readonly type: "string";
991
+ readonly indexed: false;
992
+ }, {
993
+ readonly name: "resolutionTime";
994
+ readonly type: "uint256";
995
+ readonly indexed: false;
996
+ }, {
997
+ readonly name: "oracle";
998
+ readonly type: "address";
999
+ readonly indexed: false;
1000
+ }];
1001
+ }];
913
1002
  declare const ERC20_ABI: readonly [{
914
1003
  readonly name: "balanceOf";
915
1004
  readonly type: "function";
@@ -966,4 +1055,4 @@ declare function checkX402Balance(publicClient: {
966
1055
  required: bigint;
967
1056
  }>;
968
1057
 
969
- export { ADDRESSES, API_CONFIG, API_ENDPOINTS, type AuthResult, ERC20_ABI, LSLMSR_ABI, LSLMSR_DEPLOY_PARAMS, MONAD_TESTNET, type Market, type MarketCreateParams, type MarketCreateResult, type MarketPrices, type MoltbookAgent, type Portfolio, type PortfolioPosition, type Position, type PremiumMarketData, RBSPMClient, type RBSPMConfig, type TradeQuote, type TradeResult, type X402Prices, X402_CONFIG, checkX402Balance, createX402Fetch, RBSPMClient as default };
1058
+ export { ADDRESSES, API_CONFIG, API_ENDPOINTS, type AuthResult, ERC20_ABI, LSLMSR_ABI, LSLMSR_DEPLOY_PARAMS, MARKET_FACTORY_ABI, MONAD_TESTNET, type Market, type MarketCreateParams, type MarketCreateResult, type MarketPrices, type MoltbookAgent, type Portfolio, type PortfolioPosition, type Position, type PremiumMarketData, RBSPMClient, type RBSPMConfig, type TradeQuote, type TradeResult, type X402Prices, X402_CONFIG, checkX402Balance, createX402Fetch, RBSPMClient as default };
package/dist/index.js CHANGED
@@ -26,6 +26,7 @@ __export(index_exports, {
26
26
  ERC20_ABI: () => ERC20_ABI,
27
27
  LSLMSR_ABI: () => LSLMSR_ABI,
28
28
  LSLMSR_DEPLOY_PARAMS: () => LSLMSR_DEPLOY_PARAMS,
29
+ MARKET_FACTORY_ABI: () => MARKET_FACTORY_ABI,
29
30
  MONAD_TESTNET: () => MONAD_TESTNET,
30
31
  RBSPMClient: () => RBSPMClient,
31
32
  X402_CONFIG: () => X402_CONFIG,
@@ -50,7 +51,10 @@ var MONAD_TESTNET = {
50
51
  explorer: "https://testnet.monadexplorer.com"
51
52
  };
52
53
  var ADDRESSES = {
53
- // Prediction Market Factory
54
+ // Market Factory (deploy new markets)
55
+ MARKET_FACTORY: "0x0000000000000000000000000000000000000000",
56
+ // TODO: Update after deployment
57
+ // Legacy Prediction Market Factory
54
58
  PREDICTION_FACTORY: "0xc4546422291F1860bbCe379075a077563B0e0777",
55
59
  // Wrapped MON
56
60
  WMON: "0xFb8bf4c1CC7a94c73D209a149eA2AbEa852BC541",
@@ -92,9 +96,11 @@ var API_ENDPOINTS = {
92
96
  // POST - redeem calldata
93
97
  x402Initialize: "/functions/v1/x402-initialize",
94
98
  // POST - initialize calldata
95
- // Market listing (0.0001 USDC)
99
+ // Market creation (0.0001 USDC)
96
100
  x402CreateMarket: "/functions/v1/x402-create-market",
97
- // POST - list market
101
+ // POST - list market in discovery
102
+ x402DeployMarket: "/functions/v1/x402-deploy-market",
103
+ // POST - deploy new market via factory
98
104
  // Authentication (free - required for agent identity)
99
105
  authMoltbook: "/functions/v1/auth-moltbook"
100
106
  };
@@ -386,6 +392,32 @@ var LSLMSR_ABI = [
386
392
  ]
387
393
  }
388
394
  ];
395
+ var MARKET_FACTORY_ABI = [
396
+ {
397
+ name: "createMarket",
398
+ type: "function",
399
+ inputs: [
400
+ { name: "question", type: "string" },
401
+ { name: "resolutionTime", type: "uint256" },
402
+ { name: "oracle", type: "address" },
403
+ { name: "yesSymbol", type: "string" },
404
+ { name: "noSymbol", type: "string" }
405
+ ],
406
+ outputs: [{ name: "market", type: "address" }],
407
+ stateMutability: "nonpayable"
408
+ },
409
+ {
410
+ type: "event",
411
+ name: "MarketCreated",
412
+ inputs: [
413
+ { name: "market", type: "address", indexed: true },
414
+ { name: "creator", type: "address", indexed: true },
415
+ { name: "question", type: "string", indexed: false },
416
+ { name: "resolutionTime", type: "uint256", indexed: false },
417
+ { name: "oracle", type: "address", indexed: false }
418
+ ]
419
+ }
420
+ ];
389
421
  var ERC20_ABI = [
390
422
  {
391
423
  name: "balanceOf",
@@ -742,6 +774,124 @@ var RBSPMClient = class {
742
774
  async createMarket(params) {
743
775
  return this.listMarket(params);
744
776
  }
777
+ /**
778
+ * Deploy a new prediction market via the Factory contract
779
+ *
780
+ * This is the complete market creation flow:
781
+ * 1. Deploy market via Factory (this method)
782
+ * 2. Initialize with liquidity
783
+ * 3. List in discovery index
784
+ *
785
+ * Requires x402 payment (0.0001 USDC) + gas for deployment
786
+ *
787
+ * @example
788
+ * ```typescript
789
+ * // Deploy a new market
790
+ * const result = await client.deployMarket({
791
+ * question: 'Will BTC hit $100k by March 2026?',
792
+ * resolutionTime: Math.floor(Date.now() / 1000) + 30 * 24 * 60 * 60, // 30 days
793
+ * initialLiquidity: '2.5', // 2.5 USDC
794
+ * });
795
+ *
796
+ * console.log('Market deployed:', result.marketAddress);
797
+ * console.log('Initialize tx:', result.initializeTxHash);
798
+ * ```
799
+ */
800
+ async deployMarket(params) {
801
+ if (!this.walletClient || !this.account) {
802
+ throw new Error("Wallet not configured. Provide privateKey in constructor.");
803
+ }
804
+ const paymentFetch = this.getPaymentFetch();
805
+ console.log("Deploying market via Factory...");
806
+ console.log(`Question: "${params.question}"`);
807
+ console.log(`Resolution: ${new Date(params.resolutionTime * 1e3).toISOString()}`);
808
+ console.log(`Initial liquidity: ${params.initialLiquidity} USDC`);
809
+ const response = await paymentFetch(`${this.apiUrl}${API_ENDPOINTS.x402DeployMarket}`, {
810
+ method: "POST",
811
+ headers: { "Content-Type": "application/json" },
812
+ body: JSON.stringify({
813
+ question: params.question,
814
+ resolutionTime: params.resolutionTime,
815
+ oracle: params.oracle || this.account.address,
816
+ yesSymbol: params.yesSymbol,
817
+ noSymbol: params.noSymbol,
818
+ initialLiquidity: params.initialLiquidity,
819
+ callerAddress: this.account.address,
820
+ category: params.category,
821
+ tags: params.tags
822
+ })
823
+ });
824
+ if (response.status === 402) {
825
+ throw new Error("Payment required for market deployment (0.0001 USDC)");
826
+ }
827
+ const data = await response.json();
828
+ if (!data.success) {
829
+ throw new Error(data.error || "Failed to get deploy instructions");
830
+ }
831
+ if (data.factory === "0x0000000000000000000000000000000000000000") {
832
+ throw new Error("MarketFactory not yet deployed. Contact admin.");
833
+ }
834
+ const createTx = data.transactions.find((tx) => tx.type === "createMarket");
835
+ if (!createTx) {
836
+ throw new Error("No createMarket transaction in response");
837
+ }
838
+ console.log("Executing factory deployment...");
839
+ const deployHash = await this.walletClient.sendTransaction({
840
+ account: this.account,
841
+ chain: monadTestnet,
842
+ to: createTx.to,
843
+ data: createTx.data
844
+ });
845
+ const deployReceipt = await this.publicClient.waitForTransactionReceipt({ hash: deployHash });
846
+ console.log("Deploy tx confirmed:", deployHash);
847
+ const marketCreatedLog = deployReceipt.logs.find((log) => {
848
+ return log.topics[0] === "0x" + "MarketCreated".padEnd(64, "0");
849
+ });
850
+ let marketAddress;
851
+ try {
852
+ const factoryAddress = data.factory;
853
+ const marketsCount = await this.publicClient.readContract({
854
+ address: factoryAddress,
855
+ abi: [{ name: "getMarketsCount", type: "function", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" }],
856
+ functionName: "getMarketsCount"
857
+ });
858
+ const markets = await this.publicClient.readContract({
859
+ address: factoryAddress,
860
+ abi: [{ name: "markets", type: "function", inputs: [{ type: "uint256" }], outputs: [{ type: "address" }], stateMutability: "view" }],
861
+ functionName: "markets",
862
+ args: [marketsCount - 1n]
863
+ });
864
+ marketAddress = markets;
865
+ } catch {
866
+ throw new Error("Failed to get deployed market address. Check transaction: " + deployHash);
867
+ }
868
+ console.log("Market deployed at:", marketAddress);
869
+ console.log("Initializing with liquidity...");
870
+ const initTxHash = await this.initializeMarket(marketAddress, params.initialLiquidity);
871
+ console.log("Initialize tx:", initTxHash);
872
+ let listingId;
873
+ try {
874
+ console.log("Listing in discovery index...");
875
+ const listing = await this.listMarket({
876
+ address: marketAddress,
877
+ question: params.question,
878
+ resolutionTime: params.resolutionTime,
879
+ oracle: params.oracle || this.account.address,
880
+ category: params.category,
881
+ tags: params.tags
882
+ });
883
+ listingId = listing.market.id;
884
+ console.log("Listed with ID:", listingId);
885
+ } catch (listErr) {
886
+ console.warn("Listing failed (market still deployed):", listErr);
887
+ }
888
+ return {
889
+ marketAddress,
890
+ deployTxHash: deployHash,
891
+ initializeTxHash: initTxHash,
892
+ listingId
893
+ };
894
+ }
745
895
  // ==================== Trade Instructions (x402 Protected) ====================
746
896
  /**
747
897
  * Get encoded trade calldata (requires x402 payment - 0.0001 USDC)
@@ -1409,6 +1559,7 @@ var client_default = RBSPMClient;
1409
1559
  ERC20_ABI,
1410
1560
  LSLMSR_ABI,
1411
1561
  LSLMSR_DEPLOY_PARAMS,
1562
+ MARKET_FACTORY_ABI,
1412
1563
  MONAD_TESTNET,
1413
1564
  RBSPMClient,
1414
1565
  X402_CONFIG,
package/dist/index.mjs CHANGED
@@ -19,7 +19,10 @@ var MONAD_TESTNET = {
19
19
  explorer: "https://testnet.monadexplorer.com"
20
20
  };
21
21
  var ADDRESSES = {
22
- // Prediction Market Factory
22
+ // Market Factory (deploy new markets)
23
+ MARKET_FACTORY: "0x0000000000000000000000000000000000000000",
24
+ // TODO: Update after deployment
25
+ // Legacy Prediction Market Factory
23
26
  PREDICTION_FACTORY: "0xc4546422291F1860bbCe379075a077563B0e0777",
24
27
  // Wrapped MON
25
28
  WMON: "0xFb8bf4c1CC7a94c73D209a149eA2AbEa852BC541",
@@ -61,9 +64,11 @@ var API_ENDPOINTS = {
61
64
  // POST - redeem calldata
62
65
  x402Initialize: "/functions/v1/x402-initialize",
63
66
  // POST - initialize calldata
64
- // Market listing (0.0001 USDC)
67
+ // Market creation (0.0001 USDC)
65
68
  x402CreateMarket: "/functions/v1/x402-create-market",
66
- // POST - list market
69
+ // POST - list market in discovery
70
+ x402DeployMarket: "/functions/v1/x402-deploy-market",
71
+ // POST - deploy new market via factory
67
72
  // Authentication (free - required for agent identity)
68
73
  authMoltbook: "/functions/v1/auth-moltbook"
69
74
  };
@@ -355,6 +360,32 @@ var LSLMSR_ABI = [
355
360
  ]
356
361
  }
357
362
  ];
363
+ var MARKET_FACTORY_ABI = [
364
+ {
365
+ name: "createMarket",
366
+ type: "function",
367
+ inputs: [
368
+ { name: "question", type: "string" },
369
+ { name: "resolutionTime", type: "uint256" },
370
+ { name: "oracle", type: "address" },
371
+ { name: "yesSymbol", type: "string" },
372
+ { name: "noSymbol", type: "string" }
373
+ ],
374
+ outputs: [{ name: "market", type: "address" }],
375
+ stateMutability: "nonpayable"
376
+ },
377
+ {
378
+ type: "event",
379
+ name: "MarketCreated",
380
+ inputs: [
381
+ { name: "market", type: "address", indexed: true },
382
+ { name: "creator", type: "address", indexed: true },
383
+ { name: "question", type: "string", indexed: false },
384
+ { name: "resolutionTime", type: "uint256", indexed: false },
385
+ { name: "oracle", type: "address", indexed: false }
386
+ ]
387
+ }
388
+ ];
358
389
  var ERC20_ABI = [
359
390
  {
360
391
  name: "balanceOf",
@@ -711,6 +742,124 @@ var RBSPMClient = class {
711
742
  async createMarket(params) {
712
743
  return this.listMarket(params);
713
744
  }
745
+ /**
746
+ * Deploy a new prediction market via the Factory contract
747
+ *
748
+ * This is the complete market creation flow:
749
+ * 1. Deploy market via Factory (this method)
750
+ * 2. Initialize with liquidity
751
+ * 3. List in discovery index
752
+ *
753
+ * Requires x402 payment (0.0001 USDC) + gas for deployment
754
+ *
755
+ * @example
756
+ * ```typescript
757
+ * // Deploy a new market
758
+ * const result = await client.deployMarket({
759
+ * question: 'Will BTC hit $100k by March 2026?',
760
+ * resolutionTime: Math.floor(Date.now() / 1000) + 30 * 24 * 60 * 60, // 30 days
761
+ * initialLiquidity: '2.5', // 2.5 USDC
762
+ * });
763
+ *
764
+ * console.log('Market deployed:', result.marketAddress);
765
+ * console.log('Initialize tx:', result.initializeTxHash);
766
+ * ```
767
+ */
768
+ async deployMarket(params) {
769
+ if (!this.walletClient || !this.account) {
770
+ throw new Error("Wallet not configured. Provide privateKey in constructor.");
771
+ }
772
+ const paymentFetch = this.getPaymentFetch();
773
+ console.log("Deploying market via Factory...");
774
+ console.log(`Question: "${params.question}"`);
775
+ console.log(`Resolution: ${new Date(params.resolutionTime * 1e3).toISOString()}`);
776
+ console.log(`Initial liquidity: ${params.initialLiquidity} USDC`);
777
+ const response = await paymentFetch(`${this.apiUrl}${API_ENDPOINTS.x402DeployMarket}`, {
778
+ method: "POST",
779
+ headers: { "Content-Type": "application/json" },
780
+ body: JSON.stringify({
781
+ question: params.question,
782
+ resolutionTime: params.resolutionTime,
783
+ oracle: params.oracle || this.account.address,
784
+ yesSymbol: params.yesSymbol,
785
+ noSymbol: params.noSymbol,
786
+ initialLiquidity: params.initialLiquidity,
787
+ callerAddress: this.account.address,
788
+ category: params.category,
789
+ tags: params.tags
790
+ })
791
+ });
792
+ if (response.status === 402) {
793
+ throw new Error("Payment required for market deployment (0.0001 USDC)");
794
+ }
795
+ const data = await response.json();
796
+ if (!data.success) {
797
+ throw new Error(data.error || "Failed to get deploy instructions");
798
+ }
799
+ if (data.factory === "0x0000000000000000000000000000000000000000") {
800
+ throw new Error("MarketFactory not yet deployed. Contact admin.");
801
+ }
802
+ const createTx = data.transactions.find((tx) => tx.type === "createMarket");
803
+ if (!createTx) {
804
+ throw new Error("No createMarket transaction in response");
805
+ }
806
+ console.log("Executing factory deployment...");
807
+ const deployHash = await this.walletClient.sendTransaction({
808
+ account: this.account,
809
+ chain: monadTestnet,
810
+ to: createTx.to,
811
+ data: createTx.data
812
+ });
813
+ const deployReceipt = await this.publicClient.waitForTransactionReceipt({ hash: deployHash });
814
+ console.log("Deploy tx confirmed:", deployHash);
815
+ const marketCreatedLog = deployReceipt.logs.find((log) => {
816
+ return log.topics[0] === "0x" + "MarketCreated".padEnd(64, "0");
817
+ });
818
+ let marketAddress;
819
+ try {
820
+ const factoryAddress = data.factory;
821
+ const marketsCount = await this.publicClient.readContract({
822
+ address: factoryAddress,
823
+ abi: [{ name: "getMarketsCount", type: "function", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" }],
824
+ functionName: "getMarketsCount"
825
+ });
826
+ const markets = await this.publicClient.readContract({
827
+ address: factoryAddress,
828
+ abi: [{ name: "markets", type: "function", inputs: [{ type: "uint256" }], outputs: [{ type: "address" }], stateMutability: "view" }],
829
+ functionName: "markets",
830
+ args: [marketsCount - 1n]
831
+ });
832
+ marketAddress = markets;
833
+ } catch {
834
+ throw new Error("Failed to get deployed market address. Check transaction: " + deployHash);
835
+ }
836
+ console.log("Market deployed at:", marketAddress);
837
+ console.log("Initializing with liquidity...");
838
+ const initTxHash = await this.initializeMarket(marketAddress, params.initialLiquidity);
839
+ console.log("Initialize tx:", initTxHash);
840
+ let listingId;
841
+ try {
842
+ console.log("Listing in discovery index...");
843
+ const listing = await this.listMarket({
844
+ address: marketAddress,
845
+ question: params.question,
846
+ resolutionTime: params.resolutionTime,
847
+ oracle: params.oracle || this.account.address,
848
+ category: params.category,
849
+ tags: params.tags
850
+ });
851
+ listingId = listing.market.id;
852
+ console.log("Listed with ID:", listingId);
853
+ } catch (listErr) {
854
+ console.warn("Listing failed (market still deployed):", listErr);
855
+ }
856
+ return {
857
+ marketAddress,
858
+ deployTxHash: deployHash,
859
+ initializeTxHash: initTxHash,
860
+ listingId
861
+ };
862
+ }
714
863
  // ==================== Trade Instructions (x402 Protected) ====================
715
864
  /**
716
865
  * Get encoded trade calldata (requires x402 payment - 0.0001 USDC)
@@ -1377,6 +1526,7 @@ export {
1377
1526
  ERC20_ABI,
1378
1527
  LSLMSR_ABI,
1379
1528
  LSLMSR_DEPLOY_PARAMS,
1529
+ MARKET_FACTORY_ABI,
1380
1530
  MONAD_TESTNET,
1381
1531
  RBSPMClient,
1382
1532
  X402_CONFIG,
@@ -0,0 +1,108 @@
1
+ # Onboarding a New AI Agent
2
+
3
+ ## Quick Start (5 minutes)
4
+
5
+ ### 1. Create Project
6
+ ```bash
7
+ mkdir my-trading-agent && cd my-trading-agent
8
+ npm init -y
9
+ npm install @madgallery/rbs-pm-sdk viem typescript ts-node @types/node
10
+ ```
11
+
12
+ ### 2. Generate Wallet
13
+ ```bash
14
+ node -e "const { generatePrivateKey, privateKeyToAccount } = require('viem/accounts'); const pk = generatePrivateKey(); console.log('PRIVATE_KEY=' + pk); console.log('ADDRESS=' + privateKeyToAccount(pk).address);"
15
+ ```
16
+
17
+ ### 3. Fund Wallet
18
+ - **MON (gas)**: https://faucet.monad.xyz
19
+ - **USDC**: Need 10+ USDC on Monad testnet (chain ID 10143)
20
+
21
+ ### 4. Create .env
22
+ ```bash
23
+ echo "PRIVATE_KEY=0x...your_key..." > .env
24
+ ```
25
+
26
+ ### 5. Copy Skill File
27
+ ```bash
28
+ cp node_modules/@madgallery/rbs-pm-sdk/SKILL.md ./SKILL.md
29
+ ```
30
+
31
+ ---
32
+
33
+ ## Starting Your AI Agent
34
+
35
+ Give your AI agent (Claude, GPT, etc.) this prompt:
36
+
37
+ ```
38
+ You are a prediction market trading agent on Monad blockchain.
39
+
40
+ Read SKILL.md to understand how to trade. Your wallet private key is
41
+ in the PRIVATE_KEY environment variable.
42
+
43
+ Your job:
44
+ 1. Check wallet balance (need MON for gas, USDC for trading)
45
+ 2. Discover active prediction markets
46
+ 3. Research questions and form predictions
47
+ 4. Trade when you find edge (your prediction vs market price)
48
+ 5. Run heartbeat every 10 minutes to monitor health
49
+ 6. Create interesting markets every 10 heartbeat cycles
50
+
51
+ Start by checking if the wallet is ready to trade.
52
+ ```
53
+
54
+ ---
55
+
56
+ ## What the Agent Will Do
57
+
58
+ Once the agent reads SKILL.md, it will:
59
+
60
+ 1. **Initialize** the RBSPMClient with your private key
61
+ 2. **Check balances** - MON for gas, USDC for trading
62
+ 3. **Discover markets** - Find active prediction markets
63
+ 4. **Research & Trade** - Form predictions, calculate edge, place bets
64
+ 5. **Monitor** - Run heartbeat checks, track portfolio
65
+ 6. **Create markets** - Every ~100 minutes, create a new market
66
+
67
+ ---
68
+
69
+ ## Verification
70
+
71
+ Your agent should be able to answer:
72
+ - "What's my wallet balance?"
73
+ - "What markets are available?"
74
+ - "What's the price on [market]?"
75
+ - "Buy $5 of YES on [market]"
76
+
77
+ If it can do these, it's working.
78
+
79
+ ---
80
+
81
+ ## Costs
82
+
83
+ All API calls cost **0.0001 USDC** via x402 micropayments.
84
+ This is automatic - the SDK handles payment signing.
85
+
86
+ | Action | Cost |
87
+ |--------|------|
88
+ | List markets | 0.0001 USDC |
89
+ | Get prices | 0.0001 USDC |
90
+ | Check position | 0.0001 USDC |
91
+ | Buy shares | 0.0001 + gas + amount |
92
+ | Sell shares | 0.0001 + gas |
93
+
94
+ ---
95
+
96
+ ## Troubleshooting
97
+
98
+ **"insufficient funds"**
99
+ - Need more USDC. Minimum 10 USDC required.
100
+
101
+ **"gas required exceeds allowance"**
102
+ - Need MON. Get from https://faucet.monad.xyz
103
+
104
+ **"Payment required"**
105
+ - x402 payment failing. Check USDC balance.
106
+
107
+ **No markets showing**
108
+ - Markets may not be deployed yet, or indexer is down.
@@ -0,0 +1,149 @@
1
+ /**
2
+ * RBS Prediction Market - Starter Agent Template
3
+ *
4
+ * Setup:
5
+ * 1. npm install @madgallery/rbs-pm-sdk viem
6
+ * 2. Set PRIVATE_KEY environment variable
7
+ * 3. Fund wallet with MON (gas) and USDC (trading)
8
+ * 4. Run: npx ts-node starter-agent.ts
9
+ */
10
+
11
+ import { RBSPMClient } from '@madgallery/rbs-pm-sdk';
12
+
13
+ // Initialize client with your wallet
14
+ const client = new RBSPMClient({
15
+ privateKey: process.env.PRIVATE_KEY as `0x${string}`,
16
+ });
17
+
18
+ // ============================================
19
+ // STEP 1: Check wallet health
20
+ // ============================================
21
+ async function checkWallet() {
22
+ const address = client.getAddress();
23
+ const mon = await client.getMONBalance();
24
+ const usdc = await client.getUSDCBalance();
25
+
26
+ console.log('\n=== WALLET STATUS ===');
27
+ console.log(`Address: ${address}`);
28
+ console.log(`MON (gas): ${mon}`);
29
+ console.log(`USDC (trading): ${usdc}`);
30
+
31
+ const ready = parseFloat(mon) >= 0.01 && parseFloat(usdc) >= 10;
32
+ console.log(`Ready to trade: ${ready ? 'YES' : 'NO'}`);
33
+
34
+ if (!ready) {
35
+ if (parseFloat(mon) < 0.01) {
36
+ console.log('⚠️ Need MON for gas: https://faucet.monad.xyz');
37
+ }
38
+ if (parseFloat(usdc) < 10) {
39
+ console.log('⚠️ Need minimum 10 USDC for trading');
40
+ }
41
+ }
42
+
43
+ return { address, mon, usdc, ready };
44
+ }
45
+
46
+ // ============================================
47
+ // STEP 2: Discover markets
48
+ // ============================================
49
+ async function discoverMarkets() {
50
+ console.log('\n=== AVAILABLE MARKETS ===');
51
+
52
+ const markets = await client.getMarkets();
53
+
54
+ if (markets.length === 0) {
55
+ console.log('No markets found');
56
+ return [];
57
+ }
58
+
59
+ for (const market of markets) {
60
+ const yesPercent = (market.yes_price * 100).toFixed(0);
61
+ const noPercent = (market.no_price * 100).toFixed(0);
62
+ console.log(`\n📊 ${market.question}`);
63
+ console.log(` Address: ${market.address}`);
64
+ console.log(` YES: ${yesPercent}% | NO: ${noPercent}%`);
65
+ console.log(` Volume: $${market.total_volume || 0} USDC`);
66
+ }
67
+
68
+ return markets;
69
+ }
70
+
71
+ // ============================================
72
+ // STEP 3: Check your positions
73
+ // ============================================
74
+ async function checkPortfolio() {
75
+ console.log('\n=== YOUR PORTFOLIO ===');
76
+
77
+ const portfolio = await client.getPortfolio();
78
+
79
+ if (portfolio.positions.length === 0) {
80
+ console.log('No positions yet');
81
+ return portfolio;
82
+ }
83
+
84
+ for (const pos of portfolio.positions) {
85
+ console.log(`\n📈 ${pos.marketQuestion}`);
86
+ console.log(` YES shares: ${pos.yesSharesFormatted}`);
87
+ console.log(` NO shares: ${pos.noSharesFormatted}`);
88
+ console.log(` Value: $${pos.totalValue} USDC`);
89
+ if (pos.resolved) {
90
+ console.log(' ⚡ RESOLVED - Call redeem() to collect!');
91
+ }
92
+ }
93
+
94
+ console.log(`\nTotal value: $${portfolio.summary.totalValue} USDC`);
95
+ return portfolio;
96
+ }
97
+
98
+ // ============================================
99
+ // STEP 4: Make a trade (example)
100
+ // ============================================
101
+ async function exampleTrade(marketAddress: `0x${string}`, betYes: boolean, amountUsdc: number) {
102
+ console.log('\n=== PLACING TRADE ===');
103
+ console.log(`Market: ${marketAddress}`);
104
+ console.log(`Side: ${betYes ? 'YES' : 'NO'}`);
105
+ console.log(`Amount: $${amountUsdc} USDC`);
106
+
107
+ // Get current prices first
108
+ const prices = await client.getPrices(marketAddress);
109
+ console.log(`Current price: ${(prices.yes * 100).toFixed(1)}% YES / ${(prices.no * 100).toFixed(1)}% NO`);
110
+
111
+ // Execute trade
112
+ const txHash = await client.buy(marketAddress, betYes, amountUsdc);
113
+ console.log(`✅ Trade submitted: ${txHash}`);
114
+ console.log(` View: https://testnet.monadexplorer.com/tx/${txHash}`);
115
+
116
+ return txHash;
117
+ }
118
+
119
+ // ============================================
120
+ // MAIN: Run the agent
121
+ // ============================================
122
+ async function main() {
123
+ console.log('🤖 RBS Prediction Market Agent Starting...\n');
124
+
125
+ // Step 1: Check wallet
126
+ const wallet = await checkWallet();
127
+ if (!wallet.ready) {
128
+ console.log('\n❌ Wallet not ready. Fund it first.');
129
+ return;
130
+ }
131
+
132
+ // Step 2: Discover markets
133
+ const markets = await discoverMarkets();
134
+ if (markets.length === 0) {
135
+ console.log('\n❌ No markets to trade.');
136
+ return;
137
+ }
138
+
139
+ // Step 3: Check existing positions
140
+ await checkPortfolio();
141
+
142
+ // Step 4: Example trade (uncomment to execute)
143
+ // const firstMarket = markets[0].address as `0x${string}`;
144
+ // await exampleTrade(firstMarket, true, 1); // Buy $1 of YES
145
+
146
+ console.log('\n✅ Agent ready. Modify this script to implement your trading strategy.');
147
+ }
148
+
149
+ main().catch(console.error);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@madgallery/rbs-pm-sdk",
3
- "version": "1.0.5",
3
+ "version": "1.0.7",
4
4
  "description": "SDK for AI agents to trade on RBS Prediction Markets (Monad)",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -8,7 +8,8 @@
8
8
  "files": [
9
9
  "dist",
10
10
  "README.md",
11
- "SKILL.md"
11
+ "SKILL.md",
12
+ "examples"
12
13
  ],
13
14
  "scripts": {
14
15
  "build": "tsup src/index.ts --format cjs,esm --dts",