Build, encrypt, sign, and serialize DePIN messages compatible with Neurai Core.
This library allows ESP32 devices to produce the hex payload required for the Neurai RPC method depinsubmitmsg. It replicates the functionality of the @neuraiproject/neurai-depin-msg JavaScript library in a C++ environment optimized for microcontrollers.
- Hybrid ECIES Encryption: AES-256-GCM message encryption with recipient key wrapping.
- Hardware Acceleration: Leverages ESP32's
mbedtlsfor high-performance AES-GCM encryption. - Core Compatibility: Produces serialization identical to Neurai Core (Bitcoin-style).
- Self-Contained Signing: Handles secp256k1 signing using the
uNeurailibrary. - Automatic Recipient Handling: Automatically includes the sender's public key as a recipient so the device can decrypt its own messages.
This library depends on:
- uNeurai: For Neurai-specific cryptography (ECDSA, Hashing, Base58/WIF).
- mbedtls: Bundled with the ESP32 Arduino Core (used for AES-GCM).
- Download or clone this repository.
- Copy the
NeuraiDepinMsgfolder into your Arduinolibrariesdirectory. - Ensure you have the
uNeurailibrary also installed in your Arduino IDE.
For most applications, it is recommended to use the NeuraiDepinClient class. It encapsulates all the RPC communication and encryption complexity.
#include <WiFi.h>
#include <NeuraiDepinClient.h>
NeuraiDepinClient depin;
uint64_t lastTimestamp = 0;
String lastHash = "";
void setup() {
// 1. Connect WiFi and sync NTP (User managed)
// 2. Initialize the client
depin.begin("https://rpc-depin.neurai.org", "MYTOKEN", "MY_WIF_KEY");
// 3. Sending Messages
// Send to everyone holding the token
depin.sendGroupMessage("Hello everyone!");
// Send to a specific address (fetches pubkey automatically)
depin.sendPrivateMessage("NUSS...CV", "Hello friend!");
}
void loop() {
// 4. Poll and Detect Message Type (Batch Limit: 5)
auto msgs = depin.receiveMessages(lastTimestamp, 5, lastHash);
for (auto &m : msgs) {
if (m.hash.length() > 0) lastHash = m.hash; // Update pagination cursor
if (m.decrypted) {
Serial.print("[" + m.type + "] "); // "private" or "group"
Serial.println(m.content);
}
}
delay(15000);
}For devices with limited memory (like ESP32), you can request messages in smaller batches using the limit and lastHash parameters.
// Receive up to 5 messages starting after the 'lastHash'
std::vector<IncomingMessage> msgs = depin.receiveMessages(lastTimestamp, 5, lastHash);- limit: Maximum number of messages to retrieve in one call.
- lastHash: The hash of the last received message. The server will return messages after this hash.
Always ensure you update lastHash with msg.hash from the received messages to properly advance the cursor.
If you prefer to handle the RPC communication yourself, you can use the static methods in NeuraiDepinMsg.
#include <NeuraiDepinMsg.h>
void setup() {
DepinParams params;
params.token = "MYTOKEN";
params.senderAddress = "N...";
params.senderPubKey = "02..."; // 33-byte compressed hex
params.privateKey = "WIF_OR_HEX";
params.timestamp = 1704542400;
params.message = "Hello from ESP32!";
params.recipientPubKeys = {"03..."}; // Add recipient compressed pubkeys
params.messageType = "private"; // or "group"
DepinMessageResult res = NeuraiDepinMsg::buildDepinMessage(params);
Serial.print("Hex for depinsubmitmsg: ");
Serial.println(res.hex);
}The library follows Neurai Core's cryptographic standards:
- Ephemeral Keys: A new secp256k1 key pair is generated for every message.
- KDF: Uses
KDF_SHA256for key derivation. - AES-256-GCM: Encrypts the payload and the per-recipient keys with 12-byte nonces and 16-byte authentication tags.
The final hex payload is a serialized CDepinMessage:
token(String)senderAddress(String)timestamp(Int64)messageType(Uint8)encryptedPayload(Vector)signature(Vector)
MIT