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

feat(LRAPI): add 1inch classic swap rpc #2222

Open
wants to merge 26 commits into
base: dev
Choose a base branch
from
Open

feat(LRAPI): add 1inch classic swap rpc #2222

wants to merge 26 commits into from

Conversation

dimxy
Copy link
Collaborator

@dimxy dimxy commented Sep 16, 2024

This PR adds:

  • initial code to connect to 1inch Liquidity Routing API (LRAPI) provider (see new trading_api crate)
  • two new RPCs to use 1inch classic swap API
  • 'approve' and 'allowance' RPCs (for ERC20 tokens)

(This is an ongoing work to add features requested in #1287 in the part regarding "AMM" tech adoption. We need a dedicated issue for that)

TODO:

  • create a tracking issue for this LR API feature
  • add info rpc(s) from 1inch portfolio API (profit/loss etc)
  • add rpc to create ERC-2612 approvals

@dimxy dimxy added the in progress Changes will be made from the author label Sep 16, 2024
}

/// "1inch_classic_swap_create" rpc impl
pub async fn one_inch_v6_0_classic_swap_create_rpc(
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note, that this rpc actually creates a transaction to call the swap aggregation contract. It is supposed that the GUI should sign it and send. We don't verify the tx in any way and trust the 1inch api.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then lest add this clarification to doc comment

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Copy link
Member

@laruh laruh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great start! Here is the 1st review iteration

mm2src/mm2_main/src/ext_api/one_inch.rs Outdated Show resolved Hide resolved
mm2src/mm2_main/src/ext_api.rs Outdated Show resolved Hide resolved
mm2src/trading_api/src/one_inch_api.rs Outdated Show resolved Hide resolved
mm2src/trading_api/src/one_inch_api/types.rs Outdated Show resolved Hide resolved
mm2src/trading_api/src/lib.rs Outdated Show resolved Hide resolved
mm2src/mm2_main/src/ext_api/one_inch/types.rs Outdated Show resolved Hide resolved
mm2src/trading_api/src/one_inch_api/types.rs Outdated Show resolved Hide resolved
mm2src/trading_api/src/one_inch_api/types.rs Show resolved Hide resolved
pub struct ClassicSwapQuoteRequest {
pub base: String,
pub rel: String,
pub amount: BigDecimal,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about using the U256 type for the "amount" from the beginning? We don’t have a 1inch coin, in wallet or our own trading protocol features, so we are free to use coin-specific types for external third-party trading

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I used BigDecimal to make it like most our other rpcs do (for e.g. withdraw).
But now I see I probably should use MmNumber as those classic swap rpcs are close to our "buy" and "sell" methods

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made the swap amount as MmNumber (like in our own swap rpcs). I hope this is consistent

Copy link
Member

@laruh laruh Sep 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made the swap amount as MmNumber (like in our own swap rpcs). I hope this is consistent

Hmm, I think yes. We use MmNumber type for atomic swaps and, as 1inch is a trading aggregator, then we can do the same for it.

I will leave comment as unresolved, so other people can find this.

mm2src/mm2_main/src/ext_api/one_inch/rpcs.rs Outdated Show resolved Hide resolved
@dimxy dimxy added under review and removed in progress Changes will be made from the author labels Sep 18, 2024
Copy link
Collaborator

@mariocynicys mariocynicys left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks :)
First review iteration.

mm2src/mm2_main/src/ext_api.rs Outdated Show resolved Hide resolved
mm2src/mm2_main/src/ext_api/one_inch.rs Outdated Show resolved Hide resolved
mm2src/mm2_main/src/ext_api/one_inch/types.rs Outdated Show resolved Hide resolved
mm2src/mm2_main/src/ext_api/one_inch/types.rs Outdated Show resolved Hide resolved
mm2src/mm2_main/src/ext_api/one_inch/rpcs.rs Outdated Show resolved Hide resolved
mm2src/mm2_main/src/ext_api/one_inch/types.rs Outdated Show resolved Hide resolved
mm2src/mm2_main/src/ext_api/one_inch/rpcs.rs Outdated Show resolved Hide resolved
mm2src/trading_api/src/one_inch_api.rs Outdated Show resolved Hide resolved
mm2src/trading_api/src/one_inch_api/types.rs Outdated Show resolved Hide resolved
mm2src/mm2_main/src/ext_api/one_inch/errors.rs Outdated Show resolved Hide resolved
mm2src/mm2_main/src/ext_api/one_inch/errors.rs Outdated Show resolved Hide resolved
mm2src/mm2_main/src/ext_api/one_inch/errors.rs Outdated Show resolved Hide resolved
mm2src/trading_api/src/one_inch_api/client.rs Outdated Show resolved Hide resolved
Comment on lines 56 to 99
pub fn with_fee(mut self, fee: Option<f32>) -> Self {
self.fee = fee;
self
}
pub fn with_protocols(mut self, protocols: Option<String>) -> Self {
self.protocols = protocols;
self
}
pub fn with_gas_price(mut self, gas_price: Option<String>) -> Self {
self.gas_price = gas_price;
self
}
pub fn with_complexity_level(mut self, complexity_level: Option<u32>) -> Self {
self.complexity_level = complexity_level;
self
}
pub fn with_parts(mut self, parts: Option<u32>) -> Self {
self.parts = parts;
self
}
pub fn with_main_route_parts(mut self, main_route_parts: Option<u32>) -> Self {
self.main_route_parts = main_route_parts;
self
}
pub fn with_gas_limit(mut self, gas_limit: Option<u128>) -> Self {
self.gas_limit = gas_limit;
self
}
pub fn with_include_tokens_info(mut self, include_tokens_info: Option<bool>) -> Self {
self.include_tokens_info = include_tokens_info;
self
}
pub fn with_include_protocols(mut self, include_protocols: Option<bool>) -> Self {
self.include_protocols = include_protocols;
self
}
pub fn with_include_gas(mut self, include_gas: Option<bool>) -> Self {
self.include_gas = include_gas;
self
}
pub fn with_connector_tokens(mut self, connector_tokens: Option<String>) -> Self {
self.connector_tokens = connector_tokens;
self
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not a fan of this pattern personally, but if we really want to do this I guess the best way would be creating macro which implements this pattern automatically without taking too much space in the module.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not a fan of this pattern personally, but if we really want to do this I guess the best way would be creating macro which implements this pattern automatically without taking too much space in the module.

really like this idea

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

made a macro, great idea, ty

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

@borngraced borngraced left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

great work! couple notes for first review

mm2src/trading_api/src/one_inch_api/types.rs Outdated Show resolved Hide resolved
mm2src/trading_api/src/one_inch_api/client.rs Outdated Show resolved Hide resolved
mm2src/trading_api/src/one_inch_api/client.rs Outdated Show resolved Hide resolved
@@ -866,6 +852,8 @@ impl EthCoinImpl {
let guard = self.erc20_tokens_infos.lock().unwrap();
(*guard).clone()
}

pub fn chain_id(&self) -> u64 { self.chain_id }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
pub fn chain_id(&self) -> u64 { self.chain_id }
#[inline(always)]
pub fn chain_id(&self) -> u64 { self.chain_id }

mm2src/coins/eth/eth_rpc.rs Outdated Show resolved Hide resolved
mm2src/coins/lp_coins.rs Outdated Show resolved Hide resolved
mm2src/coins/lp_coins.rs Outdated Show resolved Hide resolved
mm2src/coins/lp_coins.rs Outdated Show resolved Hide resolved
mm2src/coins/lp_coins.rs Outdated Show resolved Hide resolved
mm2src/coins/lp_coins.rs Outdated Show resolved Hide resolved
mm2src/coins/lp_coins.rs Outdated Show resolved Hide resolved
mariocynicys
mariocynicys previously approved these changes Sep 27, 2024
Copy link
Collaborator

@mariocynicys mariocynicys left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!
LGTM :)

@laruh
Copy link
Member

laruh commented Oct 4, 2024

@dimxy please fix branch conflicts

Copy link
Collaborator

@shamardy shamardy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR! First review iteration from my side where I gave the types.rs a first look.

mm2src/trading_api/Cargo.toml Outdated Show resolved Hide resolved
mm2src/trading_api/src/one_inch_api/types.rs Show resolved Hide resolved
mm2src/trading_api/src/one_inch_api/types.rs Show resolved Hide resolved
mm2src/trading_api/src/one_inch_api/types.rs Show resolved Hide resolved
mm2src/trading_api/src/one_inch_api/types.rs Show resolved Hide resolved
mm2src/trading_api/src/one_inch_api/types.rs Outdated Show resolved Hide resolved
* dev:
  fix(cosmos): fix tx broadcasting error (#2238)
  chore(solana): remove solana implementation (#2239)
  chore(cli): remove leftover subcommands from help message (#2235)
  fix(orders): fix cancel order race condition using time-based cache (#2232)
  fix(legacy-swap): taker failed spend maker payment marked as failed (#2199)
  chore(adex-cli): deprecate adex-cli (#2234)
  feat(new-RPC): connection healthcheck implementation for peers  (#2194)
  fix(proxy-signature): add message lifetime overflows (#2233)
  feat(CI): handle remote files in a safer way (#2217)
  chore(doc): update issue address in README (#2227)
  fix(merge): remove duplicated db_root function (#2229)
  feat(wallets): add `get_wallet_names` rpc (#2202)
  chore(tests): don't use `.wait()` and use `block_on` instead (#2220)
  fix(native-rpc): remove escaped response body (#2219)
  fix(clippy): fix coins mod clippy warnings in wasm (#2224)
  feat(core): handling CTRL-C signal with graceful shutdown (#2213)
  docs(README): fix typos (#2212)
  remove the non-sense arguments (#2216)
  fix(db): stop creating the all-zeroes dir on KDF start (#2218)
@dimxy
Copy link
Collaborator Author

dimxy commented Oct 17, 2024

In the recent 5 commits I fixed most review notes above,
Also changed the return swap amount type from just MmNumber to DetailedAmount as three numbers (BigDecimal, Fraction and Ratio) as in most other swap api results (for e.g. trade_preimage_rpc)
Also added deny_unknown_fields serde option to rpc requests (good to check if any param misspelled)

Copy link
Member

@borngraced borngraced left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

last notes from me

mm2src/coins/lp_coins.rs Outdated Show resolved Hide resolved
mm2src/common/common.rs Outdated Show resolved Hide resolved
mm2src/mm2_main/src/ext_api/one_inch/types.rs Outdated Show resolved Hide resolved
Comment on lines 175 to 189
impl TxFields {
pub(crate) fn from_api_value(
tx_fields: one_inch_api::types::TxFields,
decimals: u8,
) -> MmResult<Self, FromApiValueError> {
Ok(Self {
from: tx_fields.from,
to: tx_fields.to,
data: BytesJson::from(hex::decode(str_strip_0x!(tx_fields.data.as_str()))?),
value: u256_to_big_decimal(U256::from_dec_str(&tx_fields.value)?, decimals)?,
gas_price: wei_to_gwei_decimal(U256::from_dec_str(&tx_fields.gas_price)?)?,
gas: tx_fields.gas,
})
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fn from_api_tx_fields

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Comment on lines +255 to +341
fn validate_slippage(slippage: f32) -> MmResult<(), ApiClientError> {
if !(0.0..=ONE_INCH_MAX_SLIPPAGE).contains(&slippage) {
return Err(ApiClientError::OutOfBounds {
param: "slippage".to_owned(),
value: slippage.to_string(),
min: 0.0.to_string(),
max: ONE_INCH_MAX_SLIPPAGE.to_string(),
}
.into());
}
Ok(())
}

fn validate_fee(fee: &Option<f32>) -> MmResult<(), ApiClientError> {
if let Some(fee) = fee {
if !(0.0..=ONE_INCH_MAX_FEE_SHARE).contains(fee) {
return Err(ApiClientError::OutOfBounds {
param: "fee".to_owned(),
value: fee.to_string(),
min: 0.0.to_string(),
max: ONE_INCH_MAX_FEE_SHARE.to_string(),
}
.into());
}
}
Ok(())
}

fn validate_gas_limit(gas_limit: &Option<u128>) -> MmResult<(), ApiClientError> {
if let Some(gas_limit) = gas_limit {
if gas_limit > &ONE_INCH_MAX_GAS {
return Err(ApiClientError::OutOfBounds {
param: "gas_limit".to_owned(),
value: gas_limit.to_string(),
min: 0.to_string(),
max: ONE_INCH_MAX_GAS.to_string(),
}
.into());
}
}
Ok(())
}

fn validate_parts(parts: &Option<u32>) -> MmResult<(), ApiClientError> {
if let Some(parts) = parts {
if parts > &ONE_INCH_MAX_PARTS {
return Err(ApiClientError::OutOfBounds {
param: "parts".to_owned(),
value: parts.to_string(),
min: 0.to_string(),
max: ONE_INCH_MAX_PARTS.to_string(),
}
.into());
}
}
Ok(())
}

fn validate_main_route_parts(main_route_parts: &Option<u32>) -> MmResult<(), ApiClientError> {
if let Some(main_route_parts) = main_route_parts {
if main_route_parts > &ONE_INCH_MAX_MAIN_ROUTE_PARTS {
return Err(ApiClientError::OutOfBounds {
param: "main route parts".to_owned(),
value: main_route_parts.to_string(),
min: 0.to_string(),
max: ONE_INCH_MAX_MAIN_ROUTE_PARTS.to_string(),
}
.into());
}
}
Ok(())
}

fn validate_complexity_level(complexity_level: &Option<u32>) -> MmResult<(), ApiClientError> {
if let Some(complexity_level) = complexity_level {
if complexity_level > &ONE_INCH_MAX_COMPLEXITY_LEVEL {
return Err(ApiClientError::OutOfBounds {
param: "complexity level".to_owned(),
value: complexity_level.to_string(),
min: 0.to_string(),
max: ONE_INCH_MAX_COMPLEXITY_LEVEL.to_string(),
}
.into());
}
}
Ok(())
}
Copy link
Member

@borngraced borngraced Oct 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can move validation logics inside fn validate_params if you don't plan to reuse them. This will also reduce boilerplate code

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tbh I'd like to have an option to break functions like that (even if those functions are not reused), for code structuring

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

its all good. thanks!

borngraced
borngraced previously approved these changes Oct 18, 2024
Copy link
Member

@borngraced borngraced left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this feat covers WASM? no test coverage 🙂 ... otherwise, LGTM 🚀

@dimxy
Copy link
Collaborator Author

dimxy commented Oct 18, 2024

Does this feat covers WASM? no test coverage 🙂 ... otherwise, LGTM 🚀

it works in native and wasm, basically this is forward to 3party api.
Yeah, I guess I need to add couple mockable tests

Copy link
Collaborator

@shamardy shamardy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the fixes! Next review iteration!

#[serde(rename = "isFoT", default)]
pub is_fot: bool,
#[serde(rename = "logoURI")]
pub logo_uri: String,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is to be used by GUI in anyway, it should be checked for phishing links, same for any field that returns a url. I suppose it will not be used as the token logo will be retrieved when adding it as a custom token using the custom token import APIs.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in d457bee

pub decimals: u32,
pub eip2612: bool,
#[serde(rename = "isFoT", default)]
pub is_fot: bool,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To think about in future PRs as well, should deduct this fee from the amount when routing a swap (1inch then cross chain atomic swap) so the atomic swap will use the amount minus this fee.

mm2src/trading_api/src/one_inch_api/types.rs Show resolved Hide resolved
mm2src/coins/lp_coins.rs Outdated Show resolved Hide resolved
mm2src/coins/lp_coins.rs Outdated Show resolved Hide resolved
mm2src/coins/lp_coins.rs Outdated Show resolved Hide resolved
mm2src/coins/lp_coins.rs Outdated Show resolved Hide resolved
let eth_coin = find_erc20_eth_coin(&ctx, &req.coin).await?;
let amount = wei_from_big_decimal(&req.amount, eth_coin.decimals())?;
let tx = eth_coin.approve(req.spender, amount).compat().await?;
Ok(tx.tx_hash_as_bytes())
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will this be formatted in a right way?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this would return a result like that

{
  "mmrpc": "2.0",
  "result": "5136701f11060010841c9708c3eb26f6606a070b8ae43f4b98b6d7b10a545258",
  "id": null
}

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should include the 0x prefix

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not fixed yet.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in 65c4853
I can see couple places where 0x is not added though: send_raw_tx in eth and TransactionNftDetails
We apparently need a dedicated to_string conversion fn for tx_hash.

(But is it convenient for GUI when we return tx hash in different formats for different coins?)

Copy link
Collaborator

@shamardy shamardy Nov 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But is it convenient for GUI when we return tx hash in different formats for different coins

No, we should fix those cases (in a different PR of course). tx hashes and addresses should always be displayed/sent to GUIs with 0x prefix

mm2src/common/common.rs Show resolved Hide resolved
mm2src/mm2_main/src/ext_api.rs Show resolved Hide resolved
Copy link
Collaborator

@shamardy shamardy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the fixes! Last review from my side, please also fix any unfixed comment in previous review.

mm2src/mm2_main/src/rpc/lp_commands/eth.rs Outdated Show resolved Hide resolved
mm2src/trading_api/src/one_inch_api/client.rs Show resolved Hide resolved
Comment on lines +36 to +49
const ONE_INCH_V6_0_SUPPORTED_CHAINS: &[(&str, u64)] = &[
("Ethereum", 1),
("Optimism", 10),
("BSC", 56),
("Gnosis", 100),
("Polygon", 137),
("Fantom", 250),
("ZkSync", 324),
("Klaytn", 8217),
("Base", 8453),
("Arbitrum", 42161),
("Avalanche", 43114),
("Aurora", 1313161554),
];
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like this in case they add support for new chains, in next PRs you should find a way to make this configurable or look for an API that provides this info.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought of adding this into a config file (but did not find suitable one).
For the other hand, if the QA team has to add another chain they would still need to make a PR to the KDF, so maybe they could modify this const as well(?)

(Besides, I think if 1inch ever adds a new chain they will probably have to make a new version of their API, so we would need to modify the code)

mm2src/mm2_main/src/rpc/lp_commands/eth.rs Outdated Show resolved Hide resolved
mm2src/mm2_main/src/rpc/lp_commands/eth.rs Outdated Show resolved Hide resolved
mm2src/mm2_main/tests/docker_tests/docker_tests_inner.rs Outdated Show resolved Hide resolved
mm2src/mm2_main/src/rpc/dispatcher/dispatcher.rs Outdated Show resolved Hide resolved
mm2src/mm2_main/src/ext_api/one_inch/rpcs.rs Outdated Show resolved Hide resolved
mm2src/mm2_main/src/ext_api/one_inch/rpcs.rs Outdated Show resolved Hide resolved
… check for same chain for 1inch swap, move 1inch to 'lp_commands/rpc')
@dimxy
Copy link
Collaborator Author

dimxy commented Nov 9, 2024

Thank you for the review @shamardy,
I believe, I have fixed almost all outstanding notes in 65c4853.
One is still unfixed (about chain names in code) - I added my Q there

And there is a note from @laruh about which type to use to return amounts (BigDecimal, MmNumber, U256 ..)

* dev:
  fix(foot-shooting): remove leftover code that panics via RPC (#2270)
  refactor(MarketCoinOps): make `wait_for_htlc_tx_spend` async (#2265)
  feat(eth-swap): maker tpu v2 implementation (#2211)
  fix(nft): add token_id field to the tx history primary key, fix balance (#2209)
  feat(cosmos): support IBC types in tx history implementation (#2245)
  fix(hd-wallet): use `CoinBalanceMap` for UTXO and QTUM (#2259)
  fix(tests): add more sepolia endpoints in tests (#2262)
  fix(legacy-swap): check for confirmations on recover taker (#2242)
  fix(legacy-swap): remove the need for takers to confirm their payment (#2249)
  refactor(P2P): types and modules (#2256)
  fix(evm): correctly display eth addr in iguana v2 activation result (#2254)
  feat(utxo): prioritize electrum connections (#1966)
  refactor(SwapOps): make all methods async (#2251)
  refactor(SwapOps): make `send_maker_payment` async (#2250)
  remove old p2p implementation (#2248)
  feat(cosmos-offline-tests): prepare IBC channels inside the container  (#2246)
Ok(())
} else {
Err(MmError::new(ApiIntegrationRpcError::ChainNotSupported))
fn api_supports_coin(base: &EthCoin, rel: &EthCoin) -> MmResult<(), ApiIntegrationRpcError> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: should be called api_supports_pair

let eth_coin = find_erc20_eth_coin(&ctx, &req.coin).await?;
let amount = wei_from_big_decimal(&req.amount, eth_coin.decimals())?;
let tx = eth_coin.approve(req.spender, amount).compat().await?;
Ok(tx.tx_hash_as_bytes())
Copy link
Collaborator

@shamardy shamardy Nov 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But is it convenient for GUI when we return tx hash in different formats for different coins

No, we should fix those cases (in a different PR of course). tx hashes and addresses should always be displayed/sent to GUIs with 0x prefix

Copy link
Collaborator

@shamardy shamardy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the fixes! LGTM!
Please resolve conflicts, I also have one small comment :)

@shamardy
Copy link
Collaborator

@dimxy please open docs PR for this features

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants