Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add swap quote provider protocol #53

Merged
merged 56 commits into from
Jun 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
7ee3a4c
add swap quite provider interface
janndriessen May 22, 2024
e0d6b3c
build: add exports
janndriessen May 22, 2024
689cace
feat: add 0x swap quote provider
janndriessen May 22, 2024
d04febc
feat: use swap quote provider for 0x flash mint
janndriessen May 22, 2024
5d2806f
build: remove exports for duplicate declarations
janndriessen May 22, 2024
fbdc275
build: fix import
janndriessen May 22, 2024
ed2d76c
test: temporary remove arbitrum tests
janndriessen May 22, 2024
1f413b6
remove requirements zero ex v1 api for zero ex flash mint
janndriessen May 22, 2024
e5cb94a
feat: add swap quote interface
janndriessen May 23, 2024
389ae1a
test: fix zeroex provider tests
janndriessen May 23, 2024
6af9b11
test: fix tests adding new test factory config
janndriessen May 23, 2024
e877433
Merge pull request #57 from IndexCoop/feat/add-swap-quote-interface
janndriessen May 23, 2024
9bb0d52
chore: remove obsolete todo
janndriessen May 24, 2024
bd07907
build: create zeroex folder
janndriessen May 24, 2024
5e3a694
lint
janndriessen May 24, 2024
0fdfa35
feat: add zeroe ex swap data
janndriessen May 24, 2024
aba4e5e
feat: add 0x api
janndriessen May 24, 2024
f0b46f2
feat: add get swap data to zeroex adapter
janndriessen May 24, 2024
9cbc88f
feat: start adding swap quote provider to leveraged quote provider
janndriessen May 24, 2024
9f23f28
refactor: get payment token address
janndriessen May 24, 2024
a3a24ea
feat: add sources and leverage quote provider to fully use swap quote…
janndriessen May 24, 2024
772b810
refactor: remove zeroex api from constructor
janndriessen May 24, 2024
c162745
refactor: leveraged token data util function
janndriessen May 24, 2024
cecbadc
test: fix import
janndriessen May 24, 2024
c9e8878
build: fix import
janndriessen May 24, 2024
d7a034f
feat: add swap quote provider to leveraged extended
janndriessen May 24, 2024
bf73f64
feat: remove zero ex api dependency
janndriessen May 24, 2024
cfcd17c
chore: remove unsupported contract type
janndriessen May 24, 2024
c745320
feat: make swap quote provider a required dependency
janndriessen May 24, 2024
a91693a
test: remove obsolete test
janndriessen May 24, 2024
fe8056b
lint
janndriessen May 24, 2024
f795f87
test: fix test files after removing zeroex api
janndriessen May 24, 2024
c8513d9
lint
janndriessen May 24, 2024
1ecbeef
test: readd arbitrum tests
janndriessen May 24, 2024
23f14cc
test: skip eth2xfli tests
janndriessen May 24, 2024
095325a
test: fix testing for right output
janndriessen May 24, 2024
ab06e23
refactor: remove 0x utils
janndriessen May 24, 2024
7b3a996
chore: add arbitrum token addresses for util function
janndriessen May 24, 2024
5f66112
test: remove obsolete test
janndriessen May 24, 2024
12666af
feat: use rpc url for index quote provider
janndriessen May 24, 2024
cdb0720
refactor: quote folder structure
janndriessen May 24, 2024
729869f
refactor: add utils and add tests
janndriessen May 24, 2024
71e4ede
feat: add get rpc provider util function
janndriessen May 24, 2024
bc7002b
feat: make builders use rpc url
janndriessen May 24, 2024
28a0b23
feat: use rpc url for all quote providers
janndriessen May 24, 2024
7fb8539
test: fix tests adding rpc url
janndriessen May 24, 2024
c8a88c1
build: fix test script
janndriessen May 24, 2024
cc042cb
docs: update readme for v3
janndriessen May 24, 2024
0e9f5a1
Merge pull request #62 from IndexCoop/feat/add-v3
janndriessen May 24, 2024
a0ab71a
Merge pull request #61 from IndexCoop/feat/use-rpc-url
janndriessen May 24, 2024
1bc68e5
Merge pull request #60 from IndexCoop/feat/remove-0x-utils
janndriessen May 24, 2024
0b9f943
Merge pull request #59 from IndexCoop/feat/add-0x-swap-data
janndriessen May 24, 2024
9507c2c
docs: update readme
janndriessen May 27, 2024
00855bf
feat: add convenience input/output amounts to flash mint quote
janndriessen May 27, 2024
b9dfc03
docs: update quote interface
janndriessen May 27, 2024
9dcd45e
Merge pull request #63 from IndexCoop/feat/enhance-quote-return
janndriessen May 28, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,5 @@ jobs:
- run: npm run hardhat & npm run test:iceth
# - run: npm run hardhat & npm run test:icreth
# run last - as it alters the block number
- run: npm run hardhat & npm run test:eth2xfli
# skip as it can't be minted or redeemed with 0x
# - run: npm run hardhat & npm run test:eth2xfli
83 changes: 30 additions & 53 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Flash Mint SDK v2
# Flash Mint SDK v3

