Skip to content

Commit

Permalink
Merge d0ec047 into 36efe55
Browse files Browse the repository at this point in the history
  • Loading branch information
ChiTimesChi authored Nov 8, 2024
2 parents 36efe55 + d0ec047 commit c77f2e5
Show file tree
Hide file tree
Showing 13 changed files with 542 additions and 295 deletions.
6 changes: 2 additions & 4 deletions packages/sdk-router/src/module/synapseModuleSet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { BigintIsh } from '../constants'
import { BridgeQuote, BridgeRoute, FeeConfig } from './types'
import { SynapseModule } from './synapseModule'
import { applyOptionalDeadline } from '../utils/deadlines'
import { isSameAddress } from '../utils/addressUtils'
import { Query } from './query'

export abstract class SynapseModuleSet {
Expand Down Expand Up @@ -70,10 +71,7 @@ export abstract class SynapseModuleSet {
moduleAddress: string
): SynapseModule | undefined {
const module = this.getModule(chainId)
if (module?.address.toLowerCase() === moduleAddress.toLowerCase()) {
return module
}
return undefined
return isSameAddress(module?.address, moduleAddress) ? module : undefined
}

/**
Expand Down
72 changes: 69 additions & 3 deletions packages/sdk-router/src/rfq/api.integration.test.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,80 @@
import { getAllQuotes } from './api'
import { parseFixed } from '@ethersproject/bignumber'

import { getAllQuotes, getBestRelayerQuote, RelayerQuote } from './api'
import { Ticker } from './ticker'
import { ETH_NATIVE_TOKEN_ADDRESS } from '../utils/handleNativeToken'

global.fetch = require('node-fetch')

// Retry the flaky tests up to 3 times
jest.retryTimes(3)

describe('getAllQuotes', () => {
it('Integration test', async () => {
describe('Integration test: getAllQuotes', () => {
it('returns a non-empty array', async () => {
const result = await getAllQuotes()
// console.log('Current quotes: ' + JSON.stringify(result, null, 2))
expect(result.length).toBeGreaterThan(0)
})
})

describe('Integration test: getBestRelayerQuote', () => {
const ticker: Ticker = {
originToken: {
chainId: 42161,
token: ETH_NATIVE_TOKEN_ADDRESS,
},
destToken: {
chainId: 10,
token: ETH_NATIVE_TOKEN_ADDRESS,
},
}
const userAddress = '0x0000000000000000000000000000000000007331'

describe('Cases where a non-zero quote is returned', () => {
it('ARB ETH -> OP ETH; 0.01 ETH', async () => {
const result = await getBestRelayerQuote(
ticker,
parseFixed('0.01', 18),
userAddress
)
expect(result?.destAmount.gt(0)).toBe(true)
expect(result?.relayerAddress).toBeDefined()
})
})

describe('Cases where a zero quote is returned', () => {
const quoteZero: RelayerQuote = {
destAmount: parseFixed('0'),
}

beforeEach(() => {
jest.spyOn(console, 'error').mockImplementation(() => {
// Do nothing
})
})

afterEach(() => {
jest.restoreAllMocks()
})

it('ARB ETH -> OP ETH; 1337 wei', async () => {
const result = await getBestRelayerQuote(
ticker,
parseFixed('1337'),
userAddress
)
expect(result).toEqual(quoteZero)
expect(console.error).toHaveBeenCalled()
})

it('ARB ETH -> OP ETH; 10**36 wei', async () => {
const result = await getBestRelayerQuote(
ticker,
parseFixed('1', 36),
userAddress
)
expect(result).toEqual(quoteZero)
expect(console.error).toHaveBeenCalled()
})
})
})
163 changes: 156 additions & 7 deletions packages/sdk-router/src/rfq/api.test.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
import fetchMock from 'jest-fetch-mock'
import { parseFixed } from '@ethersproject/bignumber'

import { getAllQuotes } from './api'
import {
getAllQuotes,
getBestRelayerQuote,
PutRFQResponseAPI,
RelayerQuote,
} from './api'
import { Ticker } from './ticker'
import { FastBridgeQuoteAPI, unmarshallFastBridgeQuote } from './quote'

const OK_RESPONSE_TIME = 1900
const SLOW_RESPONSE_TIME = 2100

const delayedAPIPromise = (
quotes: FastBridgeQuoteAPI[],
body: string,
delay: number
): Promise<{ body: string }> => {
return new Promise((resolve) =>
setTimeout(() => resolve({ body: JSON.stringify(quotes) }), delay)
)
return new Promise((resolve) => setTimeout(() => resolve({ body }), delay))
}

describe('getAllQuotes', () => {
Expand Down Expand Up @@ -65,7 +70,7 @@ describe('getAllQuotes', () => {

it('when the response takes a long, but reasonable time to return', async () => {
fetchMock.mockResponseOnce(() =>
delayedAPIPromise(quotesAPI, OK_RESPONSE_TIME)
delayedAPIPromise(JSON.stringify(quotesAPI), OK_RESPONSE_TIME)
)
const result = await getAllQuotes()
expect(result).toEqual([
Expand Down Expand Up @@ -102,11 +107,155 @@ describe('getAllQuotes', () => {

it('when the response takes too long to return', async () => {
fetchMock.mockResponseOnce(() =>
delayedAPIPromise(quotesAPI, SLOW_RESPONSE_TIME)
delayedAPIPromise(JSON.stringify(quotesAPI), SLOW_RESPONSE_TIME)
)
const result = await getAllQuotes()
expect(result).toEqual([])
expect(console.error).toHaveBeenCalled()
})
})
})

describe('getBestRelayerQuote', () => {
const bigAmount = parseFixed('1', 24)
const bigAmountStr = '1000000000000000000000000'
const relayerAddress = '0x0000000000000000000000000000000000001337'
const quoteID = 'acbdef-123456'
const userAddress = '0x0000000000000000000000000000000000007331'

const ticker: Ticker = {
originToken: {
chainId: 1,
token: '0x0000000000000000000000000000000000000001',
},
destToken: {
chainId: 2,
token: '0x0000000000000000000000000000000000000002',
},
}

const noQuotesFound: PutRFQResponseAPI = {
success: false,
reason: 'No quotes found',
}

const quoteFound: PutRFQResponseAPI = {
success: true,
quote_id: quoteID,
dest_amount: bigAmountStr,
relayer_address: relayerAddress,
}

const quote: RelayerQuote = {
destAmount: bigAmount,
relayerAddress,
quoteID,
}

const quoteZero: RelayerQuote = {
destAmount: parseFixed('0'),
}

beforeEach(() => {
fetchMock.enableMocks()
})

afterEach(() => {
fetchMock.resetMocks()
})

describe('Returns a non-zero quote', () => {
it('when the response is ok', async () => {
fetchMock.mockResponseOnce(JSON.stringify(quoteFound))
const result = await getBestRelayerQuote(ticker, bigAmount, userAddress)
expect(result).toEqual(quote)
})

it('when the response takes a long, but reasonable time to return', async () => {
fetchMock.mockResponseOnce(() =>
delayedAPIPromise(JSON.stringify(quoteFound), OK_RESPONSE_TIME)
)
const result = await getBestRelayerQuote(ticker, bigAmount, userAddress)
expect(result).toEqual(quote)
})

it('when the user address is not provided', async () => {
fetchMock.mockResponseOnce(JSON.stringify(quoteFound))
const result = await getBestRelayerQuote(ticker, bigAmount)
expect(result).toEqual(quote)
})

it('when the response does not contain quote ID', async () => {
const responseWithoutID = { ...quoteFound, quote_id: undefined }
const quoteWithoutID = { ...quote, quoteID: undefined }
fetchMock.mockResponseOnce(JSON.stringify(responseWithoutID))
const result = await getBestRelayerQuote(ticker, bigAmount, userAddress)
expect(result).toEqual(quoteWithoutID)
})
})

describe('Returns a zero quote', () => {
beforeEach(() => {
jest.spyOn(console, 'error').mockImplementation(() => {
// Do nothing
})
})

afterEach(() => {
jest.restoreAllMocks()
})

it('when the response is not ok', async () => {
fetchMock.mockResponseOnce(JSON.stringify(quoteFound), { status: 500 })
const result = await getBestRelayerQuote(ticker, bigAmount, userAddress)
expect(result).toEqual(quoteZero)
expect(console.error).toHaveBeenCalled()
})

it('when the response success is false', async () => {
fetchMock.mockResponseOnce(JSON.stringify(noQuotesFound))
const result = await getBestRelayerQuote(ticker, bigAmount, userAddress)
expect(result).toEqual(quoteZero)
expect(console.error).toHaveBeenCalled()
})

it('when the response takes too long to return', async () => {
fetchMock.mockResponseOnce(() =>
delayedAPIPromise(JSON.stringify(quoteFound), SLOW_RESPONSE_TIME)
)
const result = await getBestRelayerQuote(ticker, bigAmount, userAddress)
expect(result).toEqual(quoteZero)
expect(console.error).toHaveBeenCalled()
})

it('when the response does not contain dest amount', async () => {
const responseWithoutDestAmount = {
...quoteFound,
dest_amount: undefined,
}
fetchMock.mockResponseOnce(JSON.stringify(responseWithoutDestAmount))
const result = await getBestRelayerQuote(ticker, bigAmount, userAddress)
expect(result).toEqual(quoteZero)
expect(console.error).toHaveBeenCalled()
})

it('when the response does not contain relayer address', async () => {
const responseWithoutRelayerAddress = {
...quoteFound,
relayer_address: undefined,
}
fetchMock.mockResponseOnce(JSON.stringify(responseWithoutRelayerAddress))
const result = await getBestRelayerQuote(ticker, bigAmount, userAddress)
expect(result).toEqual(quoteZero)
expect(console.error).toHaveBeenCalled()
})

it('when the response dest amount is zero', async () => {
const responseWithZeroDestAmount = { ...quoteFound, dest_amount: '0' }
fetchMock.mockResponseOnce(JSON.stringify(responseWithZeroDestAmount))
const result = await getBestRelayerQuote(ticker, bigAmount, userAddress)
expect(result).toEqual(quoteZero)
expect(console.error).toHaveBeenCalled()
})
})
})
Loading

0 comments on commit c77f2e5

Please sign in to comment.