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 } } // ─── Funding Sources ──────────────────────────────────────── export type FundingSourceType = 'card' | 'crypto_wallet' | 'safe_treasury' | 'bank_transfer'; export interface FundingSource { id: string; type: FundingSourceType; label: string; enabled: boolean; // Card/bank-specific transakConfig?: { fiatCurrency: string; defaultAmount?: number; }; // Crypto wallet-specific walletAddress?: string; chainId?: number; tokenAddress?: string; // Safe treasury-specific safeAddress?: string; safeChainId?: number; // Common lastUsedAt?: number; } // ─── Source Node Types ─────────────────────────────────────── export interface SourceAllocation { targetId: string percentage: number // 0-100 color: string } export interface SourceNodeData { label: string flowRate: number // tokens per month flowing out sourceType: 'recurring' | 'one-time' | 'treasury' targetAllocations: SourceAllocation[] [key: string]: unknown } // ─── 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 type SufficiencyState = 'seeking' | 'sufficient' | 'abundant' export interface FunnelNodeData { label: string currentValue: number minThreshold: number maxThreshold: number maxCapacity: number inflowRate: number // Sufficiency layer sufficientThreshold?: number // level at which funnel has "enough" (defaults to maxThreshold) dynamicOverflow?: boolean // when true, overflow routes by need instead of fixed % // Overflow goes SIDEWAYS to other funnels overflowAllocations: OverflowAllocation[] // Spending goes DOWN to outcomes/outputs spendingAllocations: SpendingAllocation[] // Integration metadata source?: IntegrationSource streamAllocations?: StreamAllocation[] splitsConfig?: SplitsConfig fundingSources?: FundingSource[] [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 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 // Serializable space config (no xyflow internals) export interface SpaceConfig { name: string nodes: FlowNode[] integrations?: IntegrationConfig createdAt: number updatedAt: number }