Skip to content

Commit 6fd8679

Browse files
authored
Add token query tests (#3559)
add token-query package tests
1 parent a8e8007 commit 6fd8679

File tree

3 files changed

+271
-0
lines changed

3 files changed

+271
-0
lines changed

tee-worker/omni-executor/Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tee-worker/omni-executor/intent/token-query/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ executor-primitives = { workspace = true }
2020
[dev-dependencies]
2121
tokio = { workspace = true }
2222
hex-literal = { workspace = true }
23+
mockall = { workspace = true }
24+
ethereum-rpc = { workspace = true, features = ["mocks"] }
25+
solana = { workspace = true, features = ["mocks"] }
26+
base64 = { workspace = true }
2327

2428
[lints]
2529
workspace = true

tee-worker/omni-executor/intent/token-query/src/lib.rs

Lines changed: 265 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,4 +152,269 @@ pub mod tests {
152152

153153
println!("Balance is {:?}", balance);
154154
}
155+
156+
#[cfg(test)]
157+
mod tests {
158+
use super::*;
159+
use alloy::primitives::{Address, U256};
160+
use executor_primitives::{EthereumToken, SolanaToken};
161+
use solana_account_decoder_client_types::{ParsedAccount, UiAccount, UiAccountData};
162+
use solana_client::rpc_request::TokenAccountsFilter;
163+
use solana_client::rpc_response::RpcKeyedAccount;
164+
use solana_sdk::pubkey::Pubkey;
165+
166+
#[tokio::test]
167+
async fn test_query_solana_native_success() {
168+
let mut mock_client = solana::mocks::MockSolanaRpcClient::new();
169+
let pubkey = Pubkey::new_unique();
170+
let expected_balance = 1000000000u64; // 1 SOL in lamports
171+
172+
mock_client
173+
.expect_get_balance()
174+
.with(mockall::predicate::eq(pubkey))
175+
.times(1)
176+
.returning(move |_| Ok(expected_balance));
177+
178+
let result = query_solana(&mock_client, &pubkey, &SolanaToken::Native).await;
179+
180+
assert_eq!(result, Ok(expected_balance));
181+
}
182+
183+
#[tokio::test]
184+
async fn test_query_solana_native_error() {
185+
let mut mock_client = solana::mocks::MockSolanaRpcClient::new();
186+
let pubkey = Pubkey::new_unique();
187+
188+
mock_client
189+
.expect_get_balance()
190+
.with(mockall::predicate::eq(pubkey))
191+
.times(1)
192+
.returning(|_| Err(()));
193+
194+
let result = query_solana(&mock_client, &pubkey, &SolanaToken::Native).await;
195+
196+
assert_eq!(result, Err(()));
197+
}
198+
199+
#[tokio::test]
200+
async fn test_query_solana_spl_success_json_format() {
201+
let mut mock_client = solana::mocks::MockSolanaRpcClient::new();
202+
let pubkey = Pubkey::new_unique();
203+
let mint_pubkey = Pubkey::new_unique();
204+
let token = SolanaToken::SPL(mint_pubkey.to_bytes().into());
205+
206+
// Create JSON response structure
207+
let parsed_json = serde_json::json!({
208+
"info": {
209+
"tokenAmount": {
210+
"amount": "500"
211+
}
212+
}
213+
});
214+
215+
let parsed_account =
216+
ParsedAccount { parsed: parsed_json, program: "spl-token".to_string(), space: 165 };
217+
218+
let account_data = UiAccountData::Json(parsed_account);
219+
220+
let rpc_account = RpcKeyedAccount {
221+
pubkey: Pubkey::new_unique().to_string(),
222+
account: UiAccount {
223+
lamports: 2039280,
224+
data: account_data,
225+
owner: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA".to_string(),
226+
executable: false,
227+
rent_epoch: 361,
228+
space: Some(165),
229+
},
230+
};
231+
232+
mock_client
233+
.expect_get_token_accounts_by_owner()
234+
.with(
235+
mockall::predicate::eq(pubkey),
236+
mockall::predicate::function(move |filter: &TokenAccountsFilter| {
237+
matches!(filter, TokenAccountsFilter::Mint(mint) if *mint == mint_pubkey)
238+
}),
239+
)
240+
.times(1)
241+
.returning(move |_, _| Ok(vec![rpc_account.clone()]));
242+
243+
let result = query_solana(&mock_client, &pubkey, &token).await;
244+
245+
assert_eq!(result, Ok(500));
246+
}
247+
248+
#[tokio::test]
249+
async fn test_query_solana_spl_multiple_accounts() {
250+
let mut mock_client = solana::mocks::MockSolanaRpcClient::new();
251+
let pubkey = Pubkey::new_unique();
252+
let mint_pubkey = Pubkey::new_unique();
253+
let token = SolanaToken::SPL(mint_pubkey.to_bytes().into());
254+
255+
// First account with 300 tokens
256+
let parsed_json1 = serde_json::json!({
257+
"info": {
258+
"tokenAmount": {
259+
"amount": "300"
260+
}
261+
}
262+
});
263+
264+
let parsed_account1 = ParsedAccount {
265+
parsed: parsed_json1,
266+
program: "spl-token".to_string(),
267+
space: 165,
268+
};
269+
270+
let account_data1 = UiAccountData::Json(parsed_account1);
271+
272+
// Second account with 700 tokens
273+
let parsed_json2 = serde_json::json!({
274+
"info": {
275+
"tokenAmount": {
276+
"amount": "700"
277+
}
278+
}
279+
});
280+
281+
let parsed_account2 = ParsedAccount {
282+
parsed: parsed_json2,
283+
program: "spl-token".to_string(),
284+
space: 165,
285+
};
286+
287+
let account_data2 = UiAccountData::Json(parsed_account2);
288+
289+
let accounts = vec![
290+
RpcKeyedAccount {
291+
pubkey: Pubkey::new_unique().to_string(),
292+
account: UiAccount {
293+
lamports: 2039280,
294+
data: account_data1,
295+
owner: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA".to_string(),
296+
executable: false,
297+
rent_epoch: 361,
298+
space: Some(165),
299+
},
300+
},
301+
RpcKeyedAccount {
302+
pubkey: Pubkey::new_unique().to_string(),
303+
account: UiAccount {
304+
lamports: 2039280,
305+
data: account_data2,
306+
owner: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA".to_string(),
307+
executable: false,
308+
rent_epoch: 361,
309+
space: Some(165),
310+
},
311+
},
312+
];
313+
314+
mock_client
315+
.expect_get_token_accounts_by_owner()
316+
.with(
317+
mockall::predicate::eq(pubkey),
318+
mockall::predicate::function(move |filter: &TokenAccountsFilter| {
319+
matches!(filter, TokenAccountsFilter::Mint(mint) if *mint == mint_pubkey)
320+
}),
321+
)
322+
.times(1)
323+
.returning(move |_, _| Ok(accounts.clone()));
324+
325+
let result = query_solana(&mock_client, &pubkey, &token).await;
326+
327+
assert_eq!(result, Ok(1000)); // 300 + 700
328+
}
329+
330+
#[tokio::test]
331+
async fn test_query_solana_spl_error() {
332+
let mut mock_client = solana::mocks::MockSolanaRpcClient::new();
333+
let pubkey = Pubkey::new_unique();
334+
let mint_pubkey = Pubkey::new_unique();
335+
let token = SolanaToken::SPL(mint_pubkey.to_bytes().into());
336+
337+
mock_client
338+
.expect_get_token_accounts_by_owner()
339+
.with(
340+
mockall::predicate::eq(pubkey),
341+
mockall::predicate::function(move |filter: &TokenAccountsFilter| {
342+
matches!(filter, TokenAccountsFilter::Mint(mint) if *mint == mint_pubkey)
343+
}),
344+
)
345+
.times(1)
346+
.returning(|_, _| Err(()));
347+
348+
let result = query_solana(&mock_client, &pubkey, &token).await;
349+
350+
assert_eq!(result, Err(()));
351+
}
352+
353+
#[tokio::test]
354+
async fn test_query_ethereum_native_success() {
355+
let mut mock_provider = ethereum_rpc::mocks::MockRpcProvider::new();
356+
let address = Address::from_str("0x70997970C51812dc3A010C7d01b50e0d17dc79C8").unwrap();
357+
let expected_balance = U256::from(1000000000000000000u64); // 1 ETH in wei
358+
359+
mock_provider
360+
.expect_get_balance()
361+
.with(mockall::predicate::eq(address))
362+
.times(1)
363+
.returning(move |_| Ok(expected_balance));
364+
365+
let result = query_ethereum(&mock_provider, address, &EthereumToken::Native).await;
366+
367+
assert_eq!(result, Ok(expected_balance));
368+
}
369+
370+
#[tokio::test]
371+
async fn test_query_ethereum_native_error() {
372+
let mut mock_provider = ethereum_rpc::mocks::MockRpcProvider::new();
373+
let address = Address::from_str("0x70997970C51812dc3A010C7d01b50e0d17dc79C8").unwrap();
374+
375+
mock_provider
376+
.expect_get_balance()
377+
.with(mockall::predicate::eq(address))
378+
.times(1)
379+
.returning(|_| Err(()));
380+
381+
let result = query_ethereum(&mock_provider, address, &EthereumToken::Native).await;
382+
383+
assert_eq!(result, Err(()));
384+
}
385+
386+
#[tokio::test]
387+
async fn test_query_ethereum_erc20_success() {
388+
let mut mock_provider = ethereum_rpc::mocks::MockRpcProvider::new();
389+
let account = Address::from_str("0x70997970C51812dc3A010C7d01b50e0d17dc79C8").unwrap();
390+
let token_address = hex!("5FC8d32690cc91D4c39d9d3abcBD16989F875707");
391+
let token = EthereumToken::ERC20(token_address.try_into().unwrap());
392+
let expected_balance = U256::from(500000000u64); // 500 tokens (with 6 decimals)
393+
394+
// Mock the call method to return the balance
395+
let balance_bytes = expected_balance.to_be_bytes_vec();
396+
mock_provider
397+
.expect_call()
398+
.times(1)
399+
.returning(move |_| Ok(balance_bytes.clone()));
400+
401+
let result = query_ethereum(&mock_provider, account, &token).await;
402+
403+
assert_eq!(result, Ok(expected_balance));
404+
}
405+
406+
#[tokio::test]
407+
async fn test_query_ethereum_erc20_error() {
408+
let mut mock_provider = ethereum_rpc::mocks::MockRpcProvider::new();
409+
let account = Address::from_str("0x70997970C51812dc3A010C7d01b50e0d17dc79C8").unwrap();
410+
let token_address = hex!("5FC8d32690cc91D4c39d9d3abcBD16989F875707");
411+
let token = EthereumToken::ERC20(token_address.try_into().unwrap());
412+
413+
mock_provider.expect_call().times(1).returning(|_| Err(()));
414+
415+
let result = query_ethereum(&mock_provider, account, &token).await;
416+
417+
assert_eq!(result, Err(()));
418+
}
419+
}
155420
}

0 commit comments

Comments
 (0)