npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

risework-pietro

v1.0.5

Published

Rise SDK for webhook validation and TypeScript types

Downloads

191

Readme

Rise SDK

Official TypeScript/JavaScript SDK for Rise's payment and webhook systems, providing both webhook validation and API client functionality.

Features

  • 📝 Comprehensive TypeScript Types - Full type definitions for all Rise webhook events and API endpoints
  • Webhook Validation - Validate webhook payloads against Zod schemas with signature verification
  • 🚀 API Client - Type-safe HTTP client for all Rise API endpoints
  • 🎯 Type Safety - Full type support for all Rise webhook events and API requests/responses with autocomplete
  • 🔒 Security First - Built-in signature verification to ensure webhooks come from Rise
  • Optimized Builds - Lightweight and fast library

Installation

npm install @riseworks-sdk
# or
yarn add @riseworks-sdk
# or
pnpm add @riseworks-sdk

Quick Start

Basic Webhook Validation

import { WebhookValidator, type RiseWebhookEvent } from '@riseworks-sdk';

const riseValidator = new WebhookValidator({
  secret: process.env.RISE_WEBHOOK_SECRET!,
  tolerance: 720 // 12 minutes tolerance
});

// Validate webhook signature and payload
const event = riseValidator.validateEvent(req.body, req.headers['x-rise-signature']);
console.log(`Event type: ${event.event_type}`);
console.log(`Event ID: ${event.id}`);

Webhook Signature Verification

For production use, verify that webhook requests actually come from Rise using the WebhookValidator class:

import express from 'express';
import { WebhookValidator, type RiseWebhookEvent } from '@riseworks-sdk';

const app = express();

// Use raw body for signature verification
app.use('/rise-webhooks', express.raw({ type: 'application/json' }));

app.post('/rise-webhooks', (req, res) => {
  const signature = req.headers['x-rise-signature'] as string;
  const secret = process.env.RISE_WEBHOOK_SECRET!;

  try {
    // Validate webhook using Rise SDK WebhookValidator with full type safety
    const riseValidator = new WebhookValidator({
      secret: secret,
      tolerance: 720 // 12 minutes tolerance
    });
    
    // Option 1: validateEvent (throws on failure)
    let event = riseValidator.validateEvent(req.body, signature);
    
    // Option 2: validateEventSafe (returns result object)
    const result = riseValidator.validateEventSafe(req.body, signature);
    if (!result.isValid) {
      console.error('Validation failed:', result.error);
      return res.status(400).json({ error: result.error });
    }
    event = result.event;

    // Signature is valid, process the event with full TypeScript support
    handleEvent(event);

    res.status(200).json({ 
      received: true,
      timestamp: new Date().toISOString(),
      event_type: event.event_type,
      event_version: event.event_version,
      idempotency_key: event.idempotency_key
    });
  } catch (error) {
    console.error('Webhook verification failed:', error instanceof Error ? error.message : String(error));
    res.status(400).json({ 
      error: 'Webhook processing failed',
      message: error instanceof Error ? error.message : String(error),
      timestamp: new Date().toISOString()
    });
  }
});

Handling Different Event Types

import type { 
  RiseWebhookEvent, 
  PaymentSentV1, 
  PaymentGroupCreatedV1, 
  DepositReceivedV1 
} from '@riseworks-sdk';

function handleEvent(event: RiseWebhookEvent) {
  switch (event.event_type) {
    case 'payment.sent':
      // Send confirmation email with full type safety
      sendPaymentConfirmation(event as PaymentSentV1);
      break;

    case 'payment.group.created':
      // Update order status with full type safety
      updateOrderStatus(event as PaymentGroupCreatedV1);
      break;

    case 'deposit.received':
      // Trigger fulfillment with full type safety
      triggerFulfillment(event as DepositReceivedV1);
      break;

    default:
      console.log('Unhandled event type:', event.event_type);
  }
}

async function sendPaymentConfirmation(event: PaymentSentV1) {
  // Your email logic here with full type safety
  console.log(`Sending confirmation for payment ${event.payment.nanoid}`);
  console.log(`Amount: ${event.payment.amount_cents} cents`);
  console.log(`Recipients: ${event.payment.recipients.length}`);
}

API Client

The Rise API Client provides type-safe methods to interact with all Rise API endpoints.

Basic API Client Usage

import { RiseApiClient } from '@riseworks-sdk';

// Initialize the API client
const riseClient = new RiseApiClient({
  jwtToken: process.env.RISE_JWT_TOKEN!,
  timeout: 30000, // Optional, defaults to 30 seconds
});

// Get current user information
const userResponse = await riseClient.me.get();
console.log('Current user:', userResponse.data.user);
console.log('Company:', userResponse.data.company);

