diff --git a/solana/data/raydiumLiquidityPoolV4_swap_1.json b/solana/data/raydiumLiquidityPoolV4_swap_1.json index fa277c7..b920089 100644 --- a/solana/data/raydiumLiquidityPoolV4_swap_1.json +++ b/solana/data/raydiumLiquidityPoolV4_swap_1.json @@ -1,8 +1,8 @@ [ { - "blockTime": 1727633484, + "blockTime": 1728015997, "meta": { - "computeUnitsConsumed": 41939, + "computeUnitsConsumed": 41147, "err": null, "fee": 1005000, "innerInstructions": [ @@ -11,21 +11,21 @@ "instructions": [ { "accounts": [ - 13, - 6, + 1, + 5, 0 ], - "data": "3s8MpY1f2PEo", + "data": "3Dc8EpW7Kr3R", "programIdIndex": 16, "stackHeight": 2 }, { "accounts": [ - 5, - 1, + 6, + 13, 26 ], - "data": "3QE7viLoNfDh", + "data": "3a5LxFwgWKbD", "programIdIndex": 16, "stackHeight": 2 } @@ -56,43 +56,43 @@ "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 3443 of 99550 compute units", "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success", "Program 675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8 invoke [1]", - "Program log: ray_log: A+E1LKzCAAAAHPYaDgAAAAABAAAAAAAAAOE1LKzCAAAAPfnuixQAAABHSrRr57wAAEBhCRUAAAAA", + "Program log: ray_log: AwDh9QUAAAAAFZl5bQgAAAACAAAAAAAAAADh9QUAAAAAr5cOfjEAAAB+AyCkd1MAAHtCtQUKAAAA", "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]", "Program log: Instruction: Transfer", - "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 4645 of 77179 compute units", + "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 4736 of 77972 compute units", "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success", "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]", "Program log: Instruction: Transfer", - "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 4736 of 69553 compute units", + "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 4645 of 70255 compute units", "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success", - "Program 675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8 consumed 32367 of 96107 compute units", + "Program 675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8 consumed 31575 of 96107 compute units", "Program 675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8 success", "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [1]", "Program log: Instruction: CloseAccount", - "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 2915 of 63740 compute units", + "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 2915 of 64532 compute units", "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success", "Program 11111111111111111111111111111111 invoke [1]", "Program 11111111111111111111111111111111 success", "Program 4pP8eDKACuV7T2rbFPE8CHxGKDYAzSdRsdMsGvz2k4oc invoke [1]", - "Program log: Received timestamp: 1727633504", - "Program log: Current timestamp: 1727633484", + "Program log: Received timestamp: 1728016016", + "Program log: Current timestamp: 1728015997", "Program log: The provided timestamp is valid.", - "Program 4pP8eDKACuV7T2rbFPE8CHxGKDYAzSdRsdMsGvz2k4oc consumed 1661 of 60675 compute units", + "Program 4pP8eDKACuV7T2rbFPE8CHxGKDYAzSdRsdMsGvz2k4oc consumed 1661 of 61467 compute units", "Program 4pP8eDKACuV7T2rbFPE8CHxGKDYAzSdRsdMsGvz2k4oc success", "Program 11111111111111111111111111111111 invoke [1]", "Program 11111111111111111111111111111111 success", "Program HQ2UUt18uJqKaQFJhgV9zaTdQxUZjNrsKFgoEDquBkcx invoke [1]", "Program log: Powered by bloXroute Trader Api", - "Program HQ2UUt18uJqKaQFJhgV9zaTdQxUZjNrsKFgoEDquBkcx consumed 803 of 58864 compute units", + "Program HQ2UUt18uJqKaQFJhgV9zaTdQxUZjNrsKFgoEDquBkcx consumed 803 of 59656 compute units", "Program HQ2UUt18uJqKaQFJhgV9zaTdQxUZjNrsKFgoEDquBkcx success" ], "postBalances": [ - 6554573528, + 1798544928, 0, 6124800, 23357760, 16258560, - 87896143341, + 212670322335, 2039280, 3591360, 457104960, @@ -108,12 +108,12 @@ 0, 1398960, 1141440, - 265173804904, - 171636311320, + 2171689787700, + 235586097093, 1009200, 1141440, - 616503706523, - 5660815704 + 617888496398, + 5660815707 ], "postTokenBalances": [ { @@ -122,28 +122,28 @@ "owner": "5Q544fKrFoe6tsEbD7S8EmxGTJYAKtTVhAW5Q5pge4j1", "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", "uiTokenAmount": { - "amount": "87894104061", + "amount": "212668283055", "decimals": 9, - "uiAmount": 87.894104061, - "uiAmountString": "87.894104061" + "uiAmount": 212.668283055, + "uiAmountString": "212.668283055" } }, { "accountIndex": 6, - "mint": "2CrtdajpSb7DpMRLKP4yMtFLbCsWZjMkEvgSTf4Ypump", + "mint": "E8yBUD4AGdxK7MbQEf85oaAvVBuSoRsGCvX2sMxSpump", "owner": "5Q544fKrFoe6tsEbD7S8EmxGTJYAKtTVhAW5Q5pge4j1", "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", "uiTokenAmount": { - "amount": "208538242678824", + "amount": "91730274337027", "decimals": 6, - "uiAmount": 208538242.678824, - "uiAmountString": "208538242.678824" + "uiAmount": 91730274.337027, + "uiAmountString": "91730274.337027" } }, { "accountIndex": 11, "mint": "So11111111111111111111111111111111111111112", - "owner": "4Q9Epf566RJjUu9akgLv4badwC5u9Y75r9mp97xEw3sS", + "owner": "42txuiS2zXURYVQUcGbYEfX1aWDTAuvRHyQ16AZqgAoX", "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", "uiTokenAmount": { "amount": "0", @@ -154,8 +154,8 @@ }, { "accountIndex": 12, - "mint": "2CrtdajpSb7DpMRLKP4yMtFLbCsWZjMkEvgSTf4Ypump", - "owner": "4Q9Epf566RJjUu9akgLv4badwC5u9Y75r9mp97xEw3sS", + "mint": "E8yBUD4AGdxK7MbQEf85oaAvVBuSoRsGCvX2sMxSpump", + "owner": "42txuiS2zXURYVQUcGbYEfX1aWDTAuvRHyQ16AZqgAoX", "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", "uiTokenAmount": { "amount": "0", @@ -166,24 +166,24 @@ }, { "accountIndex": 13, - "mint": "2CrtdajpSb7DpMRLKP4yMtFLbCsWZjMkEvgSTf4Ypump", - "owner": "Do3UdALe5F7NRXB4uYcBzZtCbAt8ssu4a5kGZVucKhC5", + "mint": "E8yBUD4AGdxK7MbQEf85oaAvVBuSoRsGCvX2sMxSpump", + "owner": "ECvj86nDupkVh1cDgxrJw3zJkw3ahcDiVB3pPTbpskjD", "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", "uiTokenAmount": { - "amount": "0", + "amount": "43045438075", "decimals": 6, - "uiAmount": null, - "uiAmountString": "0" + "uiAmount": 43045.438075, + "uiAmountString": "43045.438075" } } ], "preBalances": [ - 6206795174, + 1901449928, 0, 6124800, 23357760, 16258560, - 88249079597, + 212570322335, 2039280, 3591360, 457104960, @@ -199,12 +199,12 @@ 0, 1398960, 1141440, - 265170652002, - 171635311320, + 2171688887700, + 235585097093, 1009200, 1141440, - 616503706523, - 5660815704 + 617888496398, + 5660815707 ], "preTokenBalances": [ { @@ -213,28 +213,28 @@ "owner": "5Q544fKrFoe6tsEbD7S8EmxGTJYAKtTVhAW5Q5pge4j1", "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", "uiTokenAmount": { - "amount": "88247040317", + "amount": "212568283055", "decimals": 9, - "uiAmount": 88.247040317, - "uiAmountString": "88.247040317" + "uiAmount": 212.568283055, + "uiAmountString": "212.568283055" } }, { "accountIndex": 6, - "mint": "2CrtdajpSb7DpMRLKP4yMtFLbCsWZjMkEvgSTf4Ypump", + "mint": "E8yBUD4AGdxK7MbQEf85oaAvVBuSoRsGCvX2sMxSpump", "owner": "5Q544fKrFoe6tsEbD7S8EmxGTJYAKtTVhAW5Q5pge4j1", "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", "uiTokenAmount": { - "amount": "207702130444871", + "amount": "91773319775102", "decimals": 6, - "uiAmount": 207702130.444871, - "uiAmountString": "207702130.444871" + "uiAmount": 91773319.775102, + "uiAmountString": "91773319.775102" } }, { "accountIndex": 11, "mint": "So11111111111111111111111111111111111111112", - "owner": "4Q9Epf566RJjUu9akgLv4badwC5u9Y75r9mp97xEw3sS", + "owner": "42txuiS2zXURYVQUcGbYEfX1aWDTAuvRHyQ16AZqgAoX", "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", "uiTokenAmount": { "amount": "0", @@ -245,8 +245,8 @@ }, { "accountIndex": 12, - "mint": "2CrtdajpSb7DpMRLKP4yMtFLbCsWZjMkEvgSTf4Ypump", - "owner": "4Q9Epf566RJjUu9akgLv4badwC5u9Y75r9mp97xEw3sS", + "mint": "E8yBUD4AGdxK7MbQEf85oaAvVBuSoRsGCvX2sMxSpump", + "owner": "42txuiS2zXURYVQUcGbYEfX1aWDTAuvRHyQ16AZqgAoX", "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", "uiTokenAmount": { "amount": "0", @@ -257,14 +257,14 @@ }, { "accountIndex": 13, - "mint": "2CrtdajpSb7DpMRLKP4yMtFLbCsWZjMkEvgSTf4Ypump", - "owner": "Do3UdALe5F7NRXB4uYcBzZtCbAt8ssu4a5kGZVucKhC5", + "mint": "E8yBUD4AGdxK7MbQEf85oaAvVBuSoRsGCvX2sMxSpump", + "owner": "ECvj86nDupkVh1cDgxrJw3zJkw3ahcDiVB3pPTbpskjD", "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", "uiTokenAmount": { - "amount": "836112233953", + "amount": "0", "decimals": 6, - "uiAmount": 836112.233953, - "uiAmountString": "836112.233953" + "uiAmount": null, + "uiAmountString": "0" } } ], @@ -273,29 +273,29 @@ "Ok": null } }, - "slot": 292734971, + "slot": 293583913, "transaction": { "message": { "accountKeys": [ - "Do3UdALe5F7NRXB4uYcBzZtCbAt8ssu4a5kGZVucKhC5", - "AgcEC7E1yxeZoRVnAZTmGA86ncrPTqKkBiz1T9F5MxhN", - "9xNtkAhkGNG6fPazLe7ZFmmiJ5Mss37sBx9eoya33o4q", - "FSJ5nF2HH6mCFSD4fBEeJUZaDutTf7NUmqZ73tqU3NZp", - "5ztrMHizPxA6viApPpjNDcjG7YQZch6qqpz293U16VK6", - "2uBUq62d4HcDMTSg9ZuBySw4KGaMZi2mvaWatcXWkj4b", - "4veQuvzFqRiibczQWZj8ZX4QdVLsB4N882b5wBNFxTA8", - "ADep3qDvTT3g5jv5cQ47JNfTmZRh3jpdzydYTsxi2rJ6", - "DycbwPd9Eh7hRmfgQY2Nbw1bbSY3whaLyoja1gwFcf6c", - "BnFxXagcuk3P2Vi5zCNcyRCScnKejkLXY98GfUcTCPTf", - "Bi1q1zMcdbWBxqQFCU1LAd8z7YyP9yebixUxBA7KGDDT", - "416A7C2UwM5ZKQk31oKsNDNTLVKi2oDeiYyUTCmxw5Sg", - "CTnHaCMQg9bchADTyvitsmHvxX4PoBPgPYzYEbmTaR3m", - "D2KYhSJfjgBv92JqJ24VkTsGaEXnyFDe7JBjxuRDdFHZ", + "ECvj86nDupkVh1cDgxrJw3zJkw3ahcDiVB3pPTbpskjD", + "BjN8ABECWCntiBmKe5ZE2R4EJHz7BeovZbEuQxXYjS7X", + "2mF8wbzawjPzDoCiGBqoinbaVxMJAwRm5wQ1dtgSLZdD", + "36QFFB6e8mHKShx3HQ1AbYz8rv3hF3T9K1hG7aHmnsAY", + "AXaq4H9RHKwsAVjj2qD65S8phLoHhfqAKdrtxrj6XyeN", + "GjFUSKqBvA4GZxmjFfLSm496seqy6WUsemTCC2KPdXH4", + "9Y1ecw9HgDLpq6pNbQ94eTgd6qDtiAdVzuX55MuKwS66", + "5srEL3hnZMT49JeZjMCj8DAGPS4jx1xnHfBfKWb3Z1pU", + "B1yZSxEq8sCv5RpisZtg8iiSjHMopsD6h5HqFpmgEzSU", + "9njoyGVu9DPwVwtb4Wtx1Dzwg7b5LBydz6r1sTJJcE5Z", + "8xiEky2Hgp7tG2YJ2HFzbvEhD1VruFVwGXUWpMfLt3Q5", + "HvV92yxUL2719K4atMHbBoFVSBk4jTJ8EZtPwQCzhBjL", + "GQwY85RRE36XPjQ8Ka15Db1tcMRrJXAQRuwYrW5Y1atR", + "CnpqgDSL9hSbS58kffaALXnsp1Vk4U61MZMxRP1tTYz6", "ComputeBudget111111111111111111111111111111", "11111111111111111111111111111111", "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8", - "4Q9Epf566RJjUu9akgLv4badwC5u9Y75r9mp97xEw3sS", + "42txuiS2zXURYVQUcGbYEfX1aWDTAuvRHyQ16AZqgAoX", "4pP8eDKACuV7T2rbFPE8CHxGKDYAzSdRsdMsGvz2k4oc", "HQ2UUt18uJqKaQFJhgV9zaTdQxUZjNrsKFgoEDquBkcx" ], @@ -343,7 +343,7 @@ 0, 1 ], - "data": "3ipZWzrGnjtM6QGL2BcZh2zKPDXgZs13zC8eMeu9pfGQ7psPAXK7e23oZ5tPbKnzGY8oBKiisMgWP2Z8PFvproQC8bePpcSeceMSjwbZ9sEMP1eqoyuSBecgsYCesAy1zsVx39EL9YajbD5yE2PJQ8rCRXya4nr8BRa9W1zRe", + "data": "3ipZX1hTggYi7XxCuihpV8b8invHafWfqsoF554zGyjLmrCwryD2UW5YxwHy855ScVRRBHqAqXQX2yMZebj7eTcYJLX2WRU8BYCjXRemZdMyLZzzzoCx4NYZuxhs7zihFjRcJRYU9B2jWVVcbpdv3KbHUXuLhjDwZTGaehKUL", "programIdIndex": 15, "stackHeight": null }, @@ -375,11 +375,11 @@ 11, 12, 18, - 13, 1, + 13, 0 ], - "data": "6PKQZz9QiXKmCCdXSsN45vf", + "data": "5ucmhStLiAKrMXCAhZeWGRV", "programIdIndex": 17, "stackHeight": null }, @@ -398,13 +398,13 @@ 0, 21 ], - "data": "3Bxs41swEv8H3K5Z", + "data": "3Bxs4Tjx12waeTC3", "programIdIndex": 15, "stackHeight": null }, { "accounts": [], - "data": "HA7oZzFRp1d", + "data": "RABq3USsTaX", "programIdIndex": 19, "stackHeight": null }, @@ -424,10 +424,10 @@ "stackHeight": null } ], - "recentBlockhash": "CEkQf7vrQ7g7ej1HqZPcyMgZtjd5bYEWhwSRL6JG4GYs" + "recentBlockhash": "Gso3Ta2yvjTSHKYsrQH7PvZifU2cdraoFS4FP3sHcFbo" }, "signatures": [ - "3aQZsNRUbNXpH54GQEaxFpWZsmL554cYGGtWqqoypz8b6LUDYprbRd9AwgivXRLtFBYCU6MU6e9ANurwP8dCMV6" + "4pAEq48cQsw8VPQ5R3GSXNKS5VdLu5TDTCWuJJ8Bq8uEkohMF87HZMjwfQPQcuvq8bwv8h8HKp7fiNEAi5SKjvyQ" ] }, "version": 0 diff --git a/solana/globals/mint.go b/solana/globals/mint.go index 68c4191..20cea8c 100644 --- a/solana/globals/mint.go +++ b/solana/globals/mint.go @@ -4,3 +4,7 @@ const ( WSOL = "So11111111111111111111111111111111111111112" USDC = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v" ) + +const ( + SOLDecimals = 9 +) diff --git a/solana/parser_test.go b/solana/parser_test.go index 7215e9f..ffacae7 100644 --- a/solana/parser_test.go +++ b/solana/parser_test.go @@ -6,6 +6,7 @@ import ( "github.com/0xjeffro/tx-parser/solana/programs/computeBudget" "github.com/0xjeffro/tx-parser/solana/programs/jupiterDCA" "github.com/0xjeffro/tx-parser/solana/programs/pumpfun" + "github.com/0xjeffro/tx-parser/solana/programs/raydiumLiquidityPoolV4" "github.com/0xjeffro/tx-parser/solana/programs/systemProgram" "github.com/0xjeffro/tx-parser/solana/programs/tokenProgram" "github.com/0xjeffro/tx-parser/solana/types" @@ -449,3 +450,53 @@ func TestJupiterDcaCloseDca_0(t *testing.T) { t.Errorf("Error type assertion") } } + +func TestRaydiumLiquidityPoolV4Swap_0(t *testing.T) { + byteValue, err := readJsonFile("data/raydiumLiquidityPoolV4_swap_0.json") + if err != nil { + t.Errorf("Error reading JSON file: %v", err) + } + results, _ := Parser(byteValue) + action := results[0].Actions[4] + + if swapAction, ok := action.(*types.RaydiumLiquidityPoolV4SwapAction); ok { + assert.Equal(t, swapAction.ProgramID, raydiumLiquidityPoolV4.Program) + assert.Equal(t, swapAction.ProgramName, raydiumLiquidityPoolV4.ProgramName) + assert.Equal(t, swapAction.InstructionName, "Swap") + assert.Equal(t, swapAction.Who, "Do3UdALe5F7NRXB4uYcBzZtCbAt8ssu4a5kGZVucKhC5") + assert.Equal(t, swapAction.FromToken, "2CrtdajpSb7DpMRLKP4yMtFLbCsWZjMkEvgSTf4Ypump") + assert.Equal(t, swapAction.FromTokenAmount, uint64(836112233953)) + assert.Equal(t, swapAction.FromTokenDecimals, uint64(6)) + assert.Equal(t, swapAction.ToToken, globals.WSOL) + assert.Equal(t, swapAction.ToTokenAmount, uint64(352936256)) + assert.Equal(t, swapAction.ToTokenDecimals, uint64(globals.SOLDecimals)) + assert.Equal(t, swapAction.MinimumAmountOut, uint64(236647964)) + } else { + t.Errorf("Error type assertion") + } +} + +func TestRaydiumLiquidityPoolV4Swap_1(t *testing.T) { + byteValue, err := readJsonFile("data/raydiumLiquidityPoolV4_swap_1.json") + if err != nil { + t.Errorf("Error reading JSON file: %v", err) + } + results, _ := Parser(byteValue) + action := results[0].Actions[4] + + if swapAction, ok := action.(*types.RaydiumLiquidityPoolV4SwapAction); ok { + assert.Equal(t, swapAction.ProgramID, raydiumLiquidityPoolV4.Program) + assert.Equal(t, swapAction.ProgramName, raydiumLiquidityPoolV4.ProgramName) + assert.Equal(t, swapAction.InstructionName, "Swap") + assert.Equal(t, swapAction.Who, "ECvj86nDupkVh1cDgxrJw3zJkw3ahcDiVB3pPTbpskjD") + assert.Equal(t, swapAction.FromToken, globals.WSOL) + assert.Equal(t, swapAction.FromTokenAmount, uint64(100000000)) + assert.Equal(t, swapAction.FromTokenDecimals, uint64(globals.SOLDecimals)) + assert.Equal(t, swapAction.ToToken, "E8yBUD4AGdxK7MbQEf85oaAvVBuSoRsGCvX2sMxSpump") + assert.Equal(t, swapAction.ToTokenAmount, uint64(43045438075)) + assert.Equal(t, swapAction.ToTokenDecimals, uint64(6)) + assert.Equal(t, swapAction.MinimumAmountOut, uint64(36196423957)) + } else { + t.Errorf("Error type assertion") + } +} diff --git a/solana/programs/raydiumLiquidityPoolV4/meta.go b/solana/programs/raydiumLiquidityPoolV4/meta.go new file mode 100644 index 0000000..44ab8fd --- /dev/null +++ b/solana/programs/raydiumLiquidityPoolV4/meta.go @@ -0,0 +1,6 @@ +package raydiumLiquidityPoolV4 + +const Program = "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8" +const ProgramName = "RaydiumLiquidityPoolV4" + +const SwapDiscriminator = uint8(9) diff --git a/solana/programs/raydiumLiquidityPoolV4/parsers/index.go b/solana/programs/raydiumLiquidityPoolV4/parsers/index.go new file mode 100644 index 0000000..60b4c31 --- /dev/null +++ b/solana/programs/raydiumLiquidityPoolV4/parsers/index.go @@ -0,0 +1,28 @@ +package parsers + +import ( + "github.com/0xjeffro/tx-parser/solana/programs/raydiumLiquidityPoolV4" + "github.com/0xjeffro/tx-parser/solana/types" + "github.com/mr-tron/base58" +) + +func InstructionRouter(result *types.ParsedResult, instruction types.Instruction, instructionIdx int) (types.Action, error) { + data := instruction.Data + decode, err := base58.Decode(data) + if err != nil { + return nil, err + } + discriminator := decode[0] + switch discriminator { + case raydiumLiquidityPoolV4.SwapDiscriminator: + return SwapParser(result, instruction, instructionIdx, decode) + default: + return types.UnknownAction{ + BaseAction: types.BaseAction{ + ProgramID: result.AccountList[instruction.ProgramIDIndex], + ProgramName: raydiumLiquidityPoolV4.ProgramName, + InstructionName: "Unknown", + }, + }, nil + } +} diff --git a/solana/programs/raydiumLiquidityPoolV4/parsers/swap.go b/solana/programs/raydiumLiquidityPoolV4/parsers/swap.go new file mode 100644 index 0000000..a55b797 --- /dev/null +++ b/solana/programs/raydiumLiquidityPoolV4/parsers/swap.go @@ -0,0 +1,87 @@ +package parsers + +import ( + "github.com/0xjeffro/tx-parser/solana/globals" + "github.com/0xjeffro/tx-parser/solana/programs/raydiumLiquidityPoolV4" + "github.com/0xjeffro/tx-parser/solana/programs/tokenProgram" + TokenProgramParsers "github.com/0xjeffro/tx-parser/solana/programs/tokenProgram/parsers" + "github.com/0xjeffro/tx-parser/solana/types" + "github.com/near/borsh-go" +) + +type SwapData struct { + Discriminator uint8 + AmountIn uint64 + MinimumAmountOut uint64 +} + +func SwapParser(result *types.ParsedResult, instruction types.Instruction, instructionIdx int, decodedData []byte) (*types.RaydiumLiquidityPoolV4SwapAction, error) { + var swapData SwapData + err := borsh.Deserialize(&swapData, decodedData) + if err != nil { + return nil, err + } + + var fromToken, toToken string = globals.WSOL, globals.WSOL + var fromTokenDecimals, toTokenDecimals uint64 = globals.SOLDecimals, globals.SOLDecimals + + userSourceTokenAccount := result.AccountList[instruction.Accounts[15]] + userDestinationTokenAccount := result.AccountList[instruction.Accounts[16]] + + tokenBalances := append([]types.TokenBalance{}, result.RawTx.Meta.PreTokenBalances[:]...) + tokenBalances = append(tokenBalances, result.RawTx.Meta.PostTokenBalances[:]...) + + for _, tb := range tokenBalances { + tokenAccount := result.AccountList[tb.AccountIndex] + if tokenAccount == userSourceTokenAccount { + fromToken = tb.Mint + fromTokenDecimals = tb.UITokenAmount.Decimals + } else if tokenAccount == userDestinationTokenAccount { + toToken = tb.Mint + toTokenDecimals = tb.UITokenAmount.Decimals + } + } + + var toTokenAmount uint64 + + var associatedInnerInstructions []types.Instruction + for _, innerInstruction := range result.RawTx.Meta.InnerInstructions { + if innerInstruction.Index == instructionIdx { + associatedInnerInstructions = append(associatedInnerInstructions, innerInstruction.Instructions...) + break + } + } + for _, innerInstruction := range associatedInnerInstructions { + if result.AccountList[innerInstruction.ProgramIDIndex] == tokenProgram.Program { + action, err := TokenProgramParsers.InstructionRouter(result, innerInstruction) + if err != nil { + continue + } + transferAction, ok := action.(*types.TokenProgramTransferAction) + if ok { + if transferAction.To == userDestinationTokenAccount { + toTokenAmount = transferAction.Amount + } + } + } + } + + action := types.RaydiumLiquidityPoolV4SwapAction{ + BaseAction: types.BaseAction{ + ProgramID: raydiumLiquidityPoolV4.Program, + ProgramName: raydiumLiquidityPoolV4.ProgramName, + InstructionName: "Swap", + }, + Who: result.AccountList[instruction.Accounts[17]], + FromToken: fromToken, + FromTokenAmount: swapData.AmountIn, + FromTokenDecimals: fromTokenDecimals, + ToToken: toToken, + ToTokenAmount: toTokenAmount, + ToTokenDecimals: toTokenDecimals, + + MinimumAmountOut: swapData.MinimumAmountOut, + } + + return &action, nil +} diff --git a/solana/router.go b/solana/router.go index 3fcbc76..59b1c90 100644 --- a/solana/router.go +++ b/solana/router.go @@ -9,6 +9,8 @@ import ( JupiterDCA "github.com/0xjeffro/tx-parser/solana/programs/jupiterDCA/parsers" "github.com/0xjeffro/tx-parser/solana/programs/pumpfun" PumpfunParsers "github.com/0xjeffro/tx-parser/solana/programs/pumpfun/parsers" + "github.com/0xjeffro/tx-parser/solana/programs/raydiumLiquidityPoolV4" + RaydiumLiquidityPoolV4 "github.com/0xjeffro/tx-parser/solana/programs/raydiumLiquidityPoolV4/parsers" "github.com/0xjeffro/tx-parser/solana/programs/systemProgram" SystemProgramParsers "github.com/0xjeffro/tx-parser/solana/programs/systemProgram/parsers" "github.com/0xjeffro/tx-parser/solana/programs/tokenProgram" @@ -16,15 +18,15 @@ import ( "github.com/0xjeffro/tx-parser/solana/types" ) -func router(result *types.ParsedResult, i int) (action types.Action, err error) { +func router(result *types.ParsedResult, instructionIdx int) (action types.Action, err error) { defer func() { if r := recover(); r != nil { err = r.(error) action = nil } }() - programID := result.AccountList[result.RawTx.Transaction.Message.Instructions[i].ProgramIDIndex] - instruction := result.RawTx.Transaction.Message.Instructions[i] + programID := result.AccountList[result.RawTx.Transaction.Message.Instructions[instructionIdx].ProgramIDIndex] + instruction := result.RawTx.Transaction.Message.Instructions[instructionIdx] switch programID { case systemProgram.Program: return SystemProgramParsers.InstructionRouter(result, instruction) @@ -38,6 +40,8 @@ func router(result *types.ParsedResult, i int) (action types.Action, err error) return U6m2CDdhRgParsers.InstructionRouter(result, instruction) case jupiterDCA.Program: return JupiterDCA.InstructionRouter(result, instruction) + case raydiumLiquidityPoolV4.Program: + return RaydiumLiquidityPoolV4.InstructionRouter(result, instruction, instructionIdx) default: return types.UnknownAction{ BaseAction: types.BaseAction{ diff --git a/solana/types/raydiumLiquidityPoolV4Action.go b/solana/types/raydiumLiquidityPoolV4Action.go new file mode 100644 index 0000000..94022ba --- /dev/null +++ b/solana/types/raydiumLiquidityPoolV4Action.go @@ -0,0 +1,14 @@ +package types + +type RaydiumLiquidityPoolV4SwapAction struct { + BaseAction + Who string `json:"who"` + FromToken string `json:"fromToken"` + FromTokenAmount uint64 `json:"fromTokenAmount"` + FromTokenDecimals uint64 `json:"fromTokenDecimals"` + ToToken string `json:"toToken"` + ToTokenAmount uint64 `json:"toTokenAmount"` + ToTokenDecimals uint64 `json:"toTokenDecimals"` + + MinimumAmountOut uint64 `json:"minimumAmountOut"` +}