The Flash Mint SDK provides easy to use functions to integrate flashminting for
The Flash Mint SDK provides easy to use functions to integrate flash minting for
Index's products.

## The Contracts
Expand Down Expand Up @@ -29,27 +29,35 @@ specific FlashMint contracts.

### Quotes

In v2 we made it way easier to fetch a quote. Meet the `FlashMintQuoteProvider`.
This provider will now return the appropriate quotes for any Index token, automatically
selecting the correct FlashMint contract for you.
With v3, while you could still use other quote providers individually, we recommend
solely using the `FlashMintQuoteProvider` which will do most of the guess work for you.
This provider will return the appropriate quotes for any Index token, automatically
selecting the correct FlashMint contract for you - as well as preparing the call data.

```typescript
import { FlashMintQuoteProvider } from '@indexcoop/flash-mint-sdk'
import { FlashMintQuoteProvider, QuoteToken } from '@indexcoop/flash-mint-sdk'

// Input/output token should be of type QuoteToken with the following properties
const inputToken = {
const inputToken: QuoteToken = {
symbol: 'ETH',
decimals: 18,
address: '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE',
}
const outputToken = {
const outputToken: QuoteToken = {
symbol: 'icETH',
decimals: 18,
address: '0x7C07F7aBe10CE8e33DC6C5aD68FE033085256A84',
}

const rpcProvider = new JsonRpcProvider('')
const quoteProvider = new FlashMintQuoteProvider(rpcProvider)
// Add a RPC URL e.g. from Alchemy
const rpcUrl = ''
// Use the 0x swap quote provider configured to your needs e.g. custom base url -
// or provide your own adapter implementing the `SwapQuoteProvider` interface
const zeroexSwapQuoteProvider = new ZeroExSwapQuoteProvider()
const quoteProvider = new FlashMintQuoteProvider(
rpcUrl,
zeroexSwapQuoteProvider
)
const quote = await quoteProvider.getQuote({
isMinting: true,
inputToken,
Expand All @@ -59,8 +67,8 @@ const quote = await quoteProvider.getQuote({
})
```

The returned quote is an object with meta data but most importantly the `inputOutputAmount`
which is the quote for the given request and a `tx` object which is a tx object
The returned quote is an object including meta data but most importantly the `inputOutputAmount`
which is the quote for the given request\* and a `tx` object which is a tx object
basically ready to be send.

```typescript
Expand All @@ -71,59 +79,28 @@ interface FlashMintQuote {
isMinting: boolean
inputToken: QuoteToken
outputToken: QuoteToken
inputAmount: BigNumber
outputAmount: BigNumber
indexTokenAmount: BigNumber
inputOutputAmount: BigNumber
slippage: number
tx: TransactionRequest
}
```

You can still fetch quotes for individual FlashMint contracts e.g. using the `ZeroExQuoteProvider`.

