✅ BORA Connect

1440

When your Dapp is served in BORA network, you should add a step named "BORA Connect" after login. When an user uses Dapp with Face Wallet, it is necessary to "connect" only for the first time. "BORA Connect" sends a signed message to BORA for mapping BORA user to Dapp.


isConnected

You can know whether an user needs "Connect" or not by using isConnected method. You can get walletAddressHash, boraPortalUsn from the response and use the values to call BoraPortal API.

import { Face } from '@haechi-labs/face-sdk';
import {
  BoraPortalConnectStatusEnum,
  Network,
} from '@haechi-labs/face-types';


const face = new Face({
  network: Network.BORA, 
  apiKey: 'YOUR_DAPP_API_KEY'
});

const loginResponse = await face.auth.login();

const isConnectResponse = await face.bora.isConnected('YOUR_BAPP_USN');
if(isConnectResponse.status === BoraPortalConnectStatusEnum.Unconnected) {
  await face.bora.connect({
    bappUsn: 'YOUR_BAPP_USN',
    signature: 'YOUR_SIGNATURE_SIGNED_BY_API_SECRET',
  });
}
console.log(isConnectResponse.boraPortalUsn, isConnectResponse.walletAddressHash)

If you call connect with a wallet that is already connected to another bappUsn, the SDK will throw an error with code 4909. You can catch the error by using the isConnected call.

import { Face } from '@haechi-labs/face-sdk';
import {
  BoraPortalConnectStatusEnum,
  Network,
} from '@haechi-labs/face-types';


const face = new Face({
  network: Network.BORA, 
  apiKey: 'YOUR_DAPP_API_KEY'
});

const loginResponse = await face.auth.login();
try {
  const isConnectResponse = await face.bora.isConnected('wrong bapp usn');
  console.log(isConnectResponse);
} catch (err) {
  if (err.code === 4909) {
    console.log('the wallet is connected to other bapp usn');
  }
}

connect

After the user login to Face Wallet, you should call connect if it is the first time for the user to use the Dapp. connect makes the user to sign a message. The signed message would be sent to BORA.

import { Face } from '@haechi-labs/face-sdk';
import {
  BoraPortalConnectStatusEnum,
  Network,
} from '@haechi-labs/face-types';



const face = new Face({
  network: Network.BORA, 
  apiKey: 'YOUR_DAPP_API_KEY'
});

const loginResponse = await face.auth.login();

const isConnectedResponse = await face.bora.isConnected('YOUR_BAPP_USN');
if(isConnectedResponse.status === BoraPortalConnectStatusEnum.Unconnected) {
   await face.bora.connect({
    	bappUsn: 'YOUR_BAPP_USN',
    	signature: 'YOUR_SIGNATURE_SIGNED_BY_API_SECRET',
    });
}

How to make Signature using API Secret

You can make a Signature using Face Wallet SDK API Secret.

First, convert your API Secret to PEM format. Then, using node-forge library, derive Key object from API Secret converted to PEM format. Finally, Sign a message which is concatenated with bappUsn and walletAddress using Key object and encode it to Base64 format. For walletAddress, You can get it from the Face Wallet login response.

import forge from 'node-forge';

function createPemFromApiSecret(apiSecret: string): string {
  return `-----BEGIN RSA PRIVATE KEY-----\n${apiSecret
    .replace(/-/g, '+')
    .replace(/_/g, '/')
    .replace(/(\S{64}(?!$))/g, '$1\n')}\n-----END RSA PRIVATE KEY-----\n`;
}

function createSignatureForBoraConnect(bappUsn: string, walletAddress: string) {
  const signatureMessage = `${bappUsn}:${walletAddress}`;
  const messageDigest = forge.md.sha256.create();
    messageDigest.update(signatureMessage, 'utf8');
    const privateKey = forge.pki.privateKeyFromPem(createPemFromApiSecret(apiSecret));
    return Buffer.from(forge.util.binary.raw.decode(privateKey.sign(messageDigest))).toString(
      'base64'
    );
}

👍

How can I get my API Secret?

Please contact and request API Secret to Face Wallet Team.

❗️

API Secret should be careful not to leak outside. Also, a signature should be created in your backend, not frontend.

🚧

If a user without the BORA Connect attempts to perform a BORA-related function, a 4xx error occurs.