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

[DO NOT MERGE] Staging SYN Intents (API, SDK) #3450

Closed
wants to merge 20 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
3d3885e
chore: trigger staging api build
ChiTimesChi Dec 6, 2024
5565401
Merge branch 'feat/sdk-syn-intents' into staging/syn-intents-api-sdk
ChiTimesChi Dec 17, 2024
a8d5e40
Revert "chore: trigger staging api build"
ChiTimesChi Dec 17, 2024
650e81b
Merge branch 'feat/sdk-syn-intents' into staging/syn-intents-api-sdk
ChiTimesChi Dec 18, 2024
8b8cbc0
Merge branch 'feat/sdk-syn-intents' into staging/syn-intents-api-sdk
ChiTimesChi Dec 18, 2024
798a936
feat: expand bridge map connections [REVERT LATER]
ChiTimesChi Dec 18, 2024
e6f20d4
feat: remove SYN from Intents temporarily
ChiTimesChi Dec 20, 2024
c928462
feat: external API logging
ChiTimesChi Dec 20, 2024
60393c7
Merge branch 'feat/sdk-syn-intents' into staging/syn-intents-api-sdk
ChiTimesChi Dec 20, 2024
6f8da0b
fix: try different logging approach
ChiTimesChi Dec 20, 2024
41f4629
Merge branch 'feat/sdk-syn-intents' into staging/syn-intents-api-sdk
ChiTimesChi Dec 20, 2024
b73f836
build: add winston
ChiTimesChi Dec 20, 2024
03af5bd
fix: better logging
ChiTimesChi Dec 20, 2024
180143f
build: yarn.lock
ChiTimesChi Dec 20, 2024
f96c389
fix: use pino
ChiTimesChi Dec 20, 2024
899b9c7
fix: logging order
ChiTimesChi Dec 20, 2024
ebb85ab
Merge branch 'feat/sdk-syn-intents' into staging/syn-intents-api-sdk
ChiTimesChi Dec 20, 2024
b36e8d3
fix: Odos logger
ChiTimesChi Dec 20, 2024
26b209c
chore: log API requests
ChiTimesChi Dec 20, 2024
9bfec89
Merge branch 'feat/sdk-syn-intents' into staging/syn-intents-api-sdk
ChiTimesChi Dec 20, 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 package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
"**/@openzeppelin/*",
"**/@synapsecns/solidity-devops",
"**/ds-test",
"**/forge-std"
"**/forge-std",
"**/pino"
]
},
"repository": {
Expand Down
48 changes: 24 additions & 24 deletions packages/rest-api/src/constants/bridgeMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -308,8 +308,8 @@ export const BRIDGE_MAP = {
'0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85': {
decimals: 6,
symbol: 'USDC',
origin: ['CCTP.USDC', 'RFQ.USDC', 'nUSD'],
destination: ['CCTP.USDC', 'RFQ.USDC'],
origin: ['CCTP.USDC', 'RFQ.USDC', 'nUSD', 'Intents'],
destination: ['CCTP.USDC', 'RFQ.USDC', 'Intents'],
swappable: [
'0x67C10C397dD0Ba417329543c1a40eb48AAa7cd00',
'0x7F5c764cBc14f9669B88837ca1490cCa17c31607',
Expand Down Expand Up @@ -365,8 +365,8 @@ export const BRIDGE_MAP = {
'0x7F5c764cBc14f9669B88837ca1490cCa17c31607': {
decimals: 6,
symbol: 'USDC.e',
origin: ['CCTP.USDC', 'RFQ.USDC', 'nUSD'],
destination: ['CCTP.USDC', 'nUSD'],
origin: ['CCTP.USDC', 'RFQ.USDC', 'nUSD', 'Intents'],
destination: ['CCTP.USDC', 'nUSD', 'Intents'],
swappable: [
'0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85',
'0x67C10C397dD0Ba417329543c1a40eb48AAa7cd00',
Expand All @@ -388,8 +388,8 @@ export const BRIDGE_MAP = {
'0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9': {
decimals: 18,
symbol: 'sUSD',
origin: ['CCTP.USDC', 'RFQ.USDC', 'nUSD'],
destination: ['CCTP.USDC'],
origin: ['CCTP.USDC', 'RFQ.USDC', 'nUSD', 'Intents'],
destination: ['CCTP.USDC', 'Intents'],
swappable: [
'0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85',
'0x67C10C397dD0Ba417329543c1a40eb48AAa7cd00',
Expand All @@ -401,8 +401,8 @@ export const BRIDGE_MAP = {
'0x94b008aA00579c1307B0EF2c499aD98a8ce58e58': {
decimals: 6,
symbol: 'USDT',
origin: ['CCTP.USDC', 'RFQ.USDC', 'nUSD'],
destination: ['CCTP.USDC'],
origin: ['CCTP.USDC', 'RFQ.USDC', 'nUSD', 'Intents'],
destination: ['CCTP.USDC', 'Intents'],
swappable: [
'0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85',
'0x67C10C397dD0Ba417329543c1a40eb48AAa7cd00',
Expand All @@ -421,8 +421,8 @@ export const BRIDGE_MAP = {
'0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1': {
decimals: 18,
symbol: 'DAI',
origin: ['CCTP.USDC', 'RFQ.USDC', 'nUSD'],
destination: ['CCTP.USDC'],
origin: ['CCTP.USDC', 'RFQ.USDC', 'nUSD', 'Intents'],
destination: ['CCTP.USDC', 'Intents'],
swappable: [
'0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85',
'0x67C10C397dD0Ba417329543c1a40eb48AAa7cd00',
Expand All @@ -441,8 +441,8 @@ export const BRIDGE_MAP = {
'0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE': {
decimals: 18,
symbol: 'ETH',
origin: ['RFQ.ETH', 'nETH'],
destination: ['nETH', 'RFQ.ETH'],
origin: ['RFQ.ETH', 'nETH', 'Intents'],
destination: ['nETH', 'RFQ.ETH', 'Intents'],
swappable: [
'0x121ab82b49B2BC4c7901CA46B8277962b4350204',
'0x809DC529f07651bD43A172e8dB6f4a7a0d771036',
Expand Down Expand Up @@ -1527,8 +1527,8 @@ export const BRIDGE_MAP = {
'0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1': {
decimals: 18,
symbol: 'DAI',
origin: ['CCTP.USDC', 'RFQ.USDC', 'nUSD'],
destination: ['CCTP.USDC'],
origin: ['CCTP.USDC', 'RFQ.USDC', 'nUSD', 'Intents'],
destination: ['CCTP.USDC', 'Intents'],
swappable: [
'0x17FC002b466eEc40DaE837Fc4bE5c67993ddBd6F',
'0x2913E812Cf0dcCA30FB28E6Cac3d2DCFF4497688',
Expand All @@ -1540,8 +1540,8 @@ export const BRIDGE_MAP = {
'0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE': {
decimals: 18,
symbol: 'ETH',
origin: ['RFQ.ETH', 'nETH'],
destination: ['nETH', 'RFQ.ETH'],
origin: ['RFQ.ETH', 'nETH', 'Intents'],
destination: ['nETH', 'RFQ.ETH', 'Intents'],
swappable: [
'0x3ea9B0ab55F34Fb188824Ee288CeaEfC63cf908e',
'0x82aF49447D8a07e3bd95BD0d56f35241523fBab1',
Expand All @@ -1550,8 +1550,8 @@ export const BRIDGE_MAP = {
'0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8': {
decimals: 6,
symbol: 'USDC.e',
origin: ['CCTP.USDC', 'RFQ.USDC', 'nUSD'],
destination: ['CCTP.USDC', 'nUSD'],
origin: ['CCTP.USDC', 'RFQ.USDC', 'nUSD', 'Intents'],
destination: ['CCTP.USDC', 'nUSD', 'Intents'],
swappable: [
'0x17FC002b466eEc40DaE837Fc4bE5c67993ddBd6F',
'0x2913E812Cf0dcCA30FB28E6Cac3d2DCFF4497688',
Expand All @@ -1563,8 +1563,8 @@ export const BRIDGE_MAP = {
'0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9': {
decimals: 6,
symbol: 'USDT',
origin: ['CCTP.USDC', 'RFQ.USDC', 'nUSD'],
destination: ['CCTP.USDC', 'nUSD'],
origin: ['CCTP.USDC', 'RFQ.USDC', 'nUSD', 'Intents'],
destination: ['CCTP.USDC', 'nUSD', 'Intents'],
swappable: [
'0x17FC002b466eEc40DaE837Fc4bE5c67993ddBd6F',
'0x2913E812Cf0dcCA30FB28E6Cac3d2DCFF4497688',
Expand All @@ -1583,8 +1583,8 @@ export const BRIDGE_MAP = {
'0xaf88d065e77c8cC2239327C5EDb3A432268e5831': {
decimals: 6,
symbol: 'USDC',
origin: ['CCTP.USDC', 'RFQ.USDC', 'nUSD'],
destination: ['CCTP.USDC', 'RFQ.USDC'],
origin: ['CCTP.USDC', 'RFQ.USDC', 'nUSD', 'Intents'],
destination: ['CCTP.USDC', 'RFQ.USDC', 'Intents'],
swappable: [
'0x17FC002b466eEc40DaE837Fc4bE5c67993ddBd6F',
'0x2913E812Cf0dcCA30FB28E6Cac3d2DCFF4497688',
Expand All @@ -1596,8 +1596,8 @@ export const BRIDGE_MAP = {
'0xfc5A1A6EB076a2C7aD06eD22C90d7E710E35ad0a': {
decimals: 18,
symbol: 'GMX',
origin: ['GMX'],
destination: ['GMX'],
origin: ['GMX', 'Intents'],
destination: ['GMX', 'Intents'],
swappable: [],
},
},
Expand Down
1 change: 1 addition & 0 deletions packages/sdk-router/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
"jest": "^29.7.0",
"jsbi": "^4.3.0",
"node-cache": "^5.1.2",
"pino": "^9.5.0",
"tiny-invariant": "^1.2.0",
"toformat": "^2.0.0",
"ts-xor": "^1.1.0",
Expand Down
47 changes: 32 additions & 15 deletions packages/sdk-router/src/rfq/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
FastBridgeQuoteAPI,
unmarshallFastBridgeQuote,
} from './quote'
import { logger } from '../utils/logger'

const API_URL = 'https://rfq-api-stage.omnirpc.io'
const API_TIMEOUT = 2000
Expand Down Expand Up @@ -65,12 +66,18 @@ export const fetchWithTimeout = async (
timeout: number,
init?: RequestInit
): Promise<Response> => {
const start = Date.now()
const controller = new AbortController()
const reason = `Timeout of ${timeout}ms exceeded for ${url}`
const timeoutId = setTimeout(() => (controller.abort as any)(reason), timeout)
return fetch(url, { signal: controller.signal, ...init }).finally(() =>
clearTimeout(timeoutId)
)
return fetch(url, { signal: controller.signal, ...init })
.then((response) => {
const end = Date.now()
const timeTaken = end - start
logger.info({ url, timeTaken }, 'API request completed')
return response
})
.finally(() => clearTimeout(timeoutId))
}

/**
Expand All @@ -83,23 +90,27 @@ export const getAllQuotes = async (): Promise<FastBridgeQuote[]> => {
try {
const response = await fetchWithTimeout(`${API_URL}/quotes`, API_TIMEOUT)
if (!response.ok) {
console.error('Error fetching quotes:', response.statusText)
logger.error({ response }, 'Error fetching quotes')
return []
}
// The response is a list of quotes in the FastBridgeQuoteAPI format
const quotes: FastBridgeQuoteAPI[] = await response.json()
logger.info(
{ quotes },
`Received ${quotes.length} quotes from ${API_URL}/quotes`
)
return quotes
.map((quote) => {
try {
return unmarshallFastBridgeQuote(quote)
} catch (error) {
console.error('Error unmarshalling quote:', error)
logger.error({ quote, error }, 'Error unmarshalling quote')
return null
}
})
.filter((quote): quote is FastBridgeQuote => quote !== null)
} catch (error) {
console.error('Error fetching quotes:', error)
logger.error({ error }, 'Error fetching quotes')
return []
}
}
Expand Down Expand Up @@ -141,28 +152,34 @@ export const getBestRelayerQuote = async (
},
})
if (!response.ok) {
console.error('Error fetching quote:', response.statusText)
logger.error({ rfqRequest, response }, 'Error fetching quote')
return ZeroQuote
}
// Check that response is successful, contains non-zero dest amount, and has a relayer address
const rfqResponse: PutRFQResponseAPI = await response.json()
logger.info(
{ rfqRequest, rfqResponse },
`Received quote from ${API_URL}/rfq`
)
if (!rfqResponse.success) {
console.error(
'No RFQ quote returned:',
rfqResponse.reason ?? 'Unknown reason'
logger.error(
{
reason: rfqResponse.reason ?? 'Unknown reason',
},
'No RFQ quote returned'
)
return ZeroQuote
}
if (!rfqResponse.dest_amount || !rfqResponse.relayer_address) {
console.error(
'Error fetching quote: missing dest_amount or relayer_address in response:',
rfqResponse
logger.error(
{ rfqResponse },
'Error fetching quote: missing dest_amount or relayer_address in response:'
)
return ZeroQuote
}
const destAmount = BigNumber.from(rfqResponse.dest_amount)
if (destAmount.lte(0)) {
console.error('No RFQ quote returned')
logger.error({ rfqResponse }, 'No RFQ quote returned')
return ZeroQuote
}
return {
Expand All @@ -171,7 +188,7 @@ export const getBestRelayerQuote = async (
quoteID: rfqResponse.quote_id,
}
} catch (error) {
console.error('Error fetching quote:', error)
logger.error({ error }, 'Error fetching quote')
return ZeroQuote
}
}
22 changes: 16 additions & 6 deletions packages/sdk-router/src/rfq/engine/odosEngine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
import { AddressMap } from '../../constants'
import { isSameAddress } from '../../utils/addressUtils'
import { isNativeToken } from '../../utils/handleNativeToken'
import { logger } from '../../utils/logger'

const ODOS_API_URL = 'https://api.odos.xyz/sor'
const ODOS_API_TIMEOUT = 2000
Expand Down Expand Up @@ -112,7 +113,7 @@ export class OdosEngine implements SwapEngine {
request.inputTokens.length !== 1 ||
request.outputTokens.length !== 1
) {
console.error({ request }, 'Multi-token swaps not supported')
logger.error({ request }, 'Multi-token swaps not supported')
return EMPTY_SWAP_API_RESPONSE
}
// Get a quote with the pathID first
Expand All @@ -128,22 +129,30 @@ export class OdosEngine implements SwapEngine {
}
)
if (!response.ok) {
console.error({ request, response }, 'Error fetching Odos response')
const responseText = await response.text()
logger.error(
{ request, response, responseText },
'Error fetching Odos response'
)
return EMPTY_SWAP_API_RESPONSE
}
const odosQuoteResponse: OdosQuoteResponse = await response.json()
if (
odosQuoteResponse.outAmounts.length !== 1 ||
!odosQuoteResponse.pathId
) {
console.error({ request, response }, 'Invalid Odos response')
logger.error({ request, response }, 'Invalid Odos response')
return EMPTY_SWAP_API_RESPONSE
}
const amountOut = odosQuoteResponse.outAmounts[0]
if (amountOut === '0') {
console.info({ request, response }, 'Zero amount out')
logger.info({ request, response }, 'Zero amount out')
return EMPTY_SWAP_API_RESPONSE
}
logger.info(
{ request, response, amountOut },
'Received amount out from Odos'
)
// Once we verified the amount out, we can assemble the transaction
const assembleRequest: OdosAssembleRequest = {
userAddr: request.userAddr,
Expand All @@ -161,17 +170,18 @@ export class OdosEngine implements SwapEngine {
}
)
if (!assembleResponse.ok) {
console.error({ assembleResponse }, 'Error fetching Odos response')
logger.error({ assembleResponse }, 'Error fetching Odos response')
return EMPTY_SWAP_API_RESPONSE
}
const odosAssembleResponse: OdosAssembleResponse =
await assembleResponse.json()
logger.info({ odosAssembleResponse }, 'Received transaction from Odos')
return {
amountOut,
transaction: odosAssembleResponse.transaction,
}
} catch (error) {
console.error({ request, error }, 'Error fetching Odos response')
logger.error({ request, error }, 'Error fetching Odos response')
return EMPTY_SWAP_API_RESPONSE
}
}
Expand Down
13 changes: 9 additions & 4 deletions packages/sdk-router/src/rfq/engine/paraSwapEngine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
} from './response'
import { ChainProvider } from '../../router'
import { isNativeToken } from '../../utils/handleNativeToken'
import { logger } from '../../utils/logger'

const PARASWAP_API_URL = 'https://api.paraswap.io/swap'
const PARASWAP_API_TIMEOUT = 2000
Expand Down Expand Up @@ -110,6 +111,7 @@ export class ParaSwapEngine implements SwapEngine {

public async getResponse(request: ParaSwapRequest): Promise<SwapAPIResponse> {
try {
logger.info({ request }, 'Fetching ParaSwap response')
// Stringify every value in the request
const params = new URLSearchParams(
Object.entries(request).map(([k, v]) => {
Expand All @@ -119,7 +121,10 @@ export class ParaSwapEngine implements SwapEngine {
const url = `${PARASWAP_API_URL}?${params.toString()}`
const response = await fetchWithTimeout(url, PARASWAP_API_TIMEOUT)
if (!response.ok) {
console.error('Error fetching ParaSwap response:', response)
logger.error(
{ url, request, response },
'Error fetching ParaSwap response'
)
return EMPTY_SWAP_API_RESPONSE
}
const paraswapResponse: ParaSwapResponse = await response.json()
Expand All @@ -128,7 +133,7 @@ export class ParaSwapEngine implements SwapEngine {
transaction: paraswapResponse.txParams,
}
} catch (error) {
console.error('Error fetching ParaSwap response:', error)
logger.error({ request, error }, 'Error fetching ParaSwap response')
return EMPTY_SWAP_API_RESPONSE
}
}
Expand All @@ -143,14 +148,14 @@ export class ParaSwapEngine implements SwapEngine {
}
const provider = this.providers[chainId]
if (!provider) {
console.error('No provider found for chainId', chainId)
logger.error({ chainId }, 'No provider found')
return 0
}
const tokenContract = new Contract(token, erc20ABI, provider) as ERC20
try {
return tokenContract.decimals()
} catch (error) {
console.error('Error fetching token decimals:', error)
logger.error({ token, error }, 'Error fetching token decimals')
return 0
}
}
Expand Down
Loading
Loading