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): db implementation (wasm target) #1877

Merged
merged 136 commits into from Jul 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
136 commits
Select commit Hold shift + click to select a range
7a62de0
draft
laruh Apr 3, 2023
350f1d5
wip
laruh Apr 5, 2023
08ba26c
wip
laruh Apr 6, 2023
7d0edf1
wip
laruh Apr 10, 2023
5df609e
remove StorageFactory
laruh Apr 10, 2023
b0d965f
add wasm target in NftStorageBuilder::build
laruh Apr 10, 2023
6d12a42
Merge remote-tracking branch 'origin/dev' into add-nft-cache-support
laruh Apr 10, 2023
6d84038
add StorageOps todos
laruh Apr 10, 2023
9ef02b7
impl trait err for target err
laruh Apr 11, 2023
67133a2
change functions in Ops
laruh Apr 11, 2023
f935e5a
Merge remote-tracking branch 'origin/dev' into add-nft-cache-support
laruh Apr 11, 2023
f249593
Merge remote-tracking branch 'origin/dev' into add-nft-cache-support
laruh Apr 12, 2023
2d66f8f
wasm: add lock_db fn and From IDB errors
laruh Apr 12, 2023
9225e99
wasm: change name
laruh Apr 12, 2023
9f977f3
sql: table names
laruh Apr 12, 2023
de5cff6
sql: save create table commands
laruh Apr 13, 2023
65c702b
sql: init fnc
laruh Apr 13, 2023
52b3c32
sql: is_initialized_for fnc
laruh Apr 13, 2023
6d34df5
remove wip, leave draft
laruh Apr 20, 2023
9bf6453
add possible_spam
laruh Apr 21, 2023
0a19dba
unite traits
laruh Apr 23, 2023
9e2b935
fmt
laruh Apr 23, 2023
8349de1
wip
laruh Apr 23, 2023
d2e0653
save wip state, moralis was removed from get_nft_list
laruh Apr 24, 2023
3e5cd51
Merge remote-tracking branch 'origin/dev' into add-nft-cache-support
laruh Apr 24, 2023
7ba5c30
Merge remote-tracking branch 'origin/dev' into add-nft-cache-support
laruh Apr 25, 2023
64fa485
save state
laruh Apr 28, 2023
b37f9a8
Merge remote-tracking branch 'origin/dev' into add-nft-cache-support
laruh Apr 28, 2023
844c9e5
get_nft_list with storage
laruh Apr 28, 2023
d9c36a5
add get_nft method
laruh Apr 28, 2023
62ebf79
optimize get_nft_list_builder_preimage
laruh Apr 28, 2023
9811680
fix fmt
laruh Apr 28, 2023
d652772
wip update_nft
laruh Apr 30, 2023
190aba3
Merge remote-tracking branch 'origin/dev' into add-nft-cache-support
laruh Apr 30, 2023
8a64b4a
wip update_nft
laruh May 1, 2023
330af7a
wip update_nft
laruh May 1, 2023
c31baa0
add tx to history
laruh May 3, 2023
590cb76
wip get table
laruh May 4, 2023
8cc5413
possible_spam bool
laruh May 4, 2023
9bae1af
fix get methods
laruh May 4, 2023
1b10b14
filters send and receive
laruh May 5, 2023
12d0b60
from to filters in history
laruh May 5, 2023
429161a
get nft and latest block, delete nft
laruh May 7, 2023
d5efb28
get_nft_metadata
laruh May 7, 2023
e68155c
refresh_nft_metadata
laruh May 7, 2023
106e18d
save update nft
laruh May 8, 2023
3d5dd43
order by block_number ASC for get txs from block
laruh May 9, 2023
6fc16cf
order_desc for nft_list.block_number and nft_history.block_timestamp …
laruh May 9, 2023
2e70203
impl last scanned block
laruh May 9, 2023
c08d996
update only amount when some erc1155 tokens were sent or received
laruh May 15, 2023
342491c
fix last_scanned_block logic
laruh May 15, 2023
16f028b
Merge remote-tracking branch 'origin/dev' into add-nft-cache-support
laruh May 19, 2023
158542c
add uri meta, impl update collection name in txs history
laruh May 21, 2023
cb29933
find wallet_amount in withdraw_erc1155
laruh May 22, 2023
7941fe3
todos in wasm target
laruh May 22, 2023
3323643
update empty meta in txs
laruh May 22, 2023
9947d97
Merge remote-tracking branch 'origin/dev' into add-nft-cache-support
laruh May 25, 2023
4d2e5e2
Merge remote-tracking branch 'origin/dev' into add-nft-cache-support
laruh May 26, 2023
94b9fe8
fix conflicts
laruh May 26, 2023
b67e5e1
add todos in wasm target
laruh May 26, 2023
ef7bf54
Merge remote-tracking branch 'origin/dev' into add-nft-cache-support
laruh May 26, 2023
54220c3
split update nft into fns, add TxMeta, add RefreshMetadataReq
laruh May 28, 2023
e3d19f1
send and receive filters fix
laruh May 28, 2023
be984ef
move nft wasm db into wasm module, add tables into wasm
laruh May 31, 2023
76e2505
Merge remote-tracking branch 'origin/dev' into add-nft-cache-support
laruh Jun 1, 2023
38814e4
use ok_or_else when get_nft()
laruh Jun 1, 2023
f919a37
use pub(crate) for mod nft_storage, move import below it
laruh Jun 1, 2023
217c199
allow(dead_code) for RemoveNftResult
laruh Jun 1, 2023
bbe4be5
add LastScannedBlockTable
laruh Jun 1, 2023
9c1e2f4
error in union_sql_strings, Some for date filters,remove nft_table_bu…
laruh Jun 4, 2023
a959df2
Merge branch 'add-nft-cache-support' into nft-cache-support-wasm
laruh Jun 4, 2023
f05baaf
use u64 for block number, from fns for table structs, impl get_nft, g…
laruh Jun 5, 2023
480f648
add_nfts_to_list
laruh Jun 5, 2023
8291f20
make mod storage
laruh Jun 5, 2023
a45fd13
use prepared stmt in get_nft_list, get_tx_history
laruh Jun 6, 2023
4f16c82
move impl nft errors from lp_coins into nft mod
laruh Jun 6, 2023
72a85c1
use u64 timestamp for block_timestamp in tx history
laruh Jun 6, 2023
fa4c34e
Merge branch 'add-nft-cache-support' into nft-cache-support-wasm
laruh Jun 7, 2023
f7ff673
NftListStorageOps impl for IDB
laruh Jun 8, 2023
e80c4b0
Merge remote-tracking branch 'origin/dev' into add-nft-cache-support
laruh Jun 9, 2023
02b9f5f
make contract_type in NftTransferHistory optional
laruh Jun 9, 2023
464dbdf
polish code in update_nft, move ParseTimestampError from Internal, ad…
laruh Jun 12, 2023
8be6ab0
make contract_type mandatory
laruh Jun 12, 2023
8e3be13
contract_type is some check
laruh Jun 14, 2023
b3f7a1e
NftTxHistoryStorageOps for IDB
laruh Jun 12, 2023
84b94bc
Merge branch 'add-nft-cache-support' into nft-cache-support-wasm
laruh Jun 14, 2023
016482d
make contract_type mandatory in NftListTable
laruh Jun 14, 2023
400e445
add test_add_nfts
laruh Jun 15, 2023
f4fcc9b
initialize db first
laruh Jun 15, 2023
c49fd35
last blocks in tests
laruh Jun 15, 2023
2697d0a
remove CHAIN_BLOCK_NUMBER_INDEX
laruh Jun 15, 2023
3f09071
check get_nft
laruh Jun 15, 2023
70d1de4
add txs test
laruh Jun 15, 2023
cd64d40
add get_txs_from_block in tests
laruh Jun 15, 2023
590de5f
get_item_by_unique_index in get last scanned block
laruh Jun 15, 2023
1143057
create block_number index
laruh Jun 15, 2023
c33a014
use BeBigUint
laruh Jun 16, 2023
5ca2933
match contract_type, NOT_FOUND contract_type
laruh Jun 16, 2023
59c0db5
separate last block tests
laruh Jun 16, 2023
f3e0776
test_nft_list
laruh Jun 16, 2023
b5bd19b
test remove nft and update amount
laruh Jun 16, 2023
e18f932
test_refresh_metadata, test_tx_history
laruh Jun 16, 2023
23dd751
move for_db_tests mod
laruh Jun 18, 2023
5df10a8
Merge remote-tracking branch 'origin/dev' into add-nft-cache-support
laruh Jun 18, 2023
c7c424f
test_get_update_tx_meta
laruh Jun 18, 2023
fd7fc03
Merge branch 'add-nft-cache-support' into nft-cache-support-wasm
laruh Jun 18, 2023
d2c1e5e
check just len in test_get_update_tx_meta
laruh Jun 18, 2023
ec9ed68
Merge remote-tracking branch 'origin/dev' into nft-cache-support-wasm
laruh Jun 19, 2023
c77d236
get_uri_meta, merge_from for UriMeta
laruh Jun 19, 2023
5992d28
add token_uri in txs, json in image_details
laruh Jun 20, 2023
300091e
Merge remote-tracking branch 'origin/dev' into nft-cache-support-wasm
laruh Jun 20, 2023
5e86a83
Merge remote-tracking branch 'origin/dev' into nft-cache-support-wasm
laruh Jun 21, 2023
740a284
add check_moralis_ipfs_bafy and test it
laruh Jun 21, 2023
9f6e0c6
Merge remote-tracking branch 'origin/dev' into nft-cache-support-wasm
laruh Jun 22, 2023
f2be86a
reduce code repetition in for_db_tests.rs
laruh Jun 22, 2023
92f28aa
use protect_from_history_spam, protect_from_nft_spam
laruh Jun 23, 2023
cc6ddd6
move logic spam in meta into separate function
laruh Jun 23, 2023
7d4c7fc
reduce code duplication in check if spam
laruh Jun 25, 2023
a17e346
remove dead_code annotation
laruh Jun 25, 2023
2ce92e4
return bool in check_and_redact_metadata_field
laruh Jun 25, 2023
9b4b85e
if check in UriMeta::merge_from, line break after index_keys, get_las…
laruh Jun 26, 2023
0d8bebe
fix review notes: doc comments added, UriMeta refactored, db test fun…
laruh Jun 27, 2023
e869b0c
change block_on
laruh Jun 27, 2023
e8e13de
use common::block_on for native tests
laruh Jun 27, 2023
a0b5e4a
Merge remote-tracking branch 'origin/dev' into nft-cache-support-wasm
laruh Jun 28, 2023
7a821a2
test check for spam, test invalid moralis ipfs link, use is_initial_u…
laruh Jun 28, 2023
167bde2
rename `merge_from` to `try_to_fill_missing_fields_from`
laruh Jun 29, 2023
1746503
add my_address != tx.from_address check when receive erc721, make tra…
laruh Jun 29, 2023
755ebc6
make more fields optional
laruh Jun 29, 2023
8471fbc
use match in `handle_receive_erc721`, handle Erc721 error
laruh Jun 30, 2023
cf6ff1a
use match in `handle_receive_erc1155`, in `handle_send_erc1155` move …
laruh Jun 30, 2023
478b178
use map in `check_nft_metadata_for_spam`, impl From for `TxMeta`
laruh Jul 4, 2023
345cf5f
use common structures, combine moralis requests into one test
laruh Jul 5, 2023
221c8e4
use `build_nft_from_moralis`
laruh Jul 6, 2023
5b05033
add comments for cursor in wasm_storage, add regex to check links
laruh Jul 6, 2023
3defed0
Merge remote-tracking branch 'origin/dev' into nft-cache-support-wasm
laruh Jul 6, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions mm2src/coins/Cargo.toml
Expand Up @@ -76,6 +76,7 @@ primitives = { path = "../mm2_bitcoin/primitives" }
prost = "0.10"
protobuf = "2.20"
rand = { version = "0.7", features = ["std", "small_rng"] }
regex = "1"
rlp = { version = "0.5" }
rmp-serde = "0.14.3"
rpc = { path = "../mm2_bitcoin/rpc" }
Expand Down
551 changes: 326 additions & 225 deletions mm2src/coins/nft.rs