Sending Team Invites

// Send invites to team members with full type safety
const inviteResponse = await riseClient.invites.send({
  nanoid: 'team_1234567890',
  invites: [
    {
      email: '[email protected]',
      prefill: {
        first_name: 'John',
        last_name: 'Doe',
        phone: '+1234567890',
        company_name: 'Example Corp',
        job_title: 'Developer',
        company_size: '10-50',
        company_website: 'https://example.com',
        company_industry: 'Technology',
        company_address: '123 Main St',
        company_city: 'San Francisco',
        company_state: 'CA',
        company_zip: '94105',
        company_country: 'US',
      },
    },
  ],
  role: 'team_employee',
});

console.log('Invites sent:', inviteResponse.data.nanoids);

Creating and Executing Payments

// Step 1: Create payments (get typed data for blockchain)
const createResponse = await riseClient.payments.create({
  from: 'team_1234567890',
  to: [
    {
      to: 'user_1234567890',
      amount_cents: 100000, // $1000.00
      currency_symbol: 'USD',
      invoice_description: 'Payment for services',
    },
  ],
  pay_now: true,
  network: 'arbitrum',
});

console.log('Typed data for blockchain:', createResponse.data);

// Step 2: Execute payments (after signing the typed data)
const executeResponse = await riseClient.payments.execute({
  from: 'team_1234567890',
  to: [
    {
      to: 'user_1234567890',
      amount_cents: 100000,
      currency_symbol: 'USD',
      invoice_description: 'Payment for services',
    },
  ],
  pay_now: true,
  network: 'arbitrum',
  signer: '0x1234567890123456789012345678901234567890',
  typed_data: createResponse.data, // The typed data from step 1
  signature: '0x...', // The signature from the wallet
});

console.log('Payment executed:', executeResponse.data);

Getting Team Payments

// Get payments for a team with full type safety
const paymentsResponse = await riseClient.payments.get({
  team_nanoid: 'team_1234567890',
  state: 'all',
  start_date: '2024-01-01',
  end_date: '2024-12-31',
  query_type: 'payable',
});

console.log('Payments:', paymentsResponse.data.items);

B2B Webhook Events

// Send webhook events to Rise (B2B API)
const webhookResponse = await riseClient.webhooks.sendEvent({
  event_type: 'payment.sent',
  event_version: '1.0',
  id: 'evt_1234567890',
  timestamp: Math.floor(Date.now() / 1000),
  data: {
    payment: {
      nanoid: 'pay_1234567890',
      amount_cents: 100000,
      currency_symbol: 'USD',
      recipients: ['user_1234567890'],
    },
  },
});

console.log('Webhook event sent:', webhookResponse);

Authentication

The Rise API client uses JWT token authentication. You need to provide a JWT token when initializing the client.

JWT Token Authentication

import { RiseApiClient } from '@riseworks-sdk'

const client = new RiseApiClient({
  jwtToken: 'your-jwt-token-here',
  timeout: 30000, // Default: 30 seconds
})

API Reference

WebhookValidator

Class for validating webhook signatures and payloads.

Constructor

new WebhookValidator(options: {
  secret: string;
  tolerance?: number; // Default: 300 seconds (5 minutes)
})

Methods

validateEvent(payload, signature)

Validates a webhook event and returns the parsed event.

Parameters:

  • payload: Raw webhook payload (string, Buffer, or object)
  • signature: The x-rise-signature header value

Returns: The validated and typed webhook event

Throws: Error if validation fails

validateEventSafe(payload, signature)

Safely validates a webhook event and returns a result object.

Parameters:

  • payload: Raw webhook payload (string, Buffer, or object)
  • signature: The x-rise-signature header value

Returns: { isValid: boolean; event?: RiseWebhookEvent; error?: string }

RiseApiClient

Class for making type-safe API calls to Rise endpoints.

Constructor

new RiseApiClient(options: {
  // Authentication (choose one):
  jwtToken?: string;           // JWT token for authentication
  riseIdAuth?: {              // Rise ID authentication configuration
    riseId: string;           // Rise ID for automatic JWT generation
    privateKey: string;       // Private key for automatic JWT generation
  };
  
  // Configuration:
  environment?: 'dev' | 'stg' | 'prod'; // Default: 'prod'
  baseUrl?: string;           // Custom base URL (overrides environment)
  timeout?: number;           // Default: 30000ms
  headers?: Record<string, string>; // Custom headers
})

Authentication Methods

The Rise API client supports two authentication methods:

1. JWT Token (Traditional)

const client = new RiseApiClient({
  jwtToken: 'your-jwt-token-here',
  environment: 'prod'
})

