1use std::convert::TryInto;
2use stellar_rpc_client::{GetTransactionResponse, SimulateTransactionResponse};
3use stellar_xdr::curr::{
4 AccountEntry, AccountId, ContractEvent, ContractEventBody, ContractEventType, ContractEventV0,
5 ExtensionPoint, Hash, LedgerEntry, LedgerEntryChange, LedgerEntryData, LedgerEntryExt, Memo,
6 MuxedAccount, Operation, OperationBody, OperationMeta, OperationResult, Preconditions,
7 ScAddress, ScVal, SequenceNumber, SetOptionsOp, SorobanTransactionMeta,
8 SorobanTransactionMetaExt, Transaction, TransactionEnvelope, TransactionExt, TransactionMeta,
9 TransactionMetaV3, TransactionResult, TransactionResultExt, TransactionResultResult,
10 TransactionV1Envelope, Uint256, VecM,
11};
12
13use crate::SorobanTransactionResponse;
14
15pub struct MockTransactionResult {
16 pub success: bool,
17}
18
19pub struct MockTransactionMeta {
20 pub return_value: Option<ScVal>,
21 pub account_entry: Option<AccountEntry>,
22}
23
24pub struct MockGetTransactionResponse {
25 pub tx_result: Option<MockTransactionResult>,
26 pub tx_meta: Option<MockTransactionMeta>,
27 pub tx_envelope: Option<TransactionEnvelope>,
28}
29
30enum MockResponseType {
31 Basic,
32 WithReturnValue(ScVal),
33 WithAccountEntry(AccountEntry),
34}
35
36#[allow(dead_code)]
37pub fn mock_transaction(account_id: AccountId, operations: Vec<Operation>) -> Transaction {
38 Transaction {
39 fee: 100,
40 seq_num: SequenceNumber::from(1),
41 source_account: account_id.into(),
42 cond: Preconditions::None,
43 memo: Memo::None,
44 operations: operations.try_into().unwrap_or_default(),
45 ext: TransactionExt::V0,
46 }
47}
48
49#[allow(dead_code)]
50pub fn mock_transaction_envelope(account_id: AccountId) -> TransactionEnvelope {
51 TransactionEnvelope::Tx(TransactionV1Envelope {
52 tx: mock_transaction(account_id, vec![]),
53 signatures: Default::default(),
54 })
55}
56
57#[allow(dead_code)]
58pub fn create_contract_id_val() -> ScVal {
59 let contract_hash = Hash([1; 32]);
60 ScVal::Address(ScAddress::Contract(stellar_xdr::curr::ContractId(
61 contract_hash,
62 )))
63}
64
65#[allow(dead_code)]
66pub fn create_mock_set_options_tx_envelope() -> TransactionEnvelope {
67 let source_account = MuxedAccount::Ed25519(Uint256([0; 32]));
69
70 let set_options_op = Operation {
72 source_account: None,
73 body: OperationBody::SetOptions(SetOptionsOp {
74 inflation_dest: None,
75 clear_flags: None,
76 set_flags: None,
77 master_weight: None,
78 low_threshold: None,
79 med_threshold: None,
80 high_threshold: None,
81 home_domain: None,
82 signer: None,
83 }),
84 };
85
86 let operations = vec![set_options_op].try_into().unwrap_or_default();
88
89 TransactionEnvelope::Tx(TransactionV1Envelope {
91 tx: Transaction {
92 source_account,
93 fee: 100,
94 seq_num: 1.into(),
95 cond: Preconditions::None,
96 memo: Memo::None,
97 operations,
98 ext: TransactionExt::V0,
99 },
100 signatures: Default::default(),
101 })
102}
103
104#[allow(dead_code)]
105pub fn mock_simulate_tx_response(min_resource_fee: Option<u64>) -> SimulateTransactionResponse {
106 SimulateTransactionResponse {
107 min_resource_fee: min_resource_fee.unwrap_or(100),
108 transaction_data: "test".to_string(),
109 ..Default::default()
110 }
111}
112
113#[allow(dead_code)]
114fn mock_transaction_response_impl(response_type: MockResponseType) -> GetTransactionResponse {
115 let mut response = GetTransactionResponse {
116 status: "SUCCESS".to_string(),
117 envelope: None,
118 result: Some(create_success_tx_result()),
119 result_meta: None,
120 ledger: None,
121 events: stellar_rpc_client::GetTransactionEvents {
122 contract_events: vec![],
123 diagnostic_events: vec![],
124 transaction_events: vec![],
125 },
126 };
127
128 match response_type {
129 MockResponseType::Basic => {}
130 MockResponseType::WithReturnValue(val) => {
131 response.result_meta = Some(create_soroban_tx_meta_with_return_value(val));
132 }
133 MockResponseType::WithAccountEntry(account) => {
134 let ledger_entry = LedgerEntry {
135 last_modified_ledger_seq: 1,
136 data: LedgerEntryData::Account(account),
137 ext: LedgerEntryExt::V0,
138 };
139
140 let change = LedgerEntryChange::Updated(ledger_entry);
141 let changes = VecM::try_from(vec![change]).unwrap_or_default();
142 let op_meta = OperationMeta {
143 changes: stellar_xdr::curr::LedgerEntryChanges(changes),
144 };
145
146 let operations = VecM::try_from(vec![op_meta]).unwrap_or_default();
147 let meta = TransactionMeta::V3(TransactionMetaV3 {
148 ext: ExtensionPoint::V0,
149 soroban_meta: None,
150 tx_changes_before: Default::default(),
151 tx_changes_after: Default::default(),
152 operations,
153 });
154
155 response.result_meta = Some(meta);
156 }
157 }
158
159 response
160}
161
162#[allow(dead_code)]
163pub fn mock_transaction_response() -> SorobanTransactionResponse {
164 SorobanTransactionResponse::from(mock_transaction_response_impl(MockResponseType::Basic))
165}
166
167#[allow(dead_code)]
168pub fn mock_transaction_response_with_return_value(
169 return_val: ScVal,
170) -> SorobanTransactionResponse {
171 SorobanTransactionResponse::from(mock_transaction_response_impl(
172 MockResponseType::WithReturnValue(return_val),
173 ))
174}
175
176#[allow(dead_code)]
177pub fn mock_transaction_response_with_account_entry(
178 account: AccountEntry,
179) -> GetTransactionResponse {
180 mock_transaction_response_impl(MockResponseType::WithAccountEntry(account))
181}
182
183#[allow(dead_code)]
184fn create_success_tx_result() -> TransactionResult {
185 let empty_vec: Vec<OperationResult> = Vec::new();
187 let op_results = empty_vec.try_into().unwrap_or_default();
188
189 TransactionResult {
190 fee_charged: 100,
191 result: TransactionResultResult::TxSuccess(op_results),
192 ext: TransactionResultExt::V0,
193 }
194}
195
196#[allow(dead_code)]
197fn create_soroban_tx_meta_with_return_value(return_val: ScVal) -> TransactionMeta {
198 TransactionMeta::V3(TransactionMetaV3 {
199 ext: ExtensionPoint::V0,
200 soroban_meta: Some(SorobanTransactionMeta {
201 ext: SorobanTransactionMetaExt::V0,
202 events: Default::default(),
203 return_value: return_val,
204 diagnostic_events: Default::default(),
205 }),
206 tx_changes_before: Default::default(),
207 tx_changes_after: Default::default(),
208 operations: Default::default(),
209 })
210}
211
212#[allow(dead_code)]
213fn create_tx_meta_from_mock(mock: &MockTransactionMeta) -> TransactionMeta {
214 if let Some(return_val) = &mock.return_value {
216 return create_soroban_tx_meta_with_return_value(return_val.clone());
217 }
218
219 if let Some(account) = &mock.account_entry {
221 let ledger_entry = LedgerEntry {
223 last_modified_ledger_seq: 1,
224 data: LedgerEntryData::Account(account.clone()),
225 ext: LedgerEntryExt::V0,
226 };
227
228 let change = LedgerEntryChange::Updated(ledger_entry);
229 let changes = VecM::try_from(vec![change]).unwrap_or_default();
230 let op_meta = OperationMeta {
231 changes: stellar_xdr::curr::LedgerEntryChanges(changes),
232 };
233
234 let operations = VecM::try_from(vec![op_meta]).unwrap_or_default();
235
236 return TransactionMeta::V3(TransactionMetaV3 {
237 ext: ExtensionPoint::V0,
238 soroban_meta: None,
239 tx_changes_before: Default::default(),
240 tx_changes_after: Default::default(),
241 operations,
242 });
243 }
244
245 TransactionMeta::V3(TransactionMetaV3 {
247 ext: ExtensionPoint::V0,
248 soroban_meta: None,
249 tx_changes_before: Default::default(),
250 tx_changes_after: Default::default(),
251 operations: Default::default(),
252 })
253}
254
255#[allow(dead_code)]
256pub fn create_mock_contract_event() -> ContractEvent {
257 ContractEvent {
258 body: ContractEventBody::V0(ContractEventV0 {
259 data: ScVal::I32(0),
260 topics: VecM::default(),
261 }),
262 ext: ExtensionPoint::V0,
263 contract_id: Some(stellar_xdr::curr::ContractId(Hash([1; 32]))),
264 type_: ContractEventType::Contract,
265 }
266}