1.0.3 • Published 4 months ago

nestjs-accesstime v1.0.3

Weekly downloads
-
License
MIT
Repository
github
Last release
4 months ago

NestJS AccessTime Middleware

A NestJS middleware package for integrating with AccessTime subscription payment service.

šŸ”— Example NestJS Project

Features

  • Verify wallet signatures for incoming requests
  • Check user subscription time using the official AccessTime SDK
  • Protect your routes with middleware or guards
  • Easy integration with NestJS applications

Installation

npm install nestjs-accesstime

Usage

Module Registration

First, import and register the AccessTimeModule in your application:

import { Module } from '@nestjs/common';
import { AccessTimeModule } from 'nestjs-accesstime';

@Module({
  imports: [
    AccessTimeModule.register({
      chain: {
        id: 8453,
        rpcUrl: 'https://mainnet.base.org', // optional
      },
      contractAddress: '0xYourAccessTimeContractAddress',
      minRemainingTime: 3600, // 1 hour in seconds, optional
    }),
  ],
})
export class AppModule {}

Using the Middleware

Apply the middleware to your routes:

import { Module, MiddlewareConsumer, NestModule } from '@nestjs/common';
import { AccessTimeMiddleware } from 'nestjs-accesstime';

@Module({
  // ...
})
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    // Apply middleware to all routes
    consumer
      .apply(AccessTimeMiddleware)
      .forRoutes('*');
    
    // Or apply to specific routes
    consumer
      .apply(AccessTimeMiddleware)
      .forRoutes('protected');
  }
}

Using the Guard

Alternatively, you can use the guard to protect specific routes:

import { Controller, Get, UseGuards } from '@nestjs/common';
import { AccessTimeGuard } from 'nestjs-accesstime';

@Controller('protected')
export class ProtectedController {
  @Get()
  @UseGuards(AccessTimeGuard)
  getProtectedResource() {
    return { message: 'This is a protected resource' };
  }
}

Using the AccessTime Client

You can inject and use the AccessTime client directly in your services:

import { Injectable, Inject } from '@nestjs/common';
import { AccessTime } from 'nestjs-accesstime';

@Injectable()
export class SubscriptionService {
  constructor(
    @Inject(AccessTime) private readonly accessTimeClient: AccessTime
  ) {}
  
  async getUserAccessTime(userAddress: string): Promise<number> {
    const accessTime = await this.accessTimeClient.read.accessTimes([userAddress]);
    return Number(accessTime);
  }
  
  async getPackageDetails(packageId: number): Promise<any> {
    const packageDetails = await this.accessTimeClient.read.packages([BigInt(packageId)]);
    return {
      time: Number(packageDetails[0]),
      exists: packageDetails[1]
    };
  }
}

Client-Side Implementation

Your client needs to send requests with the required headers:

import { signMessage, hashMessage } from 'viem';

const message = 'Authenticate for AccessTime: ' + Date.now(); // Include timestamp to prevent replay attacks
const signature = await signMessage({
  message,
  account: walletAddress,
});

// Then add these headers to your request
const headers = {
  'X-ACCESSTIME-AUTH-SIGNATURE': signature,
  'X-ACCESSTIME-AUTH-MESSAGE': hashMessage(message),
};

// Make the request with these headers
fetch('https://your-api.com/protected-route', {
  headers,
});

Configuration Options

The AccessTimeModule.register() method accepts the following options:

OptionTypeDescription
chain.idnumberChain ID (supported by AccessTime)
chain.rpcUrlstring(Optional) RPC URL for the chain
contractAddressstringAccessTime contract address
minRemainingTimenumber(Optional) Minimum time in seconds a user must have remaining
accessTimeClientAccessTime(Optional) Custom AccessTime client instance

Accessing User Data

The middleware adds user data to the request object, which you can access in your controllers:

import { Controller, Get, Req } from '@nestjs/common';
import { Request } from 'express';

@Controller('user')
export class UserController {
  @Get('subscription')
  getSubscriptionInfo(@Req() request: Request) {
    const accessTimeData = request['accessTime'];
    
    return {
      address: accessTimeData.signerAddress,
      expiryTimestamp: accessTimeData.accessTimeExpiry,
      remainingTime: accessTimeData.remainingTime,
      expiresAt: new Date(accessTimeData.accessTimeExpiry * 1000).toISOString(),
    };
  }
}

License

MIT

1.0.3

4 months ago

1.0.2

4 months ago

1.0.1

4 months ago

1.0.0

4 months ago