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