aggregateGroupFunding
Fold the per-quote funding rows of a group’s children into a single QuoteGroupFunding. Pure, order-independent, no IO — fetch the rows with getQuoteFunding, then hand them to this.
import { aggregateGroupFunding, getQuoteFunding } from "@symmio/trading-core";
const quoteIds = group.quotes.flatMap((quote) => (quote.quoteId === undefined ? [] : [quote.quoteId]));
const { rows } = await getQuoteFunding(config, { quoteIds });
const funding = aggregateGroupFunding(group.quotes, rows);Sign convention
netReceived = received − paid, the P&L perspective every trading venue presents. A positive netReceived means the group has earned funding; a negative one means it has paid for it. This matches QuoteFundingData.netReceived and aggregateGroupUpnl, and is the inverse of the cost-positive on-chain int256.
A UI that renders “green = income” uses the value as-is — no negation anywhere. Every SDK surface that carries funding uses this one convention, and flipping it in one place is how sign bugs get shipped.
Settled to date only
The totals cover funding the protocol has already charged and the analytics subgraph has indexed. Funding accrued since a quote’s last funding charge is not included — it is not indexed anywhere, so it cannot be part of this sum. Label the number accordingly (“funding paid to date”), not as a live accrual.
isComplete is not optional reading
netReceived is always the sum over the children that did resolve — a lower bound while rows are still missing, never suppressed to 0n. isComplete is the flag that tells you whether to trust it:
isComplete: true— every on-chain child produced a row; the amounts are the group’s complete settled-to-date funding.isComplete: false— either the subgraph is still indexing (missingQuoteIdsnon-empty) or the group has no on-chain children at all. Treat this as “funding unknown” and render a loading/partial state; rendering it as “no funding” is wrong.
An all-optimistic group (every child still off-chain) and an empty group both report isComplete: false with netReceived: 0n — which is exactly why the flag exists.
Behaviour
- De-duplicated by
quoteId. The fold runs over the distinct on-chain ids amongquotes, so a quote listed twice contributes its funding once. Duplicate rows for the same id inrowsare likewise counted once (first row wins). - Optimistic children are skipped. A child with no
quoteIdhas nothing to look up, so it neither inflatesexpectedCountnor lands inmissingQuoteIds. - Extra rows are ignored. A row whose
quoteIdis not among the children is never summed — passing a shared, over-fetched row set is safe. - Empty input yields all-zero amounts with
isComplete: false.
Do not substitute Σ UnifiedQuote.accumulatedPaidFunding as a shortcut. That field is the quote’s cumulative funding rate index on-chain (accumulatedRate × epochsSinceStart), not a settled amount — summing it across quotes is dimensionally meaningless, and it is cost-positive where netReceived is income-positive.
Parameters
The group’s child quotes (pass group.quotes). Optimistic children are allowed and are skipped.
rowsreadonly QuoteFundingData[]requiredFunding rows fetched for those quotes — { quoteId, paid, received, netReceived }, all wei. Extras and duplicates are
tolerated.
Returns
The aggregated funding for the group, plus the resolution counters and isComplete.
Related
QuoteGroupFunding— the returned shape, field by field.getQuoteFunding— the batched subgraph read that producesrows.getQuotesEventsByType— the per-tick funding timeline behind the same totals.- React
useQuoteGroupFunding— the hook that runs the read and this fold together.