From 0e337379e5193ac98279e7cae84ba0f13b83640d Mon Sep 17 00:00:00 2001
From: Patrice Tisserand
Date: Mon, 19 Aug 2024 10:20:07 +0200
Subject: [PATCH 1/7] fix(arkchain-indexer): cancelled event are now inserted
by arkchain indexer
Add `TokenEventType` enum to modelize database token events
---
.../migrations/marketplace/0_marketplace.sql | 5 +-
ark-sqlx/src/providers/marketplace/mod.rs | 1 +
ark-sqlx/src/providers/marketplace/order.rs | 243 ++++++++----------
ark-sqlx/src/providers/marketplace/types.rs | 101 ++++++++
4 files changed, 216 insertions(+), 134 deletions(-)
create mode 100644 ark-sqlx/src/providers/marketplace/types.rs
diff --git a/ark-sqlx/migrations/marketplace/0_marketplace.sql b/ark-sqlx/migrations/marketplace/0_marketplace.sql
index 1e59f8ca..b4d32ec2 100644
--- a/ark-sqlx/migrations/marketplace/0_marketplace.sql
+++ b/ark-sqlx/migrations/marketplace/0_marketplace.sql
@@ -70,7 +70,10 @@ CREATE TABLE token_event (
order_hash TEXT,
token_id TEXT NOT NULL,
token_id_hex TEXT NOT NULL,
- event_type TEXT CHECK (event_type IN ('Listing', 'CollectionOffer', 'Offer', 'Auction', 'Fulfill', 'Cancelled', 'Executed', 'Sale', 'Mint', 'Burn', 'Transfer')),
+ event_type TEXT CHECK (event_type IN
+ ('Listing', 'CollectionOffer', 'Offer', 'Auction',
+ 'Fulfill', 'Cancelled', 'Executed', 'Sale', 'Mint',
+ 'Burn', 'Transfer', 'ListingCancelled', 'AuctionCancelled', 'OfferCancelled')),
block_timestamp BIGINT NOT NULL,
transaction_hash TEXT NULL,
to_address TEXT, -- NULL if not transfer
diff --git a/ark-sqlx/src/providers/marketplace/mod.rs b/ark-sqlx/src/providers/marketplace/mod.rs
index fd116adf..e400b54f 100644
--- a/ark-sqlx/src/providers/marketplace/mod.rs
+++ b/ark-sqlx/src/providers/marketplace/mod.rs
@@ -1,2 +1,3 @@
pub mod order;
pub use order::OrderProvider;
+pub mod types;
diff --git a/ark-sqlx/src/providers/marketplace/order.rs b/ark-sqlx/src/providers/marketplace/order.rs
index 6d6a8a9f..127695e5 100644
--- a/ark-sqlx/src/providers/marketplace/order.rs
+++ b/ark-sqlx/src/providers/marketplace/order.rs
@@ -1,4 +1,6 @@
use crate::providers::{ProviderError, SqlxCtxPg};
+use crate::providers::marketplace::types::{TokenEventType, AUCTION_CANCELLED_STR, AUCTION_STR, BURN_STR, CANCELLED_STR, COLLECTION_OFFER_STR, EXECUTED_STR, FULFILL_STR, LISTING_CANCELLED_STR, LISTING_STR, MINT_STR, OFFER_CANCELLED_STR, OFFER_STR, ROLLBACK_STR, SALE_STR, TRANSFER_STR};
+
use arkproject::diri::storage::types::{
CancelledData, ExecutedData, FulfilledData, PlacedData, RollbackStatusData,
};
@@ -15,6 +17,59 @@ use std::sync::Arc;
use tokio::sync::Mutex;
use tracing::{error, info, trace};
+// conversion from Diri string
+impl FromStr for TokenEventType {
+ type Err = &'static str;
+
+ fn from_str(s: &str) -> Result {
+ match s {
+ LISTING_STR => Ok(TokenEventType::Listing),
+ AUCTION_STR => Ok(TokenEventType::Auction),
+ OFFER_STR => Ok(TokenEventType::Offer),
+ COLLECTION_OFFER_STR => Ok(TokenEventType::CollectionOffer),
+ FULFILL_STR => Ok(TokenEventType::Fulfill),
+ EXECUTED_STR => Ok(TokenEventType::Executed),
+ CANCELLED_STR => Ok(TokenEventType::Cancelled),
+ SALE_STR => Ok(TokenEventType::Sale),
+ MINT_STR => Ok(TokenEventType::Mint),
+ BURN_STR => Ok(TokenEventType::Burn),
+ TRANSFER_STR => Ok(TokenEventType::Transfer),
+ ROLLBACK_STR => Ok(TokenEventType::Rollback),
+ LISTING_CANCELLED_STR => Ok(TokenEventType::ListingCancelled),
+ AUCTION_CANCELLED_STR => Ok(TokenEventType::AuctionCancelled),
+ OFFER_CANCELLED_STR => Ok(TokenEventType::OfferCancelled),
+ _ => Err("Unknown event type"),
+ }
+ }
+}
+
+
+impl fmt::Display for TokenEventType {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(
+ f,
+ "{}",
+ match self {
+ TokenEventType::Listing => LISTING_STR,
+ TokenEventType::Auction => AUCTION_STR,
+ TokenEventType::Offer => OFFER_STR,
+ TokenEventType::CollectionOffer => COLLECTION_OFFER_STR,
+ TokenEventType::Fulfill => FULFILL_STR,
+ TokenEventType::Executed => EXECUTED_STR,
+ TokenEventType::Cancelled => CANCELLED_STR,
+ TokenEventType::Sale => SALE_STR,
+ TokenEventType::Mint => MINT_STR,
+ TokenEventType::Burn => BURN_STR,
+ TokenEventType::Transfer => TRANSFER_STR,
+ TokenEventType::Rollback => ROLLBACK_STR,
+ TokenEventType::ListingCancelled => LISTING_CANCELLED_STR,
+ TokenEventType::AuctionCancelled => AUCTION_CANCELLED_STR,
+ TokenEventType::OfferCancelled => OFFER_CANCELLED_STR,
+ }
+ )
+ }
+}
+
#[derive(Debug)]
#[allow(clippy::enum_variant_names)]
enum RollbackStatus {
@@ -72,104 +127,6 @@ pub enum OrderStatus {
Executed,
}
-#[derive(Debug, Copy, Clone, PartialEq)]
-pub enum EventType {
- Listing,
- Auction,
- Offer,
- CollectionOffer,
- Fulfill,
- Executed,
- Cancelled,
- Mint,
- Burn,
- Transfer,
- Rollback,
-}
-
-impl From for EventType {
- fn from(s: String) -> Self {
- match s.as_str() {
- "Listing" => EventType::Listing,
- "Auction" => EventType::Auction,
- "Offer" => EventType::Offer,
- "CollectionOffer" => EventType::CollectionOffer,
- "Fulfill" => EventType::Fulfill,
- "Executed" => EventType::Executed,
- "Cancelled" => EventType::Cancelled,
- "Mint" => EventType::Mint,
- "Burn" => EventType::Burn,
- "Transfer" => EventType::Transfer,
- "Rollback" => EventType::Rollback,
- _ => {
- error!("Unknown event type: {}", s);
- EventType::Listing
- }
- }
- }
-}
-
-impl FromStr for EventType {
- type Err = &'static str;
-
- fn from_str(s: &str) -> Result {
- match s {
- "Listing" => Ok(EventType::Listing),
- "Auction" => Ok(EventType::Auction),
- "Offer" => Ok(EventType::Offer),
- "CollectionOffer" => Ok(EventType::CollectionOffer),
- "Fulfill" => Ok(EventType::Fulfill),
- "Executed" => Ok(EventType::Executed),
- "Cancelled" => Ok(EventType::Cancelled),
- "Mint" => Ok(EventType::Mint),
- "Burn" => Ok(EventType::Burn),
- "Transfer" => Ok(EventType::Transfer),
- "Rollback" => Ok(EventType::Rollback),
- _ => Err("Unknown event type"),
- }
- }
-}
-
-impl EventType {
- pub fn as_str(&self) -> &'static str {
- match self {
- EventType::Listing => "Listing",
- EventType::Auction => "Auction",
- EventType::Offer => "Offer",
- EventType::CollectionOffer => "CollectionOffer",
- EventType::Fulfill => "Fulfill",
- EventType::Executed => "Executed",
- EventType::Cancelled => "Cancelled",
- EventType::Mint => "Mint",
- EventType::Burn => "Burn",
- EventType::Transfer => "Transfer",
- EventType::Rollback => "Rollback",
- }
- }
-}
-
-impl fmt::Display for EventType {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(
- f,
- "{}",
- match self {
- EventType::Listing => "Listing",
- EventType::Auction => "Auction",
- EventType::Offer => "Offer",
- EventType::CollectionOffer => "CollectionOffer",
- EventType::Fulfill => "Fulfill",
- EventType::Executed => "Executed",
- EventType::Cancelled => "Cancelled",
- EventType::Mint => "Mint",
- EventType::Burn => "Burn",
- EventType::Transfer => "Transfer",
- EventType::Rollback => "Rollback",
- }
- )
- }
-}
-
impl fmt::Display for OrderStatus {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
@@ -187,13 +144,14 @@ impl fmt::Display for OrderStatus {
pub struct OrderProvider {}
+#[derive(sqlx::FromRow)]
struct EventHistoryData {
order_hash: String,
token_id: String,
token_id_hex: String,
contract_address: String,
chain_id: String,
- event_type: EventType,
+ event_type: TokenEventType,
block_timestamp: i64,
from_address: Option,
to_address: Option,
@@ -527,7 +485,7 @@ impl OrderProvider {
.bind(token_id)
.bind(chain_id)
.bind(order_hash)
- .bind(EventType::Fulfill.to_string())
+ .bind(TokenEventType::Fulfill.to_string())
.fetch_optional(&client.pool)
.await?;
@@ -871,7 +829,7 @@ impl OrderProvider {
let q = "
INSERT INTO token_event (token_event_id, order_hash, token_id, token_id_hex, contract_address, chain_id, event_type, block_timestamp, from_address, to_address, amount, canceled_reason)
- VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12);
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12);
";
let _r = sqlx::query(q)
@@ -893,6 +851,49 @@ impl OrderProvider {
Ok(())
}
+ async fn insert_cancel_event(
+ client: &SqlxCtxPg,
+ order_hash: String,
+ block_timestamp: i64,
+ reason: String,
+ ) -> Result<(), ProviderError> {
+ // retrieve previous order hash event
+ let query = "
+ SELECT
+ order_hash,
+ token_id,
+ token_id_hex,
+ contract_address,
+ chain_id,
+ event_type,
+ block_timestamp,
+ from_address,
+ to_address,
+ amount,
+ canceled_reason
+ FROM token_event
+ WHERE order_hash = $1
+ ORDER BY block_timestamp DESC
+ LIMIT 1
+ ";
+ if let Ok(mut event_history) = sqlx::query_as::<_, EventHistoryData>(query)
+ .bind(order_hash)
+ .fetch_one(&client.pool)
+ .await {
+ event_history.block_timestamp = block_timestamp;
+ event_history.canceled_reason = reason.into();
+ event_history.event_type = match event_history.event_type {
+ TokenEventType::Listing => TokenEventType::ListingCancelled,
+ TokenEventType::Auction => TokenEventType::AuctionCancelled,
+ TokenEventType::Offer => TokenEventType::OfferCancelled,
+ _ => TokenEventType::Cancelled,
+ };
+
+ Self::insert_event_history(client, &event_history).await?;
+ }
+ Ok(())
+ }
+
async fn offer_exists(
client: &SqlxCtxPg,
order_hash: &str,
@@ -1103,7 +1104,7 @@ impl OrderProvider {
None => return Err(ProviderError::from("Missing token id")),
};
- let event_type = EventType::from_str(&data.order_type).map_err(ProviderError::from)?;
+ let event_type = TokenEventType::from_str(&data.order_type).map_err(ProviderError::from)?;
let contract_address = Self::get_or_create_contract(
client,
&data.token_address,
@@ -1119,7 +1120,7 @@ impl OrderProvider {
}
}
- if event_type == EventType::Offer || event_type == EventType::CollectionOffer {
+ if event_type == TokenEventType::Offer || event_type == TokenEventType::CollectionOffer {
// create token without listing information
let upsert_query = "
INSERT INTO token (contract_address, token_id, token_id_hex, chain_id, updated_timestamp, listing_orderhash, block_timestamp, status)
@@ -1352,32 +1353,6 @@ impl OrderProvider {
}
}
- let token_id = match BigInt::from_str(&token_data.token_id) {
- Ok(token_id) => token_id.to_string(),
- Err(e) => {
- error!("Failed to parse token id: {}", e);
- return Err(ProviderError::from("Failed to parse token id"));
- }
- };
-
- Self::insert_event_history(
- client,
- &EventHistoryData {
- order_hash: data.order_hash.clone(),
- token_id: token_id.clone(),
- token_id_hex: token_data.token_id_hex.clone(),
- contract_address: token_data.contract_address.clone(),
- chain_id: token_data.chain_id.clone(),
- event_type: EventType::Cancelled,
- block_timestamp: block_timestamp as i64,
- canceled_reason: data.reason.clone().into(),
- to_address: None,
- amount: None,
- from_address: None,
- },
- )
- .await?;
-
Self::update_token_status(
client,
&token_data.contract_address,
@@ -1401,6 +1376,8 @@ impl OrderProvider {
{
Self::update_offer_status(client, &data.order_hash, OrderStatus::Cancelled).await?;
}
+ // insert cancelled event
+ Self::insert_cancel_event(client, data.order_hash.clone(), block_timestamp as i64, data.reason.clone()).await?;
Ok(())
}
@@ -1439,7 +1416,7 @@ impl OrderProvider {
token_id_hex: token_data.token_id_hex.clone(),
contract_address: token_data.contract_address.clone(),
chain_id: token_data.chain_id.clone(),
- event_type: EventType::Fulfill,
+ event_type: TokenEventType::Fulfill,
block_timestamp: block_timestamp as i64,
canceled_reason: None,
to_address: None,
@@ -1516,7 +1493,7 @@ impl OrderProvider {
token_id_hex: token_data.token_id_hex.clone(),
contract_address: offer_data.contract_address.clone(),
chain_id: offer_data.chain_id.clone(),
- event_type: EventType::Executed,
+ event_type: TokenEventType::Executed,
block_timestamp: block_timestamp as i64,
canceled_reason: None,
to_address,
@@ -1572,7 +1549,7 @@ impl OrderProvider {
token_id_hex: token_data.token_id_hex.clone(),
contract_address: token_data.contract_address.clone(),
chain_id: token_data.chain_id,
- event_type: EventType::Executed,
+ event_type: TokenEventType::Executed,
canceled_reason: None,
to_address: None,
amount: token_data.listing_start_amount,
@@ -1620,7 +1597,7 @@ impl OrderProvider {
token_id_hex: token_data.token_id_hex.clone(),
contract_address: token_data.contract_address,
chain_id: token_data.chain_id,
- event_type: EventType::Rollback,
+ event_type: TokenEventType::Rollback,
canceled_reason: Some(string_reason),
to_address: None,
amount: None,
diff --git a/ark-sqlx/src/providers/marketplace/types.rs b/ark-sqlx/src/providers/marketplace/types.rs
new file mode 100644
index 00000000..9bcb39e5
--- /dev/null
+++ b/ark-sqlx/src/providers/marketplace/types.rs
@@ -0,0 +1,101 @@
+
+#[derive(Debug, Copy, Clone, PartialEq)]
+pub enum TokenEventType {
+ Listing,
+ Auction,
+ Offer,
+ CollectionOffer,
+ Fulfill,
+ Executed,
+ Cancelled,
+ Sale,
+ Mint,
+ Burn,
+ Transfer,
+ Rollback,
+ // Cancel event type
+ ListingCancelled,
+ AuctionCancelled,
+ OfferCancelled,
+}
+
+
+/// DB for EventType
+pub(crate) const LISTING_STR: &str = "Listing";
+pub(crate) const AUCTION_STR: &str = "Auction";
+pub(crate) const OFFER_STR: &str = "Offer";
+pub(crate) const COLLECTION_OFFER_STR: &str = "CollectionOffer";
+pub(crate) const FULFILL_STR: &str = "Fulfill";
+pub(crate) const EXECUTED_STR: &str = "Executed";
+pub(crate) const CANCELLED_STR: &str = "Cancelled";
+pub(crate) const SALE_STR: &str = "Sale";
+pub(crate) const MINT_STR: &str = "Mint";
+pub(crate) const BURN_STR: &str = "Burn";
+pub(crate) const TRANSFER_STR: &str = "Transfer";
+pub(crate) const ROLLBACK_STR: &str = "Rollback";
+pub(crate) const LISTING_CANCELLED_STR: &str = "ListingCancelled";
+pub(crate) const AUCTION_CANCELLED_STR: &str = "AuctionCancelled";
+pub(crate) const OFFER_CANCELLED_STR: &str = "OfferCancelled";
+
+
+impl sqlx::Type for TokenEventType
+where
+ DB: sqlx::Database,
+ String: sqlx::Type,
+{
+ fn type_info() -> ::TypeInfo {
+ >::type_info()
+ }
+}
+
+impl<'r, DB> sqlx::Decode<'r, DB> for TokenEventType
+where
+ DB: sqlx::Database,
+ &'r str: sqlx::Decode<'r, DB>,
+{
+ fn decode(
+ value: >::ValueRef,
+ ) -> Result {
+ let s = <&str as sqlx::Decode>::decode(value)?;
+ match s {
+ LISTING_STR => Ok(TokenEventType::Listing),
+ COLLECTION_OFFER_STR => Ok(TokenEventType::CollectionOffer),
+ OFFER_STR => Ok(TokenEventType::Offer),
+ AUCTION_STR => Ok(TokenEventType::Auction),
+ FULFILL_STR => Ok(TokenEventType::Fulfill),
+ CANCELLED_STR => Ok(TokenEventType::Cancelled),
+ EXECUTED_STR => Ok(TokenEventType::Executed),
+ SALE_STR => Ok(TokenEventType::Sale),
+ MINT_STR => Ok(TokenEventType::Mint),
+ BURN_STR => Ok(TokenEventType::Burn),
+ TRANSFER_STR => Ok(TokenEventType::Transfer),
+ ROLLBACK_STR => Ok(TokenEventType::Rollback),
+ LISTING_CANCELLED_STR => Ok(TokenEventType::ListingCancelled),
+ AUCTION_CANCELLED_STR => Ok(TokenEventType::AuctionCancelled),
+ OFFER_CANCELLED_STR => Ok(TokenEventType::OfferCancelled),
+ _ => Err("Invalid event type".into()),
+ }
+ }
+}
+
+impl TokenEventType {
+ pub fn to_db_string(&self) -> String {
+ match self {
+ TokenEventType::Listing => LISTING_STR.to_string(),
+ TokenEventType::Auction => AUCTION_STR.to_string(),
+ TokenEventType::Offer => OFFER_STR.to_string(),
+ TokenEventType::CollectionOffer => COLLECTION_OFFER_STR.to_string(),
+ TokenEventType::Fulfill => FULFILL_STR.to_string(),
+ TokenEventType::Executed => EXECUTED_STR.to_string(),
+ TokenEventType::Cancelled => CANCELLED_STR.to_string(),
+ TokenEventType::Sale => SALE_STR.to_string(),
+ TokenEventType::Mint => MINT_STR.to_string(),
+ TokenEventType::Burn => BURN_STR.to_string(),
+ TokenEventType::Transfer => TRANSFER_STR.to_string(),
+ TokenEventType::Rollback => ROLLBACK_STR.to_string(),
+ TokenEventType::ListingCancelled => LISTING_CANCELLED_STR.to_string(),
+ TokenEventType::AuctionCancelled => AUCTION_CANCELLED_STR.to_string(),
+ TokenEventType::OfferCancelled => OFFER_CANCELLED_STR.to_string(),
+ }
+ }
+}
\ No newline at end of file
From f601d754dd1916838fda406507c59ace20e270ee Mon Sep 17 00:00:00 2001
From: Patrice Tisserand
Date: Mon, 19 Aug 2024 10:21:01 +0200
Subject: [PATCH 2/7] DRY
---
ark-marketplace-api/src/utils/db_utils.rs | 106 ++++++++++------------
1 file changed, 47 insertions(+), 59 deletions(-)
diff --git a/ark-marketplace-api/src/utils/db_utils.rs b/ark-marketplace-api/src/utils/db_utils.rs
index 3ad762a0..e9b7bcc8 100644
--- a/ark-marketplace-api/src/utils/db_utils.rs
+++ b/ark-marketplace-api/src/utils/db_utils.rs
@@ -1,4 +1,5 @@
use crate::models::token::TokenEventType;
+use ark_sqlx::providers::marketplace::types::TokenEventType as TokenEventTypeDB;
pub fn event_type_list(values: &[TokenEventType]) -> String {
let mut types = values
@@ -6,29 +7,36 @@ pub fn event_type_list(values: &[TokenEventType]) -> String {
.map(|v| format!("'{}'", v.to_db_string()))
.collect::>();
- if types.contains(&format!("'{}'", TOKEN_EVENT_SALE_STR)) {
- types.push(format!("'{}'", TOKEN_EVENT_EXECUTED_STR));
+ if types.contains(&format!("'{}'", TokenEventType::Sale.to_db_string())) {
+ types.push(format!("'{}'", TokenEventType::Executed.to_db_string()));
}
types.join(", ")
}
-/// DB conversion for TokenEventType
-const TOKEN_EVENT_LISTING_STR: &str = "Listing";
-const TOKEN_EVENT_COLLECTION_OFFER_STR: &str = "CollectionOffer";
-const TOKEN_EVENT_OFFER_STR: &str = "Offer";
-const TOKEN_EVENT_AUCTION_STR: &str = "Auction";
-const TOKEN_EVENT_FULFILL_STR: &str = "Fulfill";
-const TOKEN_EVENT_CANCELLED_STR: &str = "Cancelled";
-const TOKEN_EVENT_EXECUTED_STR: &str = "Executed";
-const TOKEN_EVENT_SALE_STR: &str = "Sale";
-const TOKEN_EVENT_MINT_STR: &str = "Mint";
-const TOKEN_EVENT_BURN_STR: &str = "Burn";
-const TOKEN_EVENT_TRANSFER_STR: &str = "Transfer";
-// Cancel event
-const TOKEN_EVENT_LISTING_CANCELLED_STR: &str = "ListingCancelled";
-const TOKEN_EVENT_AUCTION_CANCELLED_STR: &str = "AuctionCancelled";
-const TOKEN_EVENT_OFFER_CANCELLED_STR: &str = "OfferCancelled";
+
+/// Convert TokenEventType to matching keys in DB
+impl TokenEventType {
+ pub fn to_db_string(&self) -> String {
+ match self {
+ Self::Listing => TokenEventTypeDB::Listing.to_db_string(),
+ Self::CollectionOffer => TokenEventTypeDB::CollectionOffer.to_db_string(),
+ Self::Offer => TokenEventTypeDB::Offer.to_string(),
+ Self::Auction => TokenEventTypeDB::Auction.to_string(),
+ Self::Fulfill => TokenEventTypeDB::Fulfill.to_string(),
+ Self::Cancelled => TokenEventTypeDB::Cancelled.to_string(),
+ Self::Executed => TokenEventTypeDB::Executed.to_string(),
+ Self::Sale => TokenEventTypeDB::Sale.to_string(),
+ Self::Mint => TokenEventTypeDB::Mint.to_string(),
+ Self::Burn => TokenEventTypeDB::Burn.to_string(),
+ Self::Transfer => TokenEventType::Transfer.to_string(),
+ // Cancel event
+ Self::ListingCancelled => TokenEventTypeDB::ListingCancelled.to_string(),
+ Self::AuctionCancelled => TokenEventTypeDB::AuctionCancelled.to_string(),
+ Self::OfferCancelled => TokenEventTypeDB::OfferCancelled.to_string(),
+ }
+ }
+}
impl sqlx::Type for TokenEventType
where
@@ -48,47 +56,27 @@ where
fn decode(
value: >::ValueRef,
) -> Result {
- let s = <&str as sqlx::Decode>::decode(value)?;
- match s {
- TOKEN_EVENT_LISTING_STR => Ok(TokenEventType::Listing),
- TOKEN_EVENT_COLLECTION_OFFER_STR => Ok(TokenEventType::CollectionOffer),
- TOKEN_EVENT_OFFER_STR => Ok(TokenEventType::Offer),
- TOKEN_EVENT_AUCTION_STR => Ok(TokenEventType::Auction),
- TOKEN_EVENT_FULFILL_STR => Ok(TokenEventType::Fulfill),
- TOKEN_EVENT_CANCELLED_STR => Ok(TokenEventType::Cancelled),
- TOKEN_EVENT_EXECUTED_STR => Ok(TokenEventType::Executed),
- TOKEN_EVENT_SALE_STR => Ok(TokenEventType::Sale),
- TOKEN_EVENT_MINT_STR => Ok(TokenEventType::Mint),
- TOKEN_EVENT_BURN_STR => Ok(TokenEventType::Burn),
- TOKEN_EVENT_TRANSFER_STR => Ok(TokenEventType::Transfer),
- // Cancel event
- TOKEN_EVENT_LISTING_CANCELLED_STR => Ok(TokenEventType::ListingCancelled),
- TOKEN_EVENT_AUCTION_CANCELLED_STR => Ok(TokenEventType::AuctionCancelled),
- TOKEN_EVENT_OFFER_CANCELLED_STR => Ok(TokenEventType::OfferCancelled),
- _ => Err("Invalid event type".into()),
- }
- }
-}
-
-/// Convert TokenEventType to matching keys in DB
-impl TokenEventType {
- pub fn to_db_string(&self) -> String {
- match self {
- Self::Listing => TOKEN_EVENT_LISTING_STR.to_string(),
- Self::CollectionOffer => TOKEN_EVENT_COLLECTION_OFFER_STR.to_string(),
- Self::Offer => TOKEN_EVENT_OFFER_STR.to_string(),
- Self::Auction => TOKEN_EVENT_AUCTION_STR.to_string(),
- Self::Fulfill => TOKEN_EVENT_FULFILL_STR.to_string(),
- Self::Cancelled => TOKEN_EVENT_CANCELLED_STR.to_string(),
- Self::Executed => TOKEN_EVENT_EXECUTED_STR.to_string(),
- Self::Sale => TOKEN_EVENT_SALE_STR.to_string(),
- Self::Mint => TOKEN_EVENT_MINT_STR.to_string(),
- Self::Burn => TOKEN_EVENT_BURN_STR.to_string(),
- Self::Transfer => TOKEN_EVENT_TRANSFER_STR.to_string(),
- // Cancel event
- Self::ListingCancelled => TOKEN_EVENT_LISTING_CANCELLED_STR.to_string(),
- Self::AuctionCancelled => TOKEN_EVENT_AUCTION_CANCELLED_STR.to_string(),
- Self::OfferCancelled => TOKEN_EVENT_OFFER_CANCELLED_STR.to_string(),
+ if let Ok(e) = TokenEventTypeDB::decode(value) {
+ match e {
+ TokenEventTypeDB::Listing => Ok(TokenEventType::Listing),
+ TokenEventTypeDB::Auction => Ok(TokenEventType::Auction),
+ TokenEventTypeDB::Offer => Ok(TokenEventType::Offer),
+ TokenEventTypeDB::CollectionOffer => Ok(TokenEventType::CollectionOffer),
+ TokenEventTypeDB::Fulfill => Ok(TokenEventType::Offer),
+ TokenEventTypeDB::Executed => Ok(TokenEventType::Executed),
+ TokenEventTypeDB::Cancelled => Ok(TokenEventType::Cancelled),
+ TokenEventTypeDB::Sale => Ok(TokenEventType::Sale),
+ TokenEventTypeDB::Mint => Ok(TokenEventType::Mint),
+ TokenEventTypeDB::Burn => Ok(TokenEventType::Burn),
+ TokenEventTypeDB::Transfer => Ok(TokenEventType::Transfer),
+ TokenEventTypeDB::ListingCancelled => Ok(TokenEventType::ListingCancelled),
+ TokenEventTypeDB::AuctionCancelled => Ok(TokenEventType::AuctionCancelled),
+ TokenEventTypeDB::OfferCancelled => Ok(TokenEventType::OfferCancelled),
+ TokenEventTypeDB::Rollback => Err("Unsupported rollback event".into())
+ // _ => Ok(TokenEventType::Burn),
+ }
+ } else {
+ Err("Invalid event type".into())
}
}
}
From 895e790ec7f3c37dc378707e6e95c36b4c30c4d2 Mon Sep 17 00:00:00 2001
From: Patrice Tisserand
Date: Mon, 26 Aug 2024 16:28:37 +0200
Subject: [PATCH 3/7] cargo fmt
---
ark-marketplace-api/src/utils/db_utils.rs | 4 +--
ark-sqlx/src/providers/marketplace/order.rs | 28 ++++++++++++++-------
ark-sqlx/src/providers/marketplace/types.rs | 5 +---
3 files changed, 21 insertions(+), 16 deletions(-)
diff --git a/ark-marketplace-api/src/utils/db_utils.rs b/ark-marketplace-api/src/utils/db_utils.rs
index e9b7bcc8..02f5995a 100644
--- a/ark-marketplace-api/src/utils/db_utils.rs
+++ b/ark-marketplace-api/src/utils/db_utils.rs
@@ -14,7 +14,6 @@ pub fn event_type_list(values: &[TokenEventType]) -> String {
types.join(", ")
}
-
/// Convert TokenEventType to matching keys in DB
impl TokenEventType {
pub fn to_db_string(&self) -> String {
@@ -72,8 +71,7 @@ where
TokenEventTypeDB::ListingCancelled => Ok(TokenEventType::ListingCancelled),
TokenEventTypeDB::AuctionCancelled => Ok(TokenEventType::AuctionCancelled),
TokenEventTypeDB::OfferCancelled => Ok(TokenEventType::OfferCancelled),
- TokenEventTypeDB::Rollback => Err("Unsupported rollback event".into())
- // _ => Ok(TokenEventType::Burn),
+ TokenEventTypeDB::Rollback => Err("Unsupported rollback event".into()), // _ => Ok(TokenEventType::Burn),
}
} else {
Err("Invalid event type".into())
diff --git a/ark-sqlx/src/providers/marketplace/order.rs b/ark-sqlx/src/providers/marketplace/order.rs
index 127695e5..5cd20188 100644
--- a/ark-sqlx/src/providers/marketplace/order.rs
+++ b/ark-sqlx/src/providers/marketplace/order.rs
@@ -1,5 +1,9 @@
+use crate::providers::marketplace::types::{
+ TokenEventType, AUCTION_CANCELLED_STR, AUCTION_STR, BURN_STR, CANCELLED_STR,
+ COLLECTION_OFFER_STR, EXECUTED_STR, FULFILL_STR, LISTING_CANCELLED_STR, LISTING_STR, MINT_STR,
+ OFFER_CANCELLED_STR, OFFER_STR, ROLLBACK_STR, SALE_STR, TRANSFER_STR,
+};
use crate::providers::{ProviderError, SqlxCtxPg};
-use crate::providers::marketplace::types::{TokenEventType, AUCTION_CANCELLED_STR, AUCTION_STR, BURN_STR, CANCELLED_STR, COLLECTION_OFFER_STR, EXECUTED_STR, FULFILL_STR, LISTING_CANCELLED_STR, LISTING_STR, MINT_STR, OFFER_CANCELLED_STR, OFFER_STR, ROLLBACK_STR, SALE_STR, TRANSFER_STR};
use arkproject::diri::storage::types::{
CancelledData, ExecutedData, FulfilledData, PlacedData, RollbackStatusData,
@@ -43,7 +47,6 @@ impl FromStr for TokenEventType {
}
}
-
impl fmt::Display for TokenEventType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
@@ -65,7 +68,7 @@ impl fmt::Display for TokenEventType {
TokenEventType::ListingCancelled => LISTING_CANCELLED_STR,
TokenEventType::AuctionCancelled => AUCTION_CANCELLED_STR,
TokenEventType::OfferCancelled => OFFER_CANCELLED_STR,
- }
+ }
)
}
}
@@ -877,9 +880,10 @@ impl OrderProvider {
LIMIT 1
";
if let Ok(mut event_history) = sqlx::query_as::<_, EventHistoryData>(query)
- .bind(order_hash)
- .fetch_one(&client.pool)
- .await {
+ .bind(order_hash)
+ .fetch_one(&client.pool)
+ .await
+ {
event_history.block_timestamp = block_timestamp;
event_history.canceled_reason = reason.into();
event_history.event_type = match event_history.event_type {
@@ -893,7 +897,7 @@ impl OrderProvider {
}
Ok(())
}
-
+
async fn offer_exists(
client: &SqlxCtxPg,
order_hash: &str,
@@ -1376,8 +1380,14 @@ impl OrderProvider {
{
Self::update_offer_status(client, &data.order_hash, OrderStatus::Cancelled).await?;
}
- // insert cancelled event
- Self::insert_cancel_event(client, data.order_hash.clone(), block_timestamp as i64, data.reason.clone()).await?;
+ // insert cancelled event
+ Self::insert_cancel_event(
+ client,
+ data.order_hash.clone(),
+ block_timestamp as i64,
+ data.reason.clone(),
+ )
+ .await?;
Ok(())
}
diff --git a/ark-sqlx/src/providers/marketplace/types.rs b/ark-sqlx/src/providers/marketplace/types.rs
index 9bcb39e5..3421d0cd 100644
--- a/ark-sqlx/src/providers/marketplace/types.rs
+++ b/ark-sqlx/src/providers/marketplace/types.rs
@@ -1,4 +1,3 @@
-
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum TokenEventType {
Listing,
@@ -19,7 +18,6 @@ pub enum TokenEventType {
OfferCancelled,
}
-
/// DB for EventType
pub(crate) const LISTING_STR: &str = "Listing";
pub(crate) const AUCTION_STR: &str = "Auction";
@@ -37,7 +35,6 @@ pub(crate) const LISTING_CANCELLED_STR: &str = "ListingCancelled";
pub(crate) const AUCTION_CANCELLED_STR: &str = "AuctionCancelled";
pub(crate) const OFFER_CANCELLED_STR: &str = "OfferCancelled";
-
impl sqlx::Type for TokenEventType
where
DB: sqlx::Database,
@@ -98,4 +95,4 @@ impl TokenEventType {
TokenEventType::OfferCancelled => OFFER_CANCELLED_STR.to_string(),
}
}
-}
\ No newline at end of file
+}
From 2f64e2c6b3156a8a4f230da505b28349a552b64c Mon Sep 17 00:00:00 2001
From: Patrice Tisserand
Date: Mon, 26 Aug 2024 16:29:09 +0200
Subject: [PATCH 4/7] add missing dependency between ark-sqlx and
ark-marketplace-api
---
Cargo.lock | 1 +
ark-marketplace-api/Cargo.toml | 1 +
2 files changed, 2 insertions(+)
diff --git a/Cargo.lock b/Cargo.lock
index 4f177f3f..03ef5718 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -570,6 +570,7 @@ dependencies = [
"actix-web",
"actix-web-httpauth",
"anyhow",
+ "ark-sqlx",
"async-std",
"async-trait",
"aws-config",
diff --git a/ark-marketplace-api/Cargo.toml b/ark-marketplace-api/Cargo.toml
index ae2aa3a3..812ff355 100644
--- a/ark-marketplace-api/Cargo.toml
+++ b/ark-marketplace-api/Cargo.toml
@@ -10,6 +10,7 @@ actix-web = "4.4.0"
actix-cors = "0.7.0"
actix-rt = "2.9.0"
actix-web-httpauth = "0.8.1"
+ark-sqlx.workspace = true
bigdecimal = { version = "0.3", features = ["serde"] }
env_logger = "0.11.3"
num-bigint = "0.4.4"
From 9d8108f44c6ce4f1738299366716b8f35945b961 Mon Sep 17 00:00:00 2001
From: Patrice Tisserand
Date: Mon, 26 Aug 2024 18:56:06 +0200
Subject: [PATCH 5/7] fix: `from_address` and `to_address` doesn't exist in
`token_offer` table
---
ark-marketplace-api/src/db/db_access.rs | 48 +++++--------------
.../src/db/portfolio_db_access.rs | 24 +++-------
2 files changed, 18 insertions(+), 54 deletions(-)
diff --git a/ark-marketplace-api/src/db/db_access.rs b/ark-marketplace-api/src/db/db_access.rs
index 46ea7421..d2120bc1 100644
--- a/ark-marketplace-api/src/db/db_access.rs
+++ b/ark-marketplace-api/src/db/db_access.rs
@@ -570,25 +570,13 @@ impl DatabaseAccess for PgPool {
event_type_list(&[TokenEventType::Fulfill, TokenEventType::Executed])
);
- let from_select_part = format!(
- "
- CASE
- WHEN te.event_type in ({}) THEN token_offer.from_address
- ELSE te.from_address
- END AS from
- ",
- event_type_list(&[TokenEventType::Fulfill, TokenEventType::Executed])
- );
+ let from_select_part = "
+ te.from_address AS from
+ ";
- let to_select_part = format!(
- "
- CASE
- WHEN te.event_type in ({}) THEN token_offer.to_address
- ELSE te.to_address
- END AS to
- ",
- event_type_list(&[TokenEventType::Fulfill, TokenEventType::Executed])
- );
+ let to_select_part = "
+ te.to_address AS to
+ ";
let activity_sql_query = format!(
"
@@ -1208,25 +1196,13 @@ impl DatabaseAccess for PgPool {
event_type_list(&[TokenEventType::Fulfill, TokenEventType::Executed])
);
- let from_select_part = format!(
- "
- CASE
- WHEN te.event_type in ({}) THEN token_offer.from_address
- ELSE te.from_address
- END AS from
- ",
- event_type_list(&[TokenEventType::Fulfill, TokenEventType::Executed])
- );
+ let from_select_part = "
+ te.from_address AS from
+ ";
- let to_select_part = format!(
- "
- CASE
- WHEN te.event_type in ({}) THEN token_offer.to_address
- ELSE te.to_address
- END AS to
- ",
- event_type_list(&[TokenEventType::Fulfill, TokenEventType::Executed])
- );
+ let to_select_part = "
+ te.to_address AS to
+ ";
let result_ordering = format!(
"
diff --git a/ark-marketplace-api/src/db/portfolio_db_access.rs b/ark-marketplace-api/src/db/portfolio_db_access.rs
index b44749fe..7cb2f513 100644
--- a/ark-marketplace-api/src/db/portfolio_db_access.rs
+++ b/ark-marketplace-api/src/db/portfolio_db_access.rs
@@ -81,25 +81,13 @@ impl DatabaseAccess for PgPool {
event_type_list(&[TokenEventType::Fulfill, TokenEventType::Executed])
);
- let from_select_part = format!(
- "
- CASE
- WHEN te.event_type in ({}) THEN token_offer.from_address
- ELSE te.from_address
- END AS from
- ",
- event_type_list(&[TokenEventType::Fulfill, TokenEventType::Executed])
- );
+ let from_select_part = "
+ te.from_address AS from
+ ";
- let to_select_part = format!(
- "
- CASE
- WHEN te.event_type in ({}) THEN token_offer.to_address
- ELSE te.to_address
- END AS to
- ",
- event_type_list(&[TokenEventType::Fulfill, TokenEventType::Executed])
- );
+ let to_select_part = "
+ te.to_address AS to
+ ";
let from_sql_query = format!(
"
From 25a38aa7e06ecc3c4343e6c56fac090c7e6c9821 Mon Sep 17 00:00:00 2001
From: Patrice Tisserand
Date: Tue, 27 Aug 2024 00:29:25 +0200
Subject: [PATCH 6/7] fix(ark-marketplace-api): remove not more needed CTE
---
ark-marketplace-api/src/db/db_access.rs | 51 ++-----------------
.../src/db/portfolio_db_access.rs | 2 +-
2 files changed, 6 insertions(+), 47 deletions(-)
diff --git a/ark-marketplace-api/src/db/db_access.rs b/ark-marketplace-api/src/db/db_access.rs
index d2120bc1..119cad15 100644
--- a/ark-marketplace-api/src/db/db_access.rs
+++ b/ark-marketplace-api/src/db/db_access.rs
@@ -1108,54 +1108,16 @@ impl DatabaseAccess for PgPool {
) -> Result<(Vec, bool, i64), Error> {
let offset = (page - 1) * items_per_page;
- let token_event_with_previous_cte_part = format!(
- "
- WITH temporary_event_with_previous AS (
- (
- SELECT
- *,
- -- LAG() function is a window function that provides access to a row at a specified physical offset which comes before the current row.
- -- Here we want to retrieve the previous event type for given order_hash
- LAG(event_type) OVER (PARTITION BY order_hash ORDER BY block_timestamp) AS previous_event_type
- FROM token_event WHERE contract_address = $1 AND chain_id = $2 AND token_id = $3
- )
- ),
- token_event_with_previous AS (
- SELECT
- *,
- -- Create new event type if needed
- CASE
- WHEN event_type = '{executed_type}' THEN '{sale_type}'
- WHEN event_type = '{cancelled_type}' AND previous_event_type = '{listing_type}' THEN '{listing_cancelled_type}'
- WHEN event_type = '{cancelled_type}' AND previous_event_type = '{auction_type}' THEN '{auction_cancelled_type}'
- WHEN event_type = '{cancelled_type}' AND previous_event_type = '{offer_type}' THEN '{offer_cancelled_type}'
- ELSE event_type
- END AS new_event_type
- FROM temporary_event_with_previous
- WHERE contract_address = $1 AND chain_id = $2 AND token_id = $3
- )
- ",
- executed_type = TokenEventType::Executed.to_db_string(),
- sale_type = TokenEventType::Sale.to_db_string(),
- cancelled_type = TokenEventType::Cancelled.to_db_string(),
- listing_type = TokenEventType::Listing.to_db_string(),
- auction_type = TokenEventType::Auction.to_db_string(),
- offer_type = TokenEventType::Offer.to_db_string(),
- listing_cancelled_type = TokenEventType::ListingCancelled.to_db_string(),
- auction_cancelled_type = TokenEventType::AuctionCancelled.to_db_string(),
- offer_cancelled_type = TokenEventType::OfferCancelled.to_db_string(),
- );
-
let types_filter = match types {
None => String::from(""),
Some(values) => {
- format!("AND te.new_event_type IN ({})", event_type_list(values))
+ format!("AND te.event_type IN ({})", event_type_list(values))
}
};
let common_where_part = format!(
"
- FROM token_event_with_previous as te
+ FROM token_event as te
LEFT JOIN token_offer ON te.order_hash = token_offer.order_hash
LEFT JOIN token ON te.token_id = token.token_id and te.contract_address = token.contract_address and te.chain_id = token.chain_id
LEFT JOIN contract ON te.contract_address = contract.contract_address and te.chain_id = contract.chain_id
@@ -1163,7 +1125,7 @@ impl DatabaseAccess for PgPool {
AND te.chain_id = $2
AND te.token_id = $3
{}
- AND te.new_event_type NOT IN ({})
+ AND te.event_type NOT IN ({})
",
types_filter,
event_type_list(&[TokenEventType::Fulfill])
@@ -1171,11 +1133,10 @@ impl DatabaseAccess for PgPool {
let count_sql_query = format!(
"
- {}
SELECT COUNT(*) AS total
{}
",
- token_event_with_previous_cte_part, common_where_part,
+ common_where_part,
);
let total_count: Count = sqlx::query_as(&count_sql_query)
@@ -1216,11 +1177,10 @@ impl DatabaseAccess for PgPool {
let activity_sql_query = format!(
"
- {token_event_with_previous_cte}
SELECT
te.block_timestamp AS time_stamp,
te.transaction_hash,
- te.new_event_type AS activity_type,
+ te.event_type AS activity_type,
token.metadata,
contract.contract_name as collection_name,
contract.is_verified as collection_is_verified,
@@ -1231,7 +1191,6 @@ impl DatabaseAccess for PgPool {
{common_where}
{result_ordering}
",
- token_event_with_previous_cte = token_event_with_previous_cte_part,
common_where = common_where_part,
price_select = price_select_part,
from_select = from_select_part,
diff --git a/ark-marketplace-api/src/db/portfolio_db_access.rs b/ark-marketplace-api/src/db/portfolio_db_access.rs
index 7cb2f513..00d1c8e3 100644
--- a/ark-marketplace-api/src/db/portfolio_db_access.rs
+++ b/ark-marketplace-api/src/db/portfolio_db_access.rs
@@ -120,7 +120,7 @@ impl DatabaseAccess for PgPool {
{},
{}
{}
- ORDER BY te.block_timestamp {}
+ ORDER BY te.block_timestamp {}, te.token_event_id
LIMIT {} OFFSET {}
",
price_select_part,
From 0117899c1e9d937afd3eda8bea922769a6a2dd7a Mon Sep 17 00:00:00 2001
From: Patrice Tisserand
Date: Fri, 30 Aug 2024 08:22:08 +0200
Subject: [PATCH 7/7] fix clippy error
---
ark-marketplace-api/src/handlers/token_handler.rs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ark-marketplace-api/src/handlers/token_handler.rs b/ark-marketplace-api/src/handlers/token_handler.rs
index 8a48c4f9..a08e454b 100644
--- a/ark-marketplace-api/src/handlers/token_handler.rs
+++ b/ark-marketplace-api/src/handlers/token_handler.rs
@@ -75,7 +75,7 @@ pub async fn get_tokens(
let mut redis_con_ref = redis_con.get_ref().lock().await;
let mut token_ids = None;
if let Some(filters_param) = &query_parameters.filters {
- let decoded_filters = decode(&filters_param).expect("Failed to decode filters");
+ let decoded_filters = decode(filters_param).expect("Failed to decode filters");
let filters_map: HashMap =
serde_json::from_str(&decoded_filters).expect("Failed to parse JSON");