@0xsplits/splits-sdk
Version:
SDK for the 0xSplits protocol
287 lines (267 loc) • 7.47 kB
text/typescript
import { gql } from '@urql/core'
import {
formatGqlContractEarnings,
formatInternalTokenBalances,
formatTokenBalances,
} from './token'
import {
GqlOracle,
GqlSwapBalance,
GqlSwapper,
IChainlinkPairDetails,
IOracle,
ISwapBalance,
ISwapper,
ISwapperScaledOfferFactorOverrides,
IUniswapV3TWAPPairDetails,
} from './types'
import { getAddress, zeroAddress } from 'viem'
import { ZERO } from '../constants'
import { SupportedChainId } from './constants'
import { getSwapBalanceId } from '../utils'
import { Swapper } from '../types'
const UNISWAP_V3_TWAP_ORACLE_FIELDS_FRAGMENT = gql`
fragment UniswapV3TwapOracleFieldsFragment on UniswapV3TWAPOracle {
paused
defaultPeriod
pairDetails {
base {
id
}
quote {
id
}
pool
fee
period
}
}
`
const CHAINLINK_ORACLE_FIELDS_FRAGMENT = gql`
fragment ChainlinkOracleFieldsFragment on ChainlinkOracle {
paused
sequencerFeed
chainlinkPairDetails {
base {
id
}
quote {
id
}
inverted
feeds {
aggregatorV3
decimals
staleAfter
mul
}
}
}
`
export const ORACLE_FIELDS_FRAGMENT = gql`
fragment OracleFieldsFragment on Oracle {
id
type
... on UniswapV3TWAPOracle {
...UniswapV3TwapOracleFieldsFragment
}
... on ChainlinkOracle {
...ChainlinkOracleFieldsFragment
}
}
${UNISWAP_V3_TWAP_ORACLE_FIELDS_FRAGMENT}
${CHAINLINK_ORACLE_FIELDS_FRAGMENT}
`
const SWAP_BALANCE_FIELDS_FRAGMENT = gql`
fragment SwapBalanceFieldsFragment on SwapBalance {
inputToken {
id
}
inputAmount
outputToken {
id
}
outputAmount
}
`
export const SWAPPER_FIELDS_FRAGMENT = gql`
fragment SwapperFieldsFragment on Swapper {
owner {
id
}
paused
beneficiary {
id
}
tokenToBeneficiary {
id
}
oracle {
...OracleFieldsFragment
}
defaultScaledOfferFactor
scaledOfferFactorPairOverrides {
base {
id
}
quote {
id
}
scaledOfferFactor
}
swapperSwapBalances: swapBalances {
...SwapBalanceFieldsFragment
}
}
${ORACLE_FIELDS_FRAGMENT}
${SWAP_BALANCE_FIELDS_FRAGMENT}
`
export const formatGqlOracle: (arg0: GqlOracle) => IOracle = (gqlOracle) => {
if (gqlOracle.type === 'uniswapV3TWAP')
return {
address: getAddress(gqlOracle.id),
type: gqlOracle.type,
defaultPeriod: parseInt(gqlOracle.defaultPeriod),
pairDetails: gqlOracle.pairDetails?.reduce((acc, pairDetail) => {
const base = getAddress(pairDetail.base.id)
const quote = getAddress(pairDetail.quote.id)
const pairId = getSwapBalanceId(base, quote)
acc[pairId] = {
base,
quote,
pool: getAddress(pairDetail.pool),
fee: pairDetail.fee,
period: parseInt(pairDetail.period),
}
const reversePairId = getSwapBalanceId(quote, base)
acc[reversePairId] = {
base: quote,
quote: base,
pool: getAddress(pairDetail.pool),
fee: pairDetail.fee,
period: parseInt(pairDetail.period),
}
return acc
}, {} as IUniswapV3TWAPPairDetails),
}
else if (gqlOracle.type === 'chainlink')
return {
address: getAddress(gqlOracle.id),
type: gqlOracle.type,
chainlinkPairDetails: gqlOracle.chainlinkPairDetails.reduce(
(acc, pairDetail) => {
const base = getAddress(pairDetail.base.id)
const quote = getAddress(pairDetail.quote.id)
const pairId = getSwapBalanceId(base, quote)
acc[pairId] = {
base,
quote,
}
return acc
},
{} as IChainlinkPairDetails,
),
}
return {
address: getAddress(gqlOracle.id),
type: gqlOracle.type,
}
}
const formatSwapBalances: (arg0: GqlSwapBalance[]) => ISwapBalance = (
gqlSwapBalances,
) => {
return gqlSwapBalances.reduce((acc, swapBalance) => {
const inputToken = getAddress(swapBalance.inputToken.id)
const outputToken = getAddress(swapBalance.outputToken.id)
const inputAmount = BigInt(swapBalance.inputAmount)
const outputAmount = BigInt(swapBalance.outputAmount)
const swapBalanceId = getSwapBalanceId(inputToken, outputToken)
acc[swapBalanceId] = acc[swapBalanceId] ?? {
inputAmount: ZERO,
outputAmount: ZERO,
}
acc[swapBalanceId].inputAmount =
acc[swapBalanceId].inputAmount + inputAmount
acc[swapBalanceId].outputAmount =
acc[swapBalanceId].outputAmount + outputAmount
return acc
}, {} as ISwapBalance)
}
export const formatGqlSwapper: (arg0: GqlSwapper) => ISwapper = (
gqlSwapper,
) => {
return {
type: 'swapper',
address: getAddress(gqlSwapper.id),
chainId: parseInt(gqlSwapper.chainId) as SupportedChainId,
distributions: formatTokenBalances(gqlSwapper.distributions),
balances: {},
balanceQuoteAmounts: {},
splitmainBalances: formatInternalTokenBalances(gqlSwapper.internalBalances),
warehouseBalances: formatInternalTokenBalances(
gqlSwapper.warehouseBalances,
),
latestBlock: gqlSwapper.latestBlock,
latestActivity: parseInt(gqlSwapper.latestActivity),
parentEntityType: gqlSwapper.parentEntityType,
owner: getAddress(gqlSwapper.owner.id),
beneficiary: getAddress(gqlSwapper.beneficiary.id),
tokenToBeneficiary: getAddress(gqlSwapper.tokenToBeneficiary.id),
oracle: formatGqlOracle(gqlSwapper.oracle),
paused: gqlSwapper.paused,
defaultScaledOfferFactor: parseInt(gqlSwapper.defaultScaledOfferFactor),
scaledOfferFactorOverrides:
gqlSwapper.scaledOfferFactorPairOverrides.reduce((acc, override) => {
const base = getAddress(override.base.id)
const quote = getAddress(override.quote.id)
const pair = `${base}-${quote}`
acc[pair] = {
base,
quote,
scaledOfferFactor: parseInt(override.scaledOfferFactor),
}
return acc
}, {} as ISwapperScaledOfferFactorOverrides),
swapBalances: formatSwapBalances(gqlSwapper.swapperSwapBalances),
contractEarnings: formatGqlContractEarnings(gqlSwapper.contractEarnings),
}
}
export const protectedFormatSwapper = (gqlSwapper: ISwapper): Swapper => {
return {
type: 'Swapper',
address: gqlSwapper.address,
beneficiary: {
address: gqlSwapper.beneficiary,
},
tokenToBeneficiary: {
address: gqlSwapper.tokenToBeneficiary,
},
oracle: gqlSwapper.oracle,
owner:
gqlSwapper.owner !== zeroAddress
? {
address: gqlSwapper.owner,
}
: null,
paused: gqlSwapper.paused,
defaultScaledOfferFactorPercent:
(1e6 - gqlSwapper.defaultScaledOfferFactor) / 1e4,
scaledOfferFactorOverrides: Object.values(
gqlSwapper.scaledOfferFactorOverrides,
).map((scaleOfferFactorOverride) => {
const baseToken = getAddress(scaleOfferFactorOverride.base)
const quoteToken = getAddress(scaleOfferFactorOverride.quote)
const scaledOfferFactorPercent =
(1e6 - scaleOfferFactorOverride.scaledOfferFactor) / 1e4
return {
baseToken: {
address: baseToken,
},
quoteToken: {
address: quoteToken,
},
scaledOfferFactorPercent,
}
}),
}
}