55using TonLibDotNet . Types ;
66using TonLibDotNet . Types . Smc ;
77using TonLibDotNet . Utils ;
8+ using System . Diagnostics . CodeAnalysis ;
89
910namespace TonLibDotNet . Recipes
1011{
@@ -28,6 +29,11 @@ public partial class Tep74Jettons
2829 /// </summary>
2930 private const int OPBurn = 0x595f07bc ;
3031
32+ /// <summary>
33+ /// From <see href="https://github.com/ton-blockchain/token-contract/blob/main/ft/op-codes.fc">op-codes.fc</see>
34+ /// </summary>
35+ private const int OPTransferNotification = 0x7362d09c ;
36+
3137 public static readonly Tep74Jettons Instance = new ( ) ;
3238
3339 /// <summary>
@@ -264,5 +270,62 @@ public Message CreateBurnMessage(
264270 SendMode = DefaultSendMode ,
265271 } ;
266272 }
273+
274+ /// <summary>
275+ /// Checks if incoming message is a Transfer Notification, and parses it.
276+ /// </summary>
277+ /// <param name="msg">Incoming transaction message.</param>
278+ /// <param name="jettonWalletAddress">Address of jetton wallet who sent coins (compare with your known jetton wallet addresses to know what jetton has arrived).</param>
279+ /// <param name="queryId">Request number.</param>
280+ /// <param name="userWalletAddress">Address of user (master wallet) who sent jettons.</param>
281+ /// <param name="amount">Amount of jettons to burn <b>in elementary units</b>.</param>
282+ /// <param name="forwardPayload">Optional custom data.</param>
283+ /// <returns>True when message is a jetton transfer notification message and it has been parsed succesfully, false otherwise.</returns>
284+ /// <seealso href="https://github.com/ton-blockchain/TEPs/blob/master/text/0074-jettons-standard.md#1-transfer">Transfer message in TEP</seealso>
285+ public bool TryParseJettonTransferNotification (
286+ TonLibDotNet . Types . Raw . Message ? msg ,
287+ [ NotNullWhen ( true ) ] out string ? jettonWalletAddress ,
288+ [ NotNullWhen ( true ) ] out long ? queryId ,
289+ [ NotNullWhen ( true ) ] out string ? userWalletAddress ,
290+ [ NotNullWhen ( true ) ] out BigInteger ? amount ,
291+ out Cell ? forwardPayload )
292+ {
293+ jettonWalletAddress = default ;
294+ queryId = default ;
295+ userWalletAddress = default ;
296+ amount = default ;
297+ forwardPayload = default ;
298+
299+ if ( msg is null || msg . MsgData is not DataRaw data || string . IsNullOrWhiteSpace ( data . Body ) )
300+ {
301+ return false ;
302+ }
303+
304+ jettonWalletAddress = msg . Source . Value ;
305+
306+ var slice = Boc . ParseFromBase64 ( data . Body ) . RootCells [ 0 ] . BeginRead ( ) ;
307+
308+ if ( ! slice . TryCanLoad ( 32 ) )
309+ {
310+ return false ;
311+ }
312+
313+ var op = slice . LoadInt ( 32 ) ;
314+ if ( op != OPTransferNotification )
315+ {
316+ return false ;
317+ }
318+
319+ queryId = slice . LoadLong ( 64 ) ;
320+ amount = slice . LoadCoinsToBigInt ( ) ;
321+ userWalletAddress = slice . LoadAddressIntStd ( ) ;
322+
323+ if ( slice . TryCanLoadRef ( ) )
324+ {
325+ forwardPayload = slice . LoadRef ( ) ;
326+ }
327+
328+ return true ;
329+ }
267330 }
268331}
0 commit comments