Skip to content

Commit df67ac6

Browse files
committed
Next
1 parent f886bcd commit df67ac6

File tree

13 files changed

+290
-25
lines changed

13 files changed

+290
-25
lines changed

crates/sage-api/src/records/nft.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use specta::Type;
55
pub struct NftRecord {
66
pub launcher_id: String,
77
pub collection_id: Option<String>,
8+
pub collection_name: Option<String>,
89
pub minter_did: Option<String>,
910
pub owner_did: Option<String>,
1011
pub visible: bool,
@@ -19,6 +20,7 @@ pub struct NftRecord {
1920
pub struct NftInfo {
2021
pub launcher_id: String,
2122
pub collection_id: Option<String>,
23+
pub collection_name: Option<String>,
2224
pub minter_did: Option<String>,
2325
pub owner_did: Option<String>,
2426
pub visible: bool,

crates/sage-api/src/requests/get_nft_collections.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ use specta::Type;
55
pub struct GetNftCollections {
66
pub offset: u32,
77
pub limit: u32,
8+
pub include_hidden: bool,
89
}

crates/sage-api/src/requests/get_nfts.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,13 @@ use specta::Type;
55
pub struct GetNfts {
66
pub offset: u32,
77
pub limit: u32,
8+
pub sort_mode: NftSortMode,
9+
pub include_hidden: bool,
10+
}
11+
12+
#[derive(Debug, Clone, Copy, Serialize, Deserialize, Type)]
13+
#[serde(rename_all = "snake_case")]
14+
pub enum NftSortMode {
15+
Name,
16+
Recent,
817
}

crates/sage-database/src/primitives/nfts.rs

Lines changed: 216 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,20 @@ impl Database {
6363
impl<'a> DatabaseTx<'a> {
6464
pub async fn nft_collections_visible_named(
6565
&mut self,
66-
offset: u32,
6766
limit: u32,
67+
offset: u32,
6868
) -> Result<Vec<NftCollectionRow>> {
6969
nft_collections_visible_named(&mut *self.tx, offset, limit).await
7070
}
7171

72+
pub async fn nft_collections_named(
73+
&mut self,
74+
limit: u32,
75+
offset: u32,
76+
) -> Result<Vec<NftCollectionRow>> {
77+
nft_collections_named(&mut *self.tx, offset, limit).await
78+
}
79+
7280
pub async fn insert_nft_coin(
7381
&mut self,
7482
coin_id: Bytes32,
@@ -102,6 +110,18 @@ impl<'a> DatabaseTx<'a> {
102110
nfts_visible_named(&mut *self.tx, limit, offset).await
103111
}
104112

113+
pub async fn nfts_visible_recent(&mut self, limit: u32, offset: u32) -> Result<Vec<NftRow>> {
114+
nfts_visible_recent(&mut *self.tx, limit, offset).await
115+
}
116+
117+
pub async fn nfts_named(&mut self, limit: u32, offset: u32) -> Result<Vec<NftRow>> {
118+
nfts_named(&mut *self.tx, limit, offset).await
119+
}
120+
121+
pub async fn nfts_recent(&mut self, limit: u32, offset: u32) -> Result<Vec<NftRow>> {
122+
nfts_recent(&mut *self.tx, limit, offset).await
123+
}
124+
105125
pub async fn nft_count(&mut self) -> Result<u32> {
106126
nft_count(&mut *self.tx).await
107127
}
@@ -165,6 +185,10 @@ impl<'a> DatabaseTx<'a> {
165185
pub async fn nft_launcher_id(&mut self, coin_id: Bytes32) -> Result<Option<Bytes32>> {
166186
nft_launcher_id(&mut *self.tx, coin_id).await
167187
}
188+
189+
pub async fn nft_collection_name(&mut self, collection_id: Bytes32) -> Result<Option<String>> {
190+
nft_collection_name(&mut *self.tx, collection_id).await
191+
}
168192
}
169193

170194
async fn insert_nft_collection(conn: impl SqliteExecutor<'_>, row: NftCollectionRow) -> Result<()> {
@@ -198,6 +222,22 @@ async fn insert_nft_collection(conn: impl SqliteExecutor<'_>, row: NftCollection
198222
Ok(())
199223
}
200224

225+
async fn nft_collection_name(
226+
conn: impl SqliteExecutor<'_>,
227+
collection_id: Bytes32,
228+
) -> Result<Option<String>> {
229+
let collection_id = collection_id.as_ref();
230+
231+
let row = sqlx::query!(
232+
"SELECT `name` FROM `nft_collections` WHERE `collection_id` = ?",
233+
collection_id
234+
)
235+
.fetch_one(conn)
236+
.await?;
237+
238+
Ok(row.name)
239+
}
240+
201241
async fn nft_collections_visible_named(
202242
conn: impl SqliteExecutor<'_>,
203243
offset: u32,
@@ -239,6 +279,46 @@ async fn nft_collections_visible_named(
239279
Ok(collections)
240280
}
241281

282+
async fn nft_collections_named(
283+
conn: impl SqliteExecutor<'_>,
284+
offset: u32,
285+
limit: u32,
286+
) -> Result<Vec<NftCollectionRow>> {
287+
let rows = sqlx::query!(
288+
"
289+
SELECT
290+
`collection_id`,
291+
`did_id`,
292+
`metadata_collection_id`,
293+
`visible`,
294+
`name`,
295+
`icon`
296+
FROM `nft_collections` INDEXED BY `col_named`
297+
ORDER BY `visible` DESC, `is_named` DESC, `name` ASC, `collection_id` ASC
298+
LIMIT ? OFFSET ?
299+
",
300+
limit,
301+
offset
302+
)
303+
.fetch_all(conn)
304+
.await?;
305+
306+
let mut collections = Vec::new();
307+
308+
for row in rows {
309+
collections.push(NftCollectionRow {
310+
collection_id: to_bytes32(&row.collection_id)?,
311+
did_id: to_bytes32(&row.did_id)?,
312+
metadata_collection_id: row.metadata_collection_id,
313+
visible: row.visible,
314+
name: row.name,
315+
icon: row.icon,
316+
});
317+
}
318+
319+
Ok(collections)
320+
}
321+
242322
async fn nft_collection_count(conn: impl SqliteExecutor<'_>) -> Result<u32> {
243323
let row = sqlx::query!(
244324
"
@@ -631,6 +711,141 @@ async fn nfts_visible_named(
631711
Ok(nfts)
632712
}
633713

714+
async fn nfts_visible_recent(
715+
conn: impl SqliteExecutor<'_>,
716+
limit: u32,
717+
offset: u32,
718+
) -> Result<Vec<NftRow>> {
719+
let rows = sqlx::query!(
720+
"
721+
SELECT
722+
`launcher_id`,
723+
`collection_id`,
724+
`minter_did`,
725+
`owner_did`,
726+
`visible`,
727+
`sensitive_content`,
728+
`name`,
729+
`created_height`,
730+
`metadata_hash`
731+
FROM `nfts` INDEXED BY `nft_recent`
732+
WHERE `visible` = 1
733+
ORDER BY `is_pending` DESC, `created_height` DESC, `launcher_id` ASC
734+
LIMIT ? OFFSET ?
735+
",
736+
limit,
737+
offset
738+
)
739+
.fetch_all(conn)
740+
.await?;
741+
742+
let mut nfts = Vec::new();
743+
744+
for row in rows {
745+
nfts.push(NftRow {
746+
launcher_id: to_bytes32(&row.launcher_id)?,
747+
collection_id: row.collection_id.as_deref().map(to_bytes32).transpose()?,
748+
minter_did: row.minter_did.as_deref().map(to_bytes32).transpose()?,
749+
owner_did: row.owner_did.as_deref().map(to_bytes32).transpose()?,
750+
visible: row.visible,
751+
sensitive_content: row.sensitive_content,
752+
name: row.name,
753+
created_height: row.created_height.map(TryInto::try_into).transpose()?,
754+
metadata_hash: row.metadata_hash.as_deref().map(to_bytes32).transpose()?,
755+
});
756+
}
757+
758+
Ok(nfts)
759+
}
760+
761+
async fn nfts_named(conn: impl SqliteExecutor<'_>, limit: u32, offset: u32) -> Result<Vec<NftRow>> {
762+
let rows = sqlx::query!(
763+
"
764+
SELECT
765+
`launcher_id`,
766+
`collection_id`,
767+
`minter_did`,
768+
`owner_did`,
769+
`visible`,
770+
`sensitive_content`,
771+
`name`,
772+
`created_height`,
773+
`metadata_hash`
774+
FROM `nfts` INDEXED BY `nft_named`
775+
ORDER BY `visible` DESC, `is_named` DESC, `name` ASC, `launcher_id` ASC
776+
LIMIT ? OFFSET ?
777+
",
778+
limit,
779+
offset
780+
)
781+
.fetch_all(conn)
782+
.await?;
783+
784+
let mut nfts = Vec::new();
785+
786+
for row in rows {
787+
nfts.push(NftRow {
788+
launcher_id: to_bytes32(&row.launcher_id)?,
789+
collection_id: row.collection_id.as_deref().map(to_bytes32).transpose()?,
790+
minter_did: row.minter_did.as_deref().map(to_bytes32).transpose()?,
791+
owner_did: row.owner_did.as_deref().map(to_bytes32).transpose()?,
792+
visible: row.visible,
793+
sensitive_content: row.sensitive_content,
794+
name: row.name,
795+
created_height: row.created_height.map(TryInto::try_into).transpose()?,
796+
metadata_hash: row.metadata_hash.as_deref().map(to_bytes32).transpose()?,
797+
});
798+
}
799+
800+
Ok(nfts)
801+
}
802+
803+
async fn nfts_recent(
804+
conn: impl SqliteExecutor<'_>,
805+
limit: u32,
806+
offset: u32,
807+
) -> Result<Vec<NftRow>> {
808+
let rows = sqlx::query!(
809+
"
810+
SELECT
811+
`launcher_id`,
812+
`collection_id`,
813+
`minter_did`,
814+
`owner_did`,
815+
`visible`,
816+
`sensitive_content`,
817+
`name`,
818+
`created_height`,
819+
`metadata_hash`
820+
FROM `nfts` INDEXED BY `nft_recent`
821+
ORDER BY `visible` DESC, `is_pending` DESC, `created_height` DESC, `launcher_id` ASC
822+
LIMIT ? OFFSET ?
823+
",
824+
limit,
825+
offset
826+
)
827+
.fetch_all(conn)
828+
.await?;
829+
830+
let mut nfts = Vec::new();
831+
832+
for row in rows {
833+
nfts.push(NftRow {
834+
launcher_id: to_bytes32(&row.launcher_id)?,
835+
collection_id: row.collection_id.as_deref().map(to_bytes32).transpose()?,
836+
minter_did: row.minter_did.as_deref().map(to_bytes32).transpose()?,
837+
owner_did: row.owner_did.as_deref().map(to_bytes32).transpose()?,
838+
visible: row.visible,
839+
sensitive_content: row.sensitive_content,
840+
name: row.name,
841+
created_height: row.created_height.map(TryInto::try_into).transpose()?,
842+
metadata_hash: row.metadata_hash.as_deref().map(to_bytes32).transpose()?,
843+
});
844+
}
845+
846+
Ok(nfts)
847+
}
848+
634849
async fn insert_nft_coin(
635850
conn: impl SqliteExecutor<'_>,
636851
coin_id: Bytes32,

src-tauri/src/commands/data.rs

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use chia_wallet_sdk::{decode_address, encode_address};
88
use clvmr::Allocator;
99
use sage_api::{
1010
Amount, CatRecord, CoinRecord, DidRecord, GetNftCollections, GetNfts, NftCollectionRecord,
11-
NftInfo, NftRecord, NftStatus, PendingTransactionRecord, SyncStatus,
11+
NftInfo, NftRecord, NftSortMode, NftStatus, PendingTransactionRecord, SyncStatus,
1212
};
1313
use sage_database::DidRow;
1414
use sage_wallet::WalletError;
@@ -304,9 +304,13 @@ pub async fn get_nft_collections(
304304

305305
let mut tx = wallet.db.tx().await?;
306306

307-
let collections = tx
308-
.nft_collections_visible_named(request.limit, request.offset)
309-
.await?;
307+
let collections = if request.include_hidden {
308+
tx.nft_collections_named(request.limit, request.offset)
309+
.await?
310+
} else {
311+
tx.nft_collections_visible_named(request.limit, request.offset)
312+
.await?
313+
};
310314

311315
for col in collections {
312316
records.push(NftCollectionRecord {
@@ -334,7 +338,15 @@ pub async fn get_nfts(state: State<'_, AppState>, request: GetNfts) -> Result<Ve
334338

335339
let mut tx = wallet.db.tx().await?;
336340

337-
let nfts = tx.nfts_visible_named(request.limit, request.offset).await?;
341+
let nfts = match (request.sort_mode, request.include_hidden) {
342+
(NftSortMode::Name, true) => tx.nfts_named(request.limit, request.offset).await?,
343+
(NftSortMode::Name, false) => tx.nfts_visible_named(request.limit, request.offset).await?,
344+
(NftSortMode::Recent, true) => tx.nfts_recent(request.limit, request.offset).await?,
345+
(NftSortMode::Recent, false) => {
346+
tx.nfts_visible_recent(request.limit, request.offset)
347+
.await?
348+
}
349+
};
338350

339351
for nft in nfts {
340352
let data = if let Some(hash) = tx.data_hash(nft.launcher_id).await? {
@@ -343,12 +355,19 @@ pub async fn get_nfts(state: State<'_, AppState>, request: GetNfts) -> Result<Ve
343355
None
344356
};
345357

358+
let collection_name = if let Some(collection_id) = nft.collection_id {
359+
tx.nft_collection_name(collection_id).await?
360+
} else {
361+
None
362+
};
363+
346364
records.push(NftRecord {
347365
launcher_id: encode_address(nft.launcher_id.to_bytes(), "nft")?,
348366
collection_id: nft
349367
.collection_id
350368
.map(|col| encode_address(col.to_bytes(), "col"))
351369
.transpose()?,
370+
collection_name,
352371
minter_did: nft
353372
.minter_did
354373
.map(|did| encode_address(did.to_bytes(), "did:chia:"))
@@ -412,6 +431,12 @@ pub async fn get_nft(state: State<'_, AppState>, launcher_id: String) -> Result<
412431
None
413432
};
414433

434+
let collection_name = if let Some(collection_id) = nft_row.collection_id {
435+
tx.nft_collection_name(collection_id).await?
436+
} else {
437+
None
438+
};
439+
415440
tx.commit().await?;
416441

417442
Ok(Some(NftInfo {
@@ -420,6 +445,7 @@ pub async fn get_nft(state: State<'_, AppState>, launcher_id: String) -> Result<
420445
.collection_id
421446
.map(|col| encode_address(col.to_bytes(), "col"))
422447
.transpose()?,
448+
collection_name,
423449
minter_did: nft_row
424450
.minter_did
425451
.map(|did| encode_address(did.to_bytes(), "did:chia:"))

0 commit comments

Comments
 (0)