Home > Back-end >  React Native Noob question: How to use an JS library in React Native
React Native Noob question: How to use an JS library in React Native

Time:07-06

I thought it would be pretty straightforward to use a js library that is packaged with npm but I'm not having any luck. Any suggestions would be greatly appreciated. These are the steps I took.

  1. I installed a library with:

npm install hotp-totp;

  1. I then created a file for a custom component:
//otp.js
import React from 'react';
import {
  Text,
  View,
} from 'react-native';

import totp from 'hotp-totp';


const OTP  = () => {
  let secret = 'MNWRM734ZIOEZYEYCAW4I6EX';
  let token = totp(secret);
  return (
    <View>
      <Text>
        { token }
      </Text>
    </View>
  )
}

export default OTP

I then import this component and attempt to render:

//App.js
import OTP from './otp.js';

const App: () => Node = () => {

  return (
    <SafeAreaView >
      <ScrollView
        contentInsetAdjustmentBehavior="automatic">
        
        <OTP />

      </ScrollView>
    </SafeAreaView>
  );
};

When I then try to run on my Android device I get the following error trace:

 ERROR  TypeError: (0, _hotpTotp.default) is not a function. (In '(0, _hotpTotp.default)(secret)', '(0, _hotpTotp.default)' is an instance of Object)

This error is located at:
    in OTP (at App.js:74)
    in RCTView (at View.js:32)
    in View (at ScrollView.js:1682)
    in RCTScrollView (at ScrollView.js:1800)
    in ScrollView (at ScrollView.js:1826)
    in ScrollView (at App.js:69)
    in RCTView (at View.js:32)
    in View (at SafeAreaView.js:41)
    in SafeAreaView (at App.js:67)
    in App (at renderApplication.js:50)
    in RCTView (at View.js:32)
    in View (at AppContainer.js:92)
    in RCTView (at View.js:32)
    in View (at AppContainer.js:119)
    in AppContainer (at renderApplication.js:43)
    in otp(RootComponent) (at renderApplication.js:60)
 ERROR  TypeError: (0, _hotpTotp.default) is not a function. (In '(0, _hotpTotp.default)(secret)', '(0, _hotpTotp.default)' is an instance of Object)

The library hotp-totp is pretty straightforward and I include it below for reference.

/* node_modules/hotp-totp/index.js */
import base32 from 'thirty-two';

// Time-based OTP
const totp = async (secret) => {
    return hotp( secret, Math.floor(  new Date() / 30000 ) );
}

// HMAC-based OTP 
const hotp = async (secret, counter) => {

    // Uint8Array(20)
    const hmac = async (secret, counter) => {
        const keyData = Uint8Array.from(base32.decode(secret));
        const key     = await crypto.subtle.importKey(
            'raw',
            keyData,
            { name: 'HMAC', hash: { name: 'SHA-1' } },
            false,
            ['sign']
        );

        return new Uint8Array(
            await crypto.subtle.sign('HMAC', key, padCounter(counter))
        );
    }

    // Uint8Array(8)
    const padCounter = (counter) => {
        const pairs = counter.toString(16).padStart(16, '0').match(/..?/g);
        const array = pairs.map(v => parseInt(v, 16));
        return Uint8Array.from( array );
    }

    // Number
    function truncate(hs) {
        const offset = hs[19] & 0b1111;
        return ((hs[offset] & 0x7f) << 24) | (hs[offset   1] << 16) | (hs[offset   2] << 8) | hs[offset   3];
    }

    // HOTP(K, C) = truncate(HMAC(K, C))
    const num = truncate( await hmac(secret, counter) );

    // return 6 digits, padded with leading zeros
    return num.toString().padStart(6, '0').slice(-6);
}
/**/
export default {
    hotp,
    totp,
}

Any help would be greatly appreciated.

CodePudding user response:

You need to import totp like this

import {default as hotptotp} from 'hotp-totp
const {totp} = hotptotp

You can read more about it here

  • Related