2. Rise ID + Private Key (Automatic JWT Generation)

const client = new RiseApiClient({
  riseIdAuth: {
    riseId: '0x2DF5A64B859B203752C30F941035e3cfE93Bb089',
    privateKey: '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef'
  },
  environment: 'dev'
})

When using Rise ID and private key authentication, the client will:

  • Automatically generate a JWT token using SIWE (Sign-In with Ethereum) before making any requests
  • Check JWT validity before each request
  • Automatically refresh the JWT token if it expires or becomes invalid
  • Handle 401 errors by regenerating the JWT token and retrying the request

Available API Groups

The client is organized into logical groups for better discoverability and organization:

riseClient.webhooks - Webhook Operations:

  • sendEvent(data) - Send webhook events to Rise

riseClient.company - Company Management:

  • getUsers(params) - Get company users
  • updateAddress(params, data) - Update company address
  • getDetails(params) - Get organization details
  • updateDetails(params, data) - Update organization details
  • getSettings(params) - Get company settings
  • updateSettings(params, data) - Update company settings
  • getRoleSettings(params) - Get company role settings
  • updateRoleSettings(params, data) - Update company role settings
  • getContacts(params) - Get organization contacts
  • updateContacts(params, data) - Update organization contacts
  • getOwnership(params) - Get organization ownership
  • updateOwnership(params, data) - Update organization ownership

riseClient.entityBalance - Entity Balance:

  • get(params) - Get entity balance

riseClient.invites - Team Invitations:

  • send(data) - Send invites to team members
  • sendManager(data) - Send manager invites
  • executeManager(data) - Execute manager invites
  • get(params) - Get invites for a company or team

riseClient.me - Current User:

  • get() - Get current user information

riseClient.payments - Payment Operations:

  • get(params) - Get payments
  • create(data) - Create payments
  • execute(data) - Execute payments

riseClient.payroll - Payroll Management:

  • enable(data) - Enable payroll for a team
  • getTeamPayroll(params) - Get team payroll
  • getPayrollPeriod(params) - Get payroll period

riseClient.team - Team Management:

  • update(data) - Update team information

riseClient.user - User Management:

  • updateAddress(data) - Update user address
  • updateAvatar(data) - Update user avatar
  • getCompanies() - Get user companies
  • getTeams() - Get user teams

riseClient.withdraw - Withdraw Operations:

  • getSignData(params) - Get withdraw sign data
  • getFee(params) - Get withdraw fee
  • create(data) - Create withdraw request
  • execute(data) - Execute withdraw

All methods are fully typed with request and response types generated from the API schemas.

Utility Methods

// Check authentication method
client.isUsingJwtToken()     // Returns true if using JWT token
client.isUsingRiseIdAuth()   // Returns true if using Rise ID + private key

// Get current token/info
client.getToken()            // Get current JWT token
client.getRiseId()           // Get Rise ID (if provided)

// Update authentication
client.updateToken(newToken) // Update JWT token

// Manual JWT refresh (for Rise ID auth)
await client.refreshJwtToken() // Manually refresh JWT token
await client.generateJwtToken() // Generate new JWT token

// Environment management
client.getEnvironment()      // Get current environment
client.updateEnvironment(env) // Update environment

Common Event Types

The SDK supports all Rise webhook events with full type safety:

  • payment.sent - A payment has been successfully sent
  • payment.group.created - A new payment group has been created
  • deposit.received - A deposit has been received and confirmed
  • invite.accepted - A team member has accepted an invitation
  • And many more...

Automatic JWT Generation Process

When using Rise ID and private key authentication, the client follows this process:

  1. SIWE Message Request: Requests a SIWE (Sign-In with Ethereum) message from the Rise API
  2. Message Signing: Signs the message using the provided private key
  3. Nonce Extraction: Extracts the nonce from the SIWE message
  4. Signature Verification: Sends the signed message to the Rise API for verification
  5. JWT Generation: Receives a JWT token upon successful verification
  6. Automatic Refresh: Checks JWT validity before each request and refreshes when needed

The process is fully automatic and transparent to the user.

Security Best Practices

  1. Always verify signatures - Use WebhookValidator for production webhooks
  2. Use HTTPS - Always use HTTPS in production
  3. Set appropriate tolerance - Use 5-15 minutes tolerance for timestamp validation
  4. Handle errors gracefully - Log validation failures for debugging
  5. Use environment variables - Store webhook secrets securely
  6. Secure private keys - Never expose private keys in client-side code or logs
  7. Use environment-specific keys - Use different private keys for dev/staging/production

License

MIT - See LICENSE file for details