-
Notifications
You must be signed in to change notification settings - Fork 30
/
fastBridgeRouter.ts
169 lines (153 loc) · 5.62 KB
/
fastBridgeRouter.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
import { Provider } from '@ethersproject/abstract-provider'
import invariant from 'tiny-invariant'
import { Contract, PopulatedTransaction } from '@ethersproject/contracts'
import { Interface } from '@ethersproject/abi'
import { BigNumber } from '@ethersproject/bignumber'
import fastBridgeAbi from '../abi/FastBridge.json'
import fastBridgeRouterAbi from '../abi/FastBridgeRouter.json'
import { FastBridgeRouter as FastBridgeRouterContract } from '../typechain/FastBridgeRouter'
import {
FastBridge as FastBridgeContract,
IFastBridge,
} from '../typechain/FastBridge'
import {
SynapseModule,
Query,
narrowToCCTPRouterQuery,
reduceToQuery,
} from '../module'
import { BigintIsh } from '../constants'
import { getMatchingTxLog } from '../utils/logs'
import { adjustValueIfNative } from '../utils/handleNativeToken'
import { CACHE_TIMES, RouterCache } from '../utils/RouterCache'
// Define type alias
export type BridgeParams = IFastBridge.BridgeParamsStruct
export class FastBridgeRouter implements SynapseModule {
static fastBridgeInterface = new Interface(fastBridgeAbi)
static fastBridgeRouterInterface = new Interface(fastBridgeRouterAbi)
public readonly address: string
public readonly chainId: number
public readonly provider: Provider
private readonly routerContract: FastBridgeRouterContract
private fastBridgeContractCache: FastBridgeContract | undefined
// All possible events emitted by the FastBridge contract in the origin transaction (in alphabetical order)
private readonly originEvents = ['BridgeRequested']
constructor(chainId: number, provider: Provider, address: string) {
invariant(chainId, 'CHAIN_ID_UNDEFINED')
invariant(provider, 'PROVIDER_UNDEFINED')
invariant(address, 'ADDRESS_UNDEFINED')
invariant(FastBridgeRouter.fastBridgeRouterInterface, 'INTERFACE_UNDEFINED')
invariant(FastBridgeRouter.fastBridgeInterface, 'INTERFACE_UNDEFINED')
this.chainId = chainId
this.provider = provider
this.address = address
this.routerContract = new Contract(
address,
FastBridgeRouter.fastBridgeRouterInterface,
provider
) as FastBridgeRouterContract
// TODO: figure out why this breaks the tests
// this.hydrateCache()
}
// private async hydrateCache() {
// if (HYDRATION_SUPPORTED_CHAIN_IDS.includes(this.chainId)) {
// try {
// await Promise.all([this.getProtocolFeeRate()])
// } catch (e) {
// console.error(
// '[SynapseSDK: FastBridgeRouter] Error hydrating cache: ',
// e
// )
// }
// }
// }
/**
* @inheritdoc SynapseModule.bridge
*/
public async bridge(
to: string,
destChainId: number,
token: string,
amount: BigintIsh,
originQuery: Query,
destQuery: Query
): Promise<PopulatedTransaction> {
const populatedTransaction =
await this.routerContract.populateTransaction.bridge(
to,
destChainId,
token,
amount,
narrowToCCTPRouterQuery(originQuery),
narrowToCCTPRouterQuery(destQuery)
)
// Adjust the tx.value if the initial token is native
return adjustValueIfNative(
populatedTransaction,
token,
BigNumber.from(amount)
)
}
/**
* @inheritdoc SynapseModule.getSynapseTxId
*/
public async getSynapseTxId(txHash: string): Promise<string> {
// TODO: this should support older instances of FastBridge to track legacy txs
const fastBridgeContract = await this.getFastBridgeContract()
const fastBridgeLog = await getMatchingTxLog(
this.provider,
txHash,
fastBridgeContract,
this.originEvents
)
// transactionId always exists in the log as we are using the correct ABI
const parsedLog = fastBridgeContract.interface.parseLog(fastBridgeLog)
return parsedLog.args.transactionId
}
/**
* @inheritdoc SynapseModule.getBridgeTxStatus
*/
public async getBridgeTxStatus(synapseTxId: string): Promise<boolean> {
// TODO: this should support older instances of FastBridge to track legacy txs
const fastBridgeContract = await this.getFastBridgeContract()
return fastBridgeContract.bridgeRelays(synapseTxId)
}
@RouterCache(CACHE_TIMES.TEN_MINUTES)
public async chainGasAmount(): Promise<BigNumber> {
const fastBridgeContract = await this.getFastBridgeContract()
return fastBridgeContract.chainGasAmount()
}
public async getFastBridgeContract(): Promise<FastBridgeContract> {
// Populate the cache if necessary
if (!this.fastBridgeContractCache) {
const address = await this.routerContract.fastBridge()
this.fastBridgeContractCache = new Contract(
address,
FastBridgeRouter.fastBridgeInterface,
this.provider
) as FastBridgeContract
}
return this.fastBridgeContractCache
}
// ══════════════════════════════════════════ FAST BRIDGE ROUTER ONLY ══════════════════════════════════════════════
public async getOriginAmountOut(
tokenIn: string,
rfqTokens: string[],
amountIn: BigintIsh
): Promise<Query[]> {
const queries = await this.routerContract.getOriginAmountOut(
tokenIn,
rfqTokens,
amountIn
)
return queries.map(reduceToQuery)
}
/**
* @returns The protocol fee rate, multiplied by 1_000_000 (e.g. 1 basis point = 100).
*/
@RouterCache(CACHE_TIMES.TEN_MINUTES)
public async getProtocolFeeRate(): Promise<BigNumber> {
const fastBridgeContract = await this.getFastBridgeContract()
return fastBridgeContract.protocolFeeRate()
}
}