Large diffs are not rendered by default.

23 changes: 21 additions & 2 deletions mm2src/coins/nft/nft_errors.rs
Expand Up @@ -36,6 +36,7 @@ pub enum GetNftInfoError {
ParseRfc3339Err(ParseRfc3339Err),
#[display(fmt = "The contract type is required and should not be null.")]
ContractTypeIsNull,
ProtectFromSpamError(ProtectFromSpamError),
}

impl From<GetNftInfoError> for WithdrawError {
Expand Down Expand Up @@ -98,6 +99,10 @@ impl From<ParseRfc3339Err> for GetNftInfoError {
fn from(e: ParseRfc3339Err) -> Self { GetNftInfoError::ParseRfc3339Err(e) }
}

impl From<ProtectFromSpamError> for GetNftInfoError {
fn from(e: ProtectFromSpamError) -> Self { GetNftInfoError::ProtectFromSpamError(e) }
}

impl HttpStatusCode for GetNftInfoError {
fn status_code(&self) -> StatusCode {
match self {
Expand All @@ -108,7 +113,8 @@ impl HttpStatusCode for GetNftInfoError {
| GetNftInfoError::Internal(_)
| GetNftInfoError::GetEthAddressError(_)
| GetNftInfoError::TokenNotFoundInWallet { .. }
| GetNftInfoError::DbError(_) => StatusCode::INTERNAL_SERVER_ERROR,
| GetNftInfoError::DbError(_)
| GetNftInfoError::ProtectFromSpamError(_) => StatusCode::INTERNAL_SERVER_ERROR,
}
}
}
Expand Down Expand Up @@ -156,6 +162,10 @@ pub enum UpdateNftError {
LastScannedBlockNotFound {
last_nft_block: String,
},
#[display(fmt = "Attempt to receive duplicate ERC721 token in transaction hash: {}", tx_hash)]
AttemptToReceiveAlreadyOwnedErc721 {
tx_hash: String,
},
}

impl From<CreateNftStorageError> for UpdateNftError {
Expand Down Expand Up @@ -188,7 +198,8 @@ impl HttpStatusCode for UpdateNftError {
| UpdateNftError::TokenNotFoundInWallet { .. }
| UpdateNftError::InsufficientAmountInCache { .. }
| UpdateNftError::InvalidBlockOrder { .. }
| UpdateNftError::LastScannedBlockNotFound { .. } => StatusCode::INTERNAL_SERVER_ERROR,
| UpdateNftError::LastScannedBlockNotFound { .. }
| UpdateNftError::AttemptToReceiveAlreadyOwnedErc721 { .. } => StatusCode::INTERNAL_SERVER_ERROR,
}
}
}
Expand Down Expand Up @@ -219,3 +230,11 @@ impl From<SlurpError> for GetInfoFromUriError {
}
}
}

