Skip to content

Commit

Permalink
SDK: add RFQ (#1695)
Browse files Browse the repository at this point in the history
* ChainToken marshalling

* Ticker marshalling

* Chore: docs

* Scaffold FastBridge class

* Scaffold FastBridgeSet class

* Implement `getBridgeRoutes`

* Add some initial values for RFQ contracts

* Add coverage for `createNoSwapQuery`

* Add fastBridgeContract

* Implement `fastBridge.bridge()`

* Initialize set of FastBridge modules

* FastBridgeQuote type for current Quote structure

* Add `applyQuote()`

* Adjust getBridgeRoutes to current API

* Implement `getAllQuotes`

* Add API unit tests, make SDK tests pass

* Add node-fetch@^2 for integration tests

* Add URL, integration test

* Add unit tests for quote pricing

* Add some tests around zero quotes

* Hardcode rounding tests

* Use correct pricing algo

* Add tests for FastBridgeSet

* Fix: properly implement quote filtering

* Add some units tests for FastBridge class

* Mainnet API URL

* Draw the rest of the owl

* Fix: incorrect invariant

* Temp FE fix: don't apply slippage to RFQ

* [DROP IN PROD] Use local SDK for build

* Add tests for expected `bridge()` behavior

* Use correct tx.value

* [REVERT IN PROD] up the deadline for RFQ

* Update FastBridge bindings

* Temp fix: support origin sender address

* Update FastBridge addresses

* Use only quotes with age of [0 .. 5) minutes

* Skip tests: sending with non-zero gas rebate

* Temp fix for zero gas airdrop for RFQ

* Include origin/dest FastBridge address in api response

* Discard quotes with non-relevant FastBridge address

* Update addresses

* Fix: tests

* try to add rfq bridgestatus sdk call to fe

* Fix: use snake case for api quote schema

* Fix: tests

* yarn lint:fix

* Coverage for RFQ tracking

* SDK: fix median time

* Start using SDK to check status earlier

* Revert "[REVERT IN PROD] up the deadline for RFQ"

This reverts commit 8fae090.

* Add bridgeTransactions reducer to host updated Txn flow

* Expose helper hook `useBridgeTransactionsState`

* _Transaction component using SDK for status

* _Transactions component to render individual _Transaction

* Implement SDK-based Pending Transaction flow

* Persist _Transaction slice

* _Transaction tracking newly fired txs

* Provide Origin/Destination Token/Chain into _Transaction

* Basic styled _Transaction component with SDK tracking

* Add spacing between Tx

* Updated FE transaction time estimation logic and interval check frequency

* Revised the logic for estimating transaction completion time in _Transaction.tsx. Now, the system starts checking for transaction completion a few minutes before the estimated completion time.
* Reduced the interval for checking the current time in _Transactions.tsx from 30 seconds to 5 seconds.

* Adds try catch to prevent app crashing (#1762)

* Fe/sorting wip (#1770)

* Sorting wip

* Show by latest

* Merging sorting-j

* Hides debugging related kappa and time

* debug why new type isnt recognized

* Convert transactions object to list

* Render transactions in list

* Check tx is stored before adding into _transaction

* Check tx has been confirmed before adding to _transaction store

* Sorting by descending timestamp

* Allow clear tx functionality to persist

* back to optimism mainnet rpc

* Prevent refiring tx sdk queries if already complete

* Mark tx as complete once kappa and isTxComplete avail

* Check if store marked Tx complete before firing tx status hook, render persisted tx status

* `useBridgeTxStatus` hook initialized to set isComplete to true if kappa exists, save call

* Revert prev commit, require check on tx status beyond kappa avail

* Utilize `checkStatus` as guardrail check in `useBridgeTxStatus`

* removes unused prop

* removes another unused prop

* Hide debugging meta

* Hide debugging meta

* limits to 5 txns

* align time

---------

Co-authored-by: bigboydiamonds <[email protected]>

* Chore: fix lint

* Revert "[DROP IN PROD] Use local SDK for build"

This reverts commit 32dcaf6.

---------

Co-authored-by: aureliusbtc <[email protected]>
Co-authored-by: Daniel Wasserman <[email protected]>
Co-authored-by: bigboydiamonds <[email protected]>
Co-authored-by: abtestingalpha <[email protected]>
  • Loading branch information
5 people authored Jan 8, 2024
1 parent 81a4ccd commit 07fc2fc
Show file tree
Hide file tree
Showing 41 changed files with 2,613 additions and 17 deletions.
2 changes: 2 additions & 0 deletions packages/sdk-router/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@
"@types/jest": "^24.0.25",
"dotenv": "^16.3.1",
"husky": "^8.0.1",
"jest-mock-extended": "^3.0.5",
"node-fetch": "^2.0.0",
"size-limit": "^8.1.0",
"tsdx": "^0.14.1",
"tslib": "^2.4.0",
Expand Down
1 change: 1 addition & 0 deletions packages/sdk-router/src/abi/FastBridge.json
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,7 @@
{
"components": [
{ "internalType": "uint32", "name": "dstChainId", "type": "uint32" },
{ "internalType": "address", "name": "sender", "type": "address" },
{ "internalType": "address", "name": "to", "type": "address" },
{
"internalType": "address",
Expand Down
24 changes: 23 additions & 1 deletion packages/sdk-router/src/constants/addresses.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { CCTP_SUPPORTED_CHAIN_IDS, SUPPORTED_CHAIN_IDS } from './chainIds'
import {
CCTP_SUPPORTED_CHAIN_IDS,
RFQ_SUPPORTED_CHAIN_IDS,
SUPPORTED_CHAIN_IDS,
SupportedChainId,
} from './chainIds'

export type AddressMap = {
[chainId: number]: string
Expand Down Expand Up @@ -48,3 +53,20 @@ export const CCTP_ROUTER_ADDRESS_MAP: AddressMap = generateAddressMap(
CCTP_ROUTER_ADDRESS,
CCTP_ROUTER_EXCEPTION_MAP
)

/**
* FastBridge contract address for all chains except ones from FAST_BRIDGE_ADDRESS.
*
* TODO: Update this address once FastBridge is deployed.
*/
const FAST_BRIDGE_ADDRESS = ''
const FAST_BRIDGE_EXCEPTION_MAP: AddressMap = {
[SupportedChainId.OPTIMISM]: '0x743fFbd0DbF88F6fCB7FaDf58fB641da93056EdF',
[SupportedChainId.ARBITRUM]: '0xA9EBFCb6DCD416FE975D5aB862717B329407f4F7',
}

export const FAST_BRIDGE_ADDRESS_MAP: AddressMap = generateAddressMap(
RFQ_SUPPORTED_CHAIN_IDS,
FAST_BRIDGE_ADDRESS,
FAST_BRIDGE_EXCEPTION_MAP
)
10 changes: 10 additions & 0 deletions packages/sdk-router/src/constants/chainIds.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,13 @@ export const CCTP_SUPPORTED_CHAIN_IDS: number[] = [
SupportedChainId.BASE,
SupportedChainId.POLYGON, // Circle domain 7
]

/**
* List of chain ids where FastBridge (RFQ) is deployed, ordered by chain id
*
* Note: This is a subset of SUPPORTED_CHAIN_IDS.
*/
export const RFQ_SUPPORTED_CHAIN_IDS: number[] = [
SupportedChainId.OPTIMISM,
SupportedChainId.ARBITRUM,
]
10 changes: 10 additions & 0 deletions packages/sdk-router/src/constants/medianTime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,13 @@ export const MEDIAN_TIME_CCTP = {
[SupportedChainId.AVALANCHE]: 30,
[SupportedChainId.POLYGON]: 480,
}

/**
* Median time (in seconds) for a SynapseRFQ transaction to be completed,
* when the transaction is sent from a given chain.
* TODO: Update this value once we have a better estimate.
*/
export const MEDIAN_TIME_RFQ = {
[SupportedChainId.OPTIMISM]: 30,
[SupportedChainId.ARBITRUM]: 30,
}
12 changes: 12 additions & 0 deletions packages/sdk-router/src/module/query.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
modifyDeadline,
applySlippage,
applySlippageInBips,
createNoSwapQuery,
} from './query'

describe('#query', () => {
Expand Down Expand Up @@ -380,4 +381,15 @@ describe('#query', () => {
)
})
})

it('createNoSwapQuery', () => {
const query = createNoSwapQuery('1', BigNumber.from(2))
expect(query).toEqual({
routerAdapter: '0x0000000000000000000000000000000000000000',
tokenOut: '1',
minAmountOut: BigNumber.from(2),
deadline: BigNumber.from(0),
rawParams: '0x',
})
})
})
17 changes: 17 additions & 0 deletions packages/sdk-router/src/module/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,3 +165,20 @@ export const applySlippageInBips = (
): Query => {
return applySlippage(query, slipBasisPoints, 10000)
}

/**
* Creates a Query object for a no-swap bridge action.
*
* @param token - The token to bridge.
* @param amount - The amount of token to bridge.
* @returns The Query object for a no-swap bridge action.
*/
export const createNoSwapQuery = (token: string, amount: BigNumber): Query => {
return {
routerAdapter: AddressZero,
tokenOut: token,
minAmountOut: amount,
deadline: BigNumber.from(0),
rawParams: '0x',
}
}
69 changes: 69 additions & 0 deletions packages/sdk-router/src/rfq/api.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { getAllQuotes } from './api'
import { FastBridgeQuoteAPI, unmarshallFastBridgeQuote } from './quote'

describe('getAllQuotes', () => {
const quotesAPI: FastBridgeQuoteAPI[] = [
{
origin_chain_id: 1,
origin_token_addr: '0x0000000000000000000000000000000000000001',
dest_chain_id: 2,
dest_token_addr: '0x0000000000000000000000000000000000000002',
dest_amount: '3',
max_origin_amount: '4',
fixed_fee: '5',
origin_fast_bridge_address: '10',
dest_fast_bridge_address: '11',
relayer_addr: '0x0000000000000000000000000000000000000003',
updated_at: '2023-01-01T00:00:00.420Z',
},
{
origin_chain_id: 3,
origin_token_addr: '0x0000000000000000000000000000000000000004',
dest_chain_id: 4,
dest_token_addr: '0x0000000000000000000000000000000000000005',
dest_amount: '6',
max_origin_amount: '7',
fixed_fee: '8',
origin_fast_bridge_address: '20',
dest_fast_bridge_address: '21',
relayer_addr: '0x0000000000000000000000000000000000000006',
updated_at: '2023-01-02T00:00:00.420Z',
},
]

it('returns an empty array when the response is not ok', async () => {
global.fetch = jest.fn(() =>
Promise.resolve({
status: 500,
ok: false,
})
) as any

const result = await getAllQuotes()
expect(result).toEqual([])
})

it('returns a list of quotes when the response is ok', async () => {
global.fetch = jest.fn(() =>
Promise.resolve({
status: 200,
ok: true,
json: () => Promise.resolve(quotesAPI),
})
) as any

const result = await getAllQuotes()
// You might need to adjust this depending on how your unmarshallFastBridgeQuote function works
expect(result).toEqual([
unmarshallFastBridgeQuote(quotesAPI[0]),
unmarshallFastBridgeQuote(quotesAPI[1]),
])
})

it('Integration test', async () => {
global.fetch = require('node-fetch')
const result = await getAllQuotes()
console.log('Quotes: ' + JSON.stringify(result, null, 2))
expect(result.length).toBeGreaterThan(0)
})
})
23 changes: 23 additions & 0 deletions packages/sdk-router/src/rfq/api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import {
FastBridgeQuote,
FastBridgeQuoteAPI,
unmarshallFastBridgeQuote,
} from './quote'

const API_URL = 'https://rfq-api.omnirpc.io'

/**
* Hits Quoter API /quotes endpoint to get all quotes.
*
* @returns A promise that resolves to the list of quotes.
*/
export const getAllQuotes = async (): Promise<FastBridgeQuote[]> => {
const response = await fetch(API_URL + '/quotes')
// Return empty list if response is not ok
if (!response.ok) {
return []
}
// The response is a list of quotes in the FastBridgeQuoteAPI format
const quotes: FastBridgeQuoteAPI[] = await response.json()
return quotes.map(unmarshallFastBridgeQuote)
}
Loading

0 comments on commit 07fc2fc

Please sign in to comment.