```typescript
import { QuoteToken, ZeroExQuoteProvider } from '@indexcoop/flash-mint-sdk'

// Input/output token should be of type QuoteToken with the following properties
const inputToken: QuoteToken = {
symbol: 'ETH',
decimals: 18,
address: '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE',
}
const outputToken: QuoteToken = {
symbol: 'dsETH',
decimals: 18,
address: '0x341c05c0E9b33C0E38d64de76516b2Ce970bB3BE',
}
const rpcProvider = new JsonRpcProvider('')
const quoteProvider = new ZeroExQuoteProvider(rpcProvider, zeroExApiV1)
const quote = await quoteProvider.getQuote({
isMinting: true,
inputToken,
outputToken,
indexTokenAmount,
slippage: 0.1,
})
```

The quote providers for the individual FlashMint contracts will return not just
the `inputOutputAmount` but also the `swap data/component quotes`.

```typescript
interface FlashMintZeroExQuote {
componentQuotes: string[]
indexTokenAmount: BigNumber
inputOutputTokenAmount: BigNumber
}
```
\* for minting this will be the input amount, for redeeming the output amount

## Flashmint

To execute the flashminting of an Index for convenience use the `tx` object
To execute the flash minting of an Index token for convenience use the `tx` object
returned by the `FlashMintQuoteProvider`.

