Skip to content
Next
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Switch to GitLab Next
Sign in / Register
Toggle navigation
Minds Backend - Engine
Project
Project
Details
Activity
Releases
Dependency List
Cycle Analytics
Insights
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Locked Files
Issues
168
Issues
168
List
Boards
Labels
Service Desk
Milestones
Merge Requests
45
Merge Requests
45
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Minds
Minds Backend - Engine
Commits
130b7876
Commit
130b7876
authored
5 hours ago
by
Emiliano Balbuena
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
(feat): Refunds
parent
836245a1
goal/boost-campaigns-e24
1 merge request
!235
WIP: Boost Campaigns (&24)
Pipeline
#71165737
passed with stages
in 6 minutes and 57 seconds
Changes
7
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
215 additions
and
46 deletions
+215
-46
views.php
Controllers/api/v2/analytics/views.php
+3
-0
Manager.php
Core/Blockchain/Transactions/Manager.php
+12
-8
PaymentsDelegate.php
Core/Boost/Campaigns/Delegates/PaymentsDelegate.php
+126
-12
Metrics.php
Core/Boost/Campaigns/Metrics.php
+15
-22
Onchain.php
Core/Boost/Campaigns/Payments/Onchain.php
+56
-2
Payment.php
Core/Boost/Campaigns/Payments/Payment.php
+2
-2
Minds.php
Core/Minds.php
+1
-0
No files found.
Controllers/api/v2/analytics/views.php
View file @
130b7876
...
...
@@ -48,6 +48,9 @@ class views implements Interfaces\Api
->
setCampaign
(
$campaign
)
->
increment
();
$campaignsManager
->
onImpression
(
$campaign
);
// NOTE: Campaigns have a _single_ entity, for now. Refactor this when we support multiple
// Ideally, we should use a composite URN, like: urn:campaign-entity:100000321:(urn:activity:100000500)
foreach
(
$campaign
->
getEntityUrns
()
as
$entityUrn
)
{
...
...
This diff is collapsed.
Click to expand it.
Core/Blockchain/Transactions/Manager.php
View file @
130b7876
...
...
@@ -169,17 +169,21 @@ class Manager
/**
* Adds a transaction to the queue
* @param $transaction
* @param bool $handleEvents
*/
public
function
add
(
$transaction
)
public
function
add
(
$transaction
,
$handleEvents
=
true
)
{
$this
->
repo
->
add
(
$transaction
);
$this
->
queue
->
setQueue
(
"BlockchainTransactions"
)
->
send
([
'user_guid'
=>
$transaction
->
getUserGuid
(),
'timestamp'
=>
$transaction
->
getTimestamp
(),
'wallet_address'
=>
$transaction
->
getWalletAddress
(),
'tx'
=>
$transaction
->
getTx
(),
]);
if
(
$handleEvents
)
{
$this
->
queue
->
setQueue
(
"BlockchainTransactions"
)
->
send
([
'user_guid'
=>
$transaction
->
getUserGuid
(),
'timestamp'
=>
$transaction
->
getTimestamp
(),
'wallet_address'
=>
$transaction
->
getWalletAddress
(),
'tx'
=>
$transaction
->
getTx
(),
]);
}
}
/**
...
...
This diff is collapsed.
Click to expand it.
Core/Boost/Campaigns/Delegates/PaymentsDelegate.php
View file @
130b7876
...
...
@@ -9,6 +9,7 @@ namespace Minds\Core\Boost\Campaigns\Delegates;
use
Exception
;
use
Minds\Core\Boost\Campaigns\Campaign
;
use
Minds\Core\Boost\Campaigns\CampaignException
;
use
Minds\Core\Boost\Campaigns\Metrics
;
use
Minds\Core\Boost\Campaigns\Payments
;
use
Minds\Core\Boost\Campaigns\Payments\Payment
;
use
Minds\Core\Config
;
...
...
@@ -22,18 +23,25 @@ class PaymentsDelegate
/** @var Payments\Onchain */
protected
$onchainPayments
;
/** @var Metrics */
protected
$metrics
;
/**
* PaymentsDelegate constructor.
* @param Config $config
* @param Payments\Onchain $onchainPayments
* @param Metrics $metrics
* @throws Exception
*/
public
function
__construct
(
$config
=
null
,
$onchainPayments
=
null
$onchainPayments
=
null
,
$metrics
=
null
)
{
$this
->
config
=
$config
?:
Di
::
_
()
->
get
(
'Config'
);
$this
->
onchainPayments
=
$onchainPayments
?:
new
Payments\Onchain
();
$this
->
metrics
=
$metrics
?:
new
Metrics
();
}
/**
...
...
@@ -47,7 +55,14 @@ class PaymentsDelegate
// NOTE: Do not spec test. Individually test the other methods.
$this
->
validateBudget
(
$campaign
);
$this
->
registerCampaignPayment
(
$campaign
,
$paymentPayload
);
if
(
!
$paymentPayload
)
{
throw
new
CampaignException
(
'Missing payment'
);
}
$this
->
pay
(
$campaign
,
$paymentPayload
);
$this
->
validatePayments
(
$campaign
);
$campaign
=
$this
->
updateImpressionsByCpm
(
$campaign
);
...
...
@@ -69,7 +84,12 @@ class PaymentsDelegate
->
setBudgetType
(
$campaign
->
getBudgetType
());
$this
->
validateBudget
(
$campaignRef
);
$this
->
registerCampaignPayment
(
$campaignRef
,
$paymentPayload
);
if
(
$paymentPayload
)
{
// TODO: This looks wrong, we should act upon campaign, not campaignRef
$this
->
pay
(
$campaignRef
,
$paymentPayload
);
$this
->
validatePayments
(
$campaignRef
);
}
$campaign
=
$this
->
updateImpressionsByCpm
(
$campaign
);
...
...
@@ -79,14 +99,21 @@ class PaymentsDelegate
/**
* @param Campaign $campaign
* @return Campaign
* @throws CampaignException
*/
public
function
onStateChange
(
Campaign
$campaign
)
{
// NOTE: Do not spec test. Individually test the other methods.
// TODO: Check that campaign is in a final complete or incomplete status (revoked/rejected)
// TODO: Refund!
// TODO: Store refund info onto Campaign/Boost metadata
$isFinished
=
in_array
(
$campaign
->
getDeliveryStatus
(),
[
Campaign
::
REJECTED_STATUS
,
Campaign
::
REVOKED_STATUS
,
Campaign
::
COMPLETED_STATUS
]);
if
(
$isFinished
)
{
$this
->
refund
(
$campaign
);
}
return
$campaign
;
}
...
...
@@ -109,18 +136,25 @@ class PaymentsDelegate
return
$campaign
;
}
/**
* @param Campaign $campaign
* @return Campaign
*/
public
function
validatePayments
(
Campaign
$campaign
)
{
// TODO: Validate all payments
return
$campaign
;
}
/**
* @param Campaign $campaign
* @param mixed $payload
* @return Campaign
* @throws CampaignException
*/
public
function
registerCampaignPayment
(
Campaign
$campaign
,
$payload
)
public
function
pay
(
Campaign
$campaign
,
$payload
)
{
if
(
!
$payload
)
{
return
$campaign
;
}
switch
(
$campaign
->
getBudgetType
())
{
case
'tokens'
:
if
(
!
$payload
||
!
$payload
[
'txHash'
]
||
!
$payload
[
'address'
]
||
!
$payload
[
'amount'
])
{
...
...
@@ -133,7 +167,7 @@ class PaymentsDelegate
->
setCampaignGuid
(
$campaign
->
getGuid
())
->
setTx
(
$payload
[
'txHash'
])
->
setSource
(
$payload
[
'address'
])
->
setAmount
(
$payload
[
'amount'
])
->
setAmount
(
(
double
)
$payload
[
'amount'
])
->
setTimeCreated
(
time
());
try
{
...
...
@@ -153,6 +187,86 @@ class PaymentsDelegate
return
$campaign
;
}
/**
* @param Campaign $campaign
* @return Campaign
* @throws CampaignException
* @throws Exception
*/
public
function
refund
(
Campaign
$campaign
)
{
$latestPaymentSource
=
''
;
// Sum up all payments
$paid
=
0
;
foreach
(
$campaign
->
getPayments
()
as
$payment
)
{
// Sum!
$paid
+=
$payment
->
getAmount
();
if
(
$payment
->
getAmount
()
>
0
&&
$payment
->
getSource
())
{
// Grab the latest wallet used by campaign's owner
$latestPaymentSource
=
$payment
->
getSource
();
}
}
// If amount is < 0.1 (minimum fraction), don't refund
if
(
$paid
<=
0.1
)
{
return
$campaign
;
}
// Grab a fresh count of impressions met
$impressionsMet
=
$this
->
metrics
->
setCampaign
(
$campaign
)
->
get
();
// Calculate the cost of the impressions met
$cost
=
(
$impressionsMet
/
1000
)
*
$campaign
->
cpm
();
// Calculate the amount to be refunded
$amount
=
$paid
-
$cost
;
// If amount is < 0.1 (minimum fraction), don't refund
if
(
$amount
<
0.1
)
{
return
$campaign
;
}
// Execute refund
switch
(
$campaign
->
getBudgetType
())
{
case
'tokens'
:
$payment
=
new
Payment
();
$payment
->
setOwnerGuid
(
$campaign
->
getOwnerGuid
())
->
setCampaignGuid
(
$campaign
->
getGuid
())
->
setSource
(
$latestPaymentSource
)
->
setAmount
(
-
$amount
)
->
setTimeCreated
(
time
());
try
{
$this
->
onchainPayments
->
refund
(
$payment
);
}
catch
(
Exception
$e
)
{
throw
new
CampaignException
(
"Error registering refund:
{
$e
->
getMessage
()
}
"
);
}
$campaign
->
pushPayment
(
$payment
);
break
;
default
:
throw
new
CampaignException
(
'Unknown budget type'
);
}
return
$campaign
;
}
/**
* @param Campaign $campaign
* @param Payment $paymentRef
...
...
This diff is collapsed.
Click to expand it.
Core/Boost/Campaigns/Metrics.php
View file @
130b7876
...
...
@@ -7,16 +7,12 @@
namespace
Minds\Core\Boost\Campaigns
;
use
Exception
;
use
Minds\Common\Urn
;
use
Minds\Core\Counters\Manager
as
Counters
;
use
Minds\Core\Di\Di
;
use
Minds\Core\Entities\Resolver
;
class
Metrics
{
/** @var Manager */
protected
$manager
;
/** @var Counters */
protected
$counters
;
...
...
@@ -28,35 +24,27 @@ class Metrics
/**
* Metrics constructor.
* @param Manager $manager
* @param Counters $counters
* @param Resolver $resolver
* @throws Exception
*/
public
function
__construct
(
$manager
=
null
,
$counters
=
null
,
$resolver
=
null
)
{
$this
->
manager
=
$manager
?:
new
Manager
();
$this
->
counters
=
$counters
?:
Di
::
_
()
->
get
(
'Counters'
);
$this
->
resolver
=
$resolver
?:
new
Resolver
();
}
/**
* @param Campaign
|Urn|string
$campaign
* @param Campaign $campaign
* @return Metrics
* @throws Exception
*/
public
function
setCampaign
(
$campaign
)
public
function
setCampaign
(
Campaign
$campaign
)
{
if
(
is_object
(
$campaign
)
&&
$campaign
instanceof
Campaign
)
{
$this
->
campaign
=
$campaign
;
}
else
{
$this
->
campaign
=
$this
->
manager
->
get
((
string
)
$campaign
);
}
$this
->
campaign
=
$campaign
;
return
$this
;
}
...
...
@@ -80,10 +68,6 @@ class Metrics
->
setMetric
(
'boost_impressions'
)
->
increment
();
// Pass down impressions update to manager
$this
->
manager
->
onImpression
(
$this
->
campaign
);
// Increment entity counters
// NOTE: Campaigns have a _single_ entity, for now. Refactor this when we support multiple
// Ideally, we should use a composite URN, like: urn:campaign-entity:100000321:(urn:activity:100000500)
...
...
@@ -105,15 +89,24 @@ class Metrics
}
/**
* @return
Campaign
* @return
int
* @throws Exception
*/
public
function
syncImpressionsM
et
()
public
function
g
et
()
{
$count
=
$this
->
counters
return
$this
->
counters
->
setEntityGuid
(
$this
->
campaign
->
getGuid
())
->
setMetric
(
'boost_impressions'
)
->
get
(
false
);
}
/**
* @return Campaign
* @throws Exception
*/
public
function
syncImpressionsMet
()
{
$count
=
$this
->
get
();
$this
->
campaign
->
setImpressionsMet
(
$count
);
...
...
This diff is collapsed.
Click to expand it.
Core/Boost/Campaigns/Payments/Onchain.php
View file @
130b7876
...
...
@@ -10,7 +10,6 @@ use Exception;
use
Minds\Core\Blockchain\Services\Ethereum
;
use
Minds\Core\Blockchain\Transactions\Manager
as
TransactionsManager
;
use
Minds\Core\Blockchain\Transactions\Transaction
;
use
Minds\Core\Boost\Campaigns\Campaign
;
use
Minds\Core\Config
;
use
Minds\Core\Di\Di
;
use
Minds\Core\Util\BigNumber
;
...
...
@@ -57,7 +56,7 @@ class Onchain
$transaction
->
setTx
(
$payment
->
getTx
())
->
setContract
(
'boost_campaign'
)
->
setAmount
((
string
)
BigNumber
::
toPlain
(
$payment
->
getAmount
(),
18
))
->
setAmount
((
string
)
BigNumber
::
toPlain
(
$payment
->
getAmount
(),
18
)
->
neg
()
)
->
setWalletAddress
(
$payment
->
getSource
())
->
setTimestamp
(
$payment
->
getTimeCreated
())
->
setUserGuid
(
$payment
->
getOwnerGuid
())
...
...
@@ -70,4 +69,59 @@ class Onchain
return
true
;
}
/**
* @param Payment $payment
* @return Payment
* @throws Exception
*/
public
function
refund
(
Payment
$payment
)
{
$token
=
$this
->
config
->
get
(
'blockchain'
)[
'token_address'
];
$wallet
=
$this
->
config
->
get
(
'blockchain'
)[
'contracts'
][
'boost_campaigns'
][
'wallet_address'
]
??
null
;
$walletKey
=
$this
->
config
->
get
(
'blockchain'
)[
'contracts'
][
'boost_campaigns'
][
'wallet_pkey'
]
??
null
;
if
(
!
$token
)
{
throw
new
Exception
(
'Invalid token contract address used for refund'
);
}
elseif
(
!
$wallet
||
!
$walletKey
)
{
throw
new
Exception
(
'Invalid Boost Campaigns wallet address used as refund source'
);
}
elseif
(
!
$payment
->
getSource
())
{
throw
new
Exception
(
'Invalid Boost Campaign refund destination wallet address'
);
}
elseif
(
$payment
->
getAmount
()
>
0
)
{
throw
new
Exception
(
'Refunds can only happen on negative payment amounts'
);
}
$txWeiAmount
=
BigNumber
::
toPlain
(
$payment
->
getAmount
(),
18
)
->
neg
();
$refundTx
=
$this
->
eth
->
sendRawTransaction
(
$walletKey
,
[
'from'
=>
$wallet
,
'to'
=>
$token
,
'gasLimit'
=>
BigNumber
::
_
(
4612388
)
->
toHex
(
true
),
'gasPrice'
=>
BigNumber
::
_
(
10000000000
)
->
toHex
(
true
),
'data'
=>
$this
->
eth
->
encodeContractMethod
(
'transfer(address,uint256)'
,
[
$payment
->
getSource
(),
$txWeiAmount
->
toHex
(
true
),
]),
]);
$payment
->
setTx
(
$refundTx
);
$transaction
=
new
Transaction
();
$transaction
->
setTx
(
$payment
->
getTx
())
->
setContract
(
'boost_campaign'
)
->
setAmount
((
string
)
$txWeiAmount
)
->
setWalletAddress
(
$payment
->
getSource
())
->
setTimestamp
(
$payment
->
getTimeCreated
())
->
setUserGuid
(
$payment
->
getOwnerGuid
())
->
setData
([
'payment'
=>
$payment
->
export
(),
]);
$this
->
repository
->
add
(
$payment
);
$this
->
txManager
->
add
(
$transaction
,
false
);
return
$payment
;
}
}
This diff is collapsed.
Click to expand it.
Core/Boost/Campaigns/Payments/Payment.php
View file @
130b7876
...
...
@@ -20,8 +20,8 @@ use Minds\Traits\MagicAttributes;
* @method Payment setTx(string $tx)
* @method string getSource()
* @method Payment setSource(string $source)
* @method
string
getAmount()
* @method Payment setAmount(
string
$amount)
* @method
double
getAmount()
* @method Payment setAmount(
double
$amount)
* @method int getTimeCreated()
* @method Payment setTimeCreated(int $timeCreated)
*/
...
...
This diff is collapsed.
Click to expand it.
Core/Minds.php
View file @
130b7876
...
...
@@ -66,6 +66,7 @@ class Minds extends base
(
new
Config\ConfigProvider
())
->
register
();
(
new
OAuth\OAuthProvider
())
->
register
();
(
new
Sessions\SessionsProvider
())
->
register
();
(
new
Counters\CountersProvider
())
->
register
();
(
new
Boost\BoostProvider
())
->
register
();
(
new
Data\DataProvider
())
->
register
();
//(new Core\Notification\NotificationProvider())->register();
...
...
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment