Skip to content

Commit

Permalink
feat: add swap quote provider
Browse files Browse the repository at this point in the history
  • Loading branch information
janndriessen committed Sep 20, 2024
1 parent 9992167 commit 8eab9ae
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 64 deletions.
31 changes: 19 additions & 12 deletions src/quote/flashmint/wrapped/provider.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { BigNumber } from '@ethersproject/bignumber'

import { SwapQuoteProvider } from 'quote/swap'
import {
ComponentSwapData,
ComponentWrapData,
Expand All @@ -14,6 +15,7 @@ import { getRpcProvider } from 'utils/rpc-provider'
import { QuoteProvider, QuoteToken } from '../../interfaces'

export interface FlashMintWrappedQuoteRequest {
chainId: number
isMinting: boolean
inputToken: QuoteToken
outputToken: QuoteToken
Expand All @@ -31,42 +33,47 @@ export interface FlashMintWrappedQuote {
export class WrappedQuoteProvider
implements QuoteProvider<FlashMintWrappedQuoteRequest, FlashMintWrappedQuote>
{
constructor(private readonly rpcUrl: string) {}
constructor(
private readonly rpcUrl: string,
private readonly swapQuoteProvider: SwapQuoteProvider
) {}

async getQuote(
request: FlashMintWrappedQuoteRequest
): Promise<FlashMintWrappedQuote | null> {
const { inputToken, indexTokenAmount, isMinting, outputToken, slippage } =
request
console.log(
inputToken.symbol,
outputToken.symbol,
indexTokenAmount.toString(),
const {
chainId,
inputToken,
indexTokenAmount,
isMinting,
slippage
)
outputToken,
slippage,
} = request
const indexToken = isMinting ? outputToken : inputToken
const indexTokenSymbol = indexToken.symbol
const componentSwapData = isMinting
? await getIssuanceComponentSwapData(
{
chainId,
indexTokenSymbol,
indexToken: indexToken.address,
inputToken: inputToken.address,
indexTokenAmount,
},
this.rpcUrl
this.rpcUrl,
this.swapQuoteProvider
)
: await getRedemptionComponentSwapData(
{
chainId,
indexTokenSymbol,
indexToken: indexToken.address,
outputToken: outputToken.address,
indexTokenAmount,
},
this.rpcUrl
this.rpcUrl,
this.swapQuoteProvider
)
console.log(componentSwapData)
const componentWrapData = getWrapData(indexToken.symbol)
// FIXME: add check
// if (componentSwapData.length !== componentWrapData.length) return null
Expand Down
10 changes: 8 additions & 2 deletions src/quote/provider/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,14 @@ export class FlashMintQuoteProvider
)
}
case FlashMintContractType.wrapped: {
const wrappedQuoteProvider = new WrappedQuoteProvider(rpcUrl)
const wrappedQuote = await wrappedQuoteProvider.getQuote(request)
const wrappedQuoteProvider = new WrappedQuoteProvider(
rpcUrl,
swapQuoteProvider
)
const wrappedQuote = await wrappedQuoteProvider.getQuote({
...request,
chainId,
})
if (!wrappedQuote) return null
const builder = new WrappedTransactionBuilder(rpcUrl)
const txRequest: FlashMintWrappedBuildRequest = {
Expand Down
12 changes: 9 additions & 3 deletions src/utils/component-swap-data.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ import {
getRedemptionComponentSwapData,
} from 'utils/component-swap-data'
import { wei } from 'utils/numbers'
import { LocalhostProviderUrl } from 'tests/utils'
import { IndexZeroExSwapQuoteProvider, LocalhostProviderUrl } from 'tests/utils'
import { isSameAddress } from 'utils/addresses'
import { Exchange } from 'utils/swap-data'

const chainId = 1
const rpcUrl = LocalhostProviderUrl
const swapQuoteProvider = IndexZeroExSwapQuoteProvider

const indexTokenSymbol = USDCY.symbol
const indexToken = USDCY.address!
Expand All @@ -20,12 +22,14 @@ describe('getIssuanceComponentSwapData()', () => {
test('returns correct swap data based on input token USDC', async () => {
const componentSwapData = await getIssuanceComponentSwapData(
{
chainId,
indexTokenSymbol,
indexToken,
inputToken: usdc,
indexTokenAmount: wei(1),
},
rpcUrl
rpcUrl,
swapQuoteProvider
)
// FIXME: should be 5 for USDCY
expect(componentSwapData.length).toBe(6)
Expand Down Expand Up @@ -80,12 +84,14 @@ describe('getRedemptionComponentSwapData()', () => {
test('returns correct swap data based for output token USDC', async () => {
const componentSwapData = await getRedemptionComponentSwapData(
{
chainId,
indexTokenSymbol,
indexToken,
outputToken: usdc,
indexTokenAmount: wei(1),
},
rpcUrl
rpcUrl,
swapQuoteProvider
)
// FIXME: should be 5 for USDCY
expect(componentSwapData.length).toBe(6)
Expand Down
99 changes: 52 additions & 47 deletions src/utils/component-swap-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { mainnet } from 'viem/chains'

import { AddressZero } from 'constants/addresses'
import { USDC } from 'constants/tokens'
import { SwapQuote, SwapQuoteProvider } from 'quote'
import { isSameAddress } from 'utils/addresses'
import { getIssuanceModule } from 'utils/issuanceModules'
import { getRpcProvider } from 'utils/rpc-provider'
Expand Down Expand Up @@ -32,6 +33,7 @@ export interface ComponentSwapData {
}

interface ComponentSwapDataRequest {
chainId: number
indexTokenSymbol: string
indexToken: string
indexTokenAmount: BigNumber
Expand Down Expand Up @@ -137,52 +139,47 @@ interface IssuanceRequest extends ComponentSwapDataRequest {

export async function getIssuanceComponentSwapData(
request: IssuanceRequest,
rpcUrl: string
rpcUrl: string,
swapQuoteProvider: SwapQuoteProvider
): Promise<ComponentSwapData[]> {
const { indexTokenSymbol, indexToken, indexTokenAmount, inputToken } = request
const {
chainId,
indexTokenSymbol,
indexToken,
indexTokenAmount,
inputToken,
} = request
const issuance = getIssuanceContract(indexTokenSymbol, rpcUrl)
const [issuanceComponents] = await issuance.getRequiredComponentIssuanceUnits(
indexToken,
indexTokenAmount
)
const underlyingERC20sPromises: Promise<WrappedToken>[] =
issuanceComponents.map((component: string) => getUnderlyingErc20(component))
const wrappedTokens = await Promise.all(underlyingERC20sPromises)
// TODO:
// const buyAmountsPromises = issuanceComponents.map(
// (component: string, index: number) =>
// getAmountOfAssetToObtainShares(component, issuanceUnits[index], provider)
// )
// const buyAmounts = await Promise.all(buyAmountsPromises)
const buyAmounts = issuanceComponents.map(() => BigNumber.from(0))
const wrappedTokens = await Promise.all(underlyingERC20sPromises)
console.log(wrappedTokens)
// TODO: get swap data; add swap quote provider
const swaps: Promise<{ swapData: SwapData } | null>[] =
issuanceComponents.map((_: string, index: number) => {
const swapPromises: Promise<SwapQuote | null>[] = issuanceComponents.map(
(_: string, index: number) => {
const wrappedToken = wrappedTokens[index]
const underlyingERC20 = wrappedToken.underlyingErc20
console.log(
underlyingERC20.symbol === USDC.symbol,
underlyingERC20.symbol,
USDC.symbol
)
console.log(
isSameAddress(underlyingERC20.address, inputToken),
underlyingERC20.address,
inputToken
)
if (isSameAddress(underlyingERC20.address, inputToken)) return null
// const buyUnderlyingAmount = buyAmounts[index]
// const mintParams = {
// buyToken: underlyingERC20.address,
// buyAmount: buyUnderlyingAmount,
// sellToken: inputToken,
// includedSources: 'Uniswap_V3',
// }
// TODO: add swap quote provider
return null
})
const swapData = await Promise.all(swaps)
return swapQuoteProvider.getSwapQuote({
chainId,
inputToken,
outputToken: underlyingERC20.address,
outputAmount: buyAmounts[index].toString(),
// TODO: needed for USDCY?
// includedSources: 'Uniswap_V3',
})
}
)
const swapData = await Promise.all(swapPromises)
return buildComponentSwapData(
issuanceComponents,
wrappedTokens,
Expand All @@ -197,10 +194,16 @@ interface RedemptionRequest extends ComponentSwapDataRequest {

export async function getRedemptionComponentSwapData(
request: RedemptionRequest,
rpcUrl: string
rpcUrl: string,
swapQuoteProvider: SwapQuoteProvider
): Promise<ComponentSwapData[]> {
const { indexTokenSymbol, indexToken, indexTokenAmount, outputToken } =
request
const {
chainId,
indexTokenSymbol,
indexToken,
indexTokenAmount,
outputToken,
} = request
const issuance = getIssuanceContract(indexTokenSymbol, rpcUrl)
const [issuanceComponents] =
await issuance.getRequiredComponentRedemptionUnits(
Expand All @@ -210,7 +213,6 @@ export async function getRedemptionComponentSwapData(
const underlyingERC20sPromises: Promise<WrappedToken>[] =
issuanceComponents.map((component: string) => getUnderlyingErc20(component))
const wrappedTokens = await Promise.all(underlyingERC20sPromises)
console.log(wrappedTokens)
// TODO: check google docs
// const buyAmountsPromises = issuanceComponents.map(
// (component: string, index: number) =>
Expand All @@ -223,32 +225,35 @@ export async function getRedemptionComponentSwapData(
// )
// const buyAmounts = await Promise.all(buyAmountsPromises)
const buyAmounts = issuanceComponents.map(() => BigNumber.from(0))
const swaps = issuanceComponents.map((_: string, index: number) => {
const wrappedToken = wrappedTokens[index]
const underlyingERC20 = wrappedToken.underlyingErc20
if (isSameAddress(underlyingERC20.address, outputToken)) return null
// const buyUnderlyingAmount = buyAmounts[index]
// const redeemParams = {
// buyToken: outputToken,
// sellAmount: buyUnderlyingAmount,
// sellToken: underlyingERC20.address,
// includedSources: 'Uniswap_V3',
// }
return null
})
const swapPromises: Promise<SwapQuote | null>[] = issuanceComponents.map(
(_: string, index: number) => {
const wrappedToken = wrappedTokens[index]
const underlyingERC20 = wrappedToken.underlyingErc20
if (isSameAddress(underlyingERC20.address, outputToken)) return null
return swapQuoteProvider.getSwapQuote({
chainId,
inputToken: underlyingERC20.address,
inputAmount: buyAmounts[index].toString(),
outputToken,
// TODO: needed for USDCY?
// includedSources: 'Uniswap_V3',
})
}
)
const swapData = await Promise.all(swapPromises)
return buildComponentSwapData(
issuanceComponents,
wrappedTokens,
buyAmounts,
swaps
swapData
)
}

function buildComponentSwapData(
issuanceComponents: string[],
wrappedTokens: WrappedToken[],
buyAmounts: BigNumber[],
swapDataResults: any
swapDataResults: (SwapQuote | null)[]
): ComponentSwapData[] {
return issuanceComponents.map((_: string, index: number) => {
const wrappedToken = wrappedTokens[index]
Expand Down

0 comments on commit 8eab9ae

Please sign in to comment.