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(nft-swap): standalone nft maker swap contract and sepolia testenet #2100

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

Conversation

laruh
Copy link
Member

@laruh laruh commented Apr 24, 2024

related to issue #900

Etomic swap implementation approach was changed to Multi Standalone Etomic Swap contracts (see KomodoPlatform/etomic-swap#7 (comment))

At the first stage we are going to support EtomicSwapMakerNftV2 and EtomicSwapTakerV2 contracts in NFT Swap Komodefi feature, where Maker is NFT owner and Taker swaps ETH/ETH20.

  • The part related to standalone Maker Nft swap contract is r2r
  • Additionally, this commit ebac6e6 contains additional checks for malicious token_uri links like this

https://docs.moralis.io/web3-data-api/evm/reference/get-wallet-nfts?address=0xf622a6C52C94b500542E2AE6bcAD24C53Bc5b6a2&chain=polygon&format=decimal&token_addresses=[]&media_items=false
image
https://en.wikipedia.org/wiki/Zip_bomb

  • In the same commit ebac6e6 clear_all param in clear_nft_db RPC now is optional. false is default.
curl --url "http://127.0.0.1:7783" --data '{"userpass":"'$USERPASS'","method":"clear_nft_db","mmrpc":"2.0","params":{"chains":["POLYGON","BSC"]}}'

Req/Res examples for enable eth with tokens RPC

If we want to add support of other block chain types, we will need to make SignOps more generic, right now it focuses on eth types https://github.com/KomodoPlatform/komodo-defi-proxy/blob/80d92fbe1714c5052628b80d90c5a994640e3762/src/security/sign.rs#L5

use ethereum_types::{Address, H256};
use ethkey::{sign, verify_address, Secret, Signature};

we will implement this as needed.

@laruh laruh added the in progress Changes will be made from the author label Apr 24, 2024
@laruh laruh self-assigned this Apr 24, 2024
@laruh laruh changed the title feat(nft-swap): standalone nft maker swap contract and sepolia testenet support feat(nft-swap): standalone nft maker swap contract and sepolia testenet Apr 24, 2024
@laruh laruh force-pushed the standalone-nft-maker-swap-contract-sepolia-test branch from 1fbe447 to fe498fa Compare April 26, 2024 14:07
@laruh laruh force-pushed the standalone-nft-maker-swap-contract-sepolia-test branch 2 times, most recently from 9dc1ea1 to 942d139 Compare April 29, 2024 08:12
@laruh laruh force-pushed the standalone-nft-maker-swap-contract-sepolia-test branch from 942d139 to 998708b Compare April 29, 2024 08:19
Comment on lines 491 to 501
let validation_generator = ProxyAuthValidationGenerator {
coin_ticker: req.chain.to_nft_ticker().to_string(),
secret,
address: my_address,
};
let signed_message = EthCoin::generate_proxy_auth_signed_validation(validation_generator).map_err(|e| {
UpdateNftError::Internal(format!(
"KomodefiProxyAuthValidation signed message generation failed. Error: {:?}",
e
))
})?;
Copy link
Member

Choose a reason for hiding this comment

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

What if user decide to add his/her own nft endpoint? For example, on ETH we do this only if gui_auth param is true in the activation request.

Copy link
Member Author

@laruh laruh May 15, 2024

Choose a reason for hiding this comment

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

hmmm yeah, right now id user decides to use komodefi they will have to setup komodo-proxy project.

will add proxy_auth/gui_auth param then in requests (I didnt change existing gui_auth field to not to break GUI eth reqs in prod). If false the direct Http GET request will be sent to Url.

UPD: ok Im thinking about this comment #2100 (comment) (proxy_auth bool VS headers)

Copy link
Member Author

@laruh laruh May 15, 2024

Choose a reason for hiding this comment

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

UPD2: answered in the message below #2100 (comment)

Comment on lines 661 to 667
// Create a new URL instance from uri_without_cursor and modify its query to include the cursor if present
let mut uri = uri_without_cursor.clone();
if !cursor.is_empty() {
uri.set_query(Some(&cursor));
}
let payload = moralis_payload_str(uri, wrapper.signed_message.clone())?;
let response = send_post_request_to_uri(wrapper.orig_url.as_str(), payload).await?;
Copy link
Member

Choose a reason for hiding this comment

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

We should not change the way we send requests, otherwise this will not work when using endpoints without proxy. I guess you had to do this because you can't send auth payload in the get requests? Did you consider moving this payload to request headers instead of putting it into request body on the proxy side?

Copy link
Member Author

Choose a reason for hiding this comment

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

otherwise this will not work when using endpoints without proxy

Hmm even if we decide to send a GET request with the signed message in the header to the proxy layer, we will still need to include a proxy_auth parameter (set to true or false) in the NFT request to correctly build the request on the Komodefi side.

I dont think its a good idea to always include the authentication message in the header and allow users to send GET requests directly to some third-party API. I mean, I dont want to provide this user's information in the header or body to anyone if it's not necessary, thats why we should add proxy_auth param and manage this logic.

Therefore, I suggest adding a proxy_auth boolean in the following places, and if it is false, we can send the HTTP GET request directly to the endpoint:

  • In the NFT provider enum:
#[derive(Clone, Deserialize)]
#[serde(tag = "type", content = "info")]
pub enum NftProviderEnum {
    Moralis { url: Url },
}
  • In NFT wallet RPCs

Anyway, I think both approaches—header vs. body—will require refactoring in both the Komodefi and proxy repositories. Additionally, since the proxy layer supports requests based on feature logic, the proxy will always need to parse and modify incoming requests according to the feature behavior.

Copy link
Member

Choose a reason for hiding this comment

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

Hmm even if we decide to send a GET request with the signed message in the header to the proxy layer, we will still need to include a proxy_auth parameter (set to true or false) in the NFT request to correctly build the request on the Komodefi side.

Don't we have an actiation process for NFTs so we can pass proxy_auth only once? Even if we don't have, you can simply add query param to url (something like xyz.com/some/endpoint?proxy_auth=true) or even better, add a header PROXY_AUTH=1 or PROXY_AUTH=true.

I dont think its a good idea to always include the authentication message in the header and allow users to send GET requests directly to some third-party API.

I didn't understand this.

I mean, I dont want to provide this user's information in the header or body to anyone if it's not necessary

That information doesn't access to the target proxy. Right now, we remove this payload from the body and also drop the certain headers from request before we sending it to proxy.

Copy link
Member Author

@laruh laruh May 15, 2024

Choose a reason for hiding this comment

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

Don't we have an actiation process for NFTs so we can pass proxy_auth only once?

No, also I think its better to allow user to decide does RPC need to use proxy or not. Actually the same idea is for Urls fields we ask them in every rpc.

Even if we don't have, you can simply add query param to url (something like xyz.com/some/endpoint?proxy_auth=true) or even better, add a header PROXY_AUTH=1 or PROXY_AUTH=true.

In KomodoDefi RPC if we want to support both functionality: proxy and direct requests to 3rd party API, user needs to highlight do they want to use proxy or not.

curl --url "http://127.0.0.1:7783" --data '{
  "userpass": "'$USERPASS'",
  "method": "enable_eth_with_tokens",
  "mmrpc": "2.0",
  "params": {
    "ticker": "MATIC",
    "mm2": 1,
    "swap_contract_address": "0x9130b257D37A52E52F21054c4DA3450c72f595CE",
    "fallback_swap_contract": "0x9130b257D37A52E52F21054c4DA3450c72f595CE",
    "nodes": [
      {
        "url": "https://polygon-rpc.com"
      }
    ],
    "erc20_tokens_requests": [],
    "nft_req": {
      "provider":{
        "type": "Moralis",
        "info": {
          "url":"http://localhost:6150/nft-test",
          "proxy_auth":true
        }
      }
    }
  }
}'

