Conversation
|
We should keep in mind that this implementation needs quite few integration/unit tests. Maybe fill an issue or add TODO to codebase? @laruh |
I added todo plan to the issue. |
How much data is needed for dummy address?
What is the blocker for it? Why it can't pass in one test? If multiple operations are executed in mm2 for performing it, it will be more suitable as an integration test(like swap tests). |
If we are talking about just checking nft list and tx history, we need one test address that does not send or receive NFT but simply stores 1 NFT. With this test we check that moralis didt change a response structure. For withdrawing, we need two more test addresses that send 1 NFT to each other.
After withdrawing, moralis can still show transferred NFT in list and also not show new transfer in history just in time. After some more seconds moralis starts updating and you have to wait the response. It can be a situation that we dont get the response right now and wait timeout check and it fails, just bcz moralis needed some more time. |
A loop with with an interval and timeout can be applied just like in swap tests. |
Oh, I see. So lets add tests after gui-auth adding, to avoid using api key in mm config. |
# Conflicts: # mm2src/coins/eth/v2_activation.rs
10ce258
|
@ozkanonur @shamardy @sergei-boiko I fixed merge conflicts, could you re-approve please? |
related to #900
The current implementation provides support for the following functionality:
get_nft_listThis function returns list of NFTs on ETH or/and BSC chains owned by user. Mocks
get_nft_list req example
{ "userpass": "userpass", "mmrpc": "2.0", "method": "get_nft_list", "params": { "chains": [ "ETH", "BSC" ] } }get_nft_list res example
{ "mmrpc": "2.0", "result": { "count": 3, "nfts": [ { "chain": "ETH", "token_address": "0x63ad7cd8ad28102aaee0d6abd538e60c9cacc22a", "token_id": "201", "amount": "1", "owner_of": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "token_hash": "5af75272a39714801e76bd12d997d5ec", "block_number_minted": 13336357, "block_number": 13336357, "contract_type": "ERC721", "name": "Ether Ghosts", "symbol": "GHOSTS", "token_uri": "https://ipfs.moralis.io:2053/ipfs/QmS612yMoGTt1FpTWWNaCd8kTHm1afwFK25tGW4rGnFeqk/201", "metadata": "{\"name\":\"Ether Ghosts #201\",\"description\":\"10,000 Ether Ghosts have just landed on the Ethereum network. These spooky creatures will keep your wallet safe while you are sleeping\",\"attributes\":[{\"trait_type\":\"Void\",\"value\":\"Ethereal Being\"},{\"trait_type\":\"Background\",\"value\":\"Light Purple\"},{\"trait_type\":\"Type\",\"value\":\"Ghost\"},{\"trait_type\":\"Skin Color\",\"value\":\"Teal Body\"},{\"trait_type\":\"Complexion\",\"value\":\"Default\"},{\"trait_type\":\"Eyes\",\"value\":\"Bored\"},{\"trait_type\":\"Clothes\",\"value\":\"Basic\"},{\"trait_type\":\"Accessory\",\"value\":\"Sword\"}],\"image\":\"ipfs://Qma7mE5CA1MrX2MHZ9N6HefWL5kcYCPsat99gxQfqUSRGb/201.png\",\"image_url\":\"ipfs://Qma7mE5CA1MrX2MHZ9N6HefWL5kcYCPsat99gxQfqUSRGb/201.png\"}", "last_token_uri_sync": "2022-05-18T10:12:31.695Z", "last_metadata_sync": "2023-02-12T07:55:35.266Z", "minter_address": "0xa239c13c054e498b9be633262574862676d73f7f" }, { "chain": "ETH", "token_address": "0x495f947276749ce646f68ac8c248420045cb7b5e", "token_id": "71508368311469929077051951161112205629360977807816813562618393986376478490625", "amount": "1", "owner_of": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "token_hash": "95c29484506f60d018a995fc764d9fa2", "block_number_minted": 13437165, "block_number": 13437165, "contract_type": "ERC1155", "name": "OpenSea Shared Storefront", "symbol": "OPENSTORE", "token_uri": "https://api.opensea.io/api/v1/metadata/0x495f947276749Ce646f68AC8c248420045cb7b5e/0x9e184d5baa4e52222fd9e6acd72a9364d7b9166e0000000000000d0000000001", "metadata": "{\"name\":\"#11 Intern\",\"description\":null,\"external_link\":\"https://a16z.com/crypto/\",\"image\":\"https://i.seadn.io/gae/HiHsFy8vmXS-XXWKKOQpm95Ks_jfV05Z-2bO-U9oPnNWpx9Q_FbiSRccf2qaTr7KIuU2UzvdrgwCS3gEJWKHXYv8QImvlWtRxKa8?w=500&auto=format\",\"animation_url\":\"https://openseauserdata.com/files/4f771b983499dd4faca1547cfea0a956.mp4\"}", "last_token_uri_sync": "2022-12-08T04:46:42.531Z", "last_metadata_sync": "2022-12-08T04:46:44.983Z", "minter_address": "ERC1155 tokens don't have a single minter" }, { "chain": "BSC", "token_address": "0x36f8f51f65fe200311f709b797baf4e193dd0b0d", "token_id": "12", "amount": "1", "owner_of": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "token_hash": "fae04ab508314903c33a7bcad362156c", "block_number_minted": 9607444, "block_number": 19116577, "contract_type": "ERC1155", "name": "Treat NFT Minter", "symbol": "TreatNFTMinter", "token_uri": "https://treatdao.com/api/nft/12", "metadata": "{\"name\":\"Treat Me Right So I can Treat You Right\",\"image\":\"https://i.imgur.com/ojp3yGj.jpg\",\"description\":\"Beginnings are always exciting. But they are exciting only when they have an end. Let’s make the time between the two to last forever.\",\"properties\":{\"_id\":12,\"external_url\":\"https://treatdao.com/\",\"model\":{\"handle\":\"@nftdevan\",\"address\":\"0xDa88E03eCB64B068fe3C7a029A481f9E75a28DaE\"},\"createdAt\":\"2021-04-06T20:44:14.790Z\",\"tags\":[\"SFW\",\"Artistic\",\"Glamour\",\"Natural\",\"Solo\",\"Exclusive\"]},\"attributes\":[{\"trait_type\":\"Model\",\"value\":\"@nftdevan\",\"_id\":\"606cc81ecc8b31000879d054\"},{\"trait_type\":\"Max Supply\",\"value\":\"1000000\",\"_id\":\"606cc81ecc8b31000879d055\"}]}", "last_token_uri_sync": "2022-07-24T12:57:17.251Z", "last_metadata_sync": "2022-07-24T13:00:17.824Z", "minter_address": "ERC1155 tokens don't have a single minter" } ] }, "id": null }get_nft_metadataThis function returns info of one specific NFT. Current implementation sends request to Moralis.
One moment, that NFT json from moralis for Get NFT metadata has one additional param like "transfer_index": [11362111, 125, 160, 0]. You can see it in Moralis mocks for Get NFT metadata. In response for Get NFT list by wallet NFTs dont have this field. I omitted this parameter and used the same NFT structure in result that I use for get_nft_list. I did it, to be able to first try to fetch data from the list cache before sending new request to moralis.
get_nft_metadata req example
{ "userpass": "userpass", "mmrpc": "2.0", "method": "get_nft_metadata", "params": { "token_address": "0xb47e3cd837dDF8e4c57F05d70Ab865de6e193BBB", "token_id": 1, "chain": "ETH" } }get_nft_metadata res example
{ "mmrpc": "2.0", "result": { "chain": "ETH", "token_address": "0xb47e3cd837ddf8e4c57f05d70ab865de6e193bbb", "token_id": "1", "amount": "1", "owner_of": "0xb88f61e6fbda83fbfffabe364112137480398018", "token_hash": "a99d02058e62e327e79aabd57e0b88a3", "block_number_minted": 3934590, "block_number": 11362111, "contract_type": null, "name": "CRYPTOPUNKS", "symbol": "Ͼ", "token_uri": null, "metadata": "{\"image\":\"https://www.larvalabs.com/cryptopunks/cryptopunk001.png\",\"name\":\"CryptoPunk 001\",\"attributes\":[\"Smile\",\"Mohawk\"],\"description\":\"Male\"}", "last_token_uri_sync": "2023-02-11T19:23:36.655Z", "last_metadata_sync": "2022-08-22T13:27:58.122Z", "minter_address": null }, "id": null }get_nft_transfersThis function returns a transfer history of NFTs on ETH or/and BSC chains owned by user. Mocks
get_nft_transfers req example
{ "userpass": "userpass", "mmrpc": "2.0", "method": "get_nft_transfers", "params": { "chains": [ "BSC", "ETH" ] } }get_nft_transfers res example
{ "mmrpc": "2.0", "result": { "count": 4, "transfer_history": [ { "chain": "BSC", "block_number": 20379028, "block_timestamp": "2022-08-12T14:36:31.000Z", "block_hash": "0x9917f0ccd96655c3a93f9dafb59b36d99013f7135fa34246f98b324377b1efc7", "transaction_hash": "0x9b727d45a5dfae25111d45743cdd89295de9dee981c8b5a6242c1c1f1cc1905a", "transaction_index": 50, "log_index": 218, "value": "0", "contract_type": "ERC1155", "transaction_type": "Single", "token_address": "0x67af3a5765299a3e2f869c3002204c749bd185e9", "token_id": "41371", "from_address": "0x1019da05c30ece5d329af38e32e044590c13a0c1", "to_address": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "amount": "1", "verified": 1, "operator": "0x1019da05c30ece5d329af38e32e044590c13a0c1" }, { "chain": "BSC", "block_number": 19357744, "block_timestamp": "2022-07-08T01:39:37.000Z", "block_hash": "0x6d6b7efbcac98e96590c2d37b8f96f365010a930cbb45d8fe7ac196c1b3a2fc0", "transaction_hash": "0xac2d856630eb80270a3b75538977832ac6d7c19100f41b804d3c100958bcb3ab", "transaction_index": 96, "log_index": 229, "value": "0", "contract_type": "ERC721", "transaction_type": "Single", "token_address": "0x999017cb5652caf5f324a8e44f813903ba3c46eb", "token_id": "36957", "from_address": "0x0000000000000000000000000000000000000000", "to_address": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "amount": "1", "verified": 1, "operator": null }, { "chain": "ETH", "block_number": 16554884, "block_timestamp": "2023-02-04T10:40:59.000Z", "block_hash": "0x36c6be8af50d46c9ddeb3cd05c4dca870e11e4d52fce528c1c8605bb4708e201", "transaction_hash": "0x7436a277730a75079e1481888227da49e9c04fb90605f17be26b577322379d80", "transaction_index": 64, "log_index": 82, "value": "0", "contract_type": "ERC721", "transaction_type": "Single", "token_address": "0x26021ca5f9d35cbc4e984fca0c3a27b47f561d23", "token_id": "503", "from_address": "0x302ee7e96dbc6ddead7a3fdbe4352990f48baa01", "to_address": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "amount": "1", "verified": 1, "operator": null }, { "chain": "ETH", "block_number": 16552748, "block_timestamp": "2023-02-04T03:29:59.000Z", "block_hash": "0x0c442de675d1058196199ce6b39a918cb383ca8c07544872ec3b3e9ea321a578", "transaction_hash": "0xeb8c405f477d1af99a841702775ab8649b49bba03fefc82e632af568aec8008e", "transaction_index": 116, "log_index": 198, "value": "0", "contract_type": "ERC721", "transaction_type": "Single", "token_address": "0x700f045de43fce6d2c25df0288b41669b7566bbe", "token_id": "725", "from_address": "0x958c20a43f5206f186b0195ccb61acb724b2ee1e", "to_address": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "amount": "1", "verified": 1, "operator": null } ] }, "id": null }get_my_addressThis function returns wallet address for necessary coin without its activation. Currently supports only coins with
ETHprotocol type.get_my_address req example
{ "userpass": "userpass", "mmrpc": "2.0", "method": "get_my_address", "params": { "coin": "ETH" } }get_my_address res example
{ "mmrpc": "2.0", "result": { "coin":"ETH", "wallet_address": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045" }, "id": null }Current
withdraw_nftimplementation(dont forget to enable native coin of chain)
withdraw_nft req example
{ "userpass": "${USERPASS}", "method": "withdraw_nft", "mmrpc": "2.0", "params": { "type": "WithdrawErc721", "withdraw_data": { "chain": "BSC", "from": "0xf622a6C52C94b500542E2AE6bcAD24C53Bc5b6a2", "to": "0x6FAD0eC6bb76914b2a2a800686acc22970645820", "token_address": "0xfd913a305d70a60aac4faac70c739563738e1f81", "token_id": "214300047252" } } }withdraw_nft res example
{ "mmrpc": "2.0", "result": { "tx_hex": "f8cb0585012a05f200830180b494fd913a305d70a60aac4faac70c739563738e1f8180b86442842e0e000000000000000000000000f622a6c52c94b500542e2ae6bcad24c53bc5b6a20000000000000000000000006fad0ec6bb76914b2a2a800686acc2297064582000000000000000000000000000000000000000000000000000000031e54737948194a001d4374def9ee63ae913d3321757478789e498d979d0f873f38d4027cc9bd4cba035ed0f9f1f4d4fa06b5b7183ad9ed041ebf0a96dfddac2eeec6ceb3b342a0268", "tx_hash": "0ec4bb9b330b1befb7c531e0f2ef4af69126e0fc5c699b82fe4a45a23841ade8", "from": [ "0xf622a6C52C94b500542E2AE6bcAD24C53Bc5b6a2" ], "to": [ "0x6FAD0eC6bb76914b2a2a800686acc22970645820" ], "contract_type": "ERC721", "token_address": "0xfd913a305d70a60aac4faac70c739563738e1f81", "token_id": "214300047252", "amount": "1", "fee_details": { "type": "Eth", "coin": "BNB", "gas": 98484, "gas_price": "0.000000005", "total_fee": "0.00049242" }, "coin": "BNB", "block_height": 0, "timestamp": 1677336094, "internal_id": 0, "transaction_type": "NftTransfer" }, "id": null }Use
send_raw_transactionto check thatwithdraw_nftworks correctly (for erc721)send_raw_transaction req
{ "method": "send_raw_transaction", "coin": "BNB", "tx_hex": "f8cb0585012a05f200830180b494fd913a305d70a60aac4faac70c739563738e1f8180b86442842e0e000000000000000000000000f622a6c52c94b500542e2ae6bcad24c53bc5b6a20000000000000000000000006fad0ec6bb76914b2a2a800686acc2297064582000000000000000000000000000000000000000000000000000000031e54737948194a001d4374def9ee63ae913d3321757478789e498d979d0f873f38d4027cc9bd4cba035ed0f9f1f4d4fa06b5b7183ad9ed041ebf0a96dfddac2eeec6ceb3b342a0268", "userpass": "${USERPASS}" }send_raw_transaction res
{"tx_hash":"0ec4bb9b330b1befb7c531e0f2ef4af69126e0fc5c699b82fe4a45a23841ade8"}result on bscscan
Notes:
Current implementation uses api-key which is set in parameters in MM config as "api_key".
Withdrawing erc1155 support will be implemented later. Aslo adding caching is in plans.
Feature
enable-nft-integrationwas added. To compile binary please use commandcargo build --bin mm2 --features enable-nft-integration