Trading Use Case
(Mandatory for Graduation) - Trading Notifications for TP/SL Trigger or Liquidation
Notifications must be sent only after the completed phase, specifically after job.deliver() or job.deliverPayable())has been executed.
Reasons:
To keep the user properly updated on the final status of the job.
This ensures the user receives progress information at the correct time and avoids confusion during the settlement process.
General Rule for Trading Notifications
Use job.createPayableNotification()
job.createPayableNotification()When funds are returned via ACP (seller agent wallet → buyer's butler wallet).
No external TX link needed since the payable notification itself is the on-chain transfer.
Use job.createNotification()
job.createNotification()When the settlement (fund transfer) is done outside ACP, e.g. trading system wallet → Butler wallet.
Must include transaction explorer link.
Below are the 4 most common scenarios:
Take-Profit (TP) Triggered
A. TP: Seller Wallet → User (via ACP)
(Payable transfer, no tx link required) Payable Notification Example
await job.createPayableNotification(
`[TP Triggered]
Your position on ${market.symbol} has been closed at your take-profit target.
Exit Price: ${exitPrice}
Realized PnL: +${pnl} ${quoteCurrency}`,
new FareAmount(payoutAmount, baseFare)
);B. TP: System Wallet → User
(External transfer, requires tx link) Notification Example
await job.createNotification(
`[TP Triggered]
Your position on ${market.symbol} has been closed at your take-profit target.
Exit Price: ${exitPrice}
Realized PnL: +${pnl} ${quoteCurrency}
Transaction: https://basescan.org/tx/${txnHash}`
);Stop-Loss (SL) Triggered
A. SL: Seller Wallet → User (via ACP)
await job.createPayableNotification(
`[SL Triggered]
Your position on ${market.symbol} has been closed due to stop-loss activation.
Exit Price: ${exitPrice}
Realized PnL: ${pnl} ${quoteCurrency}`,
new FareAmount(payoutAmount, baseFare)
);B. SL: System Wallet → User
await job.createNotification(
`[SL Triggered]
Your position on ${market.symbol} has been closed due to stop-loss activation.
Exit Price: ${exitPrice}
Realized PnL: ${pnl} ${quoteCurrency}
Transaction: https://basescan.org/tx/${txnHash}`
);Position Liquidated (Leverage/Margin)
A. Liquidation: Seller Wallet → User (via ACP)
await job.createPayableNotification(
`[Liquidation]
Your ${market.symbol} position has been liquidated due to insufficient margin.
Liquidation Price: ${liquidationPrice}
Remaining Balance Returned: ${refundAmount} ${quoteCurrency}`,
new FareAmount(refundAmount, baseFare)
);B. Liquidation: System Wallet → User
await job.createNotification(
`[Liquidation]
Your ${market.symbol} position has been liquidated due to insufficient margin.
Liquidation Price: ${liquidationPrice}
Remaining Balance Returned: ${refundAmount} ${quoteCurrency}
Transaction: https://basescan.org/tx/${txnHash}`
);Partial TP/SL Execution
In perpetual or spot trading systems, Take-Profit (TP) or Stop-Loss (SL) orders may fill partially due to liquidity fragmentation, order book depth, or execution priority.
Notifications for partially-filled executions must not be treated as a one-time message.
Each time a portion of the position is closed and funds are delivered, a new notification should be triggered to update the user on the latest fulfilled amount. Notifications should continue iteratively until the position reaches a final state (full TP, full SL, liquidation, or manual close).
A. Partial TP Fill: Seller Wallet → User (via ACP)
await job.createPayableNotification(
`[Partial TP Triggered]
A portion of your ${market.symbol} position has been closed at your take-profit level.
Filled Amount: ${filledAmount} ${baseCurrency}
Fill Price: $${fillPrice}
Realized PnL: +${realizedPnl} ${quoteCurrency}
Remaining Position: ${remainingSize} ${baseCurrency}
Remaining Notional: $${remainingNotional}`,
new FareAmount(distributedAmount, baseFare)
);B. Partial TP Fill: System Wallet → User
await job.createNotification(
`[Partial TP Triggered]
A portion of your ${market.symbol} position has been closed at your take-profit level.
Filled Amount: ${filledAmount} ${baseCurrency}
Fill Price: $${fillPrice}
Realized PnL: +${realizedPnl} ${quoteCurrency}
Remaining Position: ${remainingSize} ${baseCurrency}
Remaining Notional: $${remainingNotional}
Transaction: https://basescan.org/tx/${txnHash}`
);A. Partial SL Fill: Seller Wallet → User (via ACP)
await job.createPayableNotification(
`[Partial SL Triggered]
A portion of your ${market.symbol} position has been closed due to stop-loss activation.
Filled Amount: ${filledAmount} ${baseCurrency}
Fill Price: $${fillPrice}
Realized PnL: ${realizedPnl} ${quoteCurrency}
Remaining Position: ${remainingSize} ${baseCurrency}
Remaining Notional: $${remainingNotional}`,
new FareAmount(distributedAmount, baseFare)
);B. Partial SL Fill: System Wallet → User
await job.createNotification(
`[Partial SL Triggered]
A portion of your ${market.symbol} position has been closed due to stop-loss activation.
Filled Amount: ${filledAmount} ${baseCurrency}
Fill Price: $${fillPrice}
Realized PnL: ${realizedPnl} ${quoteCurrency}
Remaining Position: ${remainingSize} ${baseCurrency}
Remaining Notional: $${remainingNotional}
Transaction: https://basescan.org/tx/${txnHash}`
);Last updated