```typescript
...
const quoteProvider = new FlashMintQuoteProvider(rpcProvider)
const quoteProvider = new FlashMintQuoteProvider(
rpcUrl,
zeroexSwapQuoteProvider
)
const quote = await quoteProvider.getQuote({...})
let tx = quote.tx
const gasEstimate = await provider.estimateGas(tx)
Expand All @@ -150,7 +127,7 @@ When adding new .env vars do not forget to update the [publish.yml](.github/work
1. add a test for determining the correct contract [here](./src/utils/contracts.test.ts)
2. if there is a new FlashMint contract, add it as described [below](#adding-a-new-contract)
3. additionally, add a test in [tests](./src/tests/)
4. add symbol to `function getContractType(token: string)` in `FlashMintQuoteProvider`
4. add symbol to `function getContractType(token: string)` in [src/quote/provider/utils.ts](./src/quote//provider/utils.ts) and add a test

### Adding a new contract

Expand All @@ -166,6 +143,6 @@ is still TBD. 🚧 In the meantime just open an issue.

## License

Copyright © 2023 Index Coop.
Copyright © 2024 Index Coop.

[MIT License](./LICENSE)
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"test": "jest",
"test:arbitrum": "npm test src/flashmint/builders/leveraged-extended.test.ts src/quote/leveraged-extended",
"test:builders": "npm test src/flashmint/builders/leveraged.test.ts src/flashmint/builders/zeroex.test.ts",
"test:quote": "npm test src/quote/leveraged/provider.test.ts src/quote/zeroex src/quote/indexQuoteProvider.test.ts ",
"test:quote": "npm test src/quote/flashmint/leveraged/provider.test.ts src/quote/flashmint/zeroex src/quote/provider/ ",
"test:utils": "npm test src/utils",
"test:btc2x": "npm test src/tests/btc2x.test.ts",
"test:cdeti": "npm test src/tests/cdeti",
Expand Down
2 changes: 1 addition & 1 deletion src/constants/swapdata.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* eslint-disable @typescript-eslint/no-non-null-assertion */
import { Exchange } from '../utils/swapData'
import { Exchange } from 'utils'
import { ETH, InterestCompoundingETHIndex, stETH } from './tokens'

export const noopSwapData: {
Expand Down
32 changes: 18 additions & 14 deletions src/flashmint/builders/leveraged-extended.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ import { ChainId } from 'constants/chains'
import { FlashMintLeveragedExtendedAddress } from 'constants/contracts'
import { IndexCoopEthereum2xIndex, USDC, WETH } from 'constants/tokens'
import { noopSwapData } from 'constants/swapdata'
import { LocalhostProviderArbitrum } from 'tests/utils'
import {
LocalhostProviderArbitrum,
LocalhostProviderUrlArbitrum,
} from 'tests/utils'
import { getFlashMintLeveragedContractForToken } from 'utils/contracts'
import { wei } from 'utils/numbers'
import { Exchange } from 'utils'
Expand All @@ -17,6 +20,7 @@ import {

const chainId = ChainId.Arbitrum
const provider = LocalhostProviderArbitrum
const rpcUrl = LocalhostProviderUrlArbitrum

const eth = '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE'
const usdcAddress = '0xaf88d065e77c8cC2239327C5EDb3A432268e5831'
Expand All @@ -36,31 +40,31 @@ describe('LeveragedTransactionBuilder()', () => {
const buildRequest = createBuildRequest()
buildRequest.isMinting = true
buildRequest.outputToken = ''
const builder = new LeveragedExtendedTransactionBuilder(provider)
const builder = new LeveragedExtendedTransactionBuilder(rpcUrl)
const tx = await builder.build(buildRequest)
expect(tx).toBeNull()
})

test('returns null for invalid request (no input/output token)', async () => {
const buildRequest = createBuildRequest()
buildRequest.inputToken = ''
const builder = new LeveragedExtendedTransactionBuilder(provider)
const builder = new LeveragedExtendedTransactionBuilder(rpcUrl)
const tx = await builder.build(buildRequest)
expect(tx).toBeNull()
})

test('returns null for invalid request (inputTokenAmount = 0)', async () => {
const buildRequest = createBuildRequest()
buildRequest.inputTokenAmount = BigNumber.from(0)
const builder = new LeveragedExtendedTransactionBuilder(provider)
const builder = new LeveragedExtendedTransactionBuilder(rpcUrl)
const tx = await builder.build(buildRequest)
expect(tx).toBeNull()
})

test('returns null for invalid request (outputTokenAmount = 0)', async () => {
const buildRequest = createBuildRequest()
buildRequest.outputTokenAmount = BigNumber.from(0)
const builder = new LeveragedExtendedTransactionBuilder(provider)
const builder = new LeveragedExtendedTransactionBuilder(rpcUrl)
const tx = await builder.build(buildRequest)
expect(tx).toBeNull()
})
Expand All @@ -73,7 +77,7 @@ describe('LeveragedTransactionBuilder()', () => {
fees: [],
pool: '',
}
const builder = new LeveragedExtendedTransactionBuilder(provider)
const builder = new LeveragedExtendedTransactionBuilder(rpcUrl)
const tx = await builder.build(buildRequest)
expect(tx).toBeNull()
})
Expand All @@ -86,7 +90,7 @@ describe('LeveragedTransactionBuilder()', () => {
fees: [],
pool: '0x0000000000000000000000000000000000000000',
}
const builder = new LeveragedExtendedTransactionBuilder(provider)
const builder = new LeveragedExtendedTransactionBuilder(rpcUrl)
const tx = await builder.build(buildRequest)
expect(tx).toBeNull()
})
Expand All @@ -100,7 +104,7 @@ describe('LeveragedTransactionBuilder()', () => {
fees: [3000],
pool: '0x0000000000000000000000000000000000000000',
}
const builder = new LeveragedExtendedTransactionBuilder(provider)
const builder = new LeveragedExtendedTransactionBuilder(rpcUrl)
const tx = await builder.build(buildRequest)
expect(tx).toBeNull()
})
Expand All @@ -113,7 +117,7 @@ describe('LeveragedTransactionBuilder()', () => {
fees: [500],
pool: '0x00000000000000000000000000000000000000',
}
const builder = new LeveragedExtendedTransactionBuilder(provider)
const builder = new LeveragedExtendedTransactionBuilder(rpcUrl)
const tx = await builder.build(buildRequest)
expect(tx).toBeNull()
})
Expand All @@ -126,7 +130,7 @@ describe('LeveragedTransactionBuilder()', () => {
fees: [500],
pool: '0x0000000000000000000000000000000000000000',
}
const builder = new LeveragedExtendedTransactionBuilder(provider)
const builder = new LeveragedExtendedTransactionBuilder(rpcUrl)
const tx = await builder.build(buildRequest)
expect(tx).not.toBeNull()
})
Expand All @@ -143,7 +147,7 @@ describe('LeveragedTransactionBuilder()', () => {
buildRequest.swapDataDebtCollateral,
buildRequest.swapDataInputOutputToken
)
const builder = new LeveragedExtendedTransactionBuilder(provider)
const builder = new LeveragedExtendedTransactionBuilder(rpcUrl)
const tx = await builder.build(buildRequest)
if (!tx) fail()
expect(tx.to).toBe(FlashMintLeveragedExtendedAddress)
Expand All @@ -160,7 +164,7 @@ describe('LeveragedTransactionBuilder()', () => {
buildRequest.swapDataInputOutputToken,
{ value: buildRequest.inputTokenAmount }
)
const builder = new LeveragedExtendedTransactionBuilder(provider)
const builder = new LeveragedExtendedTransactionBuilder(rpcUrl)
const tx = await builder.build(buildRequest)
if (!tx) fail()
expect(tx.to).toBe(FlashMintLeveragedExtendedAddress)
Expand All @@ -184,7 +188,7 @@ describe('LeveragedTransactionBuilder()', () => {
buildRequest.swapDataDebtCollateral,
buildRequest.swapDataInputOutputToken
)
const builder = new LeveragedExtendedTransactionBuilder(provider)
const builder = new LeveragedExtendedTransactionBuilder(rpcUrl)
const tx = await builder.build(buildRequest)
if (!tx) fail()
expect(tx.to).toBe(FlashMintLeveragedExtendedAddress)
Expand All @@ -206,7 +210,7 @@ describe('LeveragedTransactionBuilder()', () => {
buildRequest.swapDataDebtCollateral,
buildRequest.swapDataInputOutputToken
)
const builder = new LeveragedExtendedTransactionBuilder(provider)
const builder = new LeveragedExtendedTransactionBuilder(rpcUrl)
const tx = await builder.build(buildRequest)
if (!tx) fail()
expect(tx.to).toBe(FlashMintLeveragedExtendedAddress)
Expand Down
13 changes: 7 additions & 6 deletions src/flashmint/builders/leveraged-extended.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { TransactionRequest } from '@ethersproject/abstract-provider'
import { BigNumber } from '@ethersproject/bignumber'
import { JsonRpcProvider } from '@ethersproject/providers'

import { getFlashMintLeveragedContractForToken } from '../../utils/contracts'
import { Exchange, SwapData } from '../../utils/swapData'
import { getFlashMintLeveragedContractForToken } from 'utils/contracts'
import { getRpcProvider } from 'utils/rpc-provider'
import { Exchange, SwapData } from 'utils'

import { TransactionBuilder } from './interface'
import { isEmptyString, isInvalidAmount } from './utils'
Expand All @@ -30,13 +30,14 @@ export class LeveragedExtendedTransactionBuilder
TransactionRequest
>
{
constructor(private readonly provider: JsonRpcProvider) {}
constructor(private readonly rpcUrl: string) {}

async build(
request: FlashMintLeveragedExtendedBuildRequest
): Promise<TransactionRequest | null> {
const isValidRequest = this.isValidRequest(request)
if (!isValidRequest) return null
const provider = getRpcProvider(this.rpcUrl)
const {
inputToken,
inputTokenAmount,
Expand All @@ -50,13 +51,13 @@ export class LeveragedExtendedTransactionBuilder
// priceEstimateInflator,
// maxDust,
} = request
const network = await this.provider.getNetwork()
const network = await provider.getNetwork()
const chainId = network.chainId
const indexToken = isMinting ? outputToken : inputToken
const indexTokenSymbol = isMinting ? outputTokenSymbol : inputTokenSymbol
const contract = getFlashMintLeveragedContractForToken(
indexTokenSymbol,
this.provider,
provider,
chainId
)
if (isMinting) {
Expand Down
Loading