@alpha-arcade/sdk 0.1.2 → 0.2.1

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/dist/index.d.cts CHANGED
@@ -10,17 +10,20 @@ type AlphaClientConfig = {
10
10
  signer: TransactionSigner;
11
11
  /** The active Algorand address that will sign transactions */
12
12
  activeAddress: string;
13
- /** Matcher contract app ID (mainnet: 741347297) */
13
+ /** Matcher contract app ID (mainnet: 3078581851) */
14
14
  matcherAppId: number;
15
15
  /** USDC ASA ID on Algorand (mainnet: 31566704) */
16
16
  usdcAssetId: number;
17
17
  /** Base URL for the Alpha REST API (default: https://partners.alphaarcade.com/api) */
18
18
  apiBaseUrl?: string;
19
- /** API key for the Alpha partners API (passed as x-api-key header) */
20
- apiKey: string;
19
+ /** API key for the Alpha partners API. Optional -- if not provided, markets are loaded on-chain. */
20
+ apiKey?: string;
21
+ /** Market creator address for on-chain market discovery. Defaults to the Alpha Arcade mainnet creator. */
22
+ marketCreatorAddress?: string;
21
23
  };
22
- /** A prediction market returned from the Alpha API */
24
+ /** A prediction market (from the Alpha API or on-chain discovery) */
23
25
  type Market = {
26
+ /** Market ID (app ID as string for on-chain, UUID for API) */
24
27
  id: string;
25
28
  title: string;
26
29
  slug?: string;
@@ -28,9 +31,13 @@ type Market = {
28
31
  marketAppId: number;
29
32
  yesAssetId: number;
30
33
  noAssetId: number;
31
- yesProb: number;
32
- noProb: number;
33
- volume: number;
34
+ /** YES probability (API only -- not available from on-chain lookup) */
35
+ yesProb?: number;
36
+ /** NO probability (API only -- not available from on-chain lookup) */
37
+ noProb?: number;
38
+ /** Trading volume (API only -- not available from on-chain lookup) */
39
+ volume?: number;
40
+ /** End/resolution timestamp in seconds */
34
41
  endTs: number;
35
42
  resolution?: number;
36
43
  isResolved?: boolean;
@@ -39,6 +46,8 @@ type Market = {
39
46
  featured?: boolean;
40
47
  options?: MarketOption[];
41
48
  feeBase?: number;
49
+ /** Data source: 'onchain' or 'api' */
50
+ source?: 'onchain' | 'api';
42
51
  [key: string]: unknown;
43
52
  };
44
53
  /** An option within a multi-choice market */
@@ -316,7 +325,6 @@ type EscrowGlobalState = {
316
325
  * activeAddress: account.addr,
317
326
  * matcherAppId: 3078581851,
318
327
  * usdcAssetId: 31566704,
319
- * apiKey: 'YOUR_API_KEY',
320
328
  * });
321
329
  *
322
330
  * // Fetch markets
@@ -436,9 +444,10 @@ declare class AlphaClient {
436
444
  */
437
445
  getOpenOrders(marketAppId: number, walletAddress?: string): Promise<OpenOrder[]>;
438
446
  /**
439
- * Fetches all live, tradeable markets from the Alpha API.
447
+ * Fetches all live, tradeable markets.
440
448
  *
441
- * Automatically paginates to retrieve all markets.
449
+ * If an API key is configured, uses the Alpha REST API (richer data: images, categories, volume).
450
+ * Otherwise, discovers markets on-chain from the market creator address (no API key needed).
442
451
  *
443
452
  * @returns Array of live markets
444
453
  */
@@ -446,12 +455,90 @@ declare class AlphaClient {
446
455
  /**
447
456
  * Fetches a single market by its ID.
448
457
  *
449
- * @param marketId - The market ID
458
+ * If an API key is configured, uses the Alpha REST API.
459
+ * Otherwise, reads the market's on-chain global state (pass the market app ID as a string).
460
+ *
461
+ * @param marketId - The market ID (UUID for API, app ID string for on-chain)
450
462
  * @returns The market data, or null if not found
451
463
  */
452
464
  getMarket(marketId: string): Promise<Market | null>;
465
+ /**
466
+ * Fetches all live markets directly from the blockchain (no API key needed).
467
+ *
468
+ * Discovers markets by looking up all apps created by the market creator address.
469
+ * Returns core data: title, asset IDs, resolution time, fees.
470
+ * Does NOT include images, categories, volume, or probabilities.
471
+ *
472
+ * @returns Array of live markets from on-chain data
473
+ */
474
+ getMarketsOnChain(): Promise<Market[]>;
475
+ /**
476
+ * Fetches a single market by app ID directly from the blockchain (no API key needed).
477
+ *
478
+ * @param marketAppId - The market app ID
479
+ * @returns The market data, or null if not found
480
+ */
481
+ getMarketOnChain(marketAppId: number): Promise<Market | null>;
482
+ /**
483
+ * Fetches all live markets from the Alpha REST API (requires API key).
484
+ *
485
+ * Returns richer data than on-chain: images, categories, volume, probabilities.
486
+ *
487
+ * @returns Array of live markets from the API
488
+ */
489
+ getMarketsFromApi(): Promise<Market[]>;
490
+ /**
491
+ * Fetches a single market by ID from the Alpha REST API (requires API key).
492
+ *
493
+ * @param marketId - The market UUID
494
+ * @returns The market data, or null if not found
495
+ */
496
+ getMarketFromApi(marketId: string): Promise<Market | null>;
453
497
  }
454
498
 
499
+ /** The default Alpha Arcade mainnet market creator address */
500
+ declare const DEFAULT_MARKET_CREATOR_ADDRESS = "5P5Y6HTWUNG2E3VXBQDZN3ENZD3JPAIR5PKT3LOYJAPAUKOLFD6KANYTRY";
501
+ /**
502
+ * Fetches all live, tradeable markets directly from the Algorand blockchain.
503
+ *
504
+ * Discovers markets by looking up all applications created by the market creator
505
+ * address, then reading their global state. No API key required.
506
+ *
507
+ * @param config - Alpha client config
508
+ * @param options - Optional filters
509
+ * @returns Array of live markets
510
+ */
511
+ declare const getMarketsOnChain: (config: AlphaClientConfig, options?: {
512
+ activeOnly?: boolean;
513
+ }) => Promise<Market[]>;
514
+ /**
515
+ * Fetches a single market by its app ID directly from the Algorand blockchain.
516
+ *
517
+ * @param config - Alpha client config
518
+ * @param marketAppId - The market app ID (number or string)
519
+ * @returns The market data, or null if not found
520
+ */
521
+ declare const getMarketOnChain: (config: AlphaClientConfig, marketAppId: number | string) => Promise<Market | null>;
522
+ /**
523
+ * Fetches all live, tradeable markets from the Alpha REST API.
524
+ *
525
+ * Paginates automatically through all results. Requires an API key.
526
+ * Returns richer data than on-chain lookup (images, categories, volume, probabilities).
527
+ *
528
+ * @param config - Alpha client config
529
+ * @returns Array of live markets
530
+ */
531
+ declare const getMarketsFromApi: (config: AlphaClientConfig) => Promise<Market[]>;
532
+ /**
533
+ * Fetches a single market by its ID from the Alpha REST API.
534
+ * Requires an API key.
535
+ *
536
+ * @param config - Alpha client config
537
+ * @param marketId - The market ID
538
+ * @returns The market data, or null if not found
539
+ */
540
+ declare const getMarketFromApi: (config: AlphaClientConfig, marketId: string) => Promise<Market | null>;
541
+
455
542
  /**
456
543
  * Calculates the required fee amount in microunits.
457
544
  *
@@ -530,4 +617,4 @@ declare const getEscrowGlobalState: (indexerClient: algosdk.Indexer, escrowAppId
530
617
  */
531
618
  declare const checkAssetOptIn: (algodClient: algosdk.Algodv2, address: string, assetId: number) => Promise<boolean>;
532
619
 
533
- export { type AggregatedOrderbook, type AggregatedOrderbookEntry, type AggregatedOrderbookSide, AlphaClient, type AlphaClientConfig, type CancelOrderParams, type CancelOrderResult, type ClaimParams, type ClaimResult, type CounterpartyMatch, type CreateLimitOrderParams, type CreateMarketOrderParams, type CreateMarketOrderResult, type CreateOrderResult, type EscrowGlobalState, type Market, type MarketGlobalState, type MarketOption, type MergeSharesParams, type OpenOrder, type OrderSide, type Orderbook, type OrderbookEntry, type OrderbookSide, type Position, type ProposeMatchParams, type ProposeMatchResult, type SplitMergeResult, type SplitSharesParams, type WalletPosition, calculateFee, calculateFeeFromTotal, calculateMatchingOrders, checkAssetOptIn, decodeGlobalState, getEscrowGlobalState, getMarketGlobalState };
620
+ export { type AggregatedOrderbook, type AggregatedOrderbookEntry, type AggregatedOrderbookSide, AlphaClient, type AlphaClientConfig, type CancelOrderParams, type CancelOrderResult, type ClaimParams, type ClaimResult, type CounterpartyMatch, type CreateLimitOrderParams, type CreateMarketOrderParams, type CreateMarketOrderResult, type CreateOrderResult, DEFAULT_MARKET_CREATOR_ADDRESS, type EscrowGlobalState, type Market, type MarketGlobalState, type MarketOption, type MergeSharesParams, type OpenOrder, type OrderSide, type Orderbook, type OrderbookEntry, type OrderbookSide, type Position, type ProposeMatchParams, type ProposeMatchResult, type SplitMergeResult, type SplitSharesParams, type WalletPosition, calculateFee, calculateFeeFromTotal, calculateMatchingOrders, checkAssetOptIn, decodeGlobalState, getEscrowGlobalState, getMarketFromApi, getMarketGlobalState, getMarketOnChain, getMarketsFromApi, getMarketsOnChain };
package/dist/index.d.ts CHANGED
@@ -10,17 +10,20 @@ type AlphaClientConfig = {
10
10
  signer: TransactionSigner;
11
11
  /** The active Algorand address that will sign transactions */
12
12
  activeAddress: string;
13
- /** Matcher contract app ID (mainnet: 741347297) */
13
+ /** Matcher contract app ID (mainnet: 3078581851) */
14
14
  matcherAppId: number;
15
15
  /** USDC ASA ID on Algorand (mainnet: 31566704) */
16
16
  usdcAssetId: number;
17
17
  /** Base URL for the Alpha REST API (default: https://partners.alphaarcade.com/api) */
18
18
  apiBaseUrl?: string;
19
- /** API key for the Alpha partners API (passed as x-api-key header) */
20
- apiKey: string;
19
+ /** API key for the Alpha partners API. Optional -- if not provided, markets are loaded on-chain. */
20
+ apiKey?: string;
21
+ /** Market creator address for on-chain market discovery. Defaults to the Alpha Arcade mainnet creator. */
22
+ marketCreatorAddress?: string;
21
23
  };
22
- /** A prediction market returned from the Alpha API */
24
+ /** A prediction market (from the Alpha API or on-chain discovery) */
23
25
  type Market = {
26
+ /** Market ID (app ID as string for on-chain, UUID for API) */
24
27
  id: string;
25
28
  title: string;
26
29
  slug?: string;
@@ -28,9 +31,13 @@ type Market = {
28
31
  marketAppId: number;
29
32
  yesAssetId: number;
30
33
  noAssetId: number;
31
- yesProb: number;
32
- noProb: number;
33
- volume: number;
34
+ /** YES probability (API only -- not available from on-chain lookup) */
35
+ yesProb?: number;
36
+ /** NO probability (API only -- not available from on-chain lookup) */
37
+ noProb?: number;
38
+ /** Trading volume (API only -- not available from on-chain lookup) */
39
+ volume?: number;
40
+ /** End/resolution timestamp in seconds */
34
41
  endTs: number;
35
42
  resolution?: number;
36
43
  isResolved?: boolean;
@@ -39,6 +46,8 @@ type Market = {
39
46
  featured?: boolean;
40
47
  options?: MarketOption[];
41
48
  feeBase?: number;
49
+ /** Data source: 'onchain' or 'api' */
50
+ source?: 'onchain' | 'api';
42
51
  [key: string]: unknown;
43
52
  };
44
53
  /** An option within a multi-choice market */
@@ -316,7 +325,6 @@ type EscrowGlobalState = {
316
325
  * activeAddress: account.addr,
317
326
  * matcherAppId: 3078581851,
318
327
  * usdcAssetId: 31566704,
319
- * apiKey: 'YOUR_API_KEY',
320
328
  * });
321
329
  *
322
330
  * // Fetch markets
@@ -436,9 +444,10 @@ declare class AlphaClient {
436
444
  */
437
445
  getOpenOrders(marketAppId: number, walletAddress?: string): Promise<OpenOrder[]>;
438
446
  /**
439
- * Fetches all live, tradeable markets from the Alpha API.
447
+ * Fetches all live, tradeable markets.
440
448
  *
441
- * Automatically paginates to retrieve all markets.
449
+ * If an API key is configured, uses the Alpha REST API (richer data: images, categories, volume).
450
+ * Otherwise, discovers markets on-chain from the market creator address (no API key needed).
442
451
  *
443
452
  * @returns Array of live markets
444
453
  */
@@ -446,12 +455,90 @@ declare class AlphaClient {
446
455
  /**
447
456
  * Fetches a single market by its ID.
448
457
  *
449
- * @param marketId - The market ID
458
+ * If an API key is configured, uses the Alpha REST API.
459
+ * Otherwise, reads the market's on-chain global state (pass the market app ID as a string).
460
+ *
461
+ * @param marketId - The market ID (UUID for API, app ID string for on-chain)
450
462
  * @returns The market data, or null if not found
451
463
  */
452
464
  getMarket(marketId: string): Promise<Market | null>;
465
+ /**
466
+ * Fetches all live markets directly from the blockchain (no API key needed).
467
+ *
468
+ * Discovers markets by looking up all apps created by the market creator address.
469
+ * Returns core data: title, asset IDs, resolution time, fees.
470
+ * Does NOT include images, categories, volume, or probabilities.
471
+ *
472
+ * @returns Array of live markets from on-chain data
473
+ */
474
+ getMarketsOnChain(): Promise<Market[]>;
475
+ /**
476
+ * Fetches a single market by app ID directly from the blockchain (no API key needed).
477
+ *
478
+ * @param marketAppId - The market app ID
479
+ * @returns The market data, or null if not found
480
+ */
481
+ getMarketOnChain(marketAppId: number): Promise<Market | null>;
482
+ /**
483
+ * Fetches all live markets from the Alpha REST API (requires API key).
484
+ *
485
+ * Returns richer data than on-chain: images, categories, volume, probabilities.
486
+ *
487
+ * @returns Array of live markets from the API
488
+ */
489
+ getMarketsFromApi(): Promise<Market[]>;
490
+ /**
491
+ * Fetches a single market by ID from the Alpha REST API (requires API key).
492
+ *
493
+ * @param marketId - The market UUID
494
+ * @returns The market data, or null if not found
495
+ */
496
+ getMarketFromApi(marketId: string): Promise<Market | null>;
453
497
  }
454
498
 
499
+ /** The default Alpha Arcade mainnet market creator address */
500
+ declare const DEFAULT_MARKET_CREATOR_ADDRESS = "5P5Y6HTWUNG2E3VXBQDZN3ENZD3JPAIR5PKT3LOYJAPAUKOLFD6KANYTRY";
501
+ /**
502
+ * Fetches all live, tradeable markets directly from the Algorand blockchain.
503
+ *
504
+ * Discovers markets by looking up all applications created by the market creator
505
+ * address, then reading their global state. No API key required.
506
+ *
507
+ * @param config - Alpha client config
508
+ * @param options - Optional filters
509
+ * @returns Array of live markets
510
+ */
511
+ declare const getMarketsOnChain: (config: AlphaClientConfig, options?: {
512
+ activeOnly?: boolean;
513
+ }) => Promise<Market[]>;
514
+ /**
515
+ * Fetches a single market by its app ID directly from the Algorand blockchain.
516
+ *
517
+ * @param config - Alpha client config
518
+ * @param marketAppId - The market app ID (number or string)
519
+ * @returns The market data, or null if not found
520
+ */
521
+ declare const getMarketOnChain: (config: AlphaClientConfig, marketAppId: number | string) => Promise<Market | null>;
522
+ /**
523
+ * Fetches all live, tradeable markets from the Alpha REST API.
524
+ *
525
+ * Paginates automatically through all results. Requires an API key.
526
+ * Returns richer data than on-chain lookup (images, categories, volume, probabilities).
527
+ *
528
+ * @param config - Alpha client config
529
+ * @returns Array of live markets
530
+ */
531
+ declare const getMarketsFromApi: (config: AlphaClientConfig) => Promise<Market[]>;
532
+ /**
533
+ * Fetches a single market by its ID from the Alpha REST API.
534
+ * Requires an API key.
535
+ *
536
+ * @param config - Alpha client config
537
+ * @param marketId - The market ID
538
+ * @returns The market data, or null if not found
539
+ */
540
+ declare const getMarketFromApi: (config: AlphaClientConfig, marketId: string) => Promise<Market | null>;
541
+
455
542
  /**
456
543
  * Calculates the required fee amount in microunits.
457
544
  *
@@ -530,4 +617,4 @@ declare const getEscrowGlobalState: (indexerClient: algosdk.Indexer, escrowAppId
530
617
  */
531
618
  declare const checkAssetOptIn: (algodClient: algosdk.Algodv2, address: string, assetId: number) => Promise<boolean>;
532
619
 
533
- export { type AggregatedOrderbook, type AggregatedOrderbookEntry, type AggregatedOrderbookSide, AlphaClient, type AlphaClientConfig, type CancelOrderParams, type CancelOrderResult, type ClaimParams, type ClaimResult, type CounterpartyMatch, type CreateLimitOrderParams, type CreateMarketOrderParams, type CreateMarketOrderResult, type CreateOrderResult, type EscrowGlobalState, type Market, type MarketGlobalState, type MarketOption, type MergeSharesParams, type OpenOrder, type OrderSide, type Orderbook, type OrderbookEntry, type OrderbookSide, type Position, type ProposeMatchParams, type ProposeMatchResult, type SplitMergeResult, type SplitSharesParams, type WalletPosition, calculateFee, calculateFeeFromTotal, calculateMatchingOrders, checkAssetOptIn, decodeGlobalState, getEscrowGlobalState, getMarketGlobalState };
620
+ export { type AggregatedOrderbook, type AggregatedOrderbookEntry, type AggregatedOrderbookSide, AlphaClient, type AlphaClientConfig, type CancelOrderParams, type CancelOrderResult, type ClaimParams, type ClaimResult, type CounterpartyMatch, type CreateLimitOrderParams, type CreateMarketOrderParams, type CreateMarketOrderResult, type CreateOrderResult, DEFAULT_MARKET_CREATOR_ADDRESS, type EscrowGlobalState, type Market, type MarketGlobalState, type MarketOption, type MergeSharesParams, type OpenOrder, type OrderSide, type Orderbook, type OrderbookEntry, type OrderbookSide, type Position, type ProposeMatchParams, type ProposeMatchResult, type SplitMergeResult, type SplitSharesParams, type WalletPosition, calculateFee, calculateFeeFromTotal, calculateMatchingOrders, checkAssetOptIn, decodeGlobalState, getEscrowGlobalState, getMarketFromApi, getMarketGlobalState, getMarketOnChain, getMarketsFromApi, getMarketsOnChain };
package/dist/index.js CHANGED
@@ -1886,40 +1886,43 @@ var getPositions = async (config, walletAddress) => {
1886
1886
  const amount = Number(asset.amount);
1887
1887
  try {
1888
1888
  const assetInfo = await indexerClient.lookupAssetByID(assetId).do();
1889
- const creator = assetInfo.asset?.params?.creator;
1890
- if (!creator) continue;
1891
- const createdApps = await indexerClient.lookupAccountCreatedApplications(creator).limit(1).do();
1892
- if (!createdApps.applications?.length) continue;
1893
- const appId = createdApps.applications[0].id;
1894
- try {
1895
- const appInfo = await indexerClient.lookupApplications(appId).do();
1896
- const rawState = appInfo.application?.params?.["global-state"];
1897
- if (!rawState) continue;
1898
- let yesAssetIdOnChain = 0;
1899
- let noAssetIdOnChain = 0;
1900
- for (const item of rawState) {
1901
- const key = Buffer.from(item.key, "base64").toString();
1902
- if (key === "yes_asset_id") yesAssetIdOnChain = Number(item.value.uint);
1903
- if (key === "no_asset_id") noAssetIdOnChain = Number(item.value.uint);
1904
- }
1905
- if (yesAssetIdOnChain === 0 && noAssetIdOnChain === 0) continue;
1906
- const existing = positions.get(appId) ?? {
1907
- marketAppId: appId,
1908
- yesAssetId: yesAssetIdOnChain,
1909
- noAssetId: noAssetIdOnChain,
1910
- yesBalance: 0,
1911
- noBalance: 0
1912
- };
1913
- if (assetId === yesAssetIdOnChain) {
1889
+ const assetName = assetInfo.asset?.params?.name ?? "";
1890
+ const unitName = assetInfo.asset?.params?.["unit-name"] ?? "";
1891
+ if (!unitName.startsWith("ALPHA-")) continue;
1892
+ const match = assetName.match(/^Alpha Market (\d+) (Yes|No)$/);
1893
+ if (!match) continue;
1894
+ const marketAppId = Number(match[1]);
1895
+ const side = match[2];
1896
+ const existing = positions.get(marketAppId);
1897
+ if (existing) {
1898
+ if (side === "Yes") {
1914
1899
  existing.yesBalance = amount;
1915
- } else if (assetId === noAssetIdOnChain) {
1916
- existing.noBalance = amount;
1917
1900
  } else {
1901
+ existing.noBalance = amount;
1902
+ }
1903
+ } else {
1904
+ try {
1905
+ const appInfo = await indexerClient.lookupApplications(marketAppId).do();
1906
+ const rawState = appInfo.application?.params?.["global-state"];
1907
+ if (!rawState) continue;
1908
+ let yesAssetIdOnChain = 0;
1909
+ let noAssetIdOnChain = 0;
1910
+ for (const item of rawState) {
1911
+ const key = Buffer.from(item.key, "base64").toString();
1912
+ if (key === "yes_asset_id") yesAssetIdOnChain = Number(item.value.uint);
1913
+ if (key === "no_asset_id") noAssetIdOnChain = Number(item.value.uint);
1914
+ }
1915
+ if (yesAssetIdOnChain === 0 && noAssetIdOnChain === 0) continue;
1916
+ positions.set(marketAppId, {
1917
+ marketAppId,
1918
+ yesAssetId: yesAssetIdOnChain,
1919
+ noAssetId: noAssetIdOnChain,
1920
+ yesBalance: side === "Yes" ? amount : 0,
1921
+ noBalance: side === "No" ? amount : 0
1922
+ });
1923
+ } catch {
1918
1924
  continue;
1919
1925
  }
1920
- positions.set(appId, existing);
1921
- } catch {
1922
- continue;
1923
1926
  }
1924
1927
  } catch {
1925
1928
  continue;
@@ -1930,7 +1933,121 @@ var getPositions = async (config, walletAddress) => {
1930
1933
 
1931
1934
  // src/modules/markets.ts
1932
1935
  var DEFAULT_API_BASE_URL = "https://partners.alphaarcade.com/api";
1933
- var getMarkets = async (config) => {
1936
+ var DEFAULT_MARKET_CREATOR_ADDRESS = "5P5Y6HTWUNG2E3VXBQDZN3ENZD3JPAIR5PKT3LOYJAPAUKOLFD6KANYTRY";
1937
+ var groupMultiChoiceMarkets = (flatMarkets) => {
1938
+ const parentMap = /* @__PURE__ */ new Map();
1939
+ const result = [];
1940
+ for (const m of flatMarkets) {
1941
+ const separatorIdx = m.title.lastIndexOf(" : ");
1942
+ if (separatorIdx === -1) {
1943
+ result.push(m);
1944
+ continue;
1945
+ }
1946
+ const parentTitle = m.title.substring(0, separatorIdx).trim();
1947
+ const optionTitle = m.title.substring(separatorIdx + 3).trim();
1948
+ let parent = parentMap.get(parentTitle);
1949
+ if (!parent) {
1950
+ parent = {
1951
+ id: `group:${parentTitle}`,
1952
+ title: parentTitle,
1953
+ marketAppId: m.marketAppId,
1954
+ // Use first option's app ID as the parent's
1955
+ yesAssetId: 0,
1956
+ noAssetId: 0,
1957
+ endTs: m.endTs,
1958
+ isResolved: m.isResolved,
1959
+ isLive: m.isLive,
1960
+ feeBase: m.feeBase,
1961
+ source: "onchain",
1962
+ options: []
1963
+ };
1964
+ parentMap.set(parentTitle, parent);
1965
+ result.push(parent);
1966
+ }
1967
+ parent.options.push({
1968
+ id: m.id,
1969
+ title: optionTitle,
1970
+ marketAppId: m.marketAppId,
1971
+ yesAssetId: m.yesAssetId,
1972
+ noAssetId: m.noAssetId,
1973
+ yesProb: 0,
1974
+ noProb: 0
1975
+ });
1976
+ }
1977
+ return result;
1978
+ };
1979
+ var getMarketsOnChain = async (config, options) => {
1980
+ const creatorAddress = config.marketCreatorAddress ?? DEFAULT_MARKET_CREATOR_ADDRESS;
1981
+ const activeOnly = options?.activeOnly ?? true;
1982
+ const allApps = [];
1983
+ let nextToken;
1984
+ let hasMore = true;
1985
+ while (hasMore) {
1986
+ let query = config.indexerClient.lookupAccountCreatedApplications(creatorAddress).limit(100);
1987
+ if (nextToken) {
1988
+ query = query.nextToken(nextToken);
1989
+ }
1990
+ const response = await query.do();
1991
+ if (response.applications?.length) {
1992
+ allApps.push(...response.applications);
1993
+ }
1994
+ if (response["next-token"]) {
1995
+ nextToken = response["next-token"];
1996
+ } else {
1997
+ hasMore = false;
1998
+ }
1999
+ }
2000
+ const flatMarkets = [];
2001
+ for (const app of allApps) {
2002
+ if (app.deleted) continue;
2003
+ const rawState = app.params?.["global-state"];
2004
+ if (!rawState) continue;
2005
+ const state = decodeGlobalState(rawState);
2006
+ if (activeOnly && !state.is_activated) continue;
2007
+ if (activeOnly && state.is_resolved) continue;
2008
+ if (activeOnly && state.resolution_time && state.resolution_time < Math.floor(Date.now() / 1e3)) continue;
2009
+ const appId = Number(app.id);
2010
+ flatMarkets.push({
2011
+ id: String(appId),
2012
+ title: state.title || "",
2013
+ marketAppId: appId,
2014
+ yesAssetId: state.yes_asset_id || 0,
2015
+ noAssetId: state.no_asset_id || 0,
2016
+ endTs: state.resolution_time || 0,
2017
+ isResolved: !!state.is_resolved,
2018
+ isLive: !!state.is_activated && !state.is_resolved,
2019
+ feeBase: state.fee_base_percent,
2020
+ source: "onchain"
2021
+ });
2022
+ }
2023
+ return groupMultiChoiceMarkets(flatMarkets);
2024
+ };
2025
+ var getMarketOnChain = async (config, marketAppId) => {
2026
+ try {
2027
+ const appId = typeof marketAppId === "string" ? Number(marketAppId) : marketAppId;
2028
+ const appInfo = await config.algodClient.getApplicationByID(appId).do();
2029
+ const rawState = appInfo.params?.["global-state"] ?? appInfo["params"]?.["global-state"] ?? [];
2030
+ const state = decodeGlobalState(rawState);
2031
+ return {
2032
+ id: String(appId),
2033
+ title: state.title || "",
2034
+ marketAppId: appId,
2035
+ yesAssetId: state.yes_asset_id || 0,
2036
+ noAssetId: state.no_asset_id || 0,
2037
+ endTs: state.resolution_time || 0,
2038
+ isResolved: !!state.is_resolved,
2039
+ isLive: !!state.is_activated && !state.is_resolved,
2040
+ feeBase: state.fee_base_percent,
2041
+ source: "onchain"
2042
+ };
2043
+ } catch {
2044
+ return null;
2045
+ }
2046
+ };
2047
+ var getMarketsFromApi = async (config) => {
2048
+ if (!config.apiKey) {
2049
+ throw new Error("apiKey is required for API-based market fetching. Use getMarketsOnChain() instead, or pass an apiKey.");
2050
+ }
1934
2051
  const baseUrl = config.apiBaseUrl ?? DEFAULT_API_BASE_URL;
1935
2052
  const allMarkets = [];
1936
2053
  let lastEvaluatedKey;
@@ -1947,10 +2064,10 @@ var getMarkets = async (config) => {
1947
2064
  }
1948
2065
  const data = await response.json();
1949
2066
  if (Array.isArray(data)) {
1950
- allMarkets.push(...data);
2067
+ allMarkets.push(...data.map((m) => ({ ...m, source: "api" })));
1951
2068
  hasMore = false;
1952
2069
  } else if (data.markets) {
1953
- allMarkets.push(...data.markets);
2070
+ allMarkets.push(...data.markets.map((m) => ({ ...m, source: "api" })));
1954
2071
  lastEvaluatedKey = data.lastEvaluatedKey;
1955
2072
  hasMore = !!lastEvaluatedKey;
1956
2073
  } else {
@@ -1959,7 +2076,10 @@ var getMarkets = async (config) => {
1959
2076
  }
1960
2077
  return allMarkets;
1961
2078
  };
1962
- var getMarket = async (config, marketId) => {
2079
+ var getMarketFromApi = async (config, marketId) => {
2080
+ if (!config.apiKey) {
2081
+ throw new Error("apiKey is required for API-based market fetching. Use getMarketOnChain() instead, or pass an apiKey.");
2082
+ }
1963
2083
  const baseUrl = config.apiBaseUrl ?? DEFAULT_API_BASE_URL;
1964
2084
  const url = `${baseUrl}/get-market?marketId=${encodeURIComponent(marketId)}`;
1965
2085
  const response = await fetch(url, { headers: { "x-api-key": config.apiKey } });
@@ -1968,7 +2088,21 @@ var getMarket = async (config, marketId) => {
1968
2088
  throw new Error(`Alpha API error: ${response.status} ${response.statusText}`);
1969
2089
  }
1970
2090
  const data = await response.json();
1971
- return data.market ?? data ?? null;
2091
+ const market = data.market ?? data ?? null;
2092
+ if (market) market.source = "api";
2093
+ return market;
2094
+ };
2095
+ var getMarkets = async (config) => {
2096
+ if (config.apiKey) {
2097
+ return getMarketsFromApi(config);
2098
+ }
2099
+ return getMarketsOnChain(config);
2100
+ };
2101
+ var getMarket = async (config, marketId) => {
2102
+ if (config.apiKey) {
2103
+ return getMarketFromApi(config, marketId);
2104
+ }
2105
+ return getMarketOnChain(config, marketId);
1972
2106
  };
1973
2107
 
1974
2108
  // src/client.ts
@@ -1981,7 +2115,6 @@ var AlphaClient = class {
1981
2115
  if (!config.activeAddress) throw new Error("activeAddress is required");
1982
2116
  if (!config.matcherAppId) throw new Error("matcherAppId is required");
1983
2117
  if (!config.usdcAssetId) throw new Error("usdcAssetId is required");
1984
- if (!config.apiKey) throw new Error("apiKey is required");
1985
2118
  this.config = {
1986
2119
  ...config,
1987
2120
  apiBaseUrl: config.apiBaseUrl ?? "https://partners.alphaarcade.com/api"
@@ -2120,9 +2253,10 @@ var AlphaClient = class {
2120
2253
  // Markets
2121
2254
  // ============================================
2122
2255
  /**
2123
- * Fetches all live, tradeable markets from the Alpha API.
2256
+ * Fetches all live, tradeable markets.
2124
2257
  *
2125
- * Automatically paginates to retrieve all markets.
2258
+ * If an API key is configured, uses the Alpha REST API (richer data: images, categories, volume).
2259
+ * Otherwise, discovers markets on-chain from the market creator address (no API key needed).
2126
2260
  *
2127
2261
  * @returns Array of live markets
2128
2262
  */
@@ -2132,14 +2266,57 @@ var AlphaClient = class {
2132
2266
  /**
2133
2267
  * Fetches a single market by its ID.
2134
2268
  *
2135
- * @param marketId - The market ID
2269
+ * If an API key is configured, uses the Alpha REST API.
2270
+ * Otherwise, reads the market's on-chain global state (pass the market app ID as a string).
2271
+ *
2272
+ * @param marketId - The market ID (UUID for API, app ID string for on-chain)
2136
2273
  * @returns The market data, or null if not found
2137
2274
  */
2138
2275
  async getMarket(marketId) {
2139
2276
  return getMarket(this.config, marketId);
2140
2277
  }
2278
+ /**
2279
+ * Fetches all live markets directly from the blockchain (no API key needed).
2280
+ *
2281
+ * Discovers markets by looking up all apps created by the market creator address.
2282
+ * Returns core data: title, asset IDs, resolution time, fees.
2283
+ * Does NOT include images, categories, volume, or probabilities.
2284
+ *
2285
+ * @returns Array of live markets from on-chain data
2286
+ */
2287
+ async getMarketsOnChain() {
2288
+ return getMarketsOnChain(this.config);
2289
+ }
2290
+ /**
2291
+ * Fetches a single market by app ID directly from the blockchain (no API key needed).
2292
+ *
2293
+ * @param marketAppId - The market app ID
2294
+ * @returns The market data, or null if not found
2295
+ */
2296
+ async getMarketOnChain(marketAppId) {
2297
+ return getMarketOnChain(this.config, marketAppId);
2298
+ }
2299
+ /**
2300
+ * Fetches all live markets from the Alpha REST API (requires API key).
2301
+ *
2302
+ * Returns richer data than on-chain: images, categories, volume, probabilities.
2303
+ *
2304
+ * @returns Array of live markets from the API
2305
+ */
2306
+ async getMarketsFromApi() {
2307
+ return getMarketsFromApi(this.config);
2308
+ }
2309
+ /**
2310
+ * Fetches a single market by ID from the Alpha REST API (requires API key).
2311
+ *
2312
+ * @param marketId - The market UUID
2313
+ * @returns The market data, or null if not found
2314
+ */
2315
+ async getMarketFromApi(marketId) {
2316
+ return getMarketFromApi(this.config, marketId);
2317
+ }
2141
2318
  };
2142
2319
 
2143
- export { AlphaClient, calculateFee, calculateFeeFromTotal, calculateMatchingOrders, checkAssetOptIn, decodeGlobalState, getEscrowGlobalState, getMarketGlobalState };
2320
+ export { AlphaClient, DEFAULT_MARKET_CREATOR_ADDRESS, calculateFee, calculateFeeFromTotal, calculateMatchingOrders, checkAssetOptIn, decodeGlobalState, getEscrowGlobalState, getMarketFromApi, getMarketGlobalState, getMarketOnChain, getMarketsFromApi, getMarketsOnChain };
2144
2321
  //# sourceMappingURL=index.js.map
2145
2322
  //# sourceMappingURL=index.js.map