Soda Labs
Soda Labs Docs
User InterfaceHttp proxy

Onboard user example

A minimal copy-paste example that onboards a user through the Bubble HTTP proxy and returns the AES user key.

This is a minimal copy-paste example that onboards a user through the Bubble HTTP proxy using the latest JS SDK (soda-bubble-sdk) and returns the AES user key.

Quick start

  • Requirements: Node 18+, a wallet private key, default chain 84532 (Base Sepolia). Override the proxy with BUBBLE_PROXY_URL if needed.

  • Install dependencies (the SDK expects ethereumjs-util to be present):

    npm install soda-bubble-sdk ethers ethereumjs-util

Example script (onboard.mjs)

import { generateRSAKeyPair, reconstructUserKey } from "soda-bubble-sdk";
import { Wallet, getBytes } from "ethers";

const PRIVATE_KEY = process.env.PRIVATE_KEY;
if (!PRIVATE_KEY) throw new Error("Set PRIVATE_KEY in your environment");

const CHAIN_ID = Number(process.env.CHAIN_ID || 84532);
const PROXY_URL = process.env.BUBBLE_PROXY_URL || "https://proxy2.bubble.sodalabs.net";

const wallet = new Wallet(PRIVATE_KEY);

const main = async () => {
  // 1) Generate RSA keypair for the onboarding request
  const { publicKey, privateKey } = await generateRSAKeyPair();
  const publicKeyDer = new Uint8Array(publicKey);

  // 2) Sign rsa_public_key + user_address (v2 proxy format)
  const addressBytes = getBytes(wallet.address);
  const message = new Uint8Array(publicKeyDer.length + addressBytes.length);
  message.set(publicKeyDer, 0);
  message.set(addressBytes, publicKeyDer.length);
  const signature = await wallet.signMessage(message);

  // 3) Call the HTTP proxy /onboard endpoint
  const body = {
    rsa_public_key: Buffer.from(publicKeyDer).toString("base64"),
    user_signature: Buffer.from(getBytes(signature)).toString("base64"),
    address: wallet.address,
    chain_id: CHAIN_ID,
  };

  const res = await fetch(`${PROXY_URL}/onboard`, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(body),
  });
  if (!res.ok) throw new Error(await res.text());
  const { rsa_ciphertexts } = await res.json();

  // 4) Reconstruct the AES user key from MPC shares
  const ciphertext = Buffer.from(rsa_ciphertexts, "base64");
  const share0 = ciphertext.slice(0, 256).toString("hex");
  const share1 = ciphertext.slice(256).toString("hex");
  const aesKey = reconstructUserKey(privateKey, share0, share1);

  console.log("User AES key (hex):", aesKey.toString("hex"));
};

main().catch(err => {
  console.error("Onboarding failed:", err);
  process.exit(1);
});

Run it:

PRIVATE_KEY=0xabc123... CHAIN_ID=84532 node onboard.mjs

The script signs the RSA public key plus your address, POSTs to the proxy at /onboard, and prints the reconstructed AES user key you need for future encrypt/decrypt operations.

On this page