@@ -450,6 +450,41 @@ pub async fn campaign_list<C: Locked + 'static>(
450
450
Ok ( success_response ( serde_json:: to_string ( & list_response) ?) )
451
451
}
452
452
453
+ /// POST `/v5/campaign/:id/close` (auth required)
454
+ ///
455
+ /// **Can only be called by the [`Campaign.creator`]!**
456
+ /// To close a campaign, just set it's budget to what it's spent so far (so that remaining == 0)
457
+ /// newBudget = totalSpent, i.e. newBudget = oldBudget - remaining
458
+ pub async fn close_campaign_axum < C : Locked + ' static > (
459
+ Extension ( app) : Extension < Arc < Application < C > > > ,
460
+ Extension ( auth) : Extension < Auth > ,
461
+ Extension ( campaign_context) : Extension < ChainOf < Campaign > > ,
462
+ ) -> Result < Json < SuccessResponse > , ResponseError > {
463
+ let mut campaign = campaign_context. context ;
464
+
465
+ if auth. uid . to_address ( ) != campaign. creator {
466
+ Err ( ResponseError :: Forbidden (
467
+ "Request not sent by campaign creator" . to_string ( ) ,
468
+ ) )
469
+ } else {
470
+ let old_remaining = app
471
+ . campaign_remaining
472
+ . getset_remaining_to_zero ( campaign. id )
473
+ . await
474
+ . map_err ( |e| ResponseError :: BadRequest ( e. to_string ( ) ) ) ?;
475
+
476
+ campaign. budget = campaign
477
+ . budget
478
+ . checked_sub ( & UnifiedNum :: from ( old_remaining) )
479
+ . ok_or_else ( || {
480
+ ResponseError :: BadRequest ( "Campaign budget overflow/underflow" . to_string ( ) )
481
+ } ) ?;
482
+ update_campaign ( & app. pool , & campaign) . await ?;
483
+
484
+ Ok ( Json ( SuccessResponse { success : true } ) )
485
+ }
486
+ }
487
+
453
488
/// POST `/v5/campaign/:id/close` (auth required)
454
489
///
455
490
/// **Can only be called by the [`Campaign.creator`]!**
@@ -1313,7 +1348,6 @@ mod test {
1313
1348
. expect ( "Should create campaign" )
1314
1349
. 0 ;
1315
1350
1316
-
1317
1351
assert_ne ! ( DUMMY_CAMPAIGN . id, create_response. id) ;
1318
1352
1319
1353
let campaign_remaining = CampaignRemaining :: new ( app. redis . clone ( ) ) ;
@@ -1378,7 +1412,8 @@ mod test {
1378
1412
1379
1413
create_campaign_axum ( Json ( create_second) , auth. clone ( ) , app. clone ( ) )
1380
1414
. await
1381
- . expect ( "Should create campaign" ) . 0
1415
+ . expect ( "Should create campaign" )
1416
+ . 0
1382
1417
} ;
1383
1418
1384
1419
// No budget left for new campaigns
@@ -1554,12 +1589,15 @@ mod test {
1554
1589
let campaign =
1555
1590
CreateCampaign :: from_campaign_erased ( DUMMY_CAMPAIGN . clone ( ) , None ) . into_campaign ( ) ;
1556
1591
1557
- let app = setup_dummy_app ( ) . await ;
1592
+ let app_guard = setup_dummy_app ( ) . await ;
1558
1593
1559
- let channel_chain = app
1594
+ let channel_chain = app_guard
1560
1595
. config
1561
1596
. find_chain_of ( DUMMY_CAMPAIGN . channel . token )
1562
1597
. expect ( "Channel token should be whitelisted in config!" ) ;
1598
+
1599
+ let app = Extension ( Arc :: new ( app_guard. app . clone ( ) ) ) ;
1600
+
1563
1601
let channel_context = channel_chain. with_channel ( DUMMY_CAMPAIGN . channel ) ;
1564
1602
1565
1603
insert_channel ( & app. pool , & channel_context)
@@ -1569,11 +1607,12 @@ mod test {
1569
1607
. await
1570
1608
. expect ( "Should insert dummy campaign" ) ;
1571
1609
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 ( ) ) ;
1610
+ let campaign_context = Extension (
1611
+ app. config
1612
+ . find_chain_of ( campaign. channel . token )
1613
+ . expect ( "Config should have the Dummy campaign.channel.token" )
1614
+ . with ( campaign. clone ( ) ) ,
1615
+ ) ;
1577
1616
1578
1617
// Test if remaining is set to 0
1579
1618
{
@@ -1582,19 +1621,13 @@ mod test {
1582
1621
. await
1583
1622
. expect ( "should set" ) ;
1584
1623
1585
- let auth = Auth {
1624
+ let auth = Extension ( Auth {
1586
1625
era : 0 ,
1587
1626
uid : ValidatorId :: from ( campaign. creator ) ,
1588
1627
chain : campaign_context. chain . clone ( ) ,
1589
- } ;
1628
+ } ) ;
1590
1629
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)
1630
+ close_campaign_axum ( app. clone ( ) , auth. clone ( ) , campaign_context. clone ( ) )
1598
1631
. await
1599
1632
. expect ( "Should close campaign" ) ;
1600
1633
@@ -1618,19 +1651,13 @@ mod test {
1618
1651
1619
1652
// Test if an error is returned when request is not sent by creator
1620
1653
{
1621
- let auth = Auth {
1654
+ let auth = Extension ( Auth {
1622
1655
era : 0 ,
1623
1656
uid : IDS [ & LEADER ] ,
1624
1657
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" ) ;
1658
+ } ) ;
1632
1659
1633
- let res = close_campaign ( req , & app )
1660
+ let res = close_campaign_axum ( app . clone ( ) , auth , campaign_context . clone ( ) )
1634
1661
. await
1635
1662
. expect_err ( "Should return error for Bad Campaign" ) ;
1636
1663
0 commit comments