Skip to content

track prediction markets' notional volume#5764

Draft
bheluga wants to merge 4 commits intoDefiLlama:masterfrom
bheluga:pm-notional
Draft

track prediction markets' notional volume#5764
bheluga wants to merge 4 commits intoDefiLlama:masterfrom
bheluga:pm-notional

Conversation

@bheluga
Copy link
Member

@bheluga bheluga commented Jan 29, 2026

Summary by CodeRabbit

  • New Features
    • Added notional volume tracking across multiple prediction and trading platforms, including Kalshi, Limitless Exchange, Opinion, PancakeSwap Prediction, Polymarket, and others.
    • Notional volume now reported alongside standard volume metrics for enhanced data visibility.

✏️ Tip: You can customize this high-level summary in your review settings.

@bheluga bheluga marked this pull request as draft January 29, 2026 14:26
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 29, 2026

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

  • 🔍 Trigger a full review
📝 Walkthrough

Walkthrough

This PR introduces dailyNotionalVolume tracking across multiple DEX and prediction market adapters. Changes include adding notional volume computation in SQL queries, initializing new balance trackers, and updating return types across adapters and helper functions. Several adapters also modify fetch signatures and downgrade version numbers.

Changes

Cohort / File(s) Summary
Polymarket Ecosystem
helpers/polymarket.ts, dexs/polymarket/index.ts, dexs/predict-fun/index.ts, dexs/probable.ts
Updated getPolymarketVolume to return FetchResult with both dailyVolume and dailyNotionalVolume. Adapters consuming this helper now fetch and return both fields. Fetch signatures broadened to accept unused parameters (_a, _b) and adapter versions downgraded from 2 to 1 with performance comments.
Prediction & Option Markets
dexs/pancakeswap-prediction/index.ts, dexs/opinion/index.ts, dexs/limitless-exchange/index.ts, dexs/rain-one/index.ts
Added dailyNotionalVolume balance initialization and event log processing to accumulate notional volume metrics. PancakeSwap uses epoch-based bull/bear amounts; others compute from trade amounts or outcome tokens. Limitless-exchange also removes version: 2 declaration and extends fetch signature.
SQL-Based Adapters
dexs/kalshi.ts, fees/myriadmarkets/index.ts
Extended SQL queries or log parsing to compute and track notional_volume or shares fields. Updated return objects to include dailyNotionalVolume balances initialized from these computed values.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • g1nt0ki

Poem

🐰 A notional whisper through the trades so swift,
Volume shadows dancing, a mathematical gift,
Across all the markets, from Polymarket's call,
Notional volume now tracked, we capture it all!

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description check ⚠️ Warning No pull request description was provided by the author, but the template requires substantial information for new protocol listings. Provide a description explaining the changes: why notional volume tracking was added, which markets/adapters are affected, and any testing performed.
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main objective: tracking notional volume for prediction markets across multiple adapters.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@llamabutler
Copy link

The kalshi.ts adapter exports:

> adapters@1.0.0 test
> ts-node --transpile-only cli/testAdapter.ts dexs kalshi.ts

🦙 Running KALSHI.TS adapter 🦙
---------------------------------------------------
Start Date:	Wed, 28 Jan 2026 00:00:00 GMT
End Date:	Thu, 29 Jan 2026 00:00:00 GMT
---------------------------------------------------

------ ERROR ------
Error: Request failed with status code 401
    at _queryDune (/home/runner/work/dimension-adapters/dimension-adapters/helpers/dune.ts:219:22)
    at processTicksAndRejections (node:internal/process/task_queues:95:5)
Request failed with status code 401

@bheluga bheluga changed the title track prediction market notional volume track prediction markets' notional volume Jan 29, 2026
@bheluga bheluga self-assigned this Jan 29, 2026
@llamabutler
Copy link

The kalshi.ts adapter exports:

> adapters@1.0.0 test
> ts-node --transpile-only cli/testAdapter.ts dexs kalshi.ts

🦙 Running KALSHI.TS adapter 🦙
---------------------------------------------------
Start Date:	Wed, 28 Jan 2026 00:00:00 GMT
End Date:	Thu, 29 Jan 2026 00:00:00 GMT
---------------------------------------------------

------ ERROR ------
Error: Request failed with status code 401
    at _queryDune (/home/runner/work/dimension-adapters/dimension-adapters/helpers/dune.ts:219:22)
    at processTicksAndRejections (node:internal/process/task_queues:95:5)
Request failed with status code 401

@llamabutler
Copy link

The kalshi.ts adapter exports:

> adapters@1.0.0 test
> ts-node --transpile-only cli/testAdapter.ts dexs kalshi.ts

🦙 Running KALSHI.TS adapter 🦙
---------------------------------------------------
Start Date:	Thu, 29 Jan 2026 00:00:00 GMT
End Date:	Fri, 30 Jan 2026 00:00:00 GMT
---------------------------------------------------

------ ERROR ------
Error: Request failed with status code 401
    at _queryDune (/home/runner/work/dimension-adapters/dimension-adapters/helpers/dune.ts:219:22)
    at processTicksAndRejections (node:internal/process/task_queues:95:5)
Request failed with status code 401

@bheluga bheluga marked this pull request as ready for review January 30, 2026 15:57
@g1nt0ki g1nt0ki marked this pull request as draft January 30, 2026 15:59
@g1nt0ki
Copy link
Member

g1nt0ki commented Jan 30, 2026

need to update server repo to handle notional volume per category

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
dexs/pancakeswap-prediction/index.ts (1)

17-43: ⚠️ Potential issue | 🟠 Major

Normalize epoch keys to avoid mismatched bull/bear aggregation.
epochData is typed as Map<number,…> but bet.epoch is likely a BigNumber/bigint/string. If it’s a non-number, bull/bear entries won’t collide and notional will be undercounted. Normalize the key.

Proposed fix
-    const epochData: Map<number, { bullAmount: bigint; bearAmount: bigint }> = new Map();
+    const epochData: Map<string, { bullAmount: bigint; bearAmount: bigint }> = new Map();

     bullLogs.forEach(bet => {
         dailyVolume.add(ADDRESSES.bsc.WBNB, bet.amount);
-        const epoch = bet.epoch;
+        const epoch = bet.epoch.toString();
         const data = epochData.get(epoch) || { bullAmount: 0n, bearAmount: 0n };
         data.bullAmount += BigInt(bet.amount);
         epochData.set(epoch, data);
     });

     bearLogs.forEach(bet => {
         dailyVolume.add(ADDRESSES.bsc.WBNB, bet.amount);
-        const epoch = bet.epoch;
+        const epoch = bet.epoch.toString();
         const data = epochData.get(epoch) || { bullAmount: 0n, bearAmount: 0n };
         data.bearAmount += BigInt(bet.amount);
         epochData.set(epoch, data);
     });
dexs/rain-one/index.ts (1)

14-70: ⚠️ Potential issue | 🟠 Major

Map optionAmount to the correct token or exclude from collateral-denominated notional volume.

optionAmount represents option position units (shares), not collateral amounts. Adding it to dailyNotionalVolume with tokenInfo.token (the collateral) causes incorrect scaling. Either:

  • Map optionAmount to the option-token address with its decimals, or
  • Track option volume separately if Rain protocol doesn't expose option token decimals

Current code assumes both baseAmount and optionAmount use the same token/decimals, which is incorrect per Rain's protocol semantics.

🤖 Fix all issues with AI agents
In `@dexs/polymarket/index.ts`:
- Around line 109-116: Guard against null/undefined Dune totals by defaulting to
0 before dividing and calling addUSDValue: when updating dailyVolume and
dailyNotionalVolume, coalesce data[0].total_volume_usd and
data[0].total_notional_volume to 0 (e.g., via a nullish check) before dividing
by 2 and passing to addUSDValue so NaN cannot be produced; update the sites
where dailyVolume.addUSDValue(...) and dailyNotionalVolume.addUSDValue(...) are
called to use the safe default values instead.

In `@fees/myriadmarkets/index.ts`:
- Around line 27-31: The forEach callback for building marketMapping currently
uses an expression body which implicitly returns a value; change the arrow to
use a block body so it does not return anything. Specifically, update the
markets.forEach((val:any, idx:any) => marketMapping[val] = { token:
marketData[idx].token, fees: marketFees[idx] }) to markets.forEach((val:any,
idx:any) => { marketMapping[val] = { token: marketData[idx].token, fees:
marketFees[idx] }; }); keeping the same identifiers (marketMapping, markets,
marketData, marketFees) and types.
🧹 Nitpick comments (1)
dexs/kalshi.ts (1)

9-40: Dune 401 in CI — verify credentials or add a graceful fallback.
The adapter test is failing with “401 Unauthorized” from Dune. Please confirm the CI secrets for Dune are configured for this repo/branch and the query has access, or add a clearer error/fallback so tests don’t hard-fail when auth is missing.

Comment on lines 109 to 116
const dailyVolume = options.createBalances();
const dailyNotionalVolume = options.createBalances();

// Polymarket emits two OrderFilled events per trade (maker + taker), so summing them directly double-counts volume. Dividing by 2 converts this into true one-sided volume. This also normalizes swaps and merge/split fills, where maker and taker amounts can differ but still represent the same underlying trade, preventing inflated totals

dailyVolume.addUSDValue(data[0].total_volume_usd / 2);
dailyNotionalVolume.addUSDValue(data[0].total_notional_volume/2);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Guard against null/undefined totals from Dune.
If total_volume_usd or total_notional_volume is null/undefined for a day, the current division yields NaN. Consider defaulting to 0 before addUSDValue.

Proposed fix
-  dailyVolume.addUSDValue(data[0].total_volume_usd / 2);
-  dailyNotionalVolume.addUSDValue(data[0].total_notional_volume/2);
+  const totalVolume = Number(data[0]?.total_volume_usd) || 0;
+  const totalNotional = Number(data[0]?.total_notional_volume) || 0;
+  dailyVolume.addUSDValue(totalVolume / 2);
+  dailyNotionalVolume.addUSDValue(totalNotional / 2);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const dailyVolume = options.createBalances();
const dailyNotionalVolume = options.createBalances();
// Polymarket emits two OrderFilled events per trade (maker + taker), so summing them directly double-counts volume. Dividing by 2 converts this into true one-sided volume. This also normalizes swaps and merge/split fills, where maker and taker amounts can differ but still represent the same underlying trade, preventing inflated totals
dailyVolume.addUSDValue(data[0].total_volume_usd / 2);
dailyNotionalVolume.addUSDValue(data[0].total_notional_volume/2);
const dailyVolume = options.createBalances();
const dailyNotionalVolume = options.createBalances();
// Polymarket emits two OrderFilled events per trade (maker + taker), so summing them directly double-counts volume. Dividing by 2 converts this into true one-sided volume. This also normalizes swaps and merge/split fills, where maker and taker amounts can differ but still represent the same underlying trade, preventing inflated totals
const totalVolume = Number(data[0]?.total_volume_usd) || 0;
const totalNotional = Number(data[0]?.total_notional_volume) || 0;
dailyVolume.addUSDValue(totalVolume / 2);
dailyNotionalVolume.addUSDValue(totalNotional / 2);
🤖 Prompt for AI Agents
In `@dexs/polymarket/index.ts` around lines 109 - 116, Guard against
null/undefined Dune totals by defaulting to 0 before dividing and calling
addUSDValue: when updating dailyVolume and dailyNotionalVolume, coalesce
data[0].total_volume_usd and data[0].total_notional_volume to 0 (e.g., via a
nullish check) before dividing by 2 and passing to addUSDValue so NaN cannot be
produced; update the sites where dailyVolume.addUSDValue(...) and
dailyNotionalVolume.addUSDValue(...) are called to use the safe default values
instead.

Comment on lines 27 to 31
const marketMapping: any = {}
markets.forEach((val, idx) => marketMapping[val] = {
markets.forEach((val:any, idx:any) => marketMapping[val] = {
token: marketData[idx].token,
fees: marketFees[idx]
})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find the file
fd -t f "index.ts" | grep -E "fees.*myriadmarkets"

Repository: DefiLlama/dimension-adapters

Length of output: 99


🏁 Script executed:

#!/bin/bash
# Check if the file exists and read the relevant lines
if [ -f "fees/myriadmarkets/index.ts" ]; then
  echo "File exists. Reading lines 20-35 for context:"
  sed -n '20,35p' fees/myriadmarkets/index.ts | cat -n
else
  echo "File not found at fees/myriadmarkets/index.ts. Searching..."
  find . -name "index.ts" -path "*myriad*" 2>/dev/null
fi

Repository: DefiLlama/dimension-adapters

Length of output: 913


🏁 Script executed:

#!/bin/bash
# Check for biome configuration
ls -la | grep -i biome || echo "No biome config in root"
find . -name "biome.json" -o -name "biome.toml" 2>/dev/null | head -5

Repository: DefiLlama/dimension-adapters

Length of output: 148


🏁 Script executed:

#!/bin/bash
# Read the biome configuration
cat biome.json

Repository: DefiLlama/dimension-adapters

Length of output: 1847


🌐 Web query:

Biome forEach arrow function return statement lint rule

💡 Result:

Biome’s lint rule for “return statements inside forEach callbacks” is:

  • lint/suspicious/useIterableCallbackReturn (recommended / on by default since Biome v2.0.0) (biomejs.dev)

What it enforces:

  • For methods like map, filter, find, etc., the callback must consistently return a value. (biomejs.dev)
  • For forEach, a return value is disallowed (because forEach ignores returned values). (biomejs.dev)

Example that triggers it:

arr.forEach(() => {
  return 1; // flagged: should not return a value
});

(biomejs.dev)

Fix patterns:

  • Remove the returned value (or the return entirely), or if you need an early-exit style, use a loop (for...of) instead. (biomejs.dev)

Config:

{
  "linter": {
    "rules": {
      "suspicious": {
        "useIterableCallbackReturn": "error"
      }
    }
  }
}

(biomejs.dev)

Citations:


Fix forEach callback to satisfy useIterableCallbackReturn lint.
Line 9 uses an expression body that implicitly returns a value from forEach. Biome's useIterableCallbackReturn rule flags this since forEach ignores returned values. Switch to a block body to avoid the implicit return.

Proposed fix
-  markets.forEach((val:any, idx:any) => marketMapping[val] = {
-    token: marketData[idx].token,
-    fees: marketFees[idx]
-  })
+  markets.forEach((val: any, idx: any) => {
+    marketMapping[val] = {
+      token: marketData[idx].token,
+      fees: marketFees[idx],
+    }
+  })
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const marketMapping: any = {}
markets.forEach((val, idx) => marketMapping[val] = {
markets.forEach((val:any, idx:any) => marketMapping[val] = {
token: marketData[idx].token,
fees: marketFees[idx]
})
const marketMapping: any = {}
markets.forEach((val: any, idx: any) => {
marketMapping[val] = {
token: marketData[idx].token,
fees: marketFees[idx],
}
})
🧰 Tools
🪛 Biome (2.3.13)

[error] 28-28: This callback passed to forEach() iterable method should not return a value.

Either remove this return or remove the returned value.

(lint/suspicious/useIterableCallbackReturn)

🤖 Prompt for AI Agents
In `@fees/myriadmarkets/index.ts` around lines 27 - 31, The forEach callback for
building marketMapping currently uses an expression body which implicitly
returns a value; change the arrow to use a block body so it does not return
anything. Specifically, update the markets.forEach((val:any, idx:any) =>
marketMapping[val] = { token: marketData[idx].token, fees: marketFees[idx] }) to
markets.forEach((val:any, idx:any) => { marketMapping[val] = { token:
marketData[idx].token, fees: marketFees[idx] }; }); keeping the same identifiers
(marketMapping, markets, marketData, marketFees) and types.

@llamabutler
Copy link

The kalshi.ts adapter exports:

> adapters@1.0.0 test
> ts-node --transpile-only cli/testAdapter.ts dexs kalshi.ts

🦙 Running KALSHI.TS adapter 🦙
---------------------------------------------------
Start Date:	Thu, 29 Jan 2026 00:00:00 GMT
End Date:	Fri, 30 Jan 2026 00:00:00 GMT
---------------------------------------------------

------ ERROR ------
Error: Request failed with status code 401
    at _queryDune (/home/runner/work/dimension-adapters/dimension-adapters/helpers/dune.ts:219:22)
    at processTicksAndRejections (node:internal/process/task_queues:95:5)
Request failed with status code 401

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants