rfunds-online/lib/types.ts

187 lines
5.2 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';
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<FunnelNodeData | OutcomeNodeData | SourceNodeData>
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
}