As nowadays everything is done within thousands of files to make it user (developer) "friendly" (npm and what not) people forget that at the end is one line of code that really matters as all those SDKs at the end do a simple request with a string of data, that's it.

As was needing to implement Solana transactions without any SDK to a new language I tried to see what the raw transaction looks and here is one that seems to be working just fine and easy to understand too:

		curl 'https://mainnet-beta.solana.com' -H 'Content-Type: application/json' --data-raw '{"method":"sendTransaction","jsonrpc":"2.0","params":["AbYyVjpQVNsN2NNGD1FCb7IQ0Sd54S9J6A/EXk4OaNh3ETUQEJcMn1bVAuCt/MbQa6bn65SORjbAnJeyd0V7cwoBAAMFp60myZwz386Quc/IizS3GZ8jUF28vk5FzLYunsgM/+DnY5Gk8gOGDZ2ezIr1WoLgyGf07NLuFyujuBSYzUiUugAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwZGb+UhFzL/7K26csOb57yM5bvF9xJrLEObOkAAAADC/N0bl1xvkH/ORPlcnDsS33Jzb10AB9jDqL3XbS+395f9hdog8obXXkHdExfRcWg0sORo8YmYwmWo/3ZUCfFJBAMACQNAHwAAAAAAAAMABQKAGgYAAgIAAWkDAAAAp60myZwz386Quc/IizS3GZ8jUF28vk5FzLYunsgM/+ANAAAAAAAAADE2OTg5MjYxNDAwNDeAr736CAAAAKiMVAAAAAAAwvzdG5dcb5B/zkT5XJw7Et9yc29dAAfYw6i9120vt/cEAwABAhnbyFiwnj/9fw0AAAAxNjk4OTI2MTQwMDQ3",{"encoding":"base64","skipPreflight":true}],"id":"b1264dc9-3675-4173-a77c-ade56ca21e16"}'


The most important part is the params: and that long line of code which is Base64 encoded can be easily decoded and you end up with:

01 b6 32 56 3a 50 54 db 0d d8 d3 46 0f 51 42 6f 
b2 10 d1 27 79 e1 2f 49 e8 0f c4 5e 4e 0e 68 d8
77 11 35 10 10 97 0c 9f 56 d5 02 e0 ad fc c6 d0
6b a6 e7 eb 94 8e 46 36 c0 9c 97 b2 77 45 7b 73
0a 01 00 03 05 a7 ad 26 c9 9c 33 df ce 90 b9 cf
c8 8b 34 b7 19 9f 23 50 5d bc be 4e 45 cc b6 2e
9e c8 0c ff e0 e7 63 91 a4 f2 03 86 0d 9d 9e cc
8a f5 5a 82 e0 c8 67 f4 ec d2 ee 17 2b a3 b8 14
98 cd 48 94 ba 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 03 06 46 6f e5 21 17 32 ff ec ad
ba 72 c3 9b e7 bc 8c e5 bb c5 f7 12 6b 2c 43 9b
3a 40 00 00 00 c2 fc dd 1b 97 5c 6f 90 7f ce 44
f9 5c 9c 3b 12 df 72 73 6f 5d 00 07 d8 c3 a8 bd
d7 6d 2f b7 f7 97 fd 85 da 20 f2 86 d7 5e 41 dd
13 17 d1 71 68 34 b0 e4 68 f1 89 98 c2 65 a8 ff
76 54 09 f1 49 04 03 00 09 03 40 1f 00 00 00 00
00 00 03 00 05 02 80 1a 06 00 02 02 00 01 69 03
00 00 00 a7 ad 26 c9 9c 33 df ce 90 b9 cf c8 8b
34 b7 19 9f 23 50 5d bc be 4e 45 cc b6 2e 9e c8
0c ff e0 0d 00 00 00 00 00 00 00 31 36 39 38 39
32 36 31 34 30 30 34 37 80 af bd fa 08 00 00 00
a8 8c 54 00 00 00 00 00 c2 fc dd 1b 97 5c 6f 90
7f ce 44 f9 5c 9c 3b 12 df 72 73 6f 5d 00 07 d8
c3 a8 bd d7 6d 2f b7 f7 04 03 00 01 02 19 db c8
58 b0 9e 3f fd 7f 0d 00 00 00 31 36 39 38 39 32
36 31 34 30 30 34 37

