To start using the Ramp Network widget with improved integration security, you need to follow these steps:
generate a new ed25519 public/private key pair
share the public key with Ramp Network
implement Ramp Network Widget parameters signing:
timestamp query parameters to already used parameters - timestamp should be in mssignature query parameterAn example in NodeJS:
/** index.ts **/
import { generateSignedUrl } from "./rampWidget";
import { generateEd25519KeyPair } from "./generateKeys";
import * as fs from "fs";
import * as path from "path";
/**
* Main example demonstrating Ramp widget URL generation with Ed25519 signature
*/
async function main(): Promise<void> {
console.log("š Ramp Widget Signature Example\\n");
const keysDir = path.join(__dirname, "..", "keys");
const privateKeyPath = path.join(keysDir, "private_key.pem");
const publicKeyPath = path.join(keysDir, "public_key.pem");
// Step 1: Generate Ed25519 key pair if they don't exist
if (!fs.existsSync(privateKeyPath) || !fs.existsSync(publicKeyPath)) {
console.log("š Step 1: Generating Ed25519 key pair...\\n");
generateEd25519KeyPair();
console.log("\\n");
} else {
console.log("š Step 1: Using existing Ed25519 key pair\\n");
}
try {
// Step 2: Generate signed URL with default parameters
console.log("š Step 2: Generating signed widget URL...\\n");
const result = generateSignedUrl(privateKeyPath);
console.log("ā
Default Widget URL Generated:");
console.log("URL:", result.url);
console.log("Timestamp:", result.timestamp);
console.log("Signature:", result.signature.substring(0, 50) + "...");
console.log("\\n");
console.log("š Example completed successfully!");
console.log(
"\\nš” You can now use the generated signed URLs to embed the Ramp widget."
);
} catch (error) {
console.error("ā Error:", (error as Error).message);
process.exit(1);
}
}
// Run the example
if (require.main === module) {
main().catch(console.error);
}
/** generateKeys.ts **/
import * as crypto from "crypto";
import * as fs from "fs";
import * as path from "path";
export interface KeyPairResult {
publicKey: string;
privateKey: string;
publicKeyPath: string;
privateKeyPath: string;
}
/**
* Generate Ed25519 key pair for signing Ramp widget URLs
*/
export function generateEd25519KeyPair(): KeyPairResult {
console.log("Generating Ed25519 key pair...");
// Generate Ed25519 key pair
const { publicKey, privateKey } = crypto.generateKeyPairSync("ed25519", {
publicKeyEncoding: {
type: "spki",
format: "pem",
},
privateKeyEncoding: {
type: "pkcs8",
format: "pem",
},
});
// Create keys directory if it doesn't exist
const keysDir = path.join(__dirname, "..", "keys");
if (!fs.existsSync(keysDir)) {
fs.mkdirSync(keysDir);
}
// Save private key
const privateKeyPath = path.join(keysDir, "private_key.pem");
fs.writeFileSync(privateKeyPath, privateKey);
console.log(`Private key saved to: ${privateKeyPath}`);
// Save public key
const publicKeyPath = path.join(keysDir, "public_key.pem");
fs.writeFileSync(publicKeyPath, publicKey);
console.log(`Public key saved to: ${publicKeyPath}`);
console.log("\\n--- IMPORTANT ---");
console.log("Please share the PUBLIC KEY with Ramp Network:");
console.log("File location:", publicKeyPath);
console.log("\\nPublic Key Content:");
console.log(publicKey);
return { publicKey, privateKey, publicKeyPath, privateKeyPath };
}
// Run key generation if this script is executed directly
if (require.main === module) {
generateEd25519KeyPair();
}
/** rampWidget.ts **/
import * as crypto from "crypto";
import * as fs from "fs";
export interface WidgetParams {
defaultFlow?: "ONRAMP" | "OFFRAMP" | "SWAP";
enabledFlows?: string;
hostApiKey?: string;
userAddress?: string;
swapAsset?: string;
fiatCurrency?: string;
[key: string]: string | undefined;
}
export interface SignedUrlResult {
url: string;
signature: string;
timestamp: number;
queryString: string;
}
/**
* Generate signed Ramp widget URL
*/
export function generateSignedUrl(
privateKeyPath: string,
widgetParams: WidgetParams = {}
): SignedUrlResult {
// Load private key
const privateKey = fs.readFileSync(privateKeyPath, "utf8");
// Default widget parameters
const defaultParams: WidgetParams = {
defaultFlow: "ONRAMP",
enabledFlows: "ONRAMP,OFFRAMP",
hostApiKey: "API_KEY",
};
// Merge default params with provided params
const allParams: WidgetParams = { ...defaultParams, ...widgetParams };
// Build query string
const queryParams = new URLSearchParams();
Object.entries(allParams).forEach(([key, value]) => {
if (value !== undefined && value !== null) {
queryParams.append(key, value);
}
});
const queryString = queryParams.toString();
// Add timestamp and sign
const timestamp = Math.floor(Date.now());
const queryWithTimestamp = `${queryString}×tamp=${timestamp}`;
console.log("Query string to sign:", queryWithTimestamp);
// Create signature using Ed25519
const data = Buffer.from(queryWithTimestamp, "utf8");
const signature = crypto.sign(null, data, privateKey);
const base64Signature = signature.toString("base64");
// Create final URL
const baseUrl = "<https://app.demo.rampnetwork.com/>";
const finalUrl = `${baseUrl}?${queryWithTimestamp}&signature=${encodeURIComponent(
base64Signature
)}`;
return {
url: finalUrl,
signature: base64Signature,
timestamp,
queryString: queryWithTimestamp,
};
}