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

No Duplicate NFT Transfer Records #134

Merged
merged 1 commit into from
Jul 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions api/src/entities/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ pub mod nft_transfers;
pub mod project_wallets;
pub mod purchases;
pub mod sea_orm_active_enums;
pub mod transfer_charges;
1 change: 0 additions & 1 deletion api/src/entities/nft_transfers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ pub struct Model {
pub sender: String,
pub recipient: String,
pub created_at: DateTimeWithTimeZone,
pub credits_deduction_id: Option<Uuid>,
}

#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
Expand Down
2 changes: 1 addition & 1 deletion api/src/entities/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ pub use super::{
drops::Entity as Drops, metadata_json_attributes::Entity as MetadataJsonAttributes,
metadata_json_files::Entity as MetadataJsonFiles, metadata_jsons::Entity as MetadataJsons,
nft_transfers::Entity as NftTransfers, project_wallets::Entity as ProjectWallets,
purchases::Entity as Purchases,
purchases::Entity as Purchases, transfer_charges::Entity as TransferCharges,
};
16 changes: 16 additions & 0 deletions api/src/entities/transfer_charges.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.10.5

use sea_orm::entity::prelude::*;

#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
#[sea_orm(table_name = "transfer_charges")]
pub struct Model {
#[sea_orm(primary_key, auto_increment = false)]
pub id: Uuid,
pub credits_deduction_id: Option<Uuid>,
}

#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}

impl ActiveModelBehavior for ActiveModel {}
24 changes: 6 additions & 18 deletions api/src/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
prelude::{CollectionMints, Purchases},
project_wallets, purchases,
sea_orm_active_enums::{Blockchain, CreationStatus},
transfer_charges,
},
proto::{
nft_events::Event as NftEvent,
Expand Down Expand Up @@ -72,7 +73,7 @@
}
}