where the explanation of the hex code is the following:

01 // Number of signatures
b6 32 56 3a 50 54 db 0d d8 d3 46 0f 51 42 6f b2 // 1st Signature 64 bytes
10 d1 27 79 e1 2f 49 e8 0f c4 5e 4e 0e 68 d8 77
11 35 10 10 97 0c 9f 56 d5 02 e0 ad fc c6 d0 6b
a6 e7 eb 94 8e 46 36 c0 9c 97 b2 77 45 7b 73 0a

01 // Number of Signers
00 // Number of Read Only Addresses from Signers
03 // Number of Read Only Addresses Not requiring Signatures

05 // Number of Addresses
a7 ad 26 c9 9c 33 df ce 90 b9 cf c8 8b 34 b7 19 // 1st Address 32 bytes (usuallty Wallet)
9f 23 50 5d bc be 4e 45 cc b6 2e 9e c8 0c ff e0
e7 63 91 a4 f2 03 86 0d 9d 9e cc 8a f5 5a 82 e0 // 2nd Address 32 bytes
c8 67 f4 ec d2 ee 17 2b a3 b8 14 98 cd 48 94 ba
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 // 3rd Address 32 bytes
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
03 06 46 6f e5 21 17 32 ff ec ad ba 72 c3 9b e7 // 4th address 32 bytes
bc 8c e5 bb c5 f7 12 6b 2c 43 9b 3a 40 00 00 00
c2 fc dd 1b 97 5c 6f 90 7f ce 44 f9 5c 9c 3b 12 // 5th Address 32 bytes
df 72 73 6f 5d 00 07 d8 c3 a8 bd d7 6d 2f b7 f7
97 fd 85 da 20 f2 86 d7 5e 41 dd 13 17 d1 71 68 // Latest Blockhash 32 bytes
34 b0 e4 68 f1 89 98 c2 65 a8 ff 76 54 09 f1 49

04 // Number of Instructions

03 // Address Index from the Addresses above to send instruction to
00 // Addresses used
09 // Data Length
03 40 1f 00 00 00 00 00 00 // Data

03 // Address Index from the Addresses above to send instruction to
00 // Addresses used
05 // Data Length
02 80 1a 06 00 // Data

02 // Address Index from the Addresses above to send instruction to
02 // Addresses used
00 // 1st Address Index from the list above
01 // 2nd Address Index from the list above
69 // Data length
03 00 00 00 a7 ad 26 c9 9c 33 df ce 90 b9 cf c8 // Data 105 bytes
8b 34 b7 19 9f 23 50 5d bc be 4e 45 cc b6 2e 9e
c8 0c ff e0 0d 00 00 00 00 00 00 00 31 36 39 38
39 32 36 31 34 30 30 34 37 80 af bd fa 08 00 00
00 a8 8c 54 00 00 00 00 00 c2 fc dd 1b 97 5c 6f
90 7f ce 44 f9 5c 9c 3b 12 df 72 73 6f 5d 00 07
d8 c3 a8 bd d7 6d 2f b7 f7

04 // Address Index from the Addresses above to send instruction to
03 // Addresses Used
00 // 1st Address Index from the list above
01 // 2nd Address Index from the list above
02 // 3rd Address Index from the list above
19 // Data Length
db c8 58 b0 9e 3f fd 7f 0d 00 00 00 31 36 39 38 // Data 25 bytes
39 32 36 31 34 30 30 34 37

Data can be further split up but that's up to the programs to parse so won't get into that right now. FYI: Dala length is specified in Compact U16 format.

NOTE: The addresses that require signatures appear at the beginning, with addresses requesting read-write access first, and read-only accounts following. The addresses that do not require signatures follow the addresses that do, again with read-write accounts first and read-only accounts following.

This way you can easily construct any kind of transaction on Solana and simply send it over to the RPC node and that's it, should be working just fine. For signing you will need only the part without the signatures on the top, so everything below the signatures is the binnary data that you should sign and then add the signatures to the top of it.