@@ -32,7 +32,8 @@ function isAssetMatch(
3232}
3333
3434// Scan the transaction's operations for a payment that matches all expected details.
35- // Supports both `payment` and `create_account` (XLM-only) operation types.
35+ // Supports `payment`, `create_account` (XLM-only), `path_payment_strict_send`,
36+ // and `path_payment_strict_receive` operation types.
3637async function validatePaymentDetails (
3738 server : Horizon . Server ,
3839 txHash : string ,
@@ -69,6 +70,38 @@ async function validatePaymentDetails(
6970 return true ;
7071 }
7172 }
73+
74+ // Path payments: the destination asset and amount received are what matter
75+ // for the recipient, not the source asset the sender used.
76+ if (
77+ op . type === "path_payment_strict_send" ||
78+ op . type === "path_payment_strict_receive"
79+ ) {
80+ const p = op as unknown as {
81+ to : string ;
82+ // path_payment_strict_send: amount received by destination
83+ destination_amount ?: string ;
84+ // path_payment_strict_receive: the exact amount the destination receives
85+ amount ?: string ;
86+ asset_type : string ;
87+ asset_code ?: string ;
88+ asset_issuer ?: string ;
89+ } ;
90+ // The received amount field differs between the two op types
91+ const receivedAmount =
92+ op . type === "path_payment_strict_receive"
93+ ? p . amount
94+ : p . destination_amount ;
95+
96+ if (
97+ p . to === expected . recipientAddress &&
98+ receivedAmount !== undefined &&
99+ parseFloat ( receivedAmount ) === parseFloat ( expected . amount ) &&
100+ isAssetMatch ( p , expected . assetCode , expected . assetIssuer )
101+ ) {
102+ return true ;
103+ }
104+ }
72105 }
73106
74107 return false ;
0 commit comments