Skip to content

Commit

Permalink
feat: 1inch developer portal API
Browse files Browse the repository at this point in the history
  • Loading branch information
gomesalexandre committed Nov 25, 2023
1 parent 67746a6 commit 21bf4ef
Show file tree
Hide file tree
Showing 9 changed files with 82 additions and 54 deletions.
2 changes: 1 addition & 1 deletion react-app-rewired/headers/csps/defi/swappers/OneInch.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Csp } from '../../../types'

export const csp: Csp = {
'connect-src': ['https://api-shapeshift.1inch.io'],
'connect-src': ['https://api.1inch.dev'],
}
3 changes: 2 additions & 1 deletion src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,9 @@ const validators = {
REACT_APP_FEATURE_READ_ONLY_ASSETS: bool({ default: false }),
REACT_APP_FEATURE_ONE_INCH: bool({ default: false }),
REACT_APP_ONE_INCH_API_URL: url({
default: 'https://api-shapeshift.1inch.io/v5.0',
default: 'https://api.1inch.dev/swap/v5.2',
}),
REACT_APP_ONE_INCH_API_KEY: str({ default: '2qToPh5P1hx2Db8wtXUjkjozkaFa6fhI' }),
REACT_APP_FEATURE_COVALENT_JAYPEGS: bool({ default: false }),
REACT_APP_ALCHEMY_POLYGON_JAYPEGS_API_KEY: str(),
REACT_APP_ALCHEMY_OPTIMISM_JAYPEGS_API_KEY: str(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jest.mock('../utils/oneInchService', () => {
})

describe('getApprovalAddress', () => {
const apiUrl = 'https://api-shapeshift.1inch.io/v5.0'
const apiUrl = 'https://api.1inch.dev/swap/v5.2'

it('returns the correct address for the given chainId', async () => {
;(oneInchService.get as jest.Mock<unknown>).mockReturnValueOnce(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { SwapperName } from 'lib/swapper/types'

import { setupQuote } from '../../utils/test-data/setupSwapQuote'
import { oneInchService } from '../utils/oneInchService'
import type { OneInchQuoteResponse } from '../utils/types'
import { getTradeQuote } from './getTradeQuote'

jest.mock('../utils/oneInchService', () => {
Expand All @@ -30,7 +31,7 @@ jest.mock('context/PluginProvider/chainAdapterSingleton', () => ({
}))

describe('getTradeQuote', () => {
const apiUrl = 'https://api-shapeshift.1inch.io/v5.0'
const apiUrl = 'https://api.1inch.dev/swap/v5.2'
const quoteURL = `${apiUrl}/1/quote`
const approvalURL = `${apiUrl}/1/approve/spender`

Expand All @@ -44,44 +45,43 @@ describe('getTradeQuote', () => {
}),
)
case quoteURL:
return await Promise.resolve(
Ok({
data: {
fromToken: {
symbol: 'FOX',
name: 'FOX',
decimals: 18,
address: '0xc770eefad204b5180df6a14ee197d99d808ee52d',
logoURI: 'https://tokens.1inch.io/0xc770eefad204b5180df6a14ee197d99d808ee52d.png',
tags: ['tokens'],
},
toToken: {
symbol: 'WETH',
name: 'Wrapped Ether',
address: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
decimals: 18,
logoURI: 'https://tokens.1inch.io/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2.png',
wrappedNative: 'true',
tags: ['tokens', 'PEG:ETH'],
},
toTokenAmount: '16426735042245',
fromTokenAmount: '1000000000000000000',
protocols: [
const mockQuote: { data: OneInchQuoteResponse } = {
data: {
fromToken: {
symbol: 'FOX',
name: 'FOX',
decimals: 18,
address: '0xc770eefad204b5180df6a14ee197d99d808ee52d',
logoURI: 'https://tokens.1inch.io/0xc770eefad204b5180df6a14ee197d99d808ee52d.png',
tags: ['tokens'],
},
toToken: {
symbol: 'WETH',
name: 'Wrapped Ether',
address: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
decimals: 18,
logoURI: 'https://tokens.1inch.io/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2.png',
tags: ['tokens', 'PEG:ETH'],
},
toAmount: '16426735042245',
fromTokenAmount: '1000000000000000000',
protocols: [
[
[
[
{
name: 'UNISWAP_V2',
part: 100,
fromTokenAddress: '0xc770eefad204b5180df6a14ee197d99d808ee52d',
toTokenAddress: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
},
],
{
name: 'UNISWAP_V2',
part: 100,
src: '0xc770eefad204b5180df6a14ee197d99d808ee52d',
dst: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
},
],
],
estimatedGas: 189386,
},
}),
)
],
gas: 189386,
},
}

return await Promise.resolve(Ok(mockQuote))
default:
return await Promise.resolve(Ok({}))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type { Result } from '@sniptt/monads'
import { Err, Ok } from '@sniptt/monads'
import { getConfig } from 'config'
import { v4 as uuid } from 'uuid'
import { bn } from 'lib/bignumber/bignumber'
import type { GetEvmTradeQuoteInput, SwapErrorRight, TradeQuote } from 'lib/swapper/types'
import { SwapErrorType, SwapperName } from 'lib/swapper/types'
import { makeSwapErrorRight } from 'lib/swapper/utils'
Expand Down Expand Up @@ -45,12 +46,15 @@ export async function getTradeQuote(
const buyTokenPercentageFee = convertBasisPointsToPercentage(affiliateBps).toNumber()

const params: OneInchQuoteApiInput = {
fromTokenAddress: getOneInchTokenAddress(sellAsset),
toTokenAddress: getOneInchTokenAddress(buyAsset),
src: getOneInchTokenAddress(sellAsset),
dst: getOneInchTokenAddress(buyAsset),
amount: sellAmountIncludingProtocolFeesCryptoBaseUnit,
...(maybeTreasuryAddress && {
fee: buyTokenPercentageFee,
}),
includeTokensInfo: true,
includeProtocols: true,
includeGas: true,
}

const { chainReference } = fromChainId(chainId)
Expand All @@ -62,7 +66,7 @@ export async function getTradeQuote(
if (maybeQuoteResponse.isErr()) return Err(maybeQuoteResponse.unwrapErr())

const { data: quote } = maybeQuoteResponse.unwrap()
const { toTokenAmount: buyAmountAfterFeesCryptoBaseUnit } = quote
const { toAmount: buyAmountAfterFeesCryptoBaseUnit } = quote
const buyAmountBeforeFeesCryptoBaseUnit = addBasisPointAmount(
buyAmountAfterFeesCryptoBaseUnit,
affiliateBps,
Expand All @@ -78,12 +82,14 @@ export async function getTradeQuote(
if (maybeAdapter.isErr()) return Err(maybeAdapter.unwrapErr())
const adapter = maybeAdapter.unwrap()

if (!quote.gas) throw new Error('1inch quote missing gas')

try {
const { average } = await adapter.getGasFeeData()
const networkFeeCryptoBaseUnit = calcNetworkFeeCryptoBaseUnit({
...average,
supportsEIP1559,
gasLimit: quote.estimatedGas,
gasLimit: bn(quote.gas).toString(),
l1GasLimit: '0', // TODO: support l1 gas limit for accurate optimism estimations
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,12 @@ export const fetchOneInchSwap = async ({
: 0

const params: OneInchSwapApiInput = {
fromTokenAddress: getOneInchTokenAddress(sellAsset),
toTokenAddress: getOneInchTokenAddress(buyAsset),
src: getOneInchTokenAddress(sellAsset),
dst: getOneInchTokenAddress(buyAsset),
// HACK: use the receive address as the send address
// 1inch uses this to check allowance on their side
// this swapper is not cross-account so this works
fromAddress: receiveAddress,
from: receiveAddress,
amount: sellAmountIncludingProtocolFeesCryptoBaseUnit,
slippage: maximumSlippagePercentage,
allowPartialFill: false,
Expand All @@ -58,6 +58,9 @@ export const fetchOneInchSwap = async ({
referrerAddress: maybeTreasuryAddress,
fee: buyTokenPercentageFee,
}),
includeTokensInfo: true,
includeProtocols: true,
includeGas: true,
}

const { chainReference } = fromChainId(sellAsset.chainId)
Expand Down
2 changes: 1 addition & 1 deletion src/lib/swapper/swappers/OneInchSwapper/utils/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export const getRate = (response: OneInchBaseResponse): BigNumber => {
response.fromTokenAmount,
response.fromToken.decimals,
)
const toTokenAmountCryptoHuman = fromBaseUnit(response.toTokenAmount, response.toToken.decimals)
const toTokenAmountCryptoHuman = fromBaseUnit(response.toAmount, response.toToken.decimals)
return bn(toTokenAmountCryptoHuman).div(fromTokenAmountCryptoHuman)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { AxiosRequestConfig } from 'axios'
import axios from 'axios'
import { getConfig } from 'config'
import { SwapperName } from 'lib/swapper/types'
import { createCache, makeSwapperAxiosServiceMonadic } from 'lib/swapper/utils'

Expand All @@ -8,11 +9,14 @@ const maxAge = 5 * 1000 // 5 seconds
const cachedUrls: string[] = []
const cache = createCache(maxAge, cachedUrls)

const apiKey = getConfig().REACT_APP_ONE_INCH_API_KEY

const axiosConfig: AxiosRequestConfig = {
timeout: 10000,
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: `Bearer ${apiKey}`,
},
adapter: cache.adapter,
}
Expand Down
28 changes: 21 additions & 7 deletions src/lib/swapper/swappers/OneInchSwapper/utils/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,25 @@ export const oneInchSupportedChainIds = [
export type OneInchSupportedChainId = (typeof oneInchSupportedChainIds)[number]

export type OneInchQuoteApiInput = {
fromTokenAddress: string
toTokenAddress: string
src: string
dst: string
amount: string
fee?: number // fee as a percentage, e.g. to set a fee to 1.5%: fee=1.5, paid to the referrerAddress
includeTokensInfo?: boolean
includeProtocols?: boolean
includeGas?: boolean
}

// https://docs.1inch.io/docs/aggregation-protocol/api/swap-params/
export type OneInchSwapApiInput = OneInchQuoteApiInput & {
slippage: number
fromAddress: string
referrerAddress?: string
from: string
referrer?: string
allowPartialFill: boolean
disableEstimate: boolean
includeTokensInfo?: boolean
includeProtocols?: boolean
includeGas?: boolean
}

export type OneInchSpenderResponse = {
Expand All @@ -37,21 +43,29 @@ export type OneInchTokenResponse = {
address: string
decimals: number
logoURI: string
tags: string[]
}

export type OneInchQuoteResponse = OneInchBaseResponse & {
estimatedGas: string
type OneInchProtocol = {
name: string
part: number
src: string
dst: string
}

export type OneInchQuoteResponse = OneInchBaseResponse

export type OneInchSwapResponse = OneInchBaseResponse & {
tx: EvmTransaction
}

export type OneInchBaseResponse = {
fromToken: OneInchTokenResponse
toToken: OneInchTokenResponse
toTokenAmount: string
protocols: OneInchProtocol[][][]
toAmount: string
fromTokenAmount: string
gas?: number
}

export type EvmTransaction = {
Expand Down

0 comments on commit 21bf4ef

Please sign in to comment.