dont think its a good idea to always include the authentication message in the header and allow users to send GET requests directly to some third-party API.

I didn't understand this.

I mean, I dont want to provide this user's information in the header or body to anyone if it's not necessary

That information doesn't access to the target proxy. Right now, we remove this payload from the body and also drop the certain headers from request before we sending it to proxy.

I was talking about variant if we dont ask user to provide "proxy_auth" param in Komodefi RPC. It means that we dont know when to send request to proxy and when directly to 3rd party API.
KomoDefi RPC needs to have "proxy_auth" param. If its true then we build special request for Komodo Proxy layer, if false, then we send general http get request which we were doing all the time previously. Means we dont need to send req to proxy app to send it to 3rd party API.

When we are talking about nft feature, we use KomodoDefi-Proxy project to be able to send requests to komodo-moralis-proxy. If "proxy_auth" false, then user desires to send request not to komodo-moralis-proxy but directly to other 3rd party API.

I dont actually see the advantage of moving auth payload to headers. This way we have to check headers for one feature in proxy layer code and check body for other feature.
Proxy layer understands how to manage feature request by proxy_type: &ProxyType, so we dont need to over complicate the logic. If we send auth payload message for all features in body, we just need to parse payload from Body using one function
https://github.com/KomodoPlatform/komodo-defi-proxy/blob/d9922eeb44c694c160e2084d8ce0499bd86fde85/src/proxy/mod.rs#L40-L57

