diff --git a/crates/sage/src/endpoints/keys.rs b/crates/sage/src/endpoints/keys.rs index 3b59b515..5f6974f0 100644 --- a/crates/sage/src/endpoints/keys.rs +++ b/crates/sage/src/endpoints/keys.rs @@ -148,7 +148,30 @@ impl Sage { return Err(Error::InvalidKey); } } else { - let mnemonic = Mnemonic::from_str(&req.key)?; + let words: Vec<&str> = req.key.split_whitespace().collect(); + let word_count = words.len(); + + if word_count != 12 && word_count != 24 { + return Err(Error::InvalidMnemonic(format!( + "Expected 12 or 24 words, but got {word_count}." + ))); + } + + let mnemonic = Mnemonic::from_str(&req.key).map_err(|e| match e { + bip39::Error::BadWordCount(count) => Error::InvalidMnemonic(format!( + "Expected 12 or 24 words, but got {count}." + )), + bip39::Error::UnknownWord(idx) => Error::InvalidMnemonic(format!( + "Word #{} ({}) is not a valid BIP39 word.", + idx + 1, + words.get(idx).copied().unwrap_or("unknown"), + )), + bip39::Error::InvalidChecksum => Error::InvalidMnemonic( + "Invalid checksum. Please verify all words are correct and in the right order." + .to_string(), + ), + _ => Error::InvalidMnemonic(format!("Invalid mnemonic: {e}")), + })?; let master_sk = SecretKey::from_seed(&mnemonic.to_seed("")); let master_pk = master_sk.public_key(); let fingerprint = if req.save_secrets { diff --git a/crates/sage/src/endpoints/offers.rs b/crates/sage/src/endpoints/offers.rs index c80a21cc..b6d72019 100644 --- a/crates/sage/src/endpoints/offers.rs +++ b/crates/sage/src/endpoints/offers.rs @@ -81,6 +81,17 @@ impl Sage { } } + let has_offered_assets = offered.xch > 0 + || !offered.cats.is_empty() + || !offered.nfts.is_empty() + || !offered.options.is_empty(); + + if !has_offered_assets && offered.fee == 0 { + return Err(Error::InvalidAmount( + "A request-only offer requires a network fee.".to_string(), + )); + } + let mut requested = Requested::default(); let mut peer = None; diff --git a/crates/sage/src/error.rs b/crates/sage/src/error.rs index 66ff45a0..043f7e0e 100644 --- a/crates/sage/src/error.rs +++ b/crates/sage/src/error.rs @@ -122,6 +122,9 @@ pub enum Error { #[error("Invalid key")] InvalidKey, + #[error("{0}")] + InvalidMnemonic(String), + #[error("Wrong address prefix: {0}")] AddressPrefix(String), @@ -279,6 +282,7 @@ impl Error { Self::Bls(..) | Self::Hex(..) | Self::InvalidKey + | Self::InvalidMnemonic(..) | Self::TryFromSlice(..) | Self::TryFromInt(..) | Self::ParseInt(..) diff --git a/src/components/NftCard.tsx b/src/components/NftCard.tsx index d8354f1c..30dfbc6d 100644 --- a/src/components/NftCard.tsx +++ b/src/components/NftCard.tsx @@ -317,12 +317,12 @@ export function NftCard({ nft, updateNfts, selectionState }: NftCardProps) {

{nftName} - {nft.edition_total != null && nft.edition_total > 1 && ( + {nft.edition_total != null && (nft.edition_total === 0 || nft.edition_total > 1) && ( {' '} ( - {nft.edition_number} of {nft.edition_total} + {nft.edition_number} of {nft.edition_total === 0 ? '∞' : nft.edition_total} ) diff --git a/src/components/ui/dialog.tsx b/src/components/ui/dialog.tsx index c5fde55b..68beae52 100644 --- a/src/components/ui/dialog.tsx +++ b/src/components/ui/dialog.tsx @@ -64,7 +64,7 @@ const DialogContent = React.forwardRef< - Enter your mnemonic, private key, or public key above. - If it's a public key, it will be imported as a - read-only cold wallet. + Enter your 12 or 24-word mnemonic seed phrase, private + key, or public key. Words should be separated by + spaces. If it's a public key, it will be imported + as a read-only cold wallet. diff --git a/src/pages/MakeOffer.tsx b/src/pages/MakeOffer.tsx index c16c4d68..a8aa0ab6 100644 --- a/src/pages/MakeOffer.tsx +++ b/src/pages/MakeOffer.tsx @@ -86,6 +86,20 @@ export function MakeOffer() { }); return; } + + if ( + !hasOfferedTokens && + !hasOfferedNfts && + !hasOfferedOptions && + parseFloat(state.fee || '0') === 0 + ) { + addError({ + kind: 'invalid', + reason: t`A request-only offer requires a network fee.`, + }); + return; + } + setIsConfirmDialogOpen(true); }; diff --git a/src/pages/Nft.tsx b/src/pages/Nft.tsx index ad6b9e46..88f42457 100644 --- a/src/pages/Nft.tsx +++ b/src/pages/Nft.tsx @@ -272,10 +272,10 @@ export default function Nft() { address={nft?.launcher_id ?? ''} /> - {nft?.edition_total != null && nft?.edition_total > 1 && ( + {nft?.edition_total != null && (nft?.edition_total === 0 || nft?.edition_total > 1) && ( )}