pub async fn process(&self, msg: Services) -> Result<()> {

Check warning on line 76 in api/src/events.rs

View workflow job for this annotation

GitHub Actions / clippy/check/doc

docs for function returning `Result` missing `# Errors` section
match msg {
Services::Treasury(TreasuryEventKey { id, .. }, e) => match e.event {
Some(TreasuryEvent::ProjectWalletCreated(payload)) => {
Expand Down Expand Up @@ -163,7 +164,6 @@
sender: Set(payload.sender),
recipient: Set(payload.recipient),
created_at: Set(Utc::now().into()),
credits_deduction_id: Set(None),
..Default::default()
};

Expand Down Expand Up @@ -210,7 +210,6 @@
sender: Set(mint.owner),
recipient: Set(new_owner.clone()),
created_at: Set(created_at),
credits_deduction_id: Set(None),
..Default::default()
};

Expand Down Expand Up @@ -392,22 +391,14 @@
let conn = self.db.get();
let transfer_id = Uuid::from_str(&id)?;

let (nft_transfer, collection_mint) = nft_transfers::Entity::find_by_id(transfer_id)
.find_also_related(collection_mints::Entity)
let transfer_charge = transfer_charges::Entity::find()
.filter(transfer_charges::Column::CreditsDeductionId.eq(transfer_id))
.one(conn)
.await?
.context("failed to load nft transfer from db")?;
.context("failed to load transfer charge from db")?;

let collection_mint = collection_mint.context("collection mint not found")?;

let mut collection_mint_am: collection_mints::ActiveModel = collection_mint.into();
let mut nft_transfer_am: nft_transfers::ActiveModel = nft_transfer.clone().into();

if let TransferResult::Success(signature) = payload {
collection_mint_am.owner = Set(nft_transfer.recipient.clone());
nft_transfer_am.tx_signature = Set(Some(signature));

let deduction_id = nft_transfer
if let TransferResult::Success(_) = payload {
let deduction_id = transfer_charge
.credits_deduction_id
.context("deduction id not found")?;

Expand All @@ -416,9 +407,6 @@
.await?;
}

collection_mint_am.update(conn).await?;
nft_transfer_am.insert(conn).await?;

Ok(())
}
}
Expand Down
26 changes: 12 additions & 14 deletions api/src/mutations/transfer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ use crate::{
db::Connection,
entities::{
collection_mints::{self, CollectionMint},
collections, customer_wallets, drops, nft_transfers,
collections, customer_wallets, drops,
prelude::{Collections, CustomerWallets, Drops},
sea_orm_active_enums::{Blockchain, CreationStatus},
transfer_charges,
},
proto::{self, NftEventKey, TransferPolygonAsset},
Actions, AppContext, OrganizationId, UserID,
Expand Down Expand Up @@ -95,17 +96,13 @@ impl Mutation {
.await?
.ok_or(Error::new("Sender wallet is not managed by Hub"))?;

let nft_transfer_am = nft_transfers::ActiveModel {
tx_signature: Set(None),
collection_mint_id: Set(collection_mint_model.id),
sender: Set(owner_address.clone()),
recipient: Set(recipient.clone()),
let transfer_charges_am = transfer_charges::ActiveModel {
..Default::default()
};

let nft_transfer_model = nft_transfer_am.insert(conn).await?;
let transfer_charge_model = transfer_charges_am.insert(conn).await?;
let event_key = NftEventKey {
id: nft_transfer_model.id.to_string(),
id: transfer_charge_model.id.to_string(),
user_id: user_id.to_string(),
project_id: drop.project_id.to_string(),
};
Expand Down Expand Up @@ -149,7 +146,7 @@ impl Mutation {
balance,
org_id,
user_id,
nft_transfer_model.id,
transfer_charge_model.id,
collection.blockchain,
)
.await?;
Expand Down Expand Up @@ -188,14 +185,15 @@ async fn submit_pending_deduction(

let deduction_id = id.ok_or(Error::new("Organization does not have enough credits"))?;

let nft_transfer_model = nft_transfers::Entity::find_by_id(transfer_id)
let transfer_charge_model = transfer_charges::Entity::find()
.filter(transfer_charges::Column::Id.eq(transfer_id))
.one(db.get())
.await?
.ok_or(Error::new("drop not found"))?;
.ok_or(Error::new("transfer charge not found"))?;

let mut nft_transfer: nft_transfers::ActiveModel = nft_transfer_model.into();
nft_transfer.credits_deduction_id = Set(Some(deduction_id.0));
nft_transfer.update(db.get()).await?;
let mut transfer_charge: transfer_charges::ActiveModel = transfer_charge_model.into();
transfer_charge.credits_deduction_id = Set(Some(deduction_id.0));
transfer_charge.update(db.get()).await?;

Ok(())
}
Expand Down
6 changes: 6 additions & 0 deletions migration/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ mod m20230518_034021_set_default_timestamp;
mod m20230606_121315_add_collection_mint_id_to_nft_transfers;
mod m20230620_160452_make_address_nullable_on_collection_mints;
mod m20230626_111748_customer_wallets_table;
mod m20230706_130934_create_transfer_charges_table;
mod m20230706_133356_backfill_transfer_charges;
mod m20230706_134402_drop_column_credits_deduction_id_from_nft_transfers;

pub struct Migrator;

Expand Down Expand Up @@ -89,6 +92,9 @@ impl MigratorTrait for Migrator {
Box::new(m20230606_121315_add_collection_mint_id_to_nft_transfers::Migration),
Box::new(m20230620_160452_make_address_nullable_on_collection_mints::Migration),
Box::new(m20230626_111748_customer_wallets_table::Migration),
Box::new(m20230706_130934_create_transfer_charges_table::Migration),
Box::new(m20230706_133356_backfill_transfer_charges::Migration),
Box::new(m20230706_134402_drop_column_credits_deduction_id_from_nft_transfers::Migration),
]
}
}
44 changes: 44 additions & 0 deletions migration/src/m20230706_130934_create_transfer_charges_table.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
use sea_orm_migration::prelude::*;

#[derive(DeriveMigrationName)]
pub struct Migration;

#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.create_table(
Table::create()
.table(TransferCharges::Table)
.if_not_exists()
.col(
ColumnDef::new(TransferCharges::Id)
.uuid()
.not_null()
.primary_key()
.extra("default gen_random_uuid()".to_string()),
)
.col(
ColumnDef::new(TransferCharges::CreditsDeductionId)
.uuid()
.null(),
)
.to_owned(),
)
.await
}

async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.drop_table(Table::drop().table(TransferCharges::Table).to_owned())
.await
}
}

/// Learn more at https://docs.rs/sea-query#iden
#[derive(Iden)]
enum TransferCharges {
Table,
Id,
CreditsDeductionId,
}
34 changes: 34 additions & 0 deletions migration/src/m20230706_133356_backfill_transfer_charges.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
use sea_orm::{ConnectionTrait, Statement};
use sea_orm_migration::prelude::*;

#[derive(DeriveMigrationName)]
pub struct Migration;

#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
let db = manager.get_connection();

let stmt = Statement::from_string(
manager.get_database_backend(),
r#"INSERT INTO transfer_charges(credits_deduction_id) SELECT credits_deduction_id FROM nft_transfers;"#.to_string(),
);

db.execute(stmt).await?;

Ok(())
}

async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
let db = manager.get_connection();

let stmt = Statement::from_string(
manager.get_database_backend(),
r#"DELETE FROM transfer_charges;"#.to_string(),
);

db.execute(stmt).await?;

Ok(())
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
use sea_orm_migration::prelude::*;

#[derive(DeriveMigrationName)]
pub struct Migration;

#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.alter_table(
Table::alter()
.table(NftTransfers::Table)
.drop_column(NftTransfers::CreditsDeductionId)
.to_owned(),
)
.await
}

async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.alter_table(
Table::alter()
.table(NftTransfers::Table)
.add_column_if_not_exists(
ColumnDef::new(NftTransfers::CreditsDeductionId)
.uuid()
.null(),
)
.to_owned(),
)
.await
}
}

/// Learn more at https://docs.rs/sea-query#iden
#[derive(Iden)]
enum NftTransfers {
Table,
CreditsDeductionId,
}
Loading