npm package: @purefi/verifier-sdk
Description: Node.js module with the Verifier SDK for PureFI decentralized AML protocol. Providing wrappers for communicating with PureFI issuers
Author: Mikhail Radchenko
Latest version: 8.0.0

![Logo](https://user-images.githubusercontent.com/23620645/136548302-6bf7f6e0-8236-44bf-b75a-9c067e9347da.png)

# @purefi/verifier-sdk

Node.js module with the Verifier SDK for PureFI decentralized AML protocol. Providing wrappers for communicating with PureFI issuers

![typescript](https://img.shields.io/npm/types/@purefi/verifier-sdk)

## Documentation
For more detailed documentation see https://verifier-sdk.purefi.io/

## Installation

Using npm:

```bash
npm install @purefi/verifier-sdk
```

Using yarn:

```bash
yarn add @purefi/verifier-sdk
```

Using unpkg CDN:

```html
<script src="https://unpkg.com/@purefi/verifier-sdk/lib/index.umd.min.js"></script>
<!-- The library will be availble as window.PureFIModule or just PureFIModule -->
```
    
## Quick Start

### The first use case

In case you have a specific process around signing messages or you want to sign messages by yourself

CommonJS:
```javascript
const { ethers } = require('ethers');
const { PureFI, AddressType } = require('@purefi/verifier-sdk');

const privateKey = '<private_key>';
const infuraApiKey = '<infura_api_key>';
const provider = new ethers.providers.InfuraProvider('homestead', infuraApiKey);
const wallet = new ethers.Wallet(privateKey, provider);

const addresses = [
  {
    address: '0xaAaAAAAaaAAaaaAAAaaaaaAAAAAaaAaAaAAAAaaa',
    type: AddressType.WALLET,
  },
  {
    address: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB',
    type: AddressType.CONTRACT,
  },
  {
    address: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC',
  },
];

const message = JSON.stringify(addresses);

wallet
  .signMessage(message)
  .then((signature) => {
    const purefiPayload = {
      message,
      signature,
    };
    return Promise.all([
      PureFI.checkRisk(purefiPayload),
      PureFI.downloadReport(purefiPayload),
    ]);
  })
  .then(([checkRiskResponse, downloadReportResponse]) => {
    // process checkRiskResponse
    checkRiskResponse.forEach((item) => {
      const { address, riskScore, connections } = item;
      console.log(address, riskScore, connections);
    });

    // process downloadReportResponse
    const { buffer } = downloadReportResponse;
    console.log(buffer);
  })
  .catch((error) => {
    console.log(error);
  });
```

### The second use case
In case you want to delegate signing messages to PureFI

> **NOTE**
>
> *Ethers signers are compatible with PureFI out of the box.*
> *If you tend to use Web3 or other solutions just implement ISigner interface and follow along*

See details: <a href="https://verifier-sdk.purefi.io/interfaces/ISigner.html" target="">ISigner</a>

Typescript:
```typescript
import { ethers } from 'ethers';
import {
  PureFI,
  AddressType,
  PureFIErrorCodes,
  PureFIError,
  CheckRiskResponse,
  DownloadReportResponse,
} from '@purefi/verifier-sdk';

// assuming you have givenProvider
const givenProvider = ...;
const provider = new ethers.providers.Web3Provider(givenProvider);
const signer = provider.getSigner();

// empower PureFI to sign messages for you
PureFI.setSigner(signer);

async function checkRiskExample() {
  const addresstoCheck = '0xaAaAAAAaaAAaaaAAAaaaaaAAAAAaaAaAaAAAAaaa';
  try {
    const response: CheckRiskResponse = await PureFI.checkRisk(addresstoCheck);
    const { address, riskScore, connections } = response;
    console.log(address, riskScore, connections);
  } catch (error) {
    const purefiError = error as PureFIError;
    switch (purefiError.code) {
      case PureFIErrorCodes.VALIDATION: {
        console.log(purefiError.message);
        break;
      }
      // handle other cases
      default: {
        break;
      }
    }
  }
}

async function downloadReportExample() {
  const addresstoCheck = {
    address: '0xaAaAAAAaaAAaaaAAAaaaaaAAAAAaaAaAaAAAAaaa',
    type: AddressType.WALLET,
  };
  try {
    const response: DownloadReportResponse = await PureFI.downloadReport(
      addresstoCheck
    );
    const { buffer } = response;
    console.log(buffer);

    // let user to download PureFI VC certificate
    const url = window.URL.createObjectURL(new Blob([buffer]));
    const link = document.createElement('a');
    link.href = url;
    link.setAttribute('download', 'PureFI VC Certificate.pdf');
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
  } catch (error) {
    const purefiError = error as PureFIError;
    switch (purefiError.code) {
      case PureFIErrorCodes.VALIDATION: {
        console.log(purefiError.message);
        break;
      }
      // handle other cases
      default: {
        break;
      }
    }
  }
}

checkRiskExample();
downloadReportExample();
```

### The third use case
In case you want to verify that an address satisfies certain criterias

> **NOTE**
>
> For backend purposes only
>
> Highly recommended NOT to use PureFI.verifyRule method on frontend because api key can be compromised*

There are several rule types are being supported:

```typescript
// 431 - AML only rule pattern
// 030 - AML score threshold
const AML_RULE_EXAMPLE = "431030";
// To satisfy this rule an address has to
// have AML risk that does not exceed configured threshold
```

```typescript
// 777 - KYC only rule pattern
const KYC_RULE_EXAMPLE = "777";
// To satisfy this rule an address has to
// have bound KYC pass
```

```typescript
// 731 - KYC and AML rule pattern
// 040 - AML score threshold
const KYCAML_RULE_EXAMPLE = "731040";
// To satisfy this rule an address has to
// have AML risk that does not exceed configured threshold
// and
// have bound KYC pass
```

```typescript
// 631 - OPTIONAL KYC and AML rule pattern
// 040 - lower AML score threshold
// 090 - upper AML score threshold
const OPTIONALKYCAML_RULE_EXAMPLE = "631040090";
// To satisfy this rule an address either has to 
// have AML risk that does not exceed lower threshold
// or
// have AML risk score between lower and upper thresholds and have bound KYC pass
```

```typescript

// Payload is expected to be prepared on frontend/backend and passed to issuer
async function preparePayload() {
  const data = {
    sender: '0xaAaAAAAaaAAaaaAAAaaaaaAAAAAaaAaAaAAAAaaa', // user address
    receiver: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB', // contract address
    chainId: 1, // chain
    ruleId: AML_RULE_EXAMPLE, // rule to satisfy
    token: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC', // token address
    amount: BigNumber.from(1).toHexString(), // token amount in hex format
  };

  const message = JSON.stringify(data);

  // user's or custom backend signer
  const signer = jsonRpcProvider.getSigner();

  const signature = await signer.signMessage(message);

  const payload = {
    message,
    signature,
  };

  return payload;
}

// Rule verification
async function verifyRuleExample(payload) {
  try {
    const response: VerifyRuleResponse = await PureFI.verifyRule(payload);
    return response;
  } catch (error) {
    const purefiError = error as PureFIError;
    switch (purefiError.code) {
      case PureFIErrorCodes.VALIDATION: {
        console.log(purefiError.message);
        break;
      }
      // handle other cases
      default: {
        break;
      }
    }
  }
}

// Basic flow

const payload = await preparePayload();
const response = await verifyRuleExample(payload);
```

## License

[MIT](https://github.com/purefiprotocol/verifier-sdk/blob/main/LICENSE)