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