-
Notifications
You must be signed in to change notification settings - Fork 43
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add stablecoins for a2a bridging (#1373)
* feat: add stablecoins for a2a bridging * prevent infinite loop 508 * fixup * another try to prevent 508 * fix: override vercel dev typescript version * fixup * fixup * fixup * fixup * use fallback in indicative quote * use services
- Loading branch information
Showing
12 changed files
with
520 additions
and
426 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
import { BigNumber, constants } from "ethers"; | ||
|
||
import { getProvider, latestGasPriceCache } from "../../_utils"; | ||
import { buildCrossSwapTxForAllowanceHolder } from "./_utils"; | ||
import { | ||
handleBaseSwapQueryParams, | ||
BaseSwapQueryParams, | ||
getApprovalTxns, | ||
buildBaseSwapResponseJson, | ||
} from "../_utils"; | ||
import { getBalanceAndAllowance } from "../../_erc20"; | ||
import { getCrossSwapQuotes } from "../../_dexes/cross-swap-service"; | ||
import { QuoteFetchStrategies } from "../../_dexes/utils"; | ||
import { TypedVercelRequest } from "../../_types"; | ||
import { getSwapRouter02Strategy } from "../../_dexes/uniswap/swap-router-02"; | ||
|
||
// For approval-based flows, we use the `UniversalSwapAndBridge` strategy with Uniswap V3's `SwapRouter02` | ||
const quoteFetchStrategies: QuoteFetchStrategies = { | ||
default: getSwapRouter02Strategy("UniversalSwapAndBridge"), | ||
}; | ||
|
||
export async function handleApprovalSwap( | ||
request: TypedVercelRequest<BaseSwapQueryParams> | ||
) { | ||
const { | ||
integratorId, | ||
skipOriginTxEstimation, | ||
isInputNative, | ||
isOutputNative, | ||
inputToken, | ||
outputToken, | ||
amount, | ||
amountType, | ||
refundOnOrigin, | ||
refundAddress, | ||
recipient, | ||
depositor, | ||
slippageTolerance, | ||
refundToken, | ||
} = await handleBaseSwapQueryParams(request.query); | ||
|
||
const crossSwapQuotes = await getCrossSwapQuotes( | ||
{ | ||
amount, | ||
inputToken, | ||
outputToken, | ||
depositor, | ||
recipient: recipient || depositor, | ||
slippageTolerance: Number(slippageTolerance), | ||
type: amountType, | ||
refundOnOrigin, | ||
refundAddress, | ||
isInputNative, | ||
isOutputNative, | ||
}, | ||
quoteFetchStrategies | ||
); | ||
|
||
const crossSwapTx = await buildCrossSwapTxForAllowanceHolder( | ||
crossSwapQuotes, | ||
integratorId | ||
); | ||
|
||
const { originSwapQuote, bridgeQuote, destinationSwapQuote, crossSwap } = | ||
crossSwapQuotes; | ||
|
||
const originChainId = crossSwap.inputToken.chainId; | ||
const inputTokenAddress = isInputNative | ||
? constants.AddressZero | ||
: crossSwap.inputToken.address; | ||
const inputAmount = | ||
originSwapQuote?.maximumAmountIn || bridgeQuote.inputAmount; | ||
|
||
const { allowance, balance } = await getBalanceAndAllowance({ | ||
chainId: originChainId, | ||
tokenAddress: inputTokenAddress, | ||
owner: crossSwap.depositor, | ||
spender: crossSwapTx.to, | ||
}); | ||
|
||
const isSwapTxEstimationPossible = | ||
!skipOriginTxEstimation && | ||
allowance.gte(inputAmount) && | ||
balance.gte(inputAmount); | ||
|
||
let originTxGas: BigNumber | undefined; | ||
let originTxGasPrice: | ||
| { | ||
maxFeePerGas: BigNumber; | ||
maxPriorityFeePerGas: BigNumber; | ||
} | ||
| undefined; | ||
if (isSwapTxEstimationPossible) { | ||
const provider = getProvider(originChainId); | ||
[originTxGas, originTxGasPrice] = await Promise.all([ | ||
provider.estimateGas({ | ||
...crossSwapTx, | ||
from: crossSwap.depositor, | ||
}), | ||
latestGasPriceCache(originChainId).get(), | ||
]); | ||
} else { | ||
originTxGasPrice = await latestGasPriceCache(originChainId).get(); | ||
} | ||
|
||
let approvalTxns: | ||
| { | ||
chainId: number; | ||
to: string; | ||
data: string; | ||
}[] | ||
| undefined; | ||
// @TODO: Allow for just enough approval amount to be set. | ||
const approvalAmount = constants.MaxUint256; | ||
if (allowance.lt(inputAmount)) { | ||
approvalTxns = getApprovalTxns({ | ||
token: crossSwap.inputToken, | ||
spender: crossSwapTx.to, | ||
amount: approvalAmount, | ||
}); | ||
} | ||
|
||
const responseJson = buildBaseSwapResponseJson({ | ||
originChainId, | ||
inputTokenAddress, | ||
inputAmount, | ||
approvalSwapTx: { | ||
...crossSwapTx, | ||
gas: originTxGas, | ||
maxFeePerGas: originTxGasPrice?.maxFeePerGas, | ||
maxPriorityFeePerGas: originTxGasPrice?.maxPriorityFeePerGas, | ||
}, | ||
allowance, | ||
balance, | ||
approvalTxns, | ||
originSwapQuote, | ||
bridgeQuote, | ||
destinationSwapQuote, | ||
refundToken, | ||
}); | ||
return responseJson; | ||
} |
Oops, something went wrong.