Skip to content

Commit e338ec5

Browse files
committed
Refactor errors
1 parent ad2b745 commit e338ec5

File tree

9 files changed

+96
-174
lines changed

9 files changed

+96
-174
lines changed

crates/sage-wallet/src/child_kind.rs

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use chia_wallet_sdk::{run_puzzle, Cat, Condition, Did, DidInfo, HashedPtr, Nft,
77
use clvmr::Allocator;
88
use tracing::{debug_span, warn};
99

10-
use crate::ParseError;
10+
use crate::WalletError;
1111

1212
#[derive(Debug, Clone)]
1313
#[allow(clippy::large_enum_variant)]
@@ -38,7 +38,7 @@ impl ChildKind {
3838
parent_puzzle: &Program,
3939
parent_solution: &Program,
4040
coin: Coin,
41-
) -> Result<Self, ParseError> {
41+
) -> Result<Self, WalletError> {
4242
let parse_span = debug_span!(
4343
"parse from parent",
4444
parent_coin = %parent_coin.coin_id(),
@@ -52,21 +52,12 @@ impl ChildKind {
5252

5353
let mut allocator = Allocator::new();
5454

55-
let parent_puzzle_ptr = parent_puzzle
56-
.to_clvm(&mut allocator)
57-
.map_err(|_| ParseError::AllocatePuzzle)?;
58-
55+
let parent_puzzle_ptr = parent_puzzle.to_clvm(&mut allocator)?;
5956
let parent_puzzle = Puzzle::parse(&allocator, parent_puzzle_ptr);
57+
let parent_solution = parent_solution.to_clvm(&mut allocator)?;
6058

61-
let parent_solution = parent_solution
62-
.to_clvm(&mut allocator)
63-
.map_err(|_| ParseError::AllocateSolution)?;
64-
65-
let output = run_puzzle(&mut allocator, parent_puzzle_ptr, parent_solution)
66-
.map_err(|_| ParseError::Eval)?;
67-
68-
let conditions = Vec::<Condition>::from_clvm(&allocator, output)
69-
.map_err(|_| ParseError::InvalidConditions)?;
59+
let output = run_puzzle(&mut allocator, parent_puzzle_ptr, parent_solution)?;
60+
let conditions = Vec::<Condition>::from_clvm(&allocator, output)?;
7061

7162
let Some(mut create_coin) = conditions
7263
.into_iter()
@@ -140,9 +131,7 @@ impl ChildKind {
140131
return Ok(unknown);
141132
};
142133

143-
let metadata_program = Program::from_clvm(&allocator, nft.info.metadata.ptr())
144-
.map_err(|_| ParseError::Serialize)?;
145-
134+
let metadata_program = Program::from_clvm(&allocator, nft.info.metadata.ptr())?;
146135
let metadata = NftMetadata::from_clvm(&allocator, nft.info.metadata.ptr()).ok();
147136

148137
return Ok(Self::Nft {
@@ -176,8 +165,7 @@ impl ChildKind {
176165
return Ok(unknown);
177166
};
178167

179-
let metadata = Program::from_clvm(&allocator, did.info.metadata.ptr())
180-
.map_err(|_| ParseError::Serialize)?;
168+
let metadata = Program::from_clvm(&allocator, did.info.metadata.ptr())?;
181169

182170
return Ok(Self::Did {
183171
lineage_proof,

crates/sage-wallet/src/coin_kind.rs

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use chia_wallet_sdk::{CatLayer, DidInfo, HashedPtr, Layer, NftInfo, Puzzle};
77
use clvmr::Allocator;
88
use tracing::{debug_span, warn};
99

10-
use crate::ParseError;
10+
use crate::WalletError;
1111

1212
#[derive(Debug, Clone)]
1313
#[allow(clippy::large_enum_variant)]
@@ -28,16 +28,13 @@ pub enum CoinKind {
2828
}
2929

3030
impl CoinKind {
31-
pub fn from_puzzle(puzzle: &Program) -> Result<Self, ParseError> {
31+
pub fn from_puzzle(puzzle: &Program) -> Result<Self, WalletError> {
3232
let parse_span = debug_span!("parse puzzle");
3333
let _span = parse_span.enter();
3434

3535
let mut allocator = Allocator::new();
3636

37-
let puzzle_ptr = puzzle
38-
.to_clvm(&mut allocator)
39-
.map_err(|_| ParseError::AllocatePuzzle)?;
40-
37+
let puzzle_ptr = puzzle.to_clvm(&mut allocator)?;
4138
let puzzle = Puzzle::parse(&allocator, puzzle_ptr);
4239

4340
if puzzle.curried_puzzle_hash() == SINGLETON_LAUNCHER_PUZZLE_HASH {
@@ -72,9 +69,7 @@ impl CoinKind {
7269

7370
// If the coin is a NFT coin, return the relevant information.
7471
Ok(Some((nft, _inner_puzzle))) => {
75-
let metadata_program = Program::from_clvm(&allocator, nft.metadata.ptr())
76-
.map_err(|_| ParseError::Serialize)?;
77-
72+
let metadata_program = Program::from_clvm(&allocator, nft.metadata.ptr())?;
7873
let metadata = NftMetadata::from_clvm(&allocator, nft.metadata.ptr()).ok();
7974

8075
return Ok(Self::Nft {
@@ -96,8 +91,7 @@ impl CoinKind {
9691

9792
// If the coin is a DID coin, return the relevant information.
9893
Ok(Some((did, _inner_puzzle))) => {
99-
let metadata = Program::from_clvm(&allocator, did.metadata.ptr())
100-
.map_err(|_| ParseError::Serialize)?;
94+
let metadata = Program::from_clvm(&allocator, did.metadata.ptr())?;
10195

10296
return Ok(Self::Did {
10397
info: did.with_metadata(metadata),

crates/sage-wallet/src/error.rs

Lines changed: 40 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
use std::time::SystemTimeError;
22

3-
use chia::{bls::PublicKey, protocol::Bytes32};
3+
use chia::{
4+
clvm_traits::{FromClvmError, ToClvmError},
5+
protocol::Bytes32,
6+
};
47
use chia_wallet_sdk::{ClientError, CoinSelectionError, DriverError, SignerError};
8+
use clvmr::reduction::EvalErr;
59
use sage_database::DatabaseError;
610
use thiserror::Error;
7-
use tokio::task::JoinError;
11+
use tokio::{task::JoinError, time::error::Elapsed};
812

913
#[derive(Debug, Error)]
1014
pub enum WalletError {
@@ -14,90 +18,63 @@ pub enum WalletError {
1418
#[error("Client error: {0}")]
1519
Client(#[from] ClientError),
1620

17-
#[error("Sync error: {0}")]
18-
Sync(#[from] SyncError),
19-
20-
#[error("Parse error: {0}")]
21-
Parse(#[from] ParseError),
22-
2321
#[error("Driver error: {0}")]
2422
Driver(#[from] DriverError),
2523

2624
#[error("Signer error: {0}")]
2725
Signer(#[from] SignerError),
2826

29-
#[error("Join error: {0}")]
30-
Join(#[from] JoinError),
31-
3227
#[error("Coin selection error: {0}")]
3328
CoinSelection(#[from] CoinSelectionError),
3429

35-
#[error("Output amount exceeds input coin total")]
36-
InsufficientFunds,
37-
38-
#[error("Not enough keys have been derived")]
39-
InsufficientDerivations,
40-
41-
#[error("Spendable DID not found: {0}")]
42-
MissingDid(Bytes32),
43-
44-
#[error("Spendable NFT not found: {0}")]
45-
MissingNft(Bytes32),
46-
47-
#[error("Unknown public key in transaction: {0:?}")]
48-
UnknownPublicKey(PublicKey),
49-
50-
#[error("Time error: {0}")]
51-
Time(#[from] SystemTimeError),
52-
}
30+
#[error("Request error: {0}")]
31+
Request(#[from] reqwest::Error),
5332

54-
#[derive(Debug, Error)]
55-
pub enum SyncError {
5633
#[error("Timeout exceeded")]
57-
Timeout,
34+
Elapsed(#[from] Elapsed),
35+
36+
#[error("Missing coin with id {0}")]
37+
MissingCoin(Bytes32),
5838

59-
#[error("Unexpected rejection")]
60-
Rejection,
39+
#[error("Missing spend with id {0}")]
40+
MissingSpend(Bytes32),
6141

62-
#[error("Subscription limit exceeded")]
63-
SubscriptionLimit,
42+
#[error("Missing child of id {0}")]
43+
MissingChild(Bytes32),
6444

65-
#[error("Missing coin state {0}")]
66-
MissingCoinState(Bytes32),
45+
#[error("Peer misbehaved")]
46+
PeerMisbehaved,
6747

68-
#[error("Missing child coin")]
69-
MissingChild,
48+
#[error("Subscription limit reached")]
49+
SubscriptionLimitReached,
7050

71-
#[error("Unconfirmed coin {0}")]
72-
UnconfirmedCoin(Bytes32),
51+
#[error("System time error: {0}")]
52+
SystemTime(#[from] SystemTimeError),
7353

74-
#[error("Unspent coin {0}")]
75-
UnspentCoin(Bytes32),
54+
#[error("Join error: {0}")]
55+
Join(#[from] JoinError),
7656

77-
#[error("Missing puzzle and solution for {0}")]
78-
MissingPuzzleAndSolution(Bytes32),
57+
#[error("CLVM encoding error: {0}")]
58+
ToClvm(#[from] ToClvmError),
7959

80-
#[error("Error fetching CAT {0}: {1}")]
81-
FetchCat(Bytes32, reqwest::Error),
82-
}
60+
#[error("CLVM decoding error: {0}")]
61+
FromClvm(#[from] FromClvmError),
8362

84-
#[derive(Debug, Clone, Copy, PartialEq, Eq, Error)]
85-
pub enum ParseError {
86-
#[error("Could not allocate puzzle reveal")]
87-
AllocatePuzzle,
63+
#[error("CLVM error: {0}")]
64+
Clvm(#[from] EvalErr),
8865

89-
#[error("Could not allocate solution")]
90-
AllocateSolution,
66+
#[error("Insufficient funds")]
67+
InsufficientFunds,
9168

92-
#[error("Could not allocate metadata")]
93-
AllocateMetadata,
69+
#[error("Insufficient derivations")]
70+
InsufficientDerivations,
9471

95-
#[error("Could not serialize CLVM")]
96-
Serialize,
72+
#[error("Missing secret key")]
73+
UnknownPublicKey,
9774

98-
#[error("Could not evaluate puzzle and solution")]
99-
Eval,
75+
#[error("Missing DID with id {0}")]
76+
MissingDid(Bytes32),
10077

101-
#[error("Invalid condition list")]
102-
InvalidConditions,
78+
#[error("Missing NFT with id {0}")]
79+
MissingNft(Bytes32),
10380
}

crates/sage-wallet/src/queues/cat_queue.rs

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use tokio::{
1010
};
1111
use tracing::info;
1212

13-
use crate::{SyncError, SyncEvent, WalletError};
13+
use crate::{SyncEvent, WalletError};
1414

1515
#[derive(Deserialize)]
1616
struct Response {
@@ -107,7 +107,7 @@ impl CatQueue {
107107
}
108108
}
109109

110-
async fn lookup_cat(network: &Network, asset_id: Bytes32) -> Result<Response, SyncError> {
110+
async fn lookup_cat(network: &Network, asset_id: Bytes32) -> Result<Response, WalletError> {
111111
let dexie_base_url = if network.genesis_challenge == TESTNET11_CONSTANTS.genesis_challenge {
112112
"https://api-testnet.dexie.space/v1"
113113
} else {
@@ -120,14 +120,9 @@ async fn lookup_cat(network: &Network, asset_id: Bytes32) -> Result<Response, Sy
120120
"{dexie_base_url}/assets?page_size=25&page=1&type=all&code={asset_id}"
121121
)),
122122
)
123-
.await
124-
.map_err(|_| SyncError::Timeout)?
125-
.map_err(|error| SyncError::FetchCat(asset_id, error))?;
126-
127-
let response = response
128-
.json::<Response>()
129-
.await
130-
.map_err(|error| SyncError::FetchCat(asset_id, error))?;
123+
.await??
124+
.json::<Response>()
125+
.await?;
131126

132127
Ok(response)
133128
}

crates/sage-wallet/src/queues/puzzle_queue.rs

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ use tokio::{
1212
use tracing::{debug, instrument};
1313

1414
use crate::{
15-
database::insert_puzzle, fetch_nft_did, ChildKind, PeerState, SyncCommand, SyncError,
16-
SyncEvent, WalletError,
15+
database::insert_puzzle, fetch_nft_did, ChildKind, PeerState, SyncCommand, SyncEvent,
16+
WalletError,
1717
};
1818

1919
#[derive(Debug)]
@@ -96,17 +96,15 @@ impl PuzzleQueue {
9696
let addr = peer.socket_addr();
9797
let coin_id = coin_state.coin.coin_id();
9898

99-
futures.push(tokio::spawn(async move {
99+
futures.push(async move {
100100
let result = fetch_puzzle(&peer, &db, genesis_challenge, coin_state).await;
101101
(addr, coin_id, result)
102-
}));
102+
});
103103
}
104104

105105
let mut subscriptions = Vec::new();
106106

107-
while let Some(result) = futures.next().await {
108-
let (addr, coin_id, result) = result?;
109-
107+
while let Some((addr, coin_id, result)) = futures.next().await {
110108
match result {
111109
Ok(subscribe) => {
112110
if subscribe {
@@ -147,26 +145,24 @@ async fn fetch_puzzle(
147145
Duration::from_secs(5),
148146
peer.request_coin_state(vec![parent_id], None, genesis_challenge, false),
149147
)
150-
.await
151-
.map_err(|_| SyncError::Timeout)??
152-
.map_err(|_| SyncError::Rejection)?
148+
.await??
149+
.map_err(|_| WalletError::PeerMisbehaved)?
153150
.coin_states
154151
.into_iter()
155152
.next() else {
156-
return Err(SyncError::MissingCoinState(parent_id).into());
153+
return Err(WalletError::MissingCoin(parent_id));
157154
};
158155

159156
let height = coin_state
160157
.created_height
161-
.ok_or(SyncError::UnconfirmedCoin(parent_id))?;
158+
.ok_or(WalletError::MissingCoin(parent_id))?;
162159

163160
let response = timeout(
164161
Duration::from_secs(10),
165162
peer.request_puzzle_and_solution(parent_id, height),
166163
)
167-
.await
168-
.map_err(|_| SyncError::Timeout)??
169-
.map_err(|_| SyncError::MissingPuzzleAndSolution(parent_id))?;
164+
.await??
165+
.map_err(|_| WalletError::MissingSpend(parent_id))?;
170166

171167
let info = spawn_blocking(move || {
172168
ChildKind::from_parent(

0 commit comments

Comments
 (0)