Using ECDH for encryption and decryption
Use crypto_box_curve25519xsalsa20poly1305 from libsodium/nacl.

How it works, roughly summarized with all details of encoding and coordinates omitted:


Alice and Bob have public keys $A = [a]G = \underbrace{G + \dotsb + G}_{\text{$a$ times}}$ and $B = [b]G$.
Here $G$ is the standard base point of Curve25519, $a$ is a secret 256-bit integer known only to Alice, and $b$ is a secret 256-bit integer known only to Bob.
When Alice wants to send the $n^{\mathit{th}}$ message $m_n$ to Bob, she sends the box $c_n = \operatorname{crypto\_box}(m_n, n, B, a)$ to Bob.  What this does is:


Computes the shared secret key $k = H([a]B) = H([a\cdot b]G)$, where $H$ is HSalsa20.
Uses $k$ as the key and $n$ as the nonce to authenticate and encrypt the message $m_n$ using crypto_secretbox_xsalsa20poly1305.

When Bob receives the alleged $n^{\mathit{th}}$ box $c'_n$, which may be $c_n$ or may have been modified in transit or otherwise forged, he opens it with $\operatorname{crypto\_box\_open}(c'_n, n, A, b)$—but he makes sure to immediately drop it on the floor if crypto_box_open fails, meaning that it was a forgery.  What this does is:


Computes the shared secret key $k = H([b]A) = H([a\cdot b]G)$.
Uses $k$ as the key and $n$ as the nonce to authenticate and decrypt the box $c_n$ using crypto_secretbox_xsalsa20poly1305_open.



In other words, crypto_box and crypto_box_open first do a static/static Diffie–Hellman key agreement, and then use the resulting key for an authenticated cipher.

Alice and Bob must never reuse any message number or nonce $n$ with a single pair of sender/receiver public keys or else the security will evaporate.  If the communication is bidirectional, i.e. if Alice and Bob both need to send messages to each other, you might have Alice choose even values for $n$ and Bob choose odd values.