The combos channel sends every module, neg-risk, combinatorial, bridge, and migration position event from the BinaryModule, the NegRiskModule, the AutoRedeemer, and the combinatorial market contracts. We decode each one and send it after the transaction is confirmed on-chain.
Plain CTF base-layer moves are on
positions. Settlement events (resolution,
pauses) are on resolution. ERC-1155
transfers are on transfers. Combinatorial
setup (CombinatorialConditionPrepared) is on
lifecycle.
Subscribe
{
"action": "subscribe",
"id": "s1",
"channel": "combos"
}
With no filters, you get every confirmed combos event from all markets.
Filters
| Filter | Type | Required | Description |
|---|
wallets | string[] | No | Hex addresses (0x…). Keeps events where a listed address is a participant. |
market_ids | string[] | No | Condition/market IDs as hex strings. Keeps events for those markets. |
token_ids | string[] | No | Token/position IDs as decimal strings. Keeps events for the listed positions. |
market_ids and token_ids are one axis. min_usd is ignored here. Module and combinatorial events use compact bytes31/bytes29 ids and position ids, so market matching here is coarser than on trading. See Filters for the combination rule.
Events
This channel sends all twenty-five module, combinatorial, bridge, and migration events. See Onchain Data for the part each event plays.
Redemptions
| Event | data.type | Description |
|---|
Redemption | redemption | An AutoRedeemer redemption. Tracks automatic position settlement by position id. |
BinaryRedemption | binary_redemption | A BinaryModule redemption. Tracks binary market position settlement by condition id. |
NegRiskRedemption | neg_risk_redemption | A NegRiskModule redemption. Tracks neg-risk position settlement by condition id. |
PositionRedeemed | position_redeemed | A position redeemed through a module. Carries the initiator, position id, recipient, amount, and payout. |
NegRisk conversions
| Event | data.type | Description |
|---|
CollateralPositionsConverted | collateral_positions_converted | A NegRisk collateral swap between outcome positions. Tracks risk moving across neg-risk structures. |
NegRiskPositionsConverted | neg_risk_positions_converted | A NegRisk position swap at the adapter layer. Tracks risk moving across neg-risk token structures. |
PositionConverted | position_converted | A position converted inside the NegRisk module. Carries the initiator, event id, recipient, condition index, and amount. |
Module position ops
| Event | data.type | Description |
|---|
ModulePositionsMerged | module_positions_merged | Positions merged inside a module. Carries the initiator, condition id, recipient, and amount. |
ModulePositionsSplit | module_positions_split | Positions split inside a module. Carries the initiator, condition id, two recipients, and amount. |
HorizontalMerge | horizontal_merge | A NegRisk horizontal merge across outcomes. Turns a full set of outcome positions back into collateral in an event. |
HorizontalSplit | horizontal_split | A NegRisk horizontal split across outcomes. Turns collateral into a full set of outcome positions in an event. |
Combinatorial
| Event | data.type | Description |
|---|
SplitOnCondition | split_on_condition | A split for just one condition in a combinatorial market. Carries parent and child condition ids and amount. |
MergedOnCondition | merged_on_condition | A merge for just one condition in a combinatorial market. Carries parent and child condition ids and amount. |
ConvertedToYesBasket | converted_to_yes_basket | Positions turned into a yes basket. Carries the user, full condition id, and amount. |
MergedFromYesBasket | merged_from_yes_basket | Positions merged out of a yes basket. Carries the user, full condition id, and amount. |
Extracted | extracted | Positions taken out of a combinatorial structure. Carries the user, full and reduced condition ids, residual condition id, and amount. |
Injected | injected | Positions put into a combinatorial structure. Carries the user, full and reduced condition ids, residual condition id, and amount. |
Compressed | compressed | Positions compressed in the combinatorial module. Combines many positions into one token. |
CombinatorialWrapped | combinatorial_wrapped | Positions wrapped in the combinatorial module. Carries the user, underlying position id, new combinatorial position id, and amount. |
CombinatorialUnwrapped | combinatorial_unwrapped | Positions unwrapped in the combinatorial module. Carries the user, combinatorial position id, underlying position id, and amount. |
Bridge and migration
| Event | data.type | Description |
|---|
PositionMigrated | position_migrated | A position moved across module versions. Carries the sender, condition id, position id, outcome index, and amount. |
MigrationResolved | migration_resolved | A migration resolved. Carries both condition ids, legacy payouts, and v2 result numerators. |
BridgePositionMinted | bridge_position_minted | A bridge position minted. Carries the recipient address, position id, and amount. |
BridgePositionsBurned | bridge_positions_burned | Bridge positions burned on the source side. Carries arrays of position ids and amounts. |
LegacyCollateralSettled | legacy_collateral_settled | Legacy collateral settled during migration. Carries the legacy token, vault address, and amount. |
Payloads
Every frame wraps the event in the standard envelope (type, id, channel, confirmed, data) shown on Frames. Below, each block is the data object for one event — its type discriminator plus every field the ABI decodes. A full frame looks like:
{
"type": "event",
"id": "s1",
"channel": "combos",
"confirmed": true,
"data": {
"type": "neg_risk_redemption",
"from": "0x…",
"conditionId": "0x…",
"…": "…"
}
}
Module events use compact ids: conditionId is bytes31 and eventId is
bytes29 (not the bytes32 used on trading and base-layer channels).
Position ids and amounts are uint256, serialized as 0x… hex.
Redemptions
redemption
Redemption on the AutoRedeemer. An automatic position settlement, keyed by position id.
{ "type": "redemption", "from": "0x…", "positionId": "0x…", "payout": "0x…" }
| Field | Solidity type | Description |
|---|
type | string | redemption. |
from | address (hex) | Address that redeemed the position. |
positionId | uint256 (hex) | Position id redeemed. |
payout | uint256 (hex) | Collateral paid out. |
binary_redemption
BinaryRedemption on the BinaryModule. A binary-market position settled, keyed by condition id.
{
"type": "binary_redemption",
"from": "0x…",
"conditionId": "0x…",
"payout": "0x…"
}
| Field | Solidity type | Description |
|---|
type | string | binary_redemption. |
from | address (hex) | Address that redeemed the position. |
conditionId | bytes32 (hex) | Condition being redeemed. |
payout | uint256 (hex) | Collateral paid out. |
neg_risk_redemption
NegRiskRedemption on the NegRiskModule. A neg-risk position settled, keyed by condition id.
{
"type": "neg_risk_redemption",
"from": "0x…",
"conditionId": "0x…",
"payout": "0x…"
}
| Field | Solidity type | Description |
|---|
type | string | neg_risk_redemption. |
from | address (hex) | Address that redeemed the position. |
conditionId | bytes32 (hex) | Condition being redeemed. |
payout | uint256 (hex) | Collateral paid out. |
position_redeemed
PositionRedeemed on a module. A position redeemed through a module, with the initiator, recipient, and amounts.
{
"type": "position_redeemed",
"initiator": "0x…",
"positionId": "0x…",
"recipient": "0x…",
"amount": "0x…",
"payout": "0x…"
}
| Field | Solidity type | Description |
|---|
type | string | position_redeemed. |
initiator | address (hex) | Address that started the redemption. |
positionId | uint256 (hex) | Position id redeemed. |
recipient | address (hex) | Address that received the payout. |
amount | uint256 (hex) | Position amount redeemed. |
payout | uint256 (hex) | Collateral paid out. |
NegRisk conversions
collateral_positions_converted
PositionsConverted on the NegRiskCtfCollateralAdapter. A collateral swap between outcome positions, with the amount out.
{
"type": "collateral_positions_converted",
"initiator": "0x…",
"marketId": "0x…",
"indexSet": "0x…",
"amount": "0x…",
"amountOut": "0x…"
}
| Field | Solidity type | Description |
|---|
type | string | collateral_positions_converted. |
initiator | address (hex) | Address that converted the positions. |
marketId | bytes32 (hex) | Neg-risk market the conversion is in. |
indexSet | uint256 (hex) | Index set of the outcomes converted. |
amount | uint256 (hex) | Amount converted in. |
amountOut | uint256 (hex) | Amount produced by the conversion. |
neg_risk_positions_converted
PositionsConverted on the NegRiskAdapter. A neg-risk position swap at the adapter layer.
{
"type": "neg_risk_positions_converted",
"stakeholder": "0x…",
"marketId": "0x…",
"indexSet": "0x…",
"amount": "0x…"
}
| Field | Solidity type | Description |
|---|
type | string | neg_risk_positions_converted. |
stakeholder | address (hex) | Address that converted the positions. |
marketId | bytes32 (hex) | Neg-risk market the conversion is in. |
indexSet | uint256 (hex) | Index set of the outcomes converted. |
amount | uint256 (hex) | Amount converted. |
position_converted
PositionConverted on the NegRiskModule. A position converted inside the module, keyed by event id and condition index.
{
"type": "position_converted",
"initiator": "0x…",
"eventId": "0x…",
"recipient": "0x…",
"conditionIndex": "0x…",
"amount": "0x…"
}
| Field | Solidity type | Description |
|---|
type | string | position_converted. |
initiator | address (hex) | Address that converted the position. |
eventId | bytes29 (hex) | Module event the conversion is in. |
recipient | address (hex) | Address that received the result. |
conditionIndex | uint256 (hex) | Index of the condition converted. |
amount | uint256 (hex) | Amount converted. |
Module position ops
module_positions_merged
PositionsMerged on a module. Positions merged inside a module, keyed by condition id.
{
"type": "module_positions_merged",
"initiator": "0x…",
"conditionId": "0x…",
"recipient": "0x…",
"amount": "0x…"
}
| Field | Solidity type | Description |
|---|
type | string | module_positions_merged. |
initiator | address (hex) | Address that merged the positions. |
conditionId | bytes31 (hex) | Module condition id. |
recipient | address (hex) | Address that received the merge. |
amount | uint256 (hex) | Amount merged. |
module_positions_split
PositionsSplit on a module. Positions split inside a module, into two recipients.
{
"type": "module_positions_split",
"initiator": "0x…",
"conditionId": "0x…",
"recipient0": "0x…",
"recipient1": "0x…",
"amount": "0x…"
}
| Field | Solidity type | Description |
|---|
type | string | module_positions_split. |
initiator | address (hex) | Address that split the positions. |
conditionId | bytes31 (hex) | Module condition id. |
recipient0 | address (hex) | First recipient of the split. |
recipient1 | address (hex) | Second recipient of the split. |
amount | uint256 (hex) | Amount split. |
horizontal_merge
HorizontalMerge on the NegRiskModule. A full set of outcome positions merged back into collateral across an event.
{
"type": "horizontal_merge",
"initiator": "0x…",
"eventId": "0x…",
"recipient": "0x…",
"amount": "0x…"
}
| Field | Solidity type | Description |
|---|
type | string | horizontal_merge. |
initiator | address (hex) | Address that merged the positions. |
eventId | bytes29 (hex) | Module event the merge is in. |
recipient | address (hex) | Address that received the merge. |
amount | uint256 (hex) | Amount merged. |
horizontal_split
HorizontalSplit on the NegRiskModule. Collateral split into a full set of outcome positions across an event.
{
"type": "horizontal_split",
"initiator": "0x…",
"eventId": "0x…",
"recipient": "0x…",
"amount": "0x…"
}
| Field | Solidity type | Description |
|---|
type | string | horizontal_split. |
initiator | address (hex) | Address that split the positions. |
eventId | bytes29 (hex) | Module event the split is in. |
recipient | address (hex) | Address that received the split. |
amount | uint256 (hex) | Amount split. |
Combinatorial
split_on_condition
SplitOnCondition on the combinatorial module. A split on one condition inside a combinatorial market.
{
"type": "split_on_condition",
"user": "0x…",
"parentConditionId": "0x…",
"childYesConditionId": "0x…",
"childNoConditionId": "0x…",
"amount": "0x…"
}
| Field | Solidity type | Description |
|---|
type | string | split_on_condition. |
user | address (hex) | Address that split the position. |
parentConditionId | bytes31 (hex) | Parent condition being split. |
childYesConditionId | bytes31 (hex) | Child condition for the yes branch. |
childNoConditionId | bytes31 (hex) | Child condition for the no branch. |
amount | uint256 (hex) | Amount split. |
merged_on_condition
MergedOnCondition on the combinatorial module. A merge on one condition inside a combinatorial market.
{
"type": "merged_on_condition",
"user": "0x…",
"parentConditionId": "0x…",
"childYesConditionId": "0x…",
"childNoConditionId": "0x…",
"amount": "0x…"
}
| Field | Solidity type | Description |
|---|
type | string | merged_on_condition. |
user | address (hex) | Address that merged the position. |
parentConditionId | bytes31 (hex) | Parent condition being merged. |
childYesConditionId | bytes31 (hex) | Child condition for the yes branch. |
childNoConditionId | bytes31 (hex) | Child condition for the no branch. |
amount | uint256 (hex) | Amount merged. |
converted_to_yes_basket
ConvertedToYesBasket on the combinatorial module. Positions turned into a yes basket.
{
"type": "converted_to_yes_basket",
"user": "0x…",
"fullConditionId": "0x…",
"amount": "0x…"
}
| Field | Solidity type | Description |
|---|
type | string | converted_to_yes_basket. |
user | address (hex) | Address that converted the position. |
fullConditionId | bytes31 (hex) | Full combinatorial condition id. |
amount | uint256 (hex) | Amount converted. |
merged_from_yes_basket
MergedFromYesBasket on the combinatorial module. Positions merged out of a yes basket.
{
"type": "merged_from_yes_basket",
"user": "0x…",
"fullConditionId": "0x…",
"amount": "0x…"
}
| Field | Solidity type | Description |
|---|
type | string | merged_from_yes_basket. |
user | address (hex) | Address that merged the position. |
fullConditionId | bytes31 (hex) | Full combinatorial condition id. |
amount | uint256 (hex) | Amount merged. |
Extracted on the combinatorial module. Positions taken out of a combinatorial structure, leaving a residual.
{
"type": "extracted",
"user": "0x…",
"fullConditionId": "0x…",
"reducedConditionId": "0x…",
"residualConditionId": "0x…",
"amount": "0x…"
}
| Field | Solidity type | Description |
|---|
type | string | extracted. |
user | address (hex) | Address that extracted the position. |
fullConditionId | bytes31 (hex) | Full condition before extraction. |
reducedConditionId | bytes31 (hex) | Condition after the extracted leg is removed. |
residualConditionId | bytes31 (hex) | Residual condition left behind. |
amount | uint256 (hex) | Amount extracted. |
injected
Injected on the combinatorial module. Positions put into a combinatorial structure — the inverse of extracted.
{
"type": "injected",
"user": "0x…",
"fullConditionId": "0x…",
"reducedConditionId": "0x…",
"residualConditionId": "0x…",
"amount": "0x…"
}
| Field | Solidity type | Description |
|---|
type | string | injected. |
user | address (hex) | Address that injected the position. |
fullConditionId | bytes31 (hex) | Full condition after injection. |
reducedConditionId | bytes31 (hex) | Condition before the injected leg is added. |
residualConditionId | bytes31 (hex) | Residual condition combined in. |
amount | uint256 (hex) | Amount injected. |
compressed
Compressed on the combinatorial module. Many positions combined into one token.
{
"type": "compressed",
"user": "0x…",
"oldPositionId": "0x…",
"newPositionId": "0x…",
"amount": "0x…",
"positionAmount": "0x…",
"collateralOut": "0x…"
}
| Field | Solidity type | Description |
|---|
type | string | compressed. |
user | address (hex) | Address that compressed the positions. |
oldPositionId | uint256 (hex) | Position id being compressed. |
newPositionId | uint256 (hex) | Resulting compressed position id. |
amount | uint256 (hex) | Amount compressed. |
positionAmount | uint256 (hex) | Resulting position amount. |
collateralOut | uint256 (hex) | Collateral released by the compression. |
combinatorial_wrapped
Wrapped on the combinatorial module. A position wrapped into a combinatorial position token.
{
"type": "combinatorial_wrapped",
"user": "0x…",
"underlyingPositionId": "0x…",
"combinatorialPositionId": "0x…",
"amount": "0x…"
}
| Field | Solidity type | Description |
|---|
type | string | combinatorial_wrapped. |
user | address (hex) | Address that wrapped the position. |
underlyingPositionId | uint256 (hex) | Underlying position id wrapped. |
combinatorialPositionId | uint256 (hex) | Resulting combinatorial position id. |
amount | uint256 (hex) | Amount wrapped. |
combinatorial_unwrapped
Unwrapped on the combinatorial module. A combinatorial position token unwrapped back to its underlying — the inverse of combinatorial_wrapped.
{
"type": "combinatorial_unwrapped",
"user": "0x…",
"combinatorialPositionId": "0x…",
"underlyingPositionId": "0x…",
"amount": "0x…"
}
| Field | Solidity type | Description |
|---|
type | string | combinatorial_unwrapped. |
user | address (hex) | Address that unwrapped the position. |
combinatorialPositionId | uint256 (hex) | Combinatorial position id unwrapped. |
underlyingPositionId | uint256 (hex) | Resulting underlying position id. |
amount | uint256 (hex) | Amount unwrapped. |
Bridge and migration
position_migrated
PositionMigrated on a module. A position moved across module versions.
{
"type": "position_migrated",
"from": "0x…",
"conditionId": "0x…",
"positionId": "0x…",
"outcomeIndex": "0x…",
"amount": "0x…"
}
| Field | Solidity type | Description |
|---|
type | string | position_migrated. |
from | address (hex) | Address whose position migrated. |
conditionId | bytes31 (hex) | Module condition id. |
positionId | uint256 (hex) | Position id migrated. |
outcomeIndex | uint256 (hex) | Outcome index within the condition. |
amount | uint256 (hex) | Amount migrated. |
migration_resolved
MigrationResolved on a module. A migration resolved, with both condition ids, the legacy payouts, and v2 result numerators.
{
"type": "migration_resolved",
"conditionId": "0x…",
"legacyConditionId": "0x…",
"legacyPayout0": "0x…",
"legacyPayout1": "0x…",
"result0": "0x…",
"result1": "0x…"
}
| Field | Solidity type | Description |
|---|
type | string | migration_resolved. |
conditionId | bytes31 (hex) | v2 condition id. |
legacyConditionId | bytes32 (hex) | Matching legacy condition id. |
legacyPayout0 | uint256 (hex) | Legacy payout numerator for outcome 0. |
legacyPayout1 | uint256 (hex) | Legacy payout numerator for outcome 1. |
result0 | uint256 (hex) | v2 result numerator for outcome 0. |
result1 | uint256 (hex) | v2 result numerator for outcome 1. |
bridge_position_minted
BridgePositionMinted on a module. A bridge position minted on the destination side.
{
"type": "bridge_position_minted",
"to": "0x…",
"positionId": "0x…",
"amount": "0x…"
}
| Field | Solidity type | Description |
|---|
type | string | bridge_position_minted. |
to | address (hex) | Address that received the position. |
positionId | uint256 (hex) | Position id minted. |
amount | uint256 (hex) | Amount minted. |
bridge_positions_burned
BridgePositionsBurned on a module. Bridge positions burned on the source side. The positionIds and amounts arrays line up index for index.
{
"type": "bridge_positions_burned",
"positionIds": ["0x…", "0x…"],
"amounts": ["0x…", "0x…"]
}
| Field | Solidity type | Description |
|---|
type | string | bridge_positions_burned. |
positionIds | uint256[] (hex) | Position ids burned. |
amounts | uint256[] (hex) | Amount burned per id, in the same order. |
legacy_collateral_settled
LegacyCollateralSettled on a module. Legacy collateral settled during migration.
{
"type": "legacy_collateral_settled",
"legacyToken": "0x…",
"vault": "0x…",
"amount": "0x…"
}
| Field | Solidity type | Description |
|---|
type | string | legacy_collateral_settled. |
legacyToken | address (hex) | Legacy collateral token settled. |
vault | address (hex) | Vault the collateral settled to. |
amount | uint256 (hex) | Amount settled. |
Pending feed
Set confirmed: false on your subscribe to get the pending feed of this channel — the same payload shape for pending transactions sent to the BinaryModule, NegRiskModule, AutoRedeemer, and combinatorial contracts, before they are in a block. Pending events are guesses. A transaction can be dropped, replaced, or reverted. See Mempool for the full frame shape and how to handle it.
{
"action": "subscribe",
"id": "pending",
"channel": "combos",
"confirmed": false
}