Skip to main content

amp_rs/
mocks.rs

1use httpmock::prelude::*;
2use serde_json::json;
3
4/// Sets up a mock for the GET /changelog endpoint.
5///
6/// This mock returns a sample changelog with version 0.1.0.
7///
8/// # Examples
9/// ```no_run
10/// # use httpmock::prelude::*;
11/// # use amp_rs::mocks::mock_get_changelog;
12/// let server = MockServer::start();
13/// mock_get_changelog(&server);
14///
15/// // Now requests to /changelog will return the mocked response
16/// ```
17pub fn mock_get_changelog(server: &MockServer) {
18    server.mock(|when, then| {
19        when.method(GET).path("/changelog");
20        then.status(200)
21            .header("content-type", "application/json")
22            .json_body(json!({
23                "0.1.0": {
24                    "added": [
25                        "Initial release"
26                    ]
27                }
28            }));
29    });
30}
31
32/// # Panics
33/// Panics if the request body cannot be parsed as JSON
34pub fn mock_create_asset_assignments(server: &MockServer) {
35    use serde_json::Value;
36
37    server.mock(|when, then| {
38        when.method(POST)
39            .path("/assets/mock_asset_uuid/assignments/create")
40            .header("content-type", "application/json")
41            // Custom matcher to validate the request structure and data types
42            .matches(|req| {
43                // Parse the request body
44                let body: Result<Value, _> = serde_json::from_slice(req.body.as_ref().unwrap());
45                match body {
46                    Ok(json) => {
47                        // Validate that the request is wrapped in an "assignments" array
48                        if let Some(assignments) = json.get("assignments") {
49                            if let Some(assignments_array) = assignments.as_array() {
50                                // Allow any number of assignments (1 or more)
51                                if !assignments_array.is_empty() {
52                                    // Validate each assignment
53                                    for assignment in assignments_array {
54                                        let has_registered_user = assignment
55                                            .get("registered_user")
56                                            .and_then(serde_json::Value::as_i64)
57                                            .is_some();
58                                        let has_amount = assignment
59                                            .get("amount")
60                                            .and_then(serde_json::Value::as_i64)
61                                            .is_some();
62                                        let vesting_timestamp_valid = assignment
63                                            .get("vesting_timestamp")
64                                            .is_none_or(|v| v.is_null() || v.is_i64()); // Optional field
65                                        let ready_for_distribution_valid = assignment
66                                            .get("ready_for_distribution")
67                                            .is_none_or(serde_json::Value::is_boolean); // Optional field with default
68
69                                        if !(has_registered_user
70                                            && has_amount
71                                            && vesting_timestamp_valid
72                                            && ready_for_distribution_valid)
73                                        {
74                                            return false;
75                                        }
76                                    }
77                                    return true;
78                                }
79                            }
80                        }
81                        false
82                    }
83                    Err(_) => false,
84                }
85            });
86        then.status(200)
87            .header("content-type", "application/json")
88            // Response with single assignment for basic testing
89            .json_body(json!([{
90              "id": 10,
91              "registered_user": 13,
92              "amount": 100,
93              "receiving_address": null,
94              "distribution_uuid": null,
95              "ready_for_distribution": true,
96              "vesting_datetime": null,
97              "vesting_timestamp": null,
98              "has_vested": true,
99              "is_distributed": false,
100              "creator": 1,
101              "GAID": "GA3DS3emT12zDF4RGywBvJqZfhefNp",
102              "investor": 13
103            }]));
104    });
105}
106
107/// # Panics
108/// Panics if the request body cannot be parsed as JSON
109pub fn mock_create_asset_assignments_multiple(server: &MockServer) {
110    use serde_json::Value;
111
112    // First assignment request (amount: 100, user: 13)
113    server.mock(|when, then| {
114        when.method(POST)
115            .path("/assets/mock_asset_uuid/assignments/create")
116            .header("content-type", "application/json")
117            .matches(|req| {
118                let body: Result<Value, _> = serde_json::from_slice(req.body.as_ref().unwrap());
119                body.is_ok_and(|json| {
120                    json.get("assignments")
121                        .and_then(serde_json::Value::as_array)
122                        .is_some_and(|assignments| {
123                            assignments.len() == 1
124                                && assignments[0]
125                                    .get("amount")
126                                    .and_then(serde_json::Value::as_i64)
127                                    == Some(100)
128                        })
129                })
130            });
131        then.status(200)
132            .header("content-type", "application/json")
133            .json_body(json!([
134                {
135                    "id": 10,
136                    "registered_user": 13,
137                    "amount": 100,
138                    "receiving_address": null,
139                    "distribution_uuid": null,
140                    "ready_for_distribution": true,
141                    "vesting_datetime": null,
142                    "vesting_timestamp": null,
143                    "has_vested": true,
144                    "is_distributed": false,
145                    "creator": 1,
146                    "GAID": "GA3DS3emT12zDF4RGywBvJqZfhefNp",
147                    "investor": 13
148                }
149            ]));
150    });
151
152    // Second assignment request (amount: 200, user: 14)
153    server.mock(|when, then| {
154        when.method(POST)
155            .path("/assets/mock_asset_uuid/assignments/create")
156            .header("content-type", "application/json")
157            .matches(|req| {
158                let body: Result<Value, _> = serde_json::from_slice(req.body.as_ref().unwrap());
159                body.is_ok_and(|json| {
160                    json.get("assignments")
161                        .and_then(serde_json::Value::as_array)
162                        .is_some_and(|assignments| {
163                            assignments.len() == 1
164                                && assignments[0]
165                                    .get("amount")
166                                    .and_then(serde_json::Value::as_i64)
167                                    == Some(200)
168                        })
169                })
170            });
171        then.status(200)
172            .header("content-type", "application/json")
173            .json_body(json!([
174                {
175                    "id": 11,
176                    "registered_user": 14,
177                    "amount": 200,
178                    "receiving_address": null,
179                    "distribution_uuid": null,
180                    "ready_for_distribution": true,
181                    "vesting_datetime": null,
182                    "vesting_timestamp": null,
183                    "has_vested": true,
184                    "is_distributed": false,
185                    "creator": 1,
186                    "GAID": "GA4DS3emT12zDF4RGywBvJqZfhefNp",
187                    "investor": 14
188                }
189            ]));
190    });
191}
192
193pub fn mock_broadcast_transaction(server: &MockServer) {
194    server.mock(|when, then| {
195        when.method(POST).path("/tx/broadcast");
196        then.status(200)
197            .header("content-type", "application/json")
198            .json_body(json!({
199                "txid": "mock_txid",
200                "hex": "mock_tx_hex"
201            }));
202    });
203}
204
205pub fn mock_get_broadcast_status(server: &MockServer) {
206    server.mock(|when, then| {
207        when.method(GET).path("/tx/broadcast/mock_txid");
208        then.status(200)
209            .header("content-type", "application/json")
210            .json_body(json!({
211                "txid": "mock_txid",
212                "hex": "mock_tx_hex"
213            }));
214    });
215}
216
217pub fn mock_remove_asset_from_group(server: &MockServer) {
218    server.mock(|when, then| {
219        when.method(DELETE)
220            .path("/asset_groups/1/assets/mock_asset_uuid");
221        then.status(200);
222    });
223}
224
225pub fn mock_get_managers(server: &MockServer) {
226    server.mock(|when, then| {
227        when.method(GET).path("/managers");
228        then.status(200)
229            .header("content-type", "application/json")
230            .json_body(json!([{
231                "id": 1,
232                "username": "mock_manager",
233                "is_locked": false,
234                "assets": []
235            }]));
236    });
237}
238
239pub fn mock_create_manager(server: &MockServer) {
240    server.mock(|when, then| {
241        when.method(POST).path("/managers/create");
242        then.status(200)
243            .header("content-type", "application/json")
244            .json_body(json!({
245                "id": 2,
246                "username": "test_manager",
247                "is_locked": false,
248                "assets": []
249            }));
250    });
251}
252
253/// Sets up a mock for the POST `/user/obtain_token` endpoint.
254///
255/// This mock returns a successful token response with `"mock_token"`.
256///
257/// # Examples
258/// ```no_run
259/// # use httpmock::prelude::*;
260/// # use amp_rs::mocks::mock_obtain_token;
261/// let server = MockServer::start();
262/// mock_obtain_token(&server);
263///
264/// // Now token requests will return the mocked token
265/// ```
266pub fn mock_obtain_token(server: &MockServer) {
267    server.mock(|when, then| {
268        when.method(POST).path("/user/obtain_token");
269        then.status(200)
270            .header("content-type", "application/json")
271            .json_body(json!({
272                "token": "mock_token"
273            }));
274    });
275}
276
277pub fn mock_refresh_token(server: &MockServer) {
278    server.mock(|when, then| {
279        when.method(POST)
280            .path("/user/refresh_token")
281            .header("authorization", "token mock_token");
282        then.status(200)
283            .header("content-type", "application/json")
284            .json_body(json!({
285                "token": "mock_refreshed_token"
286            }));
287    });
288}
289
290pub fn mock_obtain_token_with_rate_limiting(server: &MockServer, retry_after_seconds: u64) {
291    server.mock(|when, then| {
292        when.method(POST)
293            .path("/user/obtain_token")
294            .header("content-type", "application/json");
295        then.status(429)
296            .header("retry-after", retry_after_seconds.to_string())
297            .header("content-type", "application/json")
298            .json_body(json!({
299                "error": "Too Many Requests"
300            }));
301    });
302}
303
304pub fn mock_obtain_token_server_error(server: &MockServer) {
305    server.mock(|when, then| {
306        when.method(POST)
307            .path("/user/obtain_token")
308            .header("content-type", "application/json");
309        then.status(500)
310            .header("content-type", "application/json")
311            .json_body(json!({
312                "error": "Internal Server Error"
313            }));
314    });
315}
316
317pub fn mock_refresh_token_failure(server: &MockServer) {
318    server.mock(|when, then| {
319        when.method(POST).path("/user/refresh_token");
320        then.status(401)
321            .header("content-type", "application/json")
322            .json_body(json!({
323                "error": "Invalid token"
324            }));
325    });
326}
327
328pub fn mock_get_gaid_address(server: &MockServer) {
329    server.mock(|when, then| {
330        when.method(GET)
331            .path("/gaids/GAbYScu6jkWUND2jo3L4KJxyvo55d/address");
332        then.status(200)
333            .header("content-type", "application/json")
334            .json_body(json!({
335                "address": "mock_address"
336            }));
337    });
338}
339
340pub fn mock_validate_gaid(server: &MockServer) {
341    server.mock(|when, then| {
342        when.method(GET)
343            .path("/gaids/GAbYScu6jkWUND2jo3L4KJxyvo55d/validate");
344        then.status(200)
345            .header("content-type", "application/json")
346            .json_body(json!({
347                "is_valid": true
348            }));
349    });
350}
351
352pub fn mock_get_categories(server: &MockServer) {
353    server.mock(|when, then| {
354        when.method(GET).path("/categories");
355        then.status(200)
356            .header("content-type", "application/json")
357            .json_body(json!([{
358                "id": 1,
359                "name": "Mock Category",
360                "description": "A mock category",
361                "registered_users": [],
362                "assets": []
363            }]));
364    });
365}
366
367pub fn mock_add_category(server: &MockServer) {
368    server.mock(|when, then| {
369        when.method(POST).path("/categories/add");
370        then.status(200)
371            .header("content-type", "application/json")
372            .json_body(json!({
373                "id": 2,
374                "name": "Test Category",
375                "description": "Test category description",
376                "registered_users": [],
377                "assets": []
378            }));
379    });
380}
381
382pub fn mock_add_registered_user(server: &MockServer) {
383    server.mock(|when, then| {
384        when.method(POST).path("/registered_users/add");
385        then.status(200)
386            .header("content-type", "application/json")
387            .json_body(json!({
388                "id": 2,
389                "name": "Test User",
390                "gaid": null,
391                "is_company": false,
392                "authorization_url": "https://example.com/auth_new",
393                "categories": [],
394                "creator": 1
395            }));
396    });
397}
398
399pub fn mock_delete_asset(server: &MockServer) {
400    server.mock(|when, then| {
401        when.method(DELETE)
402            .path("/assets/new_mock_asset_uuid/delete");
403        then.status(200);
404    });
405}
406
407pub fn mock_get_registered_users(server: &MockServer) {
408    server.mock(|when, then| {
409        when.method(GET).path("/registered_users");
410        then.status(200)
411            .header("content-type", "application/json")
412            .json_body(json!([{
413                "id": 1,
414                "name": "Mock User",
415                "GAID": "mock_gaid",
416                "is_company": false,
417                "authorization_url": "https://example.com/auth",
418                "categories": [],
419                "creator": 1
420            }]));
421    });
422}
423
424pub fn mock_get_registered_user(server: &MockServer) {
425    server.mock(|when, then| {
426        when.method(GET).path("/registered_users/1");
427        then.status(200)
428            .header("content-type", "application/json")
429            .json_body(json!({
430                "id": 1,
431                "name": "Mock User",
432                "gaid": "mock_gaid",
433                "is_company": false,
434                "authorization_url": "https://example.com/auth",
435                "categories": [],
436                "creator": 1
437            }));
438    });
439}
440
441pub fn mock_edit_asset(server: &MockServer) {
442    server.mock(|when, then| {
443        when.method(PUT)
444            .path("/assets/mock_asset_uuid/edit")
445            .header("content-type", "application/json");
446        then.status(200)
447            .header("content-type", "application/json")
448            .json_body(json!({
449                "name": "Mock Asset",
450                "asset_uuid": "mock_asset_uuid",
451                "issuer": 1,
452                "asset_id": "mock_asset_id",
453                "reissuance_token_id": null,
454                "requirements": [],
455                "ticker": "MOCK",
456                "precision": 8,
457                "domain": "mock.com",
458                "pubkey": "mock_pubkey",
459                "is_registered": true,
460                "is_authorized": true,
461                "is_locked": false,
462                "issuer_authorization_endpoint": "https://example.com/authorize",
463                "transfer_restricted": true
464            }));
465    });
466}
467
468/// Sets up a mock for the POST `/assets/{asset_uuid}/register` endpoint.
469///
470/// This mock returns a successful asset registration response with the Blockstream Asset Registry.
471///
472/// # Examples
473/// ```no_run
474/// # use httpmock::prelude::*;
475/// # use amp_rs::mocks::mock_register_asset;
476/// let server = MockServer::start();
477/// mock_register_asset(&server);
478///
479/// // Now asset registration requests will return the mocked response
480/// ```
481pub fn mock_register_asset(server: &MockServer) {
482    server.mock(|when, then| {
483        when.method(GET).path("/assets/mock_asset_uuid/register");
484        then.status(200)
485            .header("content-type", "application/json")
486            .json_body(json!({
487                "name": "Mock Asset",
488                "asset_uuid": "mock_asset_uuid",
489                "issuer": 1,
490                "asset_id": "6f0279e9ed041c3d710a9f57d0c02928416460c4b722ae3457a11eec381c526d",
491                "reissuance_token_id": null,
492                "requirements": [],
493                "ticker": "MOCK",
494                "precision": 8,
495                "domain": "liquidtestnet.com",
496                "pubkey": "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
497                "is_registered": true,
498                "is_authorized": true,
499                "is_locked": false,
500                "issuer_authorization_endpoint": null,
501                "transfer_restricted": false
502            }));
503    });
504}
505
506/// Sets up a mock for the GET `/assets/{asset_uuid}/register` endpoint that returns a 404 error.
507///
508/// This mock simulates the scenario where the asset UUID does not exist.
509pub fn mock_register_asset_not_found(server: &MockServer) {
510    server.mock(|when, then| {
511        when.method(GET)
512            .path("/assets/non_existent_asset_uuid/register");
513        then.status(404)
514            .header("content-type", "application/json")
515            .json_body(json!({
516                "error": "Asset not found"
517            }));
518    });
519}
520
521/// Sets up a mock for the GET `/assets/{asset_uuid}/register` endpoint that returns a 500 error.
522///
523/// This mock simulates a server error during asset registration.
524pub fn mock_register_asset_server_error(server: &MockServer) {
525    server.mock(|when, then| {
526        when.method(GET)
527            .path("/assets/server_error_asset_uuid/register");
528        then.status(500)
529            .header("content-type", "application/json")
530            .json_body(json!({
531                "error": "Internal server error"
532            }));
533    });
534}
535
536/// Sets up a mock for the GET `/assets/{asset_uuid}/register` endpoint for already registered assets.
537///
538/// This mock simulates the scenario where an asset is already registered with the registry.
539pub fn mock_register_asset_already_registered(server: &MockServer) {
540    server.mock(|when, then| {
541        when.method(GET)
542            .path("/assets/already_registered_asset_uuid/register");
543        then.status(400)
544            .header("content-type", "application/json")
545            .json_body(json!({
546                "Error": "The asset is already registered."
547            }));
548    });
549}
550
551/// Sets up a mock for the GET `/assets/{asset_uuid}/register` endpoint that verifies authentication.
552///
553/// This mock verifies that the Authorization header is correctly included in the request.
554pub fn mock_register_asset_with_auth(server: &MockServer) {
555    server.mock(|when, then| {
556        when.method(GET)
557            .path("/assets/mock_asset_uuid/register")
558            .header("authorization", "token mock_token");
559        then.status(200)
560            .header("content-type", "application/json")
561            .json_body(json!({
562                "name": "Mock Asset",
563                "asset_uuid": "mock_asset_uuid",
564                "issuer": 1,
565                "asset_id": "6f0279e9ed041c3d710a9f57d0c02928416460c4b722ae3457a11eec381c526d",
566                "reissuance_token_id": null,
567                "requirements": [],
568                "ticker": "MOCK",
569                "precision": 8,
570                "domain": "liquidtestnet.com",
571                "pubkey": "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
572                "is_registered": true,
573                "is_authorized": true,
574                "is_locked": false,
575                "issuer_authorization_endpoint": null,
576                "transfer_restricted": false
577            }));
578    });
579}
580
581/// Sets up a mock for the POST /assets/issue endpoint.
582///
583/// This mock returns a successful asset issuance response with mock data.
584///
585/// # Examples
586/// ```no_run
587/// # use httpmock::prelude::*;
588/// # use amp_rs::mocks::mock_issue_asset;
589/// let server = MockServer::start();
590/// mock_issue_asset(&server);
591///
592/// // Now asset issuance requests will return the mocked response
593/// ```
594pub fn mock_issue_asset(server: &MockServer) {
595    server.mock(|when, then| {
596        when.method(POST).path("/assets/issue");
597        then.status(200)
598            .header("content-type", "application/json")
599            .json_body(json!({
600                "name": "Test Asset",
601                "amount": 1000,
602                "destination_address": "destination_address",
603                "domain": "example.com",
604                "ticker": "TSTA",
605                "pubkey": "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
606                "is_confidential": true,
607                "is_reissuable": false,
608                "reissuance_amount": 0,
609                "reissuance_address": "reissuance_address",
610                "asset_id": "mock_asset_id",
611                "reissuance_token_id": null,
612                "asset_uuid": "new_mock_asset_uuid",
613                "txid": "mock_txid",
614                "vin": 0,
615                "asset_vout": 0,
616                "reissuance_vout": null,
617                "issuer_authorization_endpoint": null,
618                "transfer_restricted": true,
619                "issuance_assetblinder": "mock_blinder",
620                "issuance_tokenblinder": null
621            }));
622    });
623}
624
625/// Sets up a mock for the GET /assets endpoint.
626///
627/// This mock returns a list containing one sample asset with mock data.
628///
629/// # Examples
630/// ```no_run
631/// # use httpmock::prelude::*;
632/// # use amp_rs::mocks::mock_get_assets;
633/// let server = MockServer::start();
634/// mock_get_assets(&server);
635///
636/// // Now requests to /assets will return the mocked asset list
637/// ```
638pub fn mock_get_assets(server: &MockServer) {
639    server.mock(|when, then| {
640        when.method(GET).path("/assets");
641        then.status(200)
642            .header("content-type", "application/json")
643            .json_body(json!([{
644                "name": "Mock Asset",
645                "asset_uuid": "mock_asset_uuid",
646                "issuer": 1,
647                "asset_id": "mock_asset_id",
648                "reissuance_token_id": null,
649                "requirements": [],
650                "ticker": "MOCK",
651                "precision": 8,
652                "domain": "mock.com",
653                "pubkey": "mock_pubkey",
654                "is_registered": true,
655                "is_authorized": true,
656                "is_locked": false,
657                "issuer_authorization_endpoint": null,
658                "transfer_restricted": true
659            }]));
660    });
661}
662
663pub fn mock_get_asset(server: &MockServer) {
664    server.mock(|when, then| {
665        when.method(GET).path("/assets/mock_asset_uuid");
666        then.status(200)
667            .header("content-type", "application/json")
668            .json_body(json!({
669                "name": "Mock Asset",
670                "asset_uuid": "mock_asset_uuid",
671                "issuer": 1,
672                "asset_id": "mock_asset_id",
673                "reissuance_token_id": null,
674                "requirements": [],
675                "ticker": "MOCK",
676                "precision": 8,
677                "domain": "mock.com",
678                "pubkey": "mock_pubkey",
679                "is_registered": true,
680                "is_authorized": true,
681                "is_locked": false,
682                "issuer_authorization_endpoint": "https://example.com/authorize",
683                "transfer_restricted": true
684            }));
685    });
686}
687
688pub fn mock_get_manager(server: &MockServer) {
689    server.mock(|when, then| {
690        when.method(GET).path("/managers/1");
691        then.status(200)
692            .header("content-type", "application/json")
693            .json_body(json!({
694                "id": 1,
695                "username": "mock_manager",
696                "is_locked": false,
697                "assets": ["asset_uuid_1", "asset_uuid_2"]
698            }));
699    });
700}
701
702pub fn mock_manager_remove_asset(server: &MockServer) {
703    server.mock(|when, then| {
704        when.method(POST)
705            .path("/managers/1/assets/asset_uuid_1/remove");
706        then.status(200);
707    });
708
709    server.mock(|when, then| {
710        when.method(POST)
711            .path("/managers/1/assets/asset_uuid_2/remove");
712        then.status(200);
713    });
714}
715
716pub fn mock_get_current_manager_raw(server: &MockServer) {
717    server.mock(|when, then| {
718        when.method(GET).path("/managers/me");
719        then.status(200)
720            .header("content-type", "application/json")
721            .json_body(json!({
722                "id": 1,
723                "username": "current_manager",
724                "is_locked": false,
725                "assets": ["asset_uuid_1"]
726            }));
727    });
728}
729
730pub fn mock_lock_manager(server: &MockServer) {
731    server.mock(|when, then| {
732        when.method(PUT).path("/managers/1/lock");
733        then.status(200);
734    });
735}
736
737pub fn mock_lock_manager_invalid_id(server: &MockServer) {
738    server.mock(|when, then| {
739        when.method(PUT).path("/managers/999_999/lock");
740        then.status(404)
741            .header("content-type", "application/json")
742            .json_body(json!({
743                "error": "Manager not found"
744            }));
745    });
746}
747
748pub fn mock_lock_manager_server_error(server: &MockServer) {
749    server.mock(|when, then| {
750        when.method(PUT).path("/managers/1/lock");
751        then.status(500)
752            .header("content-type", "application/json")
753            .json_body(json!({
754                "error": "Internal server error"
755            }));
756    });
757}
758
759pub fn mock_add_asset_to_manager(server: &MockServer) {
760    server.mock(|when, then| {
761        when.method(PUT)
762            .path("/managers/1/assets/mock_asset_uuid/add");
763        then.status(200);
764    });
765}
766
767pub fn mock_add_asset_to_manager_invalid_manager_id(server: &MockServer) {
768    server.mock(|when, then| {
769        when.method(PUT)
770            .path("/managers/999_999/assets/mock_asset_uuid/add");
771        then.status(404)
772            .header("content-type", "application/json")
773            .json_body(json!({
774                "error": "Manager not found"
775            }));
776    });
777}
778
779pub fn mock_add_asset_to_manager_invalid_asset_uuid(server: &MockServer) {
780    server.mock(|when, then| {
781        when.method(PUT)
782            .path("/managers/1/assets/invalid_asset_uuid/add");
783        then.status(404)
784            .header("content-type", "application/json")
785            .json_body(json!({
786                "error": "Asset not found"
787            }));
788    });
789}
790
791pub fn mock_add_asset_to_manager_server_error(server: &MockServer) {
792    server.mock(|when, then| {
793        when.method(PUT)
794            .path("/managers/1/assets/mock_asset_uuid/add");
795        then.status(500)
796            .header("content-type", "application/json")
797            .json_body(json!({
798                "error": "Internal server error"
799            }));
800    });
801}
802
803pub fn mock_get_asset_assignment(server: &MockServer) {
804    server.mock(|when, then| {
805        when.method(GET)
806            .path("/assets/mock_asset_uuid/assignments/10");
807        then.status(200)
808            .header("content-type", "application/json")
809            .json_body(json!({
810                "id": 10,
811                "registered_user": 13,
812                "amount": 100,
813                "receiving_address": null,
814                "distribution_uuid": null,
815                "ready_for_distribution": true,
816                "vesting_datetime": null,
817                "vesting_timestamp": null,
818                "has_vested": true,
819                "is_distributed": false,
820                "creator": 1,
821                "GAID": "GA3DS3emT12zDF4RGywBvJqZfhefNp",
822                "investor": 13
823            }));
824    });
825}
826
827pub fn mock_unlock_manager(server: &MockServer) {
828    server.mock(|when, then| {
829        when.method(PUT).path("/managers/1/unlock");
830        then.status(200);
831    });
832}
833
834pub fn mock_add_asset_treasury_addresses(server: &MockServer) {
835    server.mock(|when, then| {
836        when.method(POST)
837            .path("/assets/mock_asset_uuid/treasury-addresses/add")
838            .header("content-type", "application/json");
839        then.status(200);
840    });
841}
842
843pub fn mock_get_asset_treasury_addresses(server: &MockServer) {
844    server.mock(|when, then| {
845        when.method(GET)
846            .path("/assets/mock_asset_uuid/treasury-addresses");
847        then.status(200)
848            .header("content-type", "application/json")
849            .json_body(json!([
850                "vjU2i2EM2viGEzSywpStMPkTX9U9QSDsLSN63kJJYVpxKJZuxaph8v5r5Jf11aqnfBVdjSbrvcJ2pw26",
851                "vjU2i2EM2viGEzSywpStMPkTX9U9QSDsLSN63kJJYVpxKJZuxaph8v5r5Jf11aqnfBVdjSbrvcJ2pw27"
852            ]));
853    });
854}
855
856pub fn mock_delete_asset_assignment(server: &MockServer) {
857    server.mock(|when, then| {
858        when.method(DELETE)
859            .path("/assets/mock_asset_uuid/assignments/10/delete");
860        then.status(200);
861    });
862}
863
864pub fn mock_lock_asset_assignment(server: &MockServer) {
865    server.mock(|when, then| {
866        when.method(PUT)
867            .path("/assets/mock_asset_uuid/assignments/10/lock");
868        then.status(200)
869            .header("content-type", "application/json")
870            .json_body(json!({
871                "id": 10,
872                "registered_user": 13,
873                "amount": 100,
874                "receiving_address": null,
875                "distribution_uuid": null,
876                "ready_for_distribution": true,
877                "vesting_datetime": null,
878                "vesting_timestamp": null,
879                "has_vested": true,
880                "is_distributed": false,
881                "creator": 1,
882                "GAID": "GA3DS3emT12zDF4RGywBvJqZfhefNp",
883                "investor": 13
884            }));
885    });
886}
887
888pub fn mock_unlock_asset_assignment(server: &MockServer) {
889    server.mock(|when, then| {
890        when.method(PUT)
891            .path("/assets/mock_asset_uuid/assignments/10/unlock");
892        then.status(200)
893            .header("content-type", "application/json")
894            .json_body(json!({
895                "id": 10,
896                "registered_user": 13,
897                "amount": 100,
898                "receiving_address": null,
899                "distribution_uuid": null,
900                "ready_for_distribution": true,
901                "vesting_datetime": null,
902                "vesting_timestamp": null,
903                "has_vested": true,
904                "is_distributed": false,
905                "creator": 1,
906                "GAID": "GA3DS3emT12zDF4RGywBvJqZfhefNp",
907                "investor": 13
908            }));
909    });
910}
911pub fn mock_lock_asset(server: &MockServer) {
912    server.mock(|when, then| {
913        when.method(PUT).path("/assets/mock_asset_uuid/lock");
914        then.status(200)
915            .header("content-type", "application/json")
916            .json_body(json!({
917                "asset_uuid": "mock_asset_uuid",
918                "name": "Mock Asset",
919                "issuer": 1,
920                "asset_id": "mock_asset_id",
921                "reissuance_token_id": "mock_reissuance_token_id",
922                "requirements": [],
923                "ticker": "MOCK",
924                "precision": 8,
925                "domain": "example.com",
926                "pubkey": "mock_pubkey",
927                "is_registered": true,
928                "is_authorized": true,
929                "is_locked": true,
930                "issuer_authorization_endpoint": "https://example.com/authorize",
931                "transfer_restricted": true
932            }));
933    });
934}
935
936pub fn mock_unlock_asset(server: &MockServer) {
937    server.mock(|when, then| {
938        when.method(PUT).path("/assets/mock_asset_uuid/unlock");
939        then.status(200)
940            .header("content-type", "application/json")
941            .json_body(json!({
942                "asset_uuid": "mock_asset_uuid",
943                "name": "Mock Asset",
944                "issuer": 1,
945                "asset_id": "mock_asset_id",
946                "reissuance_token_id": "mock_reissuance_token_id",
947                "requirements": [],
948                "ticker": "MOCK",
949                "precision": 8,
950                "domain": "example.com",
951                "pubkey": "mock_pubkey",
952                "is_registered": true,
953                "is_authorized": true,
954                "is_locked": false,
955                "issuer_authorization_endpoint": "https://example.com/authorize",
956                "transfer_restricted": true
957            }));
958    });
959}
960
961pub fn mock_edit_registered_user(server: &MockServer) {
962    server.mock(|when, then| {
963        when.method(PUT)
964            .path("/registered_users/1/edit")
965            .header("content-type", "application/json");
966        then.status(200)
967            .header("content-type", "application/json")
968            .json_body(json!({
969                "id": 1,
970                "name": "Updated User Name",
971                "GAID": "mock_gaid",
972                "is_company": false,
973                "categories": [],
974                "creator": 1
975            }));
976    });
977}
978
979pub fn mock_get_registered_user_summary(server: &MockServer) {
980    server.mock(|when, then| {
981        when.method(GET).path("/registered_users/1/summary");
982        then.status(200)
983            .header("content-type", "application/json")
984            .json_body(json!({
985                "asset_uuid": "mock_asset_uuid",
986                "asset_id": "mock_asset_id",
987                "assignments": [{
988                    "id": 1,
989                    "registered_user": 1,
990                    "amount": 1000,
991                    "receiving_address": null,
992                    "distribution_uuid": null,
993                    "ready_for_distribution": true,
994                    "vesting_datetime": null,
995                    "vesting_timestamp": null,
996                    "has_vested": true,
997                    "is_distributed": false,
998                    "creator": 1,
999                    "GAID": "mock_gaid",
1000                    "investor": 1
1001                }],
1002                "assignments_sum": 1000,
1003                "distributions": [],
1004                "distributions_sum": 0,
1005                "balance": 1000
1006            }));
1007    });
1008}
1009
1010pub fn mock_get_registered_user_gaids(server: &MockServer) {
1011    server.mock(|when, then| {
1012        when.method(GET).path("/registered_users/1/gaids");
1013        then.status(200)
1014            .header("content-type", "application/json")
1015            .json_body(json!([
1016                "GA44YYwPM8vuRMmjFL8i5kSqXhoTW2",
1017                "GAbYScu6jkWUND2jo3L4KJxyvo55d"
1018            ]));
1019    });
1020}
1021
1022pub fn mock_add_gaid_to_registered_user(server: &MockServer) {
1023    server.mock(|when, then| {
1024        when.method(POST)
1025            .path("/registered_users/1/gaids/add")
1026            .header("content-type", "application/json");
1027        then.status(200)
1028            .header("content-type", "application/json")
1029            .json_body(json!({}));
1030    });
1031}
1032
1033pub fn mock_set_default_gaid_for_registered_user(server: &MockServer) {
1034    server.mock(|when, then| {
1035        when.method(POST)
1036            .path("/registered_users/1/gaids/set-default")
1037            .header("content-type", "application/json");
1038        then.status(200)
1039            .header("content-type", "application/json")
1040            .json_body(json!({}));
1041    });
1042}
1043
1044pub fn mock_get_gaid_registered_user(server: &MockServer) {
1045    server.mock(|when, then| {
1046        when.method(GET)
1047            .path("/gaids/GA44YYwPM8vuRMmjFL8i5kSqXhoTW2/registered_user");
1048        then.status(200)
1049            .header("content-type", "application/json")
1050            .json_body(json!({
1051                "id": 1,
1052                "name": "Mock User",
1053                "GAID": "GA44YYwPM8vuRMmjFL8i5kSqXhoTW2",
1054                "is_company": false,
1055                "categories": [],
1056                "creator": 1
1057            }));
1058    });
1059}
1060
1061pub fn mock_get_gaid_balance(server: &MockServer) {
1062    server.mock(|when, then| {
1063        when.method(GET)
1064            .path("/gaids/GA44YYwPM8vuRMmjFL8i5kSqXhoTW2/balance");
1065        then.status(200)
1066            .header("content-type", "application/json")
1067            .json_body(json!([
1068                {
1069                    "asset_uuid": "716cb816-6cc7-469d-a41f-f4ed1c0d2dce",
1070                    "asset_id": "5b72739ee4097c32e9eb2fa5f43fd51b35e13323e58c511d6da91adbc4ac24ca",
1071                    "balance": 0
1072                },
1073                {
1074                    "asset_uuid": "5fd36bad-f0af-4b13-a0b5-fb1a91b751a4",
1075                    "asset_id": "ae4bfd3b5dc9d6d1dc77e1c8840fa06b4e9abeabec024cf1d9efb96935757be0",
1076                    "balance": 0
1077                }
1078            ]));
1079    });
1080}
1081
1082pub fn mock_get_gaid_asset_balance(server: &MockServer) {
1083    server.mock(|when, then| {
1084        when.method(GET)
1085            .path("/gaids/GA44YYwPM8vuRMmjFL8i5kSqXhoTW2/balance/mock_asset_uuid");
1086        then.status(200)
1087            .header("content-type", "application/json")
1088            .json_body(json!({
1089                "asset_uuid": "mock_asset_uuid",
1090                "asset_id": "mock_asset_id",
1091                "balance": 100_000
1092            }));
1093    });
1094}
1095
1096pub fn mock_add_categories_to_registered_user(server: &MockServer) {
1097    server.mock(|when, then| {
1098        when.method(PUT)
1099            .path("/registered_users/1/categories/add")
1100            .header("content-type", "application/json");
1101        then.status(200)
1102            .header("content-type", "application/json")
1103            .json_body(json!({}));
1104    });
1105}
1106
1107pub fn mock_remove_categories_from_registered_user(server: &MockServer) {
1108    server.mock(|when, then| {
1109        when.method(PUT)
1110            .path("/registered_users/1/categories/delete")
1111            .header("content-type", "application/json");
1112        then.status(200)
1113            .header("content-type", "application/json")
1114            .json_body(json!({}));
1115    });
1116}
1117
1118pub fn mock_get_asset_memo(server: &MockServer) {
1119    server.mock(|when, then| {
1120        when.method(GET).path("/assets/mock_asset_uuid/memo");
1121        then.status(200)
1122            .header("content-type", "application/json")
1123            .json_body(json!("Sample memo for mock asset"));
1124    });
1125}
1126
1127pub fn mock_set_asset_memo(server: &MockServer) {
1128    server.mock(|when, then| {
1129        when.method(POST)
1130            .path("/assets/mock_asset_uuid/memo/set")
1131            .header("content-type", "application/json");
1132        then.status(200)
1133            .header("content-type", "application/json")
1134            .json_body(json!({}));
1135    });
1136}
1137
1138pub fn mock_add_asset_to_category(server: &MockServer) {
1139    server.mock(|when, then| {
1140        when.method(PUT)
1141            .path("/categories/1/assets/mock_asset_uuid/add");
1142        then.status(200)
1143            .header("content-type", "application/json")
1144            .json_body(json!({
1145                "id": 1,
1146                "name": "Mock Category",
1147                "description": "A mock category",
1148                "registered_users": [],
1149                "assets": ["mock_asset_uuid"]
1150            }));
1151    });
1152}
1153
1154pub fn mock_remove_asset_from_category(server: &MockServer) {
1155    server.mock(|when, then| {
1156        when.method(PUT)
1157            .path("/categories/1/assets/mock_asset_uuid/remove");
1158        then.status(200)
1159            .header("content-type", "application/json")
1160            .json_body(json!({
1161                "id": 1,
1162                "name": "Mock Category",
1163                "description": "A mock category",
1164                "registered_users": [],
1165                "assets": []
1166            }));
1167    });
1168}
1169pub fn mock_get_asset_assignment_invalid_asset_uuid(server: &MockServer) {
1170    server.mock(|when, then| {
1171        when.method(GET)
1172            .path("/assets/invalid_asset_uuid/assignments/10");
1173        then.status(404)
1174            .header("content-type", "application/json")
1175            .json_body(json!({
1176                "error": "Asset not found"
1177            }));
1178    });
1179}
1180
1181pub fn mock_get_asset_assignment_invalid_assignment_id(server: &MockServer) {
1182    server.mock(|when, then| {
1183        when.method(GET)
1184            .path("/assets/mock_asset_uuid/assignments/999_999");
1185        then.status(404)
1186            .header("content-type", "application/json")
1187            .json_body(json!({
1188                "error": "Assignment not found"
1189            }));
1190    });
1191}
1192
1193pub fn mock_get_asset_assignment_non_existent(server: &MockServer) {
1194    server.mock(|when, then| {
1195        when.method(GET)
1196            .path("/assets/non_existent_asset/assignments/non_existent_assignment");
1197        then.status(404)
1198            .header("content-type", "application/json")
1199            .json_body(json!({
1200                "error": "Assignment not found"
1201            }));
1202    });
1203}
1204
1205pub fn mock_get_asset_assignment_server_error(server: &MockServer) {
1206    server.mock(|when, then| {
1207        when.method(GET)
1208            .path("/assets/mock_asset_uuid/assignments/10");
1209        then.status(500)
1210            .header("content-type", "application/json")
1211            .json_body(json!({
1212                "error": "Internal server error"
1213            }));
1214    });
1215}
1216pub fn mock_get_asset_distribution(server: &MockServer) {
1217    server.mock(|when, then| {
1218        when.method(GET)
1219            .path("/assets/mock_asset_uuid/distributions/mock_distribution_uuid");
1220        then.status(200)
1221            .header("content-type", "application/json")
1222            .json_body(json!({
1223                "distribution_uuid": "mock_distribution_uuid",
1224                "distribution_status": "CONFIRMED",
1225                "transactions": [
1226                    {
1227                        "txid": "7ceabde8d7c1596b8b4af27286681dbde9c1551614b9788b6f84b9a3789d3184",
1228                        "transaction_status": "CONFIRMED",
1229                        "included_blockheight": 2_146_947,
1230                        "confirmed_datetime": "2025-10-22T20:45:13.879485Z",
1231                        "assignments": [
1232                            {
1233                                "registered_user": 1936,
1234                                "amount": 1,
1235                                "vout": 2
1236                            }
1237                        ]
1238                    }
1239                ]
1240            }));
1241    });
1242}
1243
1244/// Sets up a mock for the `GET /assets/{asset_uuid}/balance` endpoint.
1245///
1246/// This mock returns a balance response as `Vec<GaidBalanceEntry>` (empty array).
1247/// Note: The `reissue_asset` method uses `request_json` directly to get `lost_outputs`,
1248/// but the public `get_asset_balance` method returns `Balance` (`Vec<GaidBalanceEntry>`).
1249pub fn mock_get_asset_balance(server: &MockServer) {
1250    server.mock(|when, then| {
1251        when.method(GET).path("/assets/mock_asset_uuid/balance");
1252        then.status(200)
1253            .header("content-type", "application/json")
1254            .json_body(json!([]));
1255    });
1256}
1257
1258/// Sets up a mock for the `GET /assets/{asset_uuid}/summary` endpoint.
1259///
1260/// This mock returns asset summary information including issued and reissued amounts.
1261pub fn mock_get_asset_summary(server: &MockServer) {
1262    server.mock(|when, then| {
1263        when.method(GET).path("/assets/mock_asset_uuid/summary");
1264        then.status(200)
1265            .header("content-type", "application/json")
1266            .json_body(json!({
1267                "asset_id": "mock_asset_id",
1268                "reissuance_token_id": "mock_reissuance_token_id",
1269                "issued": 2_100_000_000_000_000_i64,
1270                "reissued": 0,
1271                "assigned": 0,
1272                "distributed": 0,
1273                "burned": 0,
1274                "blacklisted": 0,
1275                "registered_users": 0,
1276                "active_registered_users": 0,
1277                "active_green_subaccounts": 0,
1278                "reissuance_tokens": 100_000
1279            }));
1280    });
1281}
1282
1283/// Sets up a mock for the `GET /assets/{asset_uuid}/summary` endpoint with reissued amount.
1284///
1285/// This mock returns asset summary with a non-zero reissued amount (for after reissuance).
1286pub fn mock_get_asset_summary_with_reissued(server: &MockServer) {
1287    server.mock(|when, then| {
1288        when.method(GET).path("/assets/mock_asset_uuid/summary");
1289        then.status(200)
1290            .header("content-type", "application/json")
1291            .json_body(json!({
1292                "asset_id": "mock_asset_id",
1293                "reissuance_token_id": "mock_reissuance_token_id",
1294                "issued": 2_100_000_000_000_000_i64,
1295                "reissued": 1_000_000_000,
1296                "assigned": 0,
1297                "distributed": 0,
1298                "burned": 0,
1299                "blacklisted": 0,
1300                "registered_users": 0,
1301                "active_registered_users": 0,
1302                "active_green_subaccounts": 0,
1303                "reissuance_tokens": 100_000
1304            }));
1305    });
1306}
1307
1308/// Sets up a mock for a reissuable asset (`GET /assets/{asset_uuid}`).
1309///
1310/// This mock returns an asset with `reissuance_token_id` set, indicating it's reissuable.
1311pub fn mock_get_reissuable_asset(server: &MockServer) {
1312    server.mock(|when, then| {
1313        when.method(GET).path("/assets/mock_asset_uuid");
1314        then.status(200)
1315            .header("content-type", "application/json")
1316            .json_body(json!({
1317                "name": "Mock Reissuable Asset",
1318                "asset_uuid": "mock_asset_uuid",
1319                "issuer": 1,
1320                "asset_id": "mock_asset_id",
1321                "reissuance_token_id": "mock_reissuance_token_id",
1322                "requirements": [],
1323                "ticker": "MOCK",
1324                "precision": 8,
1325                "domain": "mock.com",
1326                "pubkey": "mock_pubkey",
1327                "is_registered": true,
1328                "is_authorized": true,
1329                "is_locked": false,
1330                "issuer_authorization_endpoint": null,
1331                "transfer_restricted": false
1332            }));
1333    });
1334}
1335
1336/// Sets up a mock for the POST /assets/{asset_uuid}/reissue-request endpoint.
1337///
1338/// This mock returns a reissuance request response with reissuance token UTXOs.
1339pub fn mock_reissue_request(server: &MockServer) {
1340    server.mock(|when, then| {
1341        when.method(POST)
1342            .path("/assets/mock_asset_uuid/reissue-request")
1343            .header("content-type", "application/json");
1344        then.status(200)
1345            .header("content-type", "application/json")
1346            .json_body(json!({
1347                "command": "reissue",
1348                "min_supported_client_script_version": 2,
1349                "base_url": "https://amp-test.blockstream.com/api",
1350                "asset_uuid": "mock_asset_uuid",
1351                "asset_id": "mock_asset_id",
1352                "amount": 10.0,
1353                "reissuance_utxos": [
1354                    {
1355                        "txid": "mock_reissuance_txid",
1356                        "vout": 0
1357                    }
1358                ]
1359            }));
1360    });
1361}
1362
1363/// Sets up a mock for the POST /assets/{asset_uuid}/reissue-confirm endpoint.
1364///
1365/// This mock returns a successful reissuance confirmation response.
1366pub fn mock_reissue_confirm(server: &MockServer) {
1367    server.mock(|when, then| {
1368        when.method(POST)
1369            .path("/assets/mock_asset_uuid/reissue-confirm")
1370            .header("content-type", "application/json");
1371        then.status(200)
1372            .header("content-type", "application/json")
1373            .json_body(json!({
1374                "txid": "mock_reissuance_txid",
1375                "vin": 1,
1376                "reissuance_amount": 1_000_000_000
1377            }));
1378    });
1379}
1380
1381/// Sets up a mock for the `POST /assets/{asset_uuid}/burn-request` endpoint.
1382///
1383/// This mock returns a burn request response with asset information and required UTXOs.
1384pub fn mock_burn_request(server: &MockServer) {
1385    server.mock(|when, then| {
1386        when.method(POST)
1387            .path("/assets/mock_asset_uuid/burn-request")
1388            .header("content-type", "application/json");
1389        then.status(200)
1390            .header("content-type", "application/json")
1391            .json_body(json!({
1392                "command": "destroyamount",
1393                "min_supported_client_script_version": 1,
1394                "base_url": "http://localhost:8080",
1395                "asset_uuid": "mock_asset_uuid",
1396                "asset_id": "mock_asset_id",
1397                "amount": 1_000_000.0,
1398                "utxos": [
1399                    {
1400                        "txid": "mock_txid_1",
1401                        "vout": 0
1402                    },
1403                    {
1404                        "txid": "mock_txid_2",
1405                        "vout": 1
1406                    }
1407                ]
1408            }));
1409    });
1410}
1411
1412/// Sets up a mock for the `POST /assets/{asset_uuid}/burn-confirm` endpoint.
1413///
1414/// This mock returns a successful empty response (200 OK with empty body) for burn confirmation.
1415pub fn mock_burn_confirm(server: &MockServer) {
1416    server.mock(|when, then| {
1417        when.method(POST)
1418            .path("/assets/mock_asset_uuid/burn-confirm")
1419            .header("content-type", "application/json");
1420        then.status(200).body("");
1421    });
1422}
1423
1424/// Sets up a mock for the `GET /assets/{asset_uuid}/balance` endpoint used for checking lost outputs.
1425///
1426/// This mock returns an empty `lost_outputs` array indicating no lost outputs.
1427pub fn mock_get_asset_balance_no_lost_outputs(server: &MockServer) {
1428    server.mock(|when, then| {
1429        when.method(GET).path("/assets/mock_asset_uuid/balance");
1430        then.status(200)
1431            .header("content-type", "application/json")
1432            .json_body(json!({
1433                "lost_outputs": []
1434            }));
1435    });
1436}