#[derive(Clone, Debug, Deserialize, Display, EnumFromStringify, PartialEq, Serialize)]
pub enum ProtectFromSpamError {
#[from_stringify("regex::Error")]
RegexError(String),
#[from_stringify("serde_json::Error")]
SerdeError(String),
}
195 changes: 125 additions & 70 deletions mm2src/coins/nft/nft_structs.rs
Expand Up @@ -18,13 +18,17 @@ pub struct NftListReq {
#[serde(default = "ten")]
pub(crate) limit: usize,
pub(crate) page_number: Option<NonZeroUsize>,
#[serde(default)]
pub(crate) protect_from_spam: bool,
}

#[derive(Debug, Deserialize)]
pub struct NftMetadataReq {
pub(crate) token_address: Address,
pub(crate) token_id: BigDecimal,
pub(crate) chain: Chain,
#[serde(default)]
pub(crate) protect_from_spam: bool,
}

#[derive(Debug, Deserialize)]
Expand Down Expand Up @@ -128,58 +132,98 @@ impl fmt::Display for ContractType {
}
}

/// `UriMeta` structure is the object which we create from `token_uri` and `metadata`.
///
/// `token_uri` and `metadata` usually contain either `image` or `image_url` with image url.
/// But most often nft creators use only `image` name for this value (from my observation),
/// less often they use both parameters with the same url.
///
/// I suspect this is because some APIs only look for one of these image url names, so nft creators try to satisfy all sides.
/// In any case, since there is no clear standard, we have to look for both options,
/// when we build `UriMeta` from `token_uri` or `metadata`.
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub(crate) struct UriMeta {
pub(crate) image: Option<String>,
#[serde(rename(deserialize = "name"))]
#[serde(rename = "image")]
pub(crate) raw_image_url: Option<String>,
pub(crate) image_url: Option<String>,
#[serde(rename = "name")]
pub(crate) token_name: Option<String>,
description: Option<String>,
attributes: Option<Json>,
animation_url: Option<String>,
pub(crate) description: Option<String>,
pub(crate) attributes: Option<Json>,
pub(crate) animation_url: Option<String>,
pub(crate) external_url: Option<String>,
pub(crate) image_details: Option<Json>,
}

