Issue with certificate in local dev env

Hi, I’m trying to implement basic flow in my app, copying code from your web&backend demo repos.

I’m running the code locally on my pc, and I’m stuck at the “Generate MPC Keys” step.
code from web throws an error:

      fireblocksNCW = await FireblocksNCW.initialize({
        env: 'sandbox' as TEnv,
        deviceId: deviceId || '',
        messagesHandler,
        eventsHandler,
        secureStorageProvider,
        logger: new ConsoleLogger(),
      });

from the consule:

ncw-js-sdk-bundle.js:1 fireblocksNCW constructor {env: 'sandbox', tenantId: 'DEFAULT_TENANT_ID', deviceId: '***', playerId: '****'}
getServiceCertificates started
VM2517 SyntaxError: "undefined" is not valid JSON
    at JSON.parse (<anonymous>)
    at HA.getDownloadedServiceCertificates (webpack-internal:///(app-pages-browser)/./node_modules/@fireblocks/ncw-js-sdk/dist/web/ncw-js-sdk-bundle.js:18:2749845)
    at async m.initServicesCertificates (webpack-internal:///(app-pages-browser)/./node_modules/@fireblocks/ncw-js-sdk/dist/web/ncw-js-sdk-bundle.js:18:2703938)
    at async aA.init (webpack-internal:///(app-pages-browser)/./node_modules/@fireblocks/ncw-js-sdk/dist/web/ncw-js-sdk-bundle.js:18:2757111)
    at async aA.initialize (webpack-internal:///(app-pages-browser)/./node_modules/@fireblocks/ncw-js-sdk/dist/web/ncw-js-sdk-bundle.js:18:2757222)

dug inside the bundle code and it seems to fail here, but I have no idea what to do to make it work

async getDownloadedServiceCertificates() {
      const A = await this._get("NONE_SECURE", `downloadedServiceCertificates-${this._env}`);
      return A ? JSON.parse(A) : null
    }

Hi @cmfbks,

  1. Are you trying to run this from a browser?
  2. Were you able to run the ncw-web-demo flow successfully?
  3. Might be unrelated, but passing an empty string as deviceId will fail, make sure you have a value there.

deviceId is not empty, and yes I’m running it from browser, didn’t try the demo, I’m trying to implement directly in our site (without the mysql/firebase/google auth parts)

what I have attempted is to simply have a btn on my page that triggers the FireblocksNCW.initialize(), with copies of relevant code from the demo
except I’m pointing to my backend endpoint here

 return new WalletClient(userId).sendMessage(deviceId, walletId, message);

I’m also running my backend service locally, I added route for rpc msgs, however I’m not sure if the issue is related to backend.
maybe I missed some important code part, part of why I’m doing this is to understand how it works, and at the moment I don’t :slight_smile:

const generateMPCKeys: FormEventHandler = async (e: any) => {
    e.preventDefault();
    try {
      fireblocksNCW = await FireblocksNCW.initialize({
        env: 'sandbox' as TEnv,
        deviceId: deviceId || '',
        messagesHandler,
        eventsHandler,
        secureStorageProvider,
        logger: new ConsoleLogger(),
      });
      if (!fireblocksNCW) {
        throw new Error('fireblocksNCW is not initialized');
      }
      const ALGORITHMS = new Set<TMPCAlgorithm>(['MPC_CMP_ECDSA_SECP256K1']);
      await fireblocksNCW.generateMPCKeys(ALGORITHMS);
    } catch (e: any) {
      console.log(e);
    }
  };
  const messagesHandler: IMessagesHandler = {
    handleOutgoingMessage: (message: string) => {
      if (!deviceId || !walletId) {
        throw new Error('deviceId is not set');
      }
      return new WalletClient(userId).sendMessage(deviceId, walletId, message);
    },
  };
  const eventsHandler: IEventsHandler = {
    handleEvent: (event: TEvent) => {
      switch (event.type) {
        case 'key_descriptor_changed':
          // const keysStatus: Record<TMPCAlgorithm, IKeyDescriptor> =
          //   get().keysStatus ?? ({} as Record<TMPCAlgorithm, IKeyDescriptor>);
          // keysStatus[event.keyDescriptor.algorithm] = event.keyDescriptor;
          // set((state) => ({ ...state, keysStatus }));
          console.log(`key_descriptor_changed event`);
          break;

        case 'transaction_signature_changed':
          console.log(`Transaction signature status: ${event.transactionSignature.transactionSignatureStatus}`);
          break;

        case 'keys_backup':
          console.log(`Key backup status: ${JSON.stringify((event as IKeyBackupEvent).keysBackup)}`);
          break;

        case 'keys_recovery':
          console.log(`Key recover status: ${JSON.stringify((event as IKeyRecoveryEvent).keyDescriptor)}`);
          break;
      }
    },
  };
  const secureStorageProvider = new PasswordEncryptedLocalStorage(deviceId || '', () => {
    console.log('secureStorageProvider');
    const password = prompt('Enter password', '');
    if (password === null) {
      return Promise.reject(new Error('Rejected by user'));
    }
    return Promise.resolve(password || '');
  });

    return {walletId && deviceId && (
        <Button type="submit" className="mb-6 text-white" onClick={generateMPCKeys}>
          Generate Keys
        </Button>
      )}