/// Asynchronously generates and organizes payload data from an HTTP request based on the specified proxy type.
/// This function ensures that requests are properly formatted to the correct service,
/// returning a tuple with the modified request and the structured payload.
pub(crate) async fn generate_payload_from_req(
    req: Request<Body>,
    proxy_type: &ProxyType,
) -> GenericResult<(Request<Body>, PayloadData)> {
    match proxy_type {
        ProxyType::Quicknode => {
            let (req, payload) = parse_payload::<QuicknodePayload>(req, false).await?;
            Ok((req, PayloadData::Quicknode(payload)))
        }
        ProxyType::Moralis => {
            let (req, payload) = parse_payload::<MoralisPayload>(req, true).await?;
            Ok((req, PayloadData::Moralis(payload)))
        }
    }
}

well if we have new EVM feature with more complex logic for Proxy layer, which cant use parse_payload, then we'll implement new parse function for it.

Copy link
Member Author

@laruh laruh May 15, 2024

Choose a reason for hiding this comment

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

if proxy_auth is false, then it suppose that user wants to send request directly to some other API

curl --url "http://127.0.0.1:7783" --data '{"userpass":"'$USERPASS'","method":"update_nft","mmrpc":"2.0","params":{"chains":["POLYGON"],"url":"http://other.example.com","url_antispam": "https://nft.antispam.dragonhound.info", "proxy_auth":false}}'

Copy link
Member

Choose a reason for hiding this comment

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

That makes it more complicated to maintain both KDF and KDP projects

If "proxy_auth" false -> use fn send_request_to_uri if "proxy_auth" true -> create payload str and use fn send_post_request_to_uri. proxy should handle the moralis feature with proxy_type and payload type

  1. When proxy_auth is true, KDF acts like it's using different service and changes the request method.
  2. KDP is taking the POST request and converting it into GET request.

These costs are pure complexities without any benefit. So why doing that?

Copy link
Member Author

@laruh laruh May 16, 2024

Choose a reason for hiding this comment

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

we had long discussion about default urls for nft and covered urls for gas provider a bit, but you can check one of the last comments #2049 (comment) from the thread

Copy link
Member Author

@laruh laruh May 16, 2024

Choose a reason for hiding this comment

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

That makes it more complicated to maintain both KDF and KDP projects

If "proxy_auth" false -> use fn send_request_to_uri if "proxy_auth" true -> create payload str and use fn send_post_request_to_uri. proxy should handle the moralis feature with proxy_type and payload type

1. When proxy_auth is true, KDF acts like it's using different service and changes the request method.

2. KDP is taking the POST request and converting it into GET request.

These costs are pure complexities without any benefit. So why doing that?

  1. When proxy_auth is true, KDF acts like it's using different service

Well yes :D this actually means that request is going to go through the middleware service (from my point of view of course), which is KDP: KDF -> KDP->komodo.moralis.proxy->Mortalis API.

If false, then send request directly to users API (this is the old way we were sending requests before this PR):
KDF -> 3rd party user's API -> Moralis API.
If proxy_auth false, user have to insert moralis priv key themself in 3rd party API, as KDF dont do it.

  1. KDP is taking the POST request and converting it into GET request.

yep, as Moralis feature requires GET reqs.

Ok lets find the compromise, as we have common goal to make a great project, right?

Lets send GET request with payload in header from KDF to KDP if "proxy_auth":true. On KDF side I suppose its better to reuse this function adding optional Header:

pub async fn send_request_to_uri(uri: &str) -> MmResult<Json, GetInfoFromUriError>

If "proxy_auth":false then send GET request using send_request_to_uri directly to url without additional header.

And the above should be for each req where we ask "url" field

Copy link
Member Author

Choose a reason for hiding this comment

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

Implemented new parse function in KDP KomodoPlatform/komodo-defi-proxy@e8f296d for features which handle auth signed message in Header

on KDF side added this functionality support for activation process 7882e6e

Will provide send_request_to_uri support for NFT Wallet RPCs (get nft list/transfers, update) tomorrow

Copy link
Member Author

Choose a reason for hiding this comment

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

provided proxy auth and 3rd party api support d03b6d1

this ff92a20 reduces some code duplication

@laruh laruh added in progress Changes will be made from the author and removed under review labels May 17, 2024
@laruh laruh added under review and removed in progress Changes will be made from the author labels May 17, 2024
laruh added 3 commits May 17, 2024 17:09
…e-nft-maker-swap-contract-sepolia-test