impl UriMeta {
/// `try_to_fill_missing_fields_from` function doesnt change `raw_image_url` field.
/// It tries to update `image_url` field instead, if it is None.
/// As `image` is the original name of `raw_image_url` field in data from `token_uri` or `metadata`,
/// try to find **Some()** in this field first.
pub(crate) fn try_to_fill_missing_fields_from(&mut self, other: UriMeta) {
if self.image_url.is_none() {
self.image_url = other.raw_image_url.or(other.image_url);
}
if self.token_name.is_none() {
self.token_name = other.token_name;
}
if self.description.is_none() {
self.description = other.description;
}
if self.attributes.is_none() {
self.attributes = other.attributes;
}
if self.animation_url.is_none() {
self.animation_url = other.animation_url;
}
if self.external_url.is_none() {
self.external_url = other.external_url;
}
if self.image_details.is_none() {
self.image_details = other.image_details;
}
}
}

/// [`NftCommon`] structure contains common fields from [`Nft`] and [`NftFromMoralis`]
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Nft {
pub(crate) chain: Chain,
pub struct NftCommon {
pub(crate) token_address: String,
pub(crate) token_id: BigDecimal,
pub(crate) amount: BigDecimal,
pub(crate) owner_of: String,
pub(crate) token_hash: String,
pub(crate) block_number_minted: u64,
pub(crate) block_number: u64,
pub(crate) contract_type: ContractType,
pub(crate) token_hash: Option<String>,
#[serde(rename = "name")]
pub(crate) collection_name: Option<String>,
pub(crate) symbol: Option<String>,
pub(crate) token_uri: Option<String>,
pub(crate) metadata: Option<String>,
pub(crate) last_token_uri_sync: Option<String>,
pub(crate) last_metadata_sync: Option<String>,
pub(crate) minter_address: Option<String>,
pub(crate) possible_spam: Option<bool>,
#[serde(default)]
pub(crate) possible_spam: bool,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Nft {
#[serde(flatten)]
pub(crate) common: NftCommon,
pub(crate) chain: Chain,
pub(crate) block_number_minted: Option<u64>,
pub(crate) block_number: u64,
pub(crate) contract_type: ContractType,
pub(crate) uri_meta: UriMeta,
}

/// This structure is for deserializing NFT json to struct.
/// Its needed to convert fields properly, because all fields in json have string type.
/// This structure is for deserializing moralis NFT json to struct.
#[derive(Debug, Deserialize)]
pub(crate) struct NftWrapper {
pub(crate) token_address: String,
pub(crate) token_id: SerdeStringWrap<BigDecimal>,
pub(crate) amount: SerdeStringWrap<BigDecimal>,
pub(crate) owner_of: String,
pub(crate) token_hash: String,
pub(crate) block_number_minted: SerdeStringWrap<u64>,
pub(crate) struct NftFromMoralis {
#[serde(flatten)]
pub(crate) common: NftCommon,
pub(crate) block_number_minted: Option<SerdeStringWrap<u64>>,
pub(crate) block_number: SerdeStringWrap<u64>,
pub(crate) contract_type: Option<SerdeStringWrap<ContractType>>,
pub(crate) name: Option<String>,
pub(crate) symbol: Option<String>,
pub(crate) token_uri: Option<String>,
pub(crate) metadata: Option<String>,
pub(crate) last_token_uri_sync: Option<String>,
pub(crate) last_metadata_sync: Option<String>,
pub(crate) minter_address: Option<String>,
pub(crate) possible_spam: Option<bool>,
pub(crate) contract_type: Option<ContractType>,
}

#[derive(Debug)]
Expand Down Expand Up @@ -277,6 +321,8 @@ pub struct NftTransfersReq {
#[serde(default = "ten")]
pub(crate) limit: usize,
pub(crate) page_number: Option<NonZeroUsize>,
#[serde(default)]
pub(crate) protect_from_spam: bool,
}

#[derive(Debug, Display)]
Expand Down Expand Up @@ -312,53 +358,50 @@ impl fmt::Display for TransferStatus {
}
}

#[derive(Debug, Deserialize, Serialize)]
pub struct NftTransferHistory {
pub(crate) chain: Chain,
pub(crate) block_number: u64,
pub(crate) block_timestamp: u64,
pub(crate) block_hash: String,
/// [`NftTransferCommon`] structure contains common fields from [`NftTransferHistory`] and [`NftTxHistoryFromMoralis`]
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct NftTransferCommon {
pub(crate) block_hash: Option<String>,
/// Transaction hash in hexadecimal format
pub(crate) transaction_hash: String,
pub(crate) transaction_index: u64,
pub(crate) log_index: u64,
pub(crate) value: BigDecimal,
pub(crate) contract_type: ContractType,
pub(crate) transaction_type: String,
pub(crate) transaction_index: Option<u64>,
pub(crate) log_index: Option<u64>,
pub(crate) value: Option<BigDecimal>,
pub(crate) transaction_type: Option<String>,
pub(crate) token_address: String,
pub(crate) token_id: BigDecimal,
pub(crate) collection_name: Option<String>,
pub(crate) image: Option<String>,
pub(crate) token_name: Option<String>,
pub(crate) from_address: String,
pub(crate) to_address: String,
pub(crate) status: TransferStatus,
pub(crate) amount: BigDecimal,
pub(crate) verified: u64,
pub(crate) verified: Option<u64>,
pub(crate) operator: Option<String>,
pub(crate) possible_spam: Option<bool>,
#[serde(default)]
pub(crate) possible_spam: bool,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct NftTransferHistory {
#[serde(flatten)]
pub(crate) common: NftTransferCommon,
pub(crate) chain: Chain,
pub(crate) block_number: u64,
pub(crate) block_timestamp: u64,
pub(crate) contract_type: ContractType,
pub(crate) token_uri: Option<String>,
pub(crate) collection_name: Option<String>,
pub(crate) image_url: Option<String>,
pub(crate) token_name: Option<String>,
pub(crate) status: TransferStatus,
}

/// This structure is for deserializing moralis NFT transaction json to struct.
#[derive(Debug, Deserialize)]
pub(crate) struct NftTransferHistoryWrapper {
pub(crate) struct NftTxHistoryFromMoralis {
#[serde(flatten)]
pub(crate) common: NftTransferCommon,
pub(crate) block_number: SerdeStringWrap<u64>,
pub(crate) block_timestamp: String,
pub(crate) block_hash: String,
/// Transaction hash in hexadecimal format
pub(crate) transaction_hash: String,
pub(crate) transaction_index: u64,
pub(crate) log_index: u64,
pub(crate) value: SerdeStringWrap<BigDecimal>,
pub(crate) contract_type: Option<SerdeStringWrap<ContractType>>,
pub(crate) transaction_type: String,
pub(crate) token_address: String,
pub(crate) token_id: SerdeStringWrap<BigDecimal>,
pub(crate) from_address: String,
pub(crate) to_address: String,
pub(crate) amount: SerdeStringWrap<BigDecimal>,
pub(crate) verified: u64,
pub(crate) operator: Option<String>,
pub(crate) possible_spam: Option<bool>,
pub(crate) contract_type: Option<ContractType>,
}

#[derive(Debug, Serialize)]
Expand All @@ -368,11 +411,10 @@ pub struct NftsTransferHistoryList {
pub(crate) total: usize,
}

#[allow(dead_code)]
#[derive(Clone, Debug, Deserialize)]
#[derive(Copy, Clone, Debug, Deserialize)]
pub struct NftTxHistoryFilters {
#[serde(default)]
pub(crate) receive: bool,
pub receive: bool,
#[serde(default)]
pub(crate) send: bool,
pub(crate) from_date: Option<u64>,
Expand All @@ -385,18 +427,31 @@ pub struct UpdateNftReq {
pub(crate) url: Url,
}

#[derive(Debug, Deserialize)]
#[derive(Debug, Deserialize, Eq, Hash, PartialEq)]
pub struct NftTokenAddrId {
pub(crate) token_address: String,
pub(crate) token_id: BigDecimal,
}

#[allow(dead_code)]
#[derive(Debug)]
pub struct TxMeta {
pub(crate) token_address: String,
pub(crate) token_id: BigDecimal,
pub(crate) token_uri: Option<String>,
pub(crate) collection_name: Option<String>,
pub(crate) image: Option<String>,
pub(crate) image_url: Option<String>,
pub(crate) token_name: Option<String>,
}

impl From<Nft> for TxMeta {
fn from(nft_db: Nft) -> Self {
TxMeta {
token_address: nft_db.common.token_address,
token_id: nft_db.common.token_id,
token_uri: nft_db.common.token_uri,
collection_name: nft_db.common.collection_name,
image_url: nft_db.uri_meta.image_url,
token_name: nft_db.uri_meta.token_name,
}
}
}