140 lines
3.8 KiB
TypeScript
140 lines
3.8 KiB
TypeScript
import type { Node, Edge } from '@xyflow/react'
|
|
|
|
// ─── Integration Source Metadata ─────────────────────────────
|
|
|
|
export interface IntegrationSource {
|
|
type: 'rvote' | 'safe' | 'manual'
|
|
// Safe fields
|
|
safeAddress?: string
|
|
safeChainId?: number
|
|
tokenAddress?: string | null // null = native token
|
|
tokenSymbol?: string
|
|
tokenDecimals?: number
|
|
// rVote fields
|
|
rvoteSpaceSlug?: string
|
|
rvoteProposalId?: string
|
|
rvoteProposalStatus?: string
|
|
rvoteProposalScore?: number
|
|
lastFetchedAt?: number
|
|
}
|
|
|
|
// ─── Superfluid Stream (planning only) ───────────────────────
|
|
|
|
export interface StreamAllocation {
|
|
targetId: string
|
|
flowRate: number // tokens per month
|
|
tokenSymbol: string // e.g., 'DAIx', 'USDCx'
|
|
tokenAddress?: string
|
|
status: 'planned' | 'active' | 'paused'
|
|
color: string
|
|
}
|
|
|
|
// ─── 0xSplits Configuration (planning only) ──────────────────
|
|
|
|
export interface SplitRecipient {
|
|
address: string
|
|
label?: string
|
|
percentage: number // 0-100, must sum to 100
|
|
}
|
|
|
|
export interface SplitsConfig {
|
|
recipients: SplitRecipient[]
|
|
distributorFee: number // 0-10%
|
|
chainId: number
|
|
}
|
|
|
|
// ─── Integration Config (persisted per space) ────────────────
|
|
|
|
export interface IntegrationConfig {
|
|
rvote?: {
|
|
spaceSlug: string
|
|
spaceName?: string
|
|
lastSyncedAt?: number
|
|
}
|
|
safe?: {
|
|
address: string
|
|
chainIds: number[] // e.g., [100, 10] for Gnosis + Optimism
|
|
lastSyncedAt?: number
|
|
}
|
|
}
|
|
|
|
// ─── Core Flow Types ─────────────────────────────────────────
|
|
|
|
// Overflow allocation - funds flowing to OTHER FUNNELS when above max threshold
|
|
export interface OverflowAllocation {
|
|
targetId: string
|
|
percentage: number // 0-100
|
|
color: string
|
|
}
|
|
|
|
// Spending allocation - funds flowing DOWN to OUTCOMES/OUTPUTS
|
|
export interface SpendingAllocation {
|
|
targetId: string
|
|
percentage: number // 0-100
|
|
color: string
|
|
}
|
|
|
|
export interface FunnelNodeData {
|
|
label: string
|
|
currentValue: number
|
|
minThreshold: number
|
|
maxThreshold: number
|
|
maxCapacity: number
|
|
inflowRate: number
|
|
// Overflow goes SIDEWAYS to other funnels
|
|
overflowAllocations: OverflowAllocation[]
|
|
// Spending goes DOWN to outcomes/outputs
|
|
spendingAllocations: SpendingAllocation[]
|
|
// Integration metadata
|
|
source?: IntegrationSource
|
|
streamAllocations?: StreamAllocation[]
|
|
splitsConfig?: SplitsConfig
|
|
[key: string]: unknown
|
|
}
|
|
|
|
export interface OutcomeNodeData {
|
|
label: string
|
|
description?: string
|
|
fundingReceived: number
|
|
fundingTarget: number
|
|
status: 'not-started' | 'in-progress' | 'completed' | 'blocked'
|
|
// Integration metadata
|
|
source?: IntegrationSource
|
|
[key: string]: unknown
|
|
}
|
|
|
|
export type FlowNode = Node<FunnelNodeData | OutcomeNodeData>
|
|
|
|
export interface AllocationEdgeData {
|
|
allocation: number // percentage 0-100
|
|
color: string
|
|
edgeType: 'overflow' | 'spending' // overflow = sideways, spending = downward
|
|
sourceId: string
|
|
targetId: string
|
|
siblingCount: number // how many allocations in this group
|
|
onAdjust?: (sourceId: string, targetId: string, edgeType: 'overflow' | 'spending', delta: number) => void
|
|
[key: string]: unknown
|
|
}
|
|
|
|
export interface StreamEdgeData {
|
|
flowRate: number
|
|
tokenSymbol: string
|
|
status: 'planned' | 'active' | 'paused'
|
|
sourceId: string
|
|
targetId: string
|
|
[key: string]: unknown
|
|
}
|
|
|
|
export type FlowEdgeData = AllocationEdgeData | StreamEdgeData
|
|
|
|
export type FlowEdge = Edge<FlowEdgeData>
|
|
|
|
// Serializable space config (no xyflow internals)
|
|
export interface SpaceConfig {
|
|
name: string
|
|
nodes: FlowNode[]
|
|
integrations?: IntegrationConfig
|
|
createdAt: number
|
|
updatedAt: number
|
|
}
|