Conversation
0xh3rman
commented
Mar 10, 2026
- Add Bitcoin chain support to Relay swapper with PSBT-based swap data
- Add BitcoinStepData variant to StepData enum for PSBT transactions
- Map Relay gas fees as Bitcoin transaction fee (PR Use swap contract gas_limit for bitcoin transaction fee #979)
- Rename SwapQuoteData.gas_limit to limit with serde alias for backward-compatible deserialization from gasLimit JSON field
- Fix near intents test
- Add Bitcoin chain support to Relay swapper with PSBT-based swap data - Add BitcoinStepData variant to StepData enum for PSBT transactions - Map Relay gas fees as Bitcoin transaction fee (PR #979) - Rename SwapQuoteData.gas_limit to limit with serde alias for backward-compatible deserialization from gasLimit JSON field
Extract swap_provider_fee helper and simplify Bitcoin preload fee logic; parse relay swap fee limits as TransactionFee. Update relay asset mapping to use RelayChain (and remove is_evm), handle EVM zero address and token checksum more robustly, and adjust asset_to_currency accordingly. Rename gas_limit→fee_limit in mapper and stop converting RelayChain to Chain when resolving metadata. Also update near_intents test: increase test value, broaden error handling to include InputAmountError, and assert presence of a memo.
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request significantly expands the capabilities of the Relay swapper by integrating full Bitcoin chain support. It introduces the necessary data structures and logic to handle Bitcoin transactions, including PSBT-based swap data and proper mapping of Relay's gas fees to Bitcoin transaction fees. Additionally, a key refactoring was performed by renaming a core field in Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
Introduce a BitcoinChainSigner implementation that signs PSBTs (supports Relay PSBT flow; Thorchain/Chainflip not implemented). Wire the signer into gem_bitcoin (new chain_signer.rs), export it from the signer module, and register it in gemstone's GemChainSigner constructor. Add bitcoin as an optional workspace dependency and enable necessary features in the top-level Cargo.toml. Also derive PartialEq for SwapQuoteDataType to allow comparisons.
There was a problem hiding this comment.
Code Review
This pull request introduces Bitcoin support for the Relay swapper, a significant feature addition. The changes span multiple crates, including adding a BitcoinStepData variant for PSBT-based swaps and mapping Relay gas fees to Bitcoin transaction fees. A notable part of this PR is the refactoring of gas_limit to limit across the codebase for consistency, with backward compatibility handled via serde aliases. The implementation is solid, but I have identified a couple of areas for improvement related to code consistency and idiomatic Rust usage, for which I've provided suggestions.
| fn swap_provider_fee(input: &TransactionLoadInput) -> Option<Result<TransactionFee, &'static str>> { | ||
| let swap_data = input.input_type.get_swap_data().ok()?; | ||
| if swap_data.data.data_type != SwapQuoteDataType::Contract { | ||
| return None; | ||
| } | ||
| let provider = swap_data.quote.provider_data.provider; | ||
| if !matches!(provider, SwapProvider::Relay) { | ||
| return None; | ||
| } | ||
| let limit = swap_data.data.limit.as_deref()?; | ||
| Some(limit.parse::<BigInt>().map(TransactionFee::new_from_fee).map_err(|_| "invalid swap fee")) | ||
| } |
There was a problem hiding this comment.
The function swap_provider_fee can be refactored for better readability and to be more idiomatic. Using if let to destructure input.input_type directly avoids the get_swap_data() call and contains the logic for Relay swaps within a single block, improving maintainability.
fn swap_provider_fee(input: &TransactionLoadInput) -> Option<Result<TransactionFee, &'static str>> {
if let TransactionInputType::Swap(_, _, swap_data) = &input.input_type {
if swap_data.data.data_type == SwapQuoteDataType::Contract
&& matches!(swap_data.quote.provider_data.provider, SwapProvider::Relay)
{
return swap_data.data.limit.as_deref().map(|limit| {
limit
.parse::<BigInt>()
.map(TransactionFee::new_from_fee)
.map_err(|_| "invalid swap fee")
});
}
}
None
}| fn mock_swap_data_with_gas_limit(provider: SwapProvider, gas_limit: Option<&str>) -> SwapData { | ||
| let mut data = SwapData::mock_with_provider(provider); | ||
| data.data.gas_limit = gas_limit.map(|s| s.to_string()); | ||
| data.data.limit = gas_limit.map(|s| s.to_string()); | ||
| data | ||
| } |
There was a problem hiding this comment.
For consistency with the global rename of gas_limit to limit, this test helper function and its parameter should also be renamed. mock_swap_data_with_gas_limit should be mock_swap_data_with_limit, and the parameter gas_limit should be limit.
| fn mock_swap_data_with_gas_limit(provider: SwapProvider, gas_limit: Option<&str>) -> SwapData { | |
| let mut data = SwapData::mock_with_provider(provider); | |
| data.data.gas_limit = gas_limit.map(|s| s.to_string()); | |
| data.data.limit = gas_limit.map(|s| s.to_string()); | |
| data | |
| } | |
| fn mock_swap_data_with_limit(provider: SwapProvider, limit: Option<&str>) -> SwapData { | |
| let mut data = SwapData::mock_with_provider(provider); | |
| data.data.limit = limit.map(|s| s.to_string()); | |
| data | |
| } |