synapsecns/sanguine

View on GitHub
packages/synapse-interface/slices/bridge/reducer.ts

Summary

Maintainability
A
0 mins
Test Coverage
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
import { type Address } from 'viem'

import { type Token } from '@/utils/types'
import {
  getRoutePossibilities,
  getSymbol,
} from '@/utils/routeMaker/generateRoutePossibilities'
import { getFromChainIds } from '@/utils/routeMaker/getFromChainIds'
import { getFromTokens } from '@/utils/routeMaker/getFromTokens'
import { getToChainIds } from '@/utils/routeMaker/getToChainIds'
import { getToTokens } from '@/utils/routeMaker/getToTokens'
import { findTokenByRouteSymbol } from '@/utils/findTokenByRouteSymbol'
import { findValidToken } from '@/utils/findValidToken'

export interface BridgeState {
  fromChainId: number
  fromToken: Token
  toChainId: number
  toToken: Token
  fromChainIds: number[]
  toChainIds: number[]
  fromTokens: Token[]
  toTokens: Token[]

  debouncedFromValue: string
  debouncedToTokensFromValue: string
  deadlineMinutes: number | null
  destinationAddress: Address | null
}

const {
  fromChainId,
  fromToken,
  toChainId,
  toToken,
  fromChainIds,
  fromTokens,
  toChainIds,
  toTokens,
} = getRoutePossibilities({
  fromChainId: null,
  fromToken: null,
  toChainId: null,
  toToken: null,
})

export const initialState: BridgeState = {
  fromChainId,
  fromToken,
  toChainId,
  toToken,
  fromChainIds,
  toChainIds,
  fromTokens,
  toTokens,

  debouncedFromValue: '',
  debouncedToTokensFromValue: '',
  deadlineMinutes: null,
  destinationAddress: null,
}

