1
1
//! `/v5/campaign` routes
2
2
use crate :: {
3
+ application:: Qs ,
3
4
db:: {
4
5
accounting:: { get_accounting, Side } ,
5
6
campaign:: {
@@ -21,8 +22,10 @@ use hyper::{Body, Request, Response};
21
22
use primitives:: {
22
23
campaign_validator:: Validator ,
23
24
sentry:: {
24
- campaign_create:: CreateCampaign , campaign_list:: CampaignListQuery ,
25
- campaign_modify:: ModifyCampaign , SuccessResponse ,
25
+ campaign_create:: CreateCampaign ,
26
+ campaign_list:: { CampaignListQuery , CampaignListResponse } ,
27
+ campaign_modify:: ModifyCampaign ,
28
+ SuccessResponse ,
26
29
} ,
27
30
spender:: Spendable ,
28
31
Address , Campaign , CampaignId , ChainOf , Channel , ChannelId , Deposit , UnifiedNum ,
@@ -425,6 +428,29 @@ where
425
428
Ok ( success_response ( serde_json:: to_string ( & campaign) ?) )
426
429
}
427
430
431
+ /// GET `/v5/campaign/list`
432
+ pub async fn campaign_list_axum < C : Locked + ' static > (
433
+ Extension ( app) : Extension < Arc < Application < C > > > ,
434
+ Qs ( query) : Qs < CampaignListQuery > ,
435
+ ) -> Result < Json < CampaignListResponse > , ResponseError > {
436
+ let limit = app. config . campaigns_find_limit ;
437
+ let skip = query
438
+ . page
439
+ . checked_mul ( limit. into ( ) )
440
+ . ok_or_else ( || ResponseError :: BadRequest ( "Page and/or limit is too large" . into ( ) ) ) ?;
441
+ let list_response = list_campaigns (
442
+ & app. pool ,
443
+ skip,
444
+ limit,
445
+ query. creator ,
446
+ query. validator ,
447
+ & query. active_to_ge ,
448
+ )
449
+ . await ?;
450
+
451
+ Ok ( Json ( list_response) )
452
+ }
453
+
428
454
/// GET `/v5/campaign/list`
429
455
pub async fn campaign_list < C : Locked + ' static > (
430
456
req : Request < Body > ,
@@ -450,6 +476,41 @@ pub async fn campaign_list<C: Locked + 'static>(
450
476
Ok ( success_response ( serde_json:: to_string ( & list_response) ?) )
451
477
}
452
478
479
+ /// POST `/v5/campaign/:id/close` (auth required)
480
+ ///
481
+ /// **Can only be called by the [`Campaign.creator`]!**
482
+ /// To close a campaign, just set it's budget to what it's spent so far (so that remaining == 0)
483
+ /// newBudget = totalSpent, i.e. newBudget = oldBudget - remaining
484
+ pub async fn close_campaign_axum < C : Locked + ' static > (
485
+ Extension ( app) : Extension < Arc < Application < C > > > ,
486
+ Extension ( auth) : Extension < Auth > ,
487
+ Extension ( campaign_context) : Extension < ChainOf < Campaign > > ,
488
+ ) -> Result < Json < SuccessResponse > , ResponseError > {
489
+ let mut campaign = campaign_context. context ;
490
+
491
+ if auth. uid . to_address ( ) != campaign. creator {
492
+ Err ( ResponseError :: Forbidden (
493
+ "Request not sent by campaign creator" . to_string ( ) ,
494
+ ) )
495
+ } else {
496
+ let old_remaining = app
497
+ . campaign_remaining
498
+ . getset_remaining_to_zero ( campaign. id )
499
+ . await
500
+ . map_err ( |e| ResponseError :: BadRequest ( e. to_string ( ) ) ) ?;
501
+
502
+ campaign. budget = campaign
503
+ . budget
504
+ . checked_sub ( & UnifiedNum :: from ( old_remaining) )
505
+ . ok_or_else ( || {
506
+ ResponseError :: BadRequest ( "Campaign budget overflow/underflow" . to_string ( ) )
507
+ } ) ?;
508
+ update_campaign ( & app. pool , & campaign) . await ?;
509
+
510
+ Ok ( Json ( SuccessResponse { success : true } ) )
511
+ }
512
+ }
513
+
453
514
/// POST `/v5/campaign/:id/close` (auth required)
454
515
///
455
516
/// **Can only be called by the [`Campaign.creator`]!**
@@ -1259,7 +1320,7 @@ mod test {
1259
1320
use primitives:: {
1260
1321
campaign:: validators:: Validators ,
1261
1322
config:: GANACHE_CONFIG ,
1262
- sentry:: campaign_list:: { CampaignListResponse , ValidatorParam } ,
1323
+ sentry:: campaign_list:: ValidatorParam ,
1263
1324
test_util:: {
1264
1325
CREATOR , DUMMY_CAMPAIGN , DUMMY_VALIDATOR_FOLLOWER , DUMMY_VALIDATOR_LEADER , FOLLOWER ,
1265
1326
GUARDIAN , IDS , LEADER , LEADER_2 , PUBLISHER_2 ,
@@ -1313,7 +1374,6 @@ mod test {
1313
1374
. expect ( "Should create campaign" )
1314
1375
. 0 ;
1315
1376
1316
-
1317
1377
assert_ne ! ( DUMMY_CAMPAIGN . id, create_response. id) ;
1318
1378
1319
1379
let campaign_remaining = CampaignRemaining :: new ( app. redis . clone ( ) ) ;
@@ -1378,7 +1438,8 @@ mod test {
1378
1438
1379
1439
create_campaign_axum ( Json ( create_second) , auth. clone ( ) , app. clone ( ) )
1380
1440
. await
1381
- . expect ( "Should create campaign" ) . 0
1441
+ . expect ( "Should create campaign" )
1442
+ . 0
1382
1443
} ;
1383
1444
1384
1445
// No budget left for new campaigns
@@ -1554,12 +1615,15 @@ mod test {
1554
1615
let campaign =
1555
1616
CreateCampaign :: from_campaign_erased ( DUMMY_CAMPAIGN . clone ( ) , None ) . into_campaign ( ) ;
1556
1617
1557
- let app = setup_dummy_app ( ) . await ;
1618
+ let app_guard = setup_dummy_app ( ) . await ;
1558
1619
1559
- let channel_chain = app
1620
+ let channel_chain = app_guard
1560
1621
. config
1561
1622
. find_chain_of ( DUMMY_CAMPAIGN . channel . token )
1562
1623
. expect ( "Channel token should be whitelisted in config!" ) ;
1624
+
1625
+ let app = Extension ( Arc :: new ( app_guard. app . clone ( ) ) ) ;
1626
+
1563
1627
let channel_context = channel_chain. with_channel ( DUMMY_CAMPAIGN . channel ) ;
1564
1628
1565
1629
insert_channel ( & app. pool , & channel_context)
@@ -1569,11 +1633,12 @@ mod test {
1569
1633
. await
1570
1634
. expect ( "Should insert dummy campaign" ) ;
1571
1635
1572
- let campaign_context = app
1573
- . config
1574
- . find_chain_of ( campaign. channel . token )
1575
- . expect ( "Config should have the Dummy campaign.channel.token" )
1576
- . with ( campaign. clone ( ) ) ;
1636
+ let campaign_context = Extension (
1637
+ app. config
1638
+ . find_chain_of ( campaign. channel . token )
1639
+ . expect ( "Config should have the Dummy campaign.channel.token" )
1640
+ . with ( campaign. clone ( ) ) ,
1641
+ ) ;
1577
1642
1578
1643
// Test if remaining is set to 0
1579
1644
{
@@ -1582,19 +1647,13 @@ mod test {
1582
1647
. await
1583
1648
. expect ( "should set" ) ;
1584
1649
1585
- let auth = Auth {
1650
+ let auth = Extension ( Auth {
1586
1651
era : 0 ,
1587
1652
uid : ValidatorId :: from ( campaign. creator ) ,
1588
1653
chain : campaign_context. chain . clone ( ) ,
1589
- } ;
1654
+ } ) ;
1590
1655
1591
- let req = Request :: builder ( )
1592
- . extension ( auth)
1593
- . extension ( campaign_context. clone ( ) )
1594
- . body ( Body :: empty ( ) )
1595
- . expect ( "Should build Request" ) ;
1596
-
1597
- close_campaign ( req, & app)
1656
+ close_campaign_axum ( app. clone ( ) , auth. clone ( ) , campaign_context. clone ( ) )
1598
1657
. await
1599
1658
. expect ( "Should close campaign" ) ;
1600
1659
@@ -1618,19 +1677,13 @@ mod test {
1618
1677
1619
1678
// Test if an error is returned when request is not sent by creator
1620
1679
{
1621
- let auth = Auth {
1680
+ let auth = Extension ( Auth {
1622
1681
era : 0 ,
1623
1682
uid : IDS [ & LEADER ] ,
1624
1683
chain : campaign_context. chain . clone ( ) ,
1625
- } ;
1626
-
1627
- let req = Request :: builder ( )
1628
- . extension ( auth)
1629
- . extension ( campaign_context. clone ( ) )
1630
- . body ( Body :: empty ( ) )
1631
- . expect ( "Should build Request" ) ;
1684
+ } ) ;
1632
1685
1633
- let res = close_campaign ( req , & app )
1686
+ let res = close_campaign_axum ( app . clone ( ) , auth , campaign_context . clone ( ) )
1634
1687
. await
1635
1688
. expect_err ( "Should return error for Bad Campaign" ) ;
1636
1689
@@ -1641,18 +1694,12 @@ mod test {
1641
1694
}
1642
1695
}
1643
1696
1644
- async fn res_to_campaign_list_response ( res : Response < Body > ) -> CampaignListResponse {
1645
- let json = hyper:: body:: to_bytes ( res. into_body ( ) )
1646
- . await
1647
- . expect ( "Should get json" ) ;
1648
-
1649
- serde_json:: from_slice ( & json) . expect ( "Should deserialize CampaignListResponse" )
1650
- }
1651
-
1652
1697
#[ tokio:: test]
1653
1698
async fn test_campaign_list ( ) {
1654
- let mut app = setup_dummy_app ( ) . await ;
1655
- app. config . campaigns_find_limit = 2 ;
1699
+ let mut app_guard = setup_dummy_app ( ) . await ;
1700
+ app_guard. config . campaigns_find_limit = 2 ;
1701
+ let app = Extension ( Arc :: new ( app_guard. app . clone ( ) ) ) ;
1702
+
1656
1703
// Setting up new leader and a channel and campaign which use it on Ganache #1337
1657
1704
let dummy_leader_2 = ValidatorDesc {
1658
1705
id : IDS [ & LEADER_2 ] ,
@@ -1770,14 +1817,6 @@ mod test {
1770
1817
. await
1771
1818
. expect ( "Should insert dummy campaign" ) ;
1772
1819
1773
- let build_request = |query : CampaignListQuery | {
1774
- let query = serde_qs:: to_string ( & query) . expect ( "should parse query" ) ;
1775
- Request :: builder ( )
1776
- . uri ( format ! ( "http://127.0.0.1/v5/campaign/list?{}" , query) )
1777
- . body ( Body :: empty ( ) )
1778
- . expect ( "Should build Request" )
1779
- } ;
1780
-
1781
1820
// Test for dummy leader
1782
1821
{
1783
1822
let query = CampaignListQuery {
@@ -1786,10 +1825,11 @@ mod test {
1786
1825
creator : None ,
1787
1826
validator : Some ( ValidatorParam :: Leader ( DUMMY_VALIDATOR_LEADER . id ) ) ,
1788
1827
} ;
1789
- let res = campaign_list ( build_request ( query) , & app)
1828
+
1829
+ let res = campaign_list_axum ( app. clone ( ) , Qs ( query) )
1790
1830
. await
1791
- . expect ( "should get campaigns" ) ;
1792
- let res = res_to_campaign_list_response ( res ) . await ;
1831
+ . expect ( "should get campaigns" )
1832
+ . 0 ;
1793
1833
1794
1834
assert_eq ! (
1795
1835
res. campaigns,
@@ -1804,10 +1844,10 @@ mod test {
1804
1844
creator : None ,
1805
1845
validator : Some ( ValidatorParam :: Leader ( DUMMY_VALIDATOR_LEADER . id ) ) ,
1806
1846
} ;
1807
- let res = campaign_list ( build_request ( query ) , & app )
1847
+ let res = campaign_list_axum ( app . clone ( ) , Qs ( query ) )
1808
1848
. await
1809
- . expect ( "should get campaigns" ) ;
1810
- let res = res_to_campaign_list_response ( res ) . await ;
1849
+ . expect ( "should get campaigns" )
1850
+ . 0 ;
1811
1851
1812
1852
assert_eq ! (
1813
1853
res. campaigns,
@@ -1827,10 +1867,10 @@ mod test {
1827
1867
creator : None ,
1828
1868
validator : Some ( ValidatorParam :: Validator ( DUMMY_VALIDATOR_FOLLOWER . id ) ) ,
1829
1869
} ;
1830
- let res = campaign_list ( build_request ( query ) , & app )
1870
+ let res = campaign_list_axum ( app . clone ( ) , Qs ( query ) )
1831
1871
. await
1832
- . expect ( "should get campaigns" ) ;
1833
- let res = res_to_campaign_list_response ( res ) . await ;
1872
+ . expect ( "should get campaigns" )
1873
+ . 0 ;
1834
1874
1835
1875
assert_eq ! (
1836
1876
res. campaigns,
@@ -1845,10 +1885,10 @@ mod test {
1845
1885
creator : None ,
1846
1886
validator : Some ( ValidatorParam :: Validator ( DUMMY_VALIDATOR_FOLLOWER . id ) ) ,
1847
1887
} ;
1848
- let res = campaign_list ( build_request ( query ) , & app )
1888
+ let res = campaign_list_axum ( app . clone ( ) , Qs ( query ) )
1849
1889
. await
1850
- . expect ( "should get campaigns" ) ;
1851
- let res = res_to_campaign_list_response ( res ) . await ;
1890
+ . expect ( "should get campaigns" )
1891
+ . 0 ;
1852
1892
1853
1893
assert_eq ! (
1854
1894
res. campaigns,
@@ -1868,10 +1908,10 @@ mod test {
1868
1908
creator : None ,
1869
1909
validator : Some ( ValidatorParam :: Leader ( dummy_leader_2. id ) ) ,
1870
1910
} ;
1871
- let res = campaign_list ( build_request ( query ) , & app )
1911
+ let res = campaign_list_axum ( app . clone ( ) , Qs ( query ) )
1872
1912
. await
1873
- . expect ( "should get campaigns" ) ;
1874
- let res = res_to_campaign_list_response ( res ) . await ;
1913
+ . expect ( "should get campaigns" )
1914
+ . 0 ;
1875
1915
1876
1916
assert_eq ! (
1877
1917
res. campaigns,
@@ -1892,10 +1932,10 @@ mod test {
1892
1932
creator : None ,
1893
1933
validator : Some ( ValidatorParam :: Validator ( dummy_follower_2. id ) ) ,
1894
1934
} ;
1895
- let res = campaign_list ( build_request ( query ) , & app )
1935
+ let res = campaign_list_axum ( app . clone ( ) , Qs ( query ) )
1896
1936
. await
1897
- . expect ( "should get campaigns" ) ;
1898
- let res = res_to_campaign_list_response ( res ) . await ;
1937
+ . expect ( "should get campaigns" )
1938
+ . 0 ;
1899
1939
1900
1940
assert_eq ! (
1901
1941
res. campaigns,
@@ -1916,10 +1956,10 @@ mod test {
1916
1956
creator : Some ( * PUBLISHER_2 ) ,
1917
1957
validator : None ,
1918
1958
} ;
1919
- let res = campaign_list ( build_request ( query ) , & app )
1959
+ let res = campaign_list_axum ( app . clone ( ) , Qs ( query ) )
1920
1960
. await
1921
- . expect ( "should get campaigns" ) ;
1922
- let res = res_to_campaign_list_response ( res ) . await ;
1961
+ . expect ( "should get campaigns" )
1962
+ . 0 ;
1923
1963
1924
1964
assert_eq ! (
1925
1965
res. campaigns,
@@ -1937,10 +1977,10 @@ mod test {
1937
1977
creator : None ,
1938
1978
validator : None ,
1939
1979
} ;
1940
- let res = campaign_list ( build_request ( query ) , & app )
1980
+ let res = campaign_list_axum ( app . clone ( ) , Qs ( query ) )
1941
1981
. await
1942
- . expect ( "should get campaigns" ) ;
1943
- let res = res_to_campaign_list_response ( res ) . await ;
1982
+ . expect ( "should get campaigns" )
1983
+ . 0 ;
1944
1984
1945
1985
assert_eq ! (
1946
1986
res. campaigns,
0 commit comments