From 555598535dc4ead33c6076d86444bccca49b8ffa Mon Sep 17 00:00:00 2001
From: thesn10 <38666407+thesn10@users.noreply.github.com>
Date: Thu, 25 Jun 2026 20:21:28 +0200
Subject: [PATCH] feat: add name and description fields to ListingAccount;
update form, table, detail, dashboard
---
app/src/components/CreateListingForm.tsx | 20 +
app/src/components/Dashboard.tsx | 2 +-
app/src/components/ListingDetail.tsx | 30 +-
app/src/components/ListingsTable.tsx | 2 +-
.../src/instructions/create_listing.rs | 4 +
.../src/instructions/update_listing.rs | 4 +
programs/solisting/src/lib.rs | 10 +-
programs/solisting/src/state.rs | 4 +
programs/solisting/tests/common/mod.rs | 8 +
programs/solisting/tests/test_listings.rs | 12 +-
programs/solisting/tests/test_orders.rs | 22 +-
.../accounts/solistingStateListingAccount.ts | 8 +
.../generated/instructions/createListing.ts | 12 +
.../generated/instructions/updateListing.ts | 10 +
sdk/src/idl/solisting.json | 24 +
target/idl/solisting.json | 1169 +++++++++--------
16 files changed, 765 insertions(+), 576 deletions(-)
diff --git a/app/src/components/CreateListingForm.tsx b/app/src/components/CreateListingForm.tsx
index b0eb1a7..03f09f7 100644
--- a/app/src/components/CreateListingForm.tsx
+++ b/app/src/components/CreateListingForm.tsx
@@ -26,6 +26,8 @@ interface FormState {
price: string
quantity: string
oracle: string
+ name: string
+ description: string
metadataUri: string
alts: AltEntry[]
resolvers: string[]
@@ -39,6 +41,8 @@ function blank(): FormState {
price: '',
quantity: '',
oracle: '',
+ name: '',
+ description: '',
metadataUri: '',
alts: [],
resolvers: [],
@@ -148,6 +152,8 @@ export function CreateListingForm({ editPk }: Props) {
: (Number(d.price) / 1e9).toString(),
quantity: String(d.quantity),
oracle: isSome(d.canonicalOracle) ? d.canonicalOracle.value : '',
+ name: d.name ?? '',
+ description: d.description ?? '',
metadataUri: d.metadataUri ?? '',
alts: d.altCurrencies.map((a) => ({
currency:
@@ -265,6 +271,8 @@ export function CreateListingForm({ editPk }: Props) {
altCurrencies,
acceptedResolvers,
quantity: quantityN,
+ name: form.name,
+ description: form.description,
metadataUri: form.metadataUri,
})
await sendTx([ix as never], [['listings'], ['listing', editPk]], 'update_listing')
@@ -278,6 +286,8 @@ export function CreateListingForm({ editPk }: Props) {
altCurrencies,
acceptedResolvers,
quantity: quantityN,
+ name: form.name,
+ description: form.description,
metadataUri: form.metadataUri,
})
await sendTx([ix as never], [['listings']], 'create_listing')
@@ -337,6 +347,16 @@ export function CreateListingForm({ editPk }: Props) {
gap: 22,
}}
>
+ {/* NAME + DESCRIPTION */}
+
+
+
+
+
+
+
+
+
{/* CANONICAL CURRENCY */}
diff --git a/app/src/components/Dashboard.tsx b/app/src/components/Dashboard.tsx
index 981e6a4..0cd5c14 100644
--- a/app/src/components/Dashboard.tsx
+++ b/app/src/components/Dashboard.tsx
@@ -168,7 +168,7 @@ export function Dashboard() {
>
- Listing #{String(l.data.listingId)}
+ {l.data.name || `Listing #${String(l.data.listingId)}`}
{l.data.isActive ? 'Active' : 'Inactive'}
diff --git a/app/src/components/ListingDetail.tsx b/app/src/components/ListingDetail.tsx
index 47837f4..807e0ba 100644
--- a/app/src/components/ListingDetail.tsx
+++ b/app/src/components/ListingDetail.tsx
@@ -54,14 +54,16 @@ export function ListingDetail({ pk, walletAddress, onUpdate, onClose, onPlaceOrd
LISTING ACCOUNT · #{String(d.listingId)}
- {abbrev(pk)}
+ {d.name || abbrev(pk)}
{d.isActive ? 'Active' : 'Inactive'}
- {d.metadataUri && (
+ {(d.description || d.metadataUri) && (
- {d.metadataUri}
+ {d.description || (
+ {d.metadataUri}
+ )}
)}
@@ -70,20 +72,22 @@ export function ListingDetail({ pk, walletAddress, onUpdate, onClose, onPlaceOrd
ACCOUNT FIELDS
navigator.clipboard.writeText(pk)} />
-
#{String(d.listingId)}
navigator.clipboard.writeText(d.seller)} onClick={() => router.push(`/search?q=${d.seller}`)} />
-
{fmtListingPrice()}
-
-
- {d.canonicalCurrency.__kind === 'Sol' ? 'SOL (native)' : `SPL · ${abbrev((d.canonicalCurrency as { mint: string }).mint)}`}
+ #{String(d.listingId)}
+
+
+ {d.canonicalCurrency.__kind === 'Sol' ? 'SOL' : `SPL · ${abbrev((d.canonicalCurrency as { mint: string }).mint)}`}
- {canonicalOracleAddr && (
-
- navigator.clipboard.writeText(canonicalOracleAddr)} />
-
- )}
+ {fmtListingPrice()}
+
+ {canonicalOracleAddr
+ ? navigator.clipboard.writeText(canonicalOracleAddr)} />
+ : None — priced directly
+ }
+
{d.isActive ? 'Active' : 'Inactive'}
+ {d.bump}
{d.metadataUri && (
<>
diff --git a/app/src/components/ListingsTable.tsx b/app/src/components/ListingsTable.tsx
index 9e31dc4..c1ac5fd 100644
--- a/app/src/components/ListingsTable.tsx
+++ b/app/src/components/ListingsTable.tsx
@@ -108,7 +108,7 @@ export function ListingsTable() {
>
- {l.data.metadataUri || abbrev(l.address)}
+ {l.data.name || abbrev(l.address)}
#{String(l.data.listingId)} · {abbrev(l.address)}
diff --git a/programs/solisting/src/instructions/create_listing.rs b/programs/solisting/src/instructions/create_listing.rs
index f9f5f55..73caea3 100644
--- a/programs/solisting/src/instructions/create_listing.rs
+++ b/programs/solisting/src/instructions/create_listing.rs
@@ -29,6 +29,8 @@ pub fn handler(
alt_currencies: Vec
,
accepted_resolvers: Vec,
quantity: u32,
+ name: String,
+ description: String,
metadata_uri: String,
) -> Result<()> {
let listing = &mut ctx.accounts.listing_account;
@@ -40,6 +42,8 @@ pub fn handler(
listing.accepted_resolvers = accepted_resolvers;
listing.quantity = quantity;
listing.quantity_reserved = 0;
+ listing.name = name;
+ listing.description = description;
listing.metadata_uri = metadata_uri;
listing.listing_id = listing_id;
listing.is_active = true;
diff --git a/programs/solisting/src/instructions/update_listing.rs b/programs/solisting/src/instructions/update_listing.rs
index bb09af4..267d2d2 100644
--- a/programs/solisting/src/instructions/update_listing.rs
+++ b/programs/solisting/src/instructions/update_listing.rs
@@ -25,6 +25,8 @@ pub fn handler(
alt_currencies: Vec,
accepted_resolvers: Vec,
quantity: u32,
+ name: String,
+ description: String,
metadata_uri: String,
) -> Result<()> {
let listing = &mut ctx.accounts.listing_account;
@@ -34,6 +36,8 @@ pub fn handler(
listing.alt_currencies = alt_currencies;
listing.accepted_resolvers = accepted_resolvers;
listing.quantity = quantity;
+ listing.name = name;
+ listing.description = description;
listing.metadata_uri = metadata_uri;
Ok(())
}
diff --git a/programs/solisting/src/lib.rs b/programs/solisting/src/lib.rs
index 11195c4..17de565 100644
--- a/programs/solisting/src/lib.rs
+++ b/programs/solisting/src/lib.rs
@@ -31,11 +31,14 @@ pub mod solisting {
alt_currencies: Vec,
accepted_resolvers: Vec,
quantity: u32,
+ name: String,
+ description: String,
metadata_uri: String,
) -> Result<()> {
create_listing::handler(
ctx, listing_id, canonical_currency, price,
- canonical_oracle, alt_currencies, accepted_resolvers, quantity, metadata_uri,
+ canonical_oracle, alt_currencies, accepted_resolvers, quantity,
+ name, description, metadata_uri,
)
}
@@ -48,11 +51,14 @@ pub mod solisting {
alt_currencies: Vec,
accepted_resolvers: Vec,
quantity: u32,
+ name: String,
+ description: String,
metadata_uri: String,
) -> Result<()> {
update_listing::handler(
ctx, canonical_currency, price,
- canonical_oracle, alt_currencies, accepted_resolvers, quantity, metadata_uri,
+ canonical_oracle, alt_currencies, accepted_resolvers, quantity,
+ name, description, metadata_uri,
)
}
diff --git a/programs/solisting/src/state.rs b/programs/solisting/src/state.rs
index 16e7cd0..47b90af 100644
--- a/programs/solisting/src/state.rs
+++ b/programs/solisting/src/state.rs
@@ -52,6 +52,10 @@ pub struct ListingAccount {
pub quantity: u32,
/// Units held by pending orders. available = quantity - quantity_reserved.
pub quantity_reserved: u32,
+ #[max_len(64)]
+ pub name: String,
+ #[max_len(256)]
+ pub description: String,
#[max_len(256)]
pub metadata_uri: String,
pub listing_id: u64,
diff --git a/programs/solisting/tests/common/mod.rs b/programs/solisting/tests/common/mod.rs
index acf881a..4c4872b 100644
--- a/programs/solisting/tests/common/mod.rs
+++ b/programs/solisting/tests/common/mod.rs
@@ -101,6 +101,8 @@ pub fn ix_create_listing(
alt_currencies: Vec,
accepted_resolvers: Vec,
quantity: u32,
+ name: String,
+ description: String,
metadata_uri: String,
) -> Instruction {
let listing_account = listing_pda(seller, listing_id);
@@ -114,6 +116,8 @@ pub fn ix_create_listing(
alt_currencies,
accepted_resolvers,
quantity,
+ name,
+ description,
metadata_uri,
}
.data(),
@@ -136,6 +140,8 @@ pub fn ix_update_listing(
alt_currencies: Vec,
accepted_resolvers: Vec,
quantity: u32,
+ name: String,
+ description: String,
metadata_uri: String,
) -> Instruction {
let listing_account = listing_pda(seller, listing_id);
@@ -148,6 +154,8 @@ pub fn ix_update_listing(
alt_currencies,
accepted_resolvers,
quantity,
+ name,
+ description,
metadata_uri,
}
.data(),
diff --git a/programs/solisting/tests/test_listings.rs b/programs/solisting/tests/test_listings.rs
index f36ffda..bd44f2a 100644
--- a/programs/solisting/tests/test_listings.rs
+++ b/programs/solisting/tests/test_listings.rs
@@ -17,7 +17,7 @@ fn seller_can_create_sol_only_listing() {
vec![],
vec![],
10,
- "ipfs://test".to_string(),
+ "".to_string(), "".to_string(), "ipfs://test".to_string(),
);
send(&mut svm, &[ix], &[&seller]);
@@ -48,7 +48,7 @@ fn seller_can_create_listing_with_usdc_alt_stablecoin() {
}],
vec![],
5,
- "ipfs://x".to_string(),
+ "".to_string(), "".to_string(), "ipfs://x".to_string(),
);
send(&mut svm, &[ix], &[&seller]);
@@ -75,7 +75,7 @@ fn seller_can_create_listing_with_bonk_alt_oracle() {
}],
vec![],
5,
- "".to_string(),
+ "".to_string(), "".to_string(), "".to_string(),
);
send(&mut svm, &[ix], &[&seller]);
@@ -90,7 +90,7 @@ fn seller_can_update_listing() {
let listing_id: u64 = 2;
let ix = ix_create_listing(
&seller.pubkey(), listing_id, Currency::Sol, 1_000_000_000,
- None, vec![], vec![], 10, "".to_string(),
+ None, vec![], vec![], 10, "".to_string(), "".to_string(), "".to_string(),
);
send(&mut svm, &[ix], &[&seller]);
@@ -103,7 +103,7 @@ fn seller_can_update_listing() {
vec![],
vec![],
20,
- "ipfs://new".to_string(),
+ "".to_string(), "".to_string(), "ipfs://new".to_string(),
);
send(&mut svm, &[ix_update], &[&seller]);
@@ -118,7 +118,7 @@ fn seller_can_close_listing() {
let listing_id: u64 = 3;
let ix = ix_create_listing(
&seller.pubkey(), listing_id, Currency::Sol, 1_000_000_000,
- None, vec![], vec![], 5, "".to_string(),
+ None, vec![], vec![], 5, "".to_string(), "".to_string(), "".to_string(),
);
send(&mut svm, &[ix], &[&seller]);
diff --git a/programs/solisting/tests/test_orders.rs b/programs/solisting/tests/test_orders.rs
index b6f7bf0..d2c6624 100644
--- a/programs/solisting/tests/test_orders.rs
+++ b/programs/solisting/tests/test_orders.rs
@@ -10,7 +10,7 @@ fn buyer_can_create_order_canonical_sol() {
let price = 100_000_000u64;
let ix = ix_create_listing(
&seller.pubkey(), listing_id, Currency::Sol, price,
- None, vec![], vec![], 5, "".to_string(),
+ None, vec![], vec![], 5, "".to_string(), "".to_string(), "".to_string(),
);
send(&mut svm, &[ix], &[&seller]);
@@ -42,7 +42,7 @@ fn create_order_fails_if_listing_inactive() {
let listing_id = 2u64;
let ix = ix_create_listing(
&seller.pubkey(), listing_id, Currency::Sol, 1_000_000_000,
- None, vec![], vec![], 1, "".to_string(),
+ None, vec![], vec![], 1, "".to_string(), "".to_string(), "".to_string(),
);
send(&mut svm, &[ix], &[&seller]);
let ix_close = ix_close_listing(&seller.pubkey(), listing_id);
@@ -62,7 +62,7 @@ fn create_order_fails_if_out_of_stock() {
let listing_id = 3u64;
let ix = ix_create_listing(
&seller.pubkey(), listing_id, Currency::Sol, 100_000_000,
- None, vec![], vec![], 1, "".to_string(),
+ None, vec![], vec![], 1, "".to_string(), "".to_string(), "".to_string(),
);
send(&mut svm, &[ix], &[&seller]);
send(
@@ -87,7 +87,7 @@ fn create_order_fails_if_currency_not_accepted() {
let listing_id = 4u64;
let ix = ix_create_listing(
&seller.pubkey(), listing_id, Currency::Sol, 100_000_000,
- None, vec![], vec![], 5, "".to_string(),
+ None, vec![], vec![], 5, "".to_string(), "".to_string(), "".to_string(),
);
send(&mut svm, &[ix], &[&seller]);
@@ -110,7 +110,7 @@ fn create_order_fails_if_resolver_not_accepted() {
let allowed_resolver = Pubkey::new_unique();
let ix = ix_create_listing(
&seller.pubkey(), listing_id, Currency::Sol, 100_000_000,
- None, vec![], vec![allowed_resolver], 5, "".to_string(),
+ None, vec![], vec![allowed_resolver], 5, "".to_string(), "".to_string(), "".to_string(),
);
send(&mut svm, &[ix], &[&seller]);
@@ -132,7 +132,7 @@ fn seller_accept_creates_active_descro_escrow() {
let price = 100_000_000u64;
send(
&mut svm,
- &[ix_create_listing(&seller.pubkey(), listing_id, Currency::Sol, price, None, vec![], vec![], 5, "".to_string())],
+ &[ix_create_listing(&seller.pubkey(), listing_id, Currency::Sol, price, None, vec![], vec![], 5, "".to_string(), "".to_string(), "".to_string())],
&[&seller],
);
let order_id = 1u64;
@@ -166,7 +166,7 @@ fn seller_can_reject_order() {
let price = 100_000_000u64;
send(
&mut svm,
- &[ix_create_listing(&seller.pubkey(), listing_id, Currency::Sol, price, None, vec![], vec![], 5, "".to_string())],
+ &[ix_create_listing(&seller.pubkey(), listing_id, Currency::Sol, price, None, vec![], vec![], 5, "".to_string(), "".to_string(), "".to_string())],
&[&seller],
);
send(
@@ -197,7 +197,7 @@ fn buyer_can_cancel_order() {
let listing_id = 21u64;
send(
&mut svm,
- &[ix_create_listing(&seller.pubkey(), listing_id, Currency::Sol, 100_000_000, None, vec![], vec![], 5, "".to_string())],
+ &[ix_create_listing(&seller.pubkey(), listing_id, Currency::Sol, 100_000_000, None, vec![], vec![], 5, "".to_string(), "".to_string(), "".to_string())],
&[&seller],
);
send(
@@ -223,7 +223,7 @@ fn reject_handles_already_cancelled_escrow() {
let listing_id = 22u64;
send(
&mut svm,
- &[ix_create_listing(&seller.pubkey(), listing_id, Currency::Sol, 100_000_000, None, vec![], vec![], 5, "".to_string())],
+ &[ix_create_listing(&seller.pubkey(), listing_id, Currency::Sol, 100_000_000, None, vec![], vec![], 5, "".to_string(), "".to_string(), "".to_string())],
&[&seller],
);
send(
@@ -250,7 +250,7 @@ fn anyone_can_close_stale_order_after_terminal_escrow() {
let listing_id = 30u64;
send(
&mut svm,
- &[ix_create_listing(&seller.pubkey(), listing_id, Currency::Sol, 100_000_000, None, vec![], vec![], 5, "".to_string())],
+ &[ix_create_listing(&seller.pubkey(), listing_id, Currency::Sol, 100_000_000, None, vec![], vec![], 5, "".to_string(), "".to_string(), "".to_string())],
&[&seller],
);
send(
@@ -284,7 +284,7 @@ fn close_stale_order_fails_if_escrow_still_active() {
let listing_id = 31u64;
send(
&mut svm,
- &[ix_create_listing(&seller.pubkey(), listing_id, Currency::Sol, 100_000_000, None, vec![], vec![], 5, "".to_string())],
+ &[ix_create_listing(&seller.pubkey(), listing_id, Currency::Sol, 100_000_000, None, vec![], vec![], 5, "".to_string(), "".to_string(), "".to_string())],
&[&seller],
);
send(
diff --git a/sdk/src/generated/solisting/src/generated/accounts/solistingStateListingAccount.ts b/sdk/src/generated/solisting/src/generated/accounts/solistingStateListingAccount.ts
index 6c877ce..28f6ca8 100644
--- a/sdk/src/generated/solisting/src/generated/accounts/solistingStateListingAccount.ts
+++ b/sdk/src/generated/solisting/src/generated/accounts/solistingStateListingAccount.ts
@@ -96,6 +96,8 @@ export type SolistingStateListingAccount = {
quantity: number;
/** Units held by pending orders. available = quantity - quantity_reserved. */
quantityReserved: number;
+ name: string;
+ description: string;
metadataUri: string;
listingId: bigint;
isActive: boolean;
@@ -125,6 +127,8 @@ export type SolistingStateListingAccountArgs = {
quantity: number;
/** Units held by pending orders. available = quantity - quantity_reserved. */
quantityReserved: number;
+ name: string;
+ description: string;
metadataUri: string;
listingId: number | bigint;
isActive: boolean;
@@ -147,6 +151,8 @@ export function getSolistingStateListingAccountEncoder(): Encoder;
acceptedResolvers: Array;
quantity: number;
+ name: string;
+ description: string;
metadataUri: string;
};
@@ -122,6 +124,8 @@ export type CreateListingInstructionDataArgs = {
altCurrencies: Array;
acceptedResolvers: Array;
quantity: number;
+ name: string;
+ description: string;
metadataUri: string;
};
@@ -139,6 +143,8 @@ export function getCreateListingInstructionDataEncoder(): Encoder ({ ...value, discriminator: CREATE_LISTING_DISCRIMINATOR }),
@@ -158,6 +164,8 @@ export function getCreateListingInstructionDataDecoder(): Decoder;
acceptedResolvers: Array;
quantity: number;
+ name: string;
+ description: string;
metadataUri: string;
};
@@ -111,6 +113,8 @@ export type UpdateListingInstructionDataArgs = {
altCurrencies: Array;
acceptedResolvers: Array;
quantity: number;
+ name: string;
+ description: string;
metadataUri: string;
};
@@ -127,6 +131,8 @@ export function getUpdateListingInstructionDataEncoder(): Encoder ({ ...value, discriminator: UPDATE_LISTING_DISCRIMINATOR }),
@@ -145,6 +151,8 @@ export function getUpdateListingInstructionDataDecoder(): Decoder