# Conflicts:
#	mm2src/coins/eth.rs
#	mm2src/coins/eth/nft_swap_v2/mod.rs
#	mm2src/coins/eth/v2_activation.rs
#	mm2src/mm2_main/Cargo.toml
#	mm2src/mm2_main/tests/docker_tests/eth_docker_tests.rs
…hcore_transaction::Action in eth_docker_tests.rs separately
@laruh laruh force-pushed the standalone-nft-maker-swap-contract-sepolia-test branch from b359ea7 to 9c3ff07 Compare May 21, 2024 07:56
@laruh
Copy link
Member Author

laruh commented Jun 17, 2024

PS: if someone will have more notes, I would like to fix them in this PR #2129 to avoid conflicts

shamardy
shamardy previously approved these changes Jun 21, 2024
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.

Great work! Only non-blocker comments.
@mariocynicys @onur-ozkan can you please check if your comments are resolved and if you have any more comments.
@laruh I guess I will have to review, approve and then merge this PR #2129 first and also this PR KomodoPlatform/komodo-defi-proxy#22 before merging this. Is that correct?

}
match block_on(GETH_WEB3.eth().block_number().timeout(Duration::from_secs(6))) {
Ok(Ok(block_number)) => {
println!("Geth node is ready, latest block number: {:?}", block_number);
Copy link
Collaborator

Choose a reason for hiding this comment

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

We shouldn't use println in tests, we should use log! macro instead

Copy link
Member Author

Choose a reason for hiding this comment

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

agree, fixed here e672485

)
.unwrap();

println!("Transaction sent: {:?}", result);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same with println

Copy link
Member Author

Choose a reason for hiding this comment

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

done e672485

@laruh
Copy link
Member Author

laruh commented Jun 22, 2024

@laruh I guess I will have to review, approve and then merge this PR #2129 first and also this PR KomodoPlatform/komodo-defi-proxy#22 before merging this. Is that correct?

@shamardy
I think this #2100 PR can be merged in dev first, before #2129 if I dont have review notes which require me to refactor the whole architecture. Then I would prefer to do such big changes in #2129 (to avoid conflicts and messed up logic). In this case, yes we have to merge #2129 to #2100 and then #2100 to dev. If #2100 approved with non-blocker changes like your note, then I can do the changes right in this branch and merge it to #2129.

as for proxy PRs. I have two:

To sum up:
So if #2100 is approved without breaking changes for #2129 branch, then we can merge it to dev, and I will change merge branch to dev in #2129.

Proxies PRs:
#2100 uses this feature KomodoPlatform/komodo-defi-proxy#22
#2129 additionally started to use this pr quicknode refactoring KomodoPlatform/komodo-defi-proxy#23

If #2100 will be fully approved, then it means that reviewers agreed with KomodoPlatform/komodo-defi-proxy#22 logic, same for #2129 and KomodoPlatform/komodo-defi-proxy#23

Proxy prs can get more non braking notes after komodefi being approved, but if reviewers decide to change the format of request to Proxy layer, then we have to update komodefi nft opened prs, or open new if previous were merged

@laruh
Copy link
Member Author

laruh commented Jun 24, 2024

reqs examples how to enable nft, with platform coin and separately

curl --url "http://127.0.0.1:7783" --data '{
  "userpass": "'$USERPASS'",
  "method": "enable_eth_with_tokens",
  "mmrpc": "2.0",
  "params": {
    "ticker": "MATIC",
    "mm2": 1,
    "swap_contract_address": "0x9130b257D37A52E52F21054c4DA3450c72f595CE",
    "maker_swap_v2_contract": "0x9130b257D37A52E52F21054c4DA3450c72f595CE",
    "taker_swap_v2_contract": "0x9130b257D37A52E52F21054c4DA3450c72f595CE",
    "fallback_swap_contract": "0x9130b257D37A52E52F21054c4DA3450c72f595CE",
    "nodes": [
      {
        "url": "https://polygon-rpc.com"
      }
    ],
    "erc20_tokens_requests": [],
    "nft_req": {
      "provider":{
        "type": "Moralis",
        "info": {
          "url":"http://localhost:6150/nft-test",
          "proxy_auth":true
        }
      }
    }
  }
}'

curl --url "http://127.0.0.1:7783" --data '{
  "userpass": "'$USERPASS'",
  "method": "enable_nft",
  "mmrpc": "2.0",
  "params": {
    "ticker": "NFT_MATIC",
    "activation_params": {
      "provider":{
        "type": "Moralis",
        "info": {
          "url":"http://localhost:6150/nft-test",
          "proxy_auth":true
        }
      }
    }
  }
}'

…e-nft-maker-swap-contract-sepolia-test

# Conflicts:
#	mm2src/mm2_main/tests/docker_tests/docker_tests_common.rs
#	mm2src/mm2_main/tests/docker_tests_main.rs
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.

None yet

4 participants