export const bridgeSlice = createSlice({
  name: 'bridge',
  initialState,
  reducers: {
    setFromChainId: (state, action: PayloadAction<number>) => {
      const incomingFromChainId = action.payload

      const validFromTokens = getFromTokens({
        fromChainId: incomingFromChainId ?? null,
        fromTokenRouteSymbol: state.fromToken?.routeSymbol ?? null,
        toChainId: state.toChainId ?? null,
        toTokenRouteSymbol: null,
      })
        ?.map(getSymbol)
        .map((s) => findTokenByRouteSymbol(s))
        .filter(Boolean)

      const validToChainIds = getToChainIds({
        fromChainId: incomingFromChainId ?? null,
        fromTokenRouteSymbol: null,
        toChainId: state.toChainId ?? null,
        toTokenRouteSymbol: null,
      })

      const validToTokens = getToTokens({
        fromChainId: incomingFromChainId ?? null,
        fromTokenRouteSymbol: state.fromToken?.routeSymbol ?? null,
        toChainId: null,
        toTokenRouteSymbol: null,
      })
        ?.map(getSymbol)
        .map((s) => findTokenByRouteSymbol(s))
        .filter(Boolean)

      let validFromToken
      let validToChainId
      let validToToken

      if (
        validFromTokens?.some(
          (token) => token?.routeSymbol === state.fromToken?.routeSymbol
        )
      ) {
        validFromToken = state.fromToken
      } else {
        validFromToken = findValidToken(
          validFromTokens,
          state.toToken?.routeSymbol,
          state.toToken?.swapableType
        )
      }

      if (
        validToChainIds?.includes(state.toChainId) &&
        incomingFromChainId !== state.toChainId
      ) {
        validToChainId = state.toChainId
      } else {
        validToChainId = null
      }

      if (
        validToTokens?.some(
          (token) => token?.routeSymbol === state.toToken?.routeSymbol
        )
      ) {
        validToToken = state.toToken
      } else {
        validToToken = findValidToken(
          validToTokens,
          state.fromToken?.routeSymbol,
          state.fromToken?.swapableType
        )
      }

      const {
        fromChainId,
        fromToken,
        toChainId,
        toToken,
        fromChainIds,
        fromTokens,
        toChainIds,
        toTokens,
      } = getRoutePossibilities({
        fromChainId: incomingFromChainId,
        fromToken: validFromToken,
        toChainId: validToChainId,
        toToken: validToToken,
      })

      state.fromChainId = fromChainId
      state.fromToken = fromToken
      state.toChainId = toChainId
      state.toToken = toToken
      state.fromChainIds = fromChainIds
      state.fromTokens = fromTokens
      state.toChainIds = toChainIds
      state.toTokens = toTokens
    },
    setFromToken: (state, action: PayloadAction<Token>) => {
      const incomingFromToken = action.payload

      const validFromChainIds = getFromChainIds({
        fromChainId: state.fromChainId ?? null,
        fromTokenRouteSymbol: incomingFromToken?.routeSymbol ?? null,
        toChainId: null,
        toTokenRouteSymbol: null,
      })

      const validToChainIds = getToChainIds({
        fromChainId: state.fromChainId ?? null,
        fromTokenRouteSymbol: incomingFromToken?.routeSymbol ?? null,
        toChainId: null,
        toTokenRouteSymbol: null,
      })

      const validToTokens = getToTokens({
        fromChainId: state.fromChainId ?? null,
        fromTokenRouteSymbol: incomingFromToken?.routeSymbol ?? null,
        toChainId: state.toChainId ?? null,
        toTokenRouteSymbol: null,
      })
        ?.map(getSymbol)
        .map((s) => findTokenByRouteSymbol(s))
        .filter(Boolean)

      let validFromChainId
      let validToChainId
      let validToToken

      if (validFromChainIds?.includes(state.fromChainId)) {
        validFromChainId = state.fromChainId
      } else {
        validFromChainId = null
      }

      if (validToChainIds?.includes(state.toChainId)) {
        validToChainId = state.toChainId
      } else {
        validToChainId = null
      }

      if (
        validToTokens?.some(
          (token) => token?.routeSymbol === state.toToken?.routeSymbol
        )
      ) {
        validToToken = state.toToken
      } else {
        validToToken = findValidToken(
          validToTokens,
          incomingFromToken?.routeSymbol,
          incomingFromToken?.swapableType
        )
      }

      const {
        fromChainId,
        fromToken,
        toChainId,
        toToken,
        fromChainIds,
        fromTokens,
        toChainIds,
        toTokens,
      } = getRoutePossibilities({
        fromChainId: validFromChainId,
        fromToken: incomingFromToken,
        toChainId: validToChainId,
        toToken: validToToken,
      })

      state.fromChainId = fromChainId
      state.fromToken = fromToken
      state.toToken = state.toChainId ? toToken : null
      state.toChainId = toChainId
      state.fromChainIds = fromChainIds
      state.fromTokens = fromTokens
      state.toChainIds = toChainIds
      state.toTokens = toTokens
    },
    setToChainId: (state, action: PayloadAction<number>) => {
      const incomingToChainId = action.payload

      const validFromChainIds = getFromChainIds({
        fromChainId: state.fromChainId ?? null,
        fromTokenRouteSymbol: null,
        toChainId: incomingToChainId ?? null,
        toTokenRouteSymbol: null,
      })

      const validFromTokens = getFromTokens({
        fromChainId: state.fromChainId ?? null,
        fromTokenRouteSymbol: state.fromToken?.routeSymbol ?? null,
        toChainId: incomingToChainId ?? null,
        toTokenRouteSymbol: state.toToken?.routeSymbol ?? null,
      })
        ?.map(getSymbol)
        .map((s) => findTokenByRouteSymbol(s))
        .filter(Boolean)

      const validToTokens = getToTokens({
        fromChainId: state.fromChainId ?? null,
        fromTokenRouteSymbol: state.fromToken?.routeSymbol ?? null,
        toChainId: incomingToChainId ?? null,
        toTokenRouteSymbol: state.toToken?.routeSymbol ?? null,
      })
        ?.map(getSymbol)
        .map((s) => findTokenByRouteSymbol(s))
        .filter(Boolean)

      let validFromChainId
      let validFromToken
      let validToToken

      if (
        validFromChainIds?.includes(state.fromChainId) &&
        incomingToChainId !== state.fromChainId
      ) {
        validFromChainId = state.fromChainId
      } else {
        validFromChainId = null
      }

      if (
        validFromTokens?.some(
          (token) => token?.routeSymbol === state.fromToken?.routeSymbol
        )
      ) {
        validFromToken = state.fromToken
      } else {
        validFromToken = findValidToken(
          validFromTokens,
          state.fromToken?.routeSymbol,
          state.fromToken?.swapableType
        )
      }

      if (
        validToTokens?.some(
          (token) => token?.routeSymbol === state.toToken?.routeSymbol
        )
      ) {
        validToToken = state.toToken
      } else {
        validToToken = findValidToken(
          validToTokens,
          state.fromToken?.routeSymbol,
          state.fromToken?.swapableType
        )
      }

      const {
        fromChainId,
        fromToken,
        toChainId,
        toToken,
        fromChainIds,
        fromTokens,
        toChainIds,
        toTokens,
      } = getRoutePossibilities({
        fromChainId: validFromChainId,
        fromToken: validFromToken,
        toChainId: incomingToChainId,
        toToken: validToToken,
      })

      state.fromChainId = fromChainId
      state.fromToken = fromToken
      state.toChainId = toChainId
      state.toToken = toToken
      state.fromChainIds = fromChainIds
      state.fromTokens = fromTokens
      state.toChainIds = toChainIds
      state.toTokens = toTokens
    },
    setToToken: (state, action: PayloadAction<Token>) => {
      const incomingToToken = action.payload

      const validFromChainIds = getFromChainIds({
        fromChainId: state.fromChainId ?? null,
        fromTokenRouteSymbol: null,
        toChainId: state.toChainId ?? null,
        toTokenRouteSymbol: incomingToToken?.routeSymbol ?? null,
      })

      const validFromTokens = getFromTokens({
        fromChainId: state.fromChainId ?? null,
        fromTokenRouteSymbol: state.fromToken?.routeSymbol ?? null,
        toChainId: state.toChainId ?? null,
        toTokenRouteSymbol: incomingToToken?.routeSymbol ?? null,
      })
        ?.map(getSymbol)
        .map((s) => findTokenByRouteSymbol(s))
        .filter(Boolean)

      const validToChainIds = getToChainIds({
        fromChainId: null,
        fromTokenRouteSymbol: null,
        toChainId: state.toChainId ?? null,
        toTokenRouteSymbol: incomingToToken?.routeSymbol ?? null,
      })

      let validFromChainId
      let validFromToken
      let validToChainId

      if (validFromChainIds?.includes(state.fromChainId)) {
        validFromChainId = state.fromChainId
      } else {
        validFromChainId = null
      }

      if (
        validFromTokens?.some(
          (token) => token?.routeSymbol === state.fromToken?.routeSymbol
        )
      ) {
        validFromToken = state.fromToken
      } else {
        validFromToken = findValidToken(
          validFromTokens,
          incomingToToken?.routeSymbol,
          incomingToToken?.swapableType
        )
      }

      if (validToChainIds?.includes(state.toChainId)) {
        validToChainId = state.toChainId
      } else {
        validToChainId = null
      }

      const {
        fromChainId,
        fromToken,
        toChainId,
        toToken,
        fromChainIds,
        fromTokens,
        toChainIds,
        toTokens,
      } = getRoutePossibilities({
        fromChainId: validFromChainId,
        fromToken: validFromToken,
        toChainId: validToChainId,
        toToken: incomingToToken,
      })

      state.fromChainId = fromChainId
      state.fromToken = fromToken
      state.toChainId = toChainId
      state.toToken = toToken
      state.fromChainIds = fromChainIds
      state.fromTokens = fromTokens
      state.toChainIds = toChainIds
      state.toTokens = toTokens
    },
    updateDebouncedFromValue: (state, action: PayloadAction<string>) => {
      state.debouncedFromValue = action.payload
    },
    updateDebouncedToTokensFromValue: (
      state,
      action: PayloadAction<string>
    ) => {
      state.debouncedToTokensFromValue = action.payload
    },
    setDeadlineMinutes: (state, action: PayloadAction<number | null>) => {
      state.deadlineMinutes = action.payload
    },
    setDestinationAddress: (state, action: PayloadAction<Address | null>) => {
      state.destinationAddress = action.payload
    },
    clearDestinationAddress: (state) => {
      state.destinationAddress = initialState.destinationAddress
    },
    resetBridgeInputs: (state) => {
      state.fromChainId = initialState.fromChainId
      state.fromToken = initialState.fromToken
      state.toChainId = initialState.toChainId
      state.toToken = initialState.toToken
      state.debouncedFromValue = initialState.debouncedFromValue
    },
  },
})

export const {
  updateDebouncedFromValue,
  updateDebouncedToTokensFromValue,
  setFromChainId,
  setToChainId,
  setFromToken,
  setToToken,
  setDeadlineMinutes,
  setDestinationAddress,
  resetBridgeInputs,
  clearDestinationAddress,
} = bridgeSlice.actions

export default bridgeSlice.reducer