215 lines
6.1 KiB
TypeScript
215 lines
6.1 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
|
|
}
|
|
}
|
|
|
|
// ─── Funding Sources ────────────────────────────────────────
|
|
|
|
export type FundingSourceType = 'card' | 'crypto_wallet' | 'safe_treasury' | 'bank_transfer' | 'ridentity';
|
|
|
|
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;
|
|
// rIdentity-specific
|
|
encryptIdUserId?: string;
|
|
// Common
|
|
lastUsedAt?: number;
|
|
}
|
|
|
|
// ─── Source Node Types ──────────────────────────────────────
|
|
|
|
export interface SourceAllocation {
|
|
targetId: string
|
|
percentage: number // 0-100
|
|
color: string
|
|
}
|
|
|
|
export interface SourceNodeData {
|
|
label: string
|
|
sourceType: 'card' | 'safe_wallet' | 'ridentity' | 'unconfigured'
|
|
flowRate: number
|
|
targetAllocations: SourceAllocation[]
|
|
// Card-specific
|
|
transakConfig?: { fiatCurrency: string; defaultAmount?: number }
|
|
// Safe/Wallet-specific
|
|
walletAddress?: string
|
|
chainId?: number
|
|
safeAddress?: string
|
|
// rIdentity-specific
|
|
encryptIdUserId?: string
|
|
[key: string]: unknown
|
|
}
|
|
|
|
// ─── Outcome Phase Types ────────────────────────────────────
|
|
|
|
export interface PhaseTask {
|
|
label: string
|
|
completed: boolean
|
|
}
|
|
|
|
export interface OutcomePhase {
|
|
label: string // e.g., "Phase 1: Research"
|
|
fundingThreshold: number // funding level to unlock this phase
|
|
tasks: PhaseTask[]
|
|
}
|
|
|
|
|
|
// ─── 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'
|
|
phases?: OutcomePhase[] // ordered by fundingThreshold ascending
|
|
// Integration metadata
|
|
source?: IntegrationSource
|
|
// Optional detail fields
|
|
completedAt?: number
|
|
milestones?: Array<{ label: string; completedAt?: number }>
|
|
[key: string]: unknown
|
|
}
|
|
|
|
export type FlowNode = Node<FunnelNodeData | OutcomeNodeData | SourceNodeData>
|
|
|
|
export interface AllocationEdgeData {
|
|
allocation: number // percentage 0-100
|
|
color: string
|
|
edgeType: 'overflow' | 'spending' | 'source' // overflow = sideways, spending = downward, source = top-down from source
|
|
sourceId: string
|
|
targetId: string
|
|
siblingCount: number // how many allocations in this group
|
|
onAdjust?: (sourceId: string, targetId: string, edgeType: 'overflow' | 'spending' | 'source', 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
|
|
}
|