3.3.5 • Published 21 days ago

@privateid/cryptonets-web-sdk v3.3.5

Weekly downloads
-
License
See AWS EULA Temp...
Repository
github
Last release
21 days ago

Powered by Private Identity® https://www.privateid.com

FEATURES

BUILD

Prerequisite

Sign up on the waitlist on https://www.privateid.com to obtain your apiKey.

Installation

npm install @privateid/cryptonets-web-sdk

Copy the necessary dependencies to the public folder of your app.

"prestart": "cp -R ./node_modules/@privateid/cryptonets-web-sdk/wasm public/&& cp -R ./node_modules/@privateid/cryptonets-web-sdk/workers public/",
"prebuild": "cp -R ./node_modules/@privateid/cryptonets-web-sdk/wasm public/ && cp -R ./node_modules/@privateid/cryptonets-web-sdk/workers public/"

Add the necessary environment variables on the .env file in the root of your project

SKIP_PREFLIGHT_CHECK=true
REACT_APP_API_URL= 
REACT_APP_API_KEY=

Optional environment variable

REACT_APP_API_ORCHESTRATION=
REACT_APP_SET_CACHE= true | false (Used for predict caching)

Load the WASM Module

The first step is to load and initialize the wasm module.

import { loadPrivIdModule } from '@privateid/cryptonets-web-sdk';

const isSupported = await loadPrivIdModule();

In case of .env file (evironment variable) does not work for you we have added a support to set the variables on load.

import { loadPrivIdModule } from '@privateid/cryptonets-web-sdk';

const isSupported =await loadPrivIdModule(
  api_url, 
  api_key,
  api_orchestration_url,
  wasm_url,
);
StatusDescription
api_urlEquivalent to env variable REACT_APP_API_URL
api_keyEquivalent to env variable REACT_APP_API_KEY
api_orchestration_urlEquivalent to env variable REACT_APP_API_ORCHESTRATION_URL
wasm_urlPlease set it the same with api_url or REACT_APP_API_URL
cache_config?optional field by default "true". if false wasm would not save anything in cache memory
timeout?optional field where you can set the timeout of api call
useCdn?optional field, by default "false" download wasm from package. If "true" wasm will be loaded from CDN setup

The loadPrivIdModule() function returns an object to check if the device is supporting WASM and WebRTC.

{
    support: boolean,
    message: string,
}

Open or switch camera or close camera

The first step is to load and initialize the wasm module.

Open the camera

To open user camera use the openCamera function with element id of the video tag in the DOM

import { openCamera } from '@privateid/cryptonets-web-sdk';

const { devices, faceMode } = await openCamera(element);

it returns list of the available video devices.

Switch to another camera

To switch to another media device use the switchCamera function with the ID of the device to be used

import { switchCamera } from '@privateid/cryptonets-web-sdk';

switchCamera(deviceID);

for the mobile phone we can select whether it's front or back camera for this we pass 'front' or 'back' to the switch function

import { switchCamera } from '@privateid/cryptonets-web-sdk';

switchCamera('front');

Close the camera

To close user camera use the closeCamera function with element id of the video tag in the DOM.

import { closeCamera } from '@privateid/cryptonets-web-sdk';

closeCamera(element); // Will specifically look for the element id and will close that camera
closeCamera(); // By default will close opened camera using openCamera

isValid

Live demo: https://age.devel.private.id

isValid only exercises the is_valid() call and does not find identity. The function detects if there is a valid face in the camera view or in an ImageData Array.

isValid accepts three parameters.

  • callback: callback function to perform actions.
  • imageData: imageData to perform the face captcha on (optional)
  • config: internal configurable settings (optional)
import { isValid } from '@privateid/cryptonets-web-sdk';

 await isValid(callback, imageData, config);

Face CAPTCHA returns 26 possible coded results.

PropertyDescription
-100Internal error
-1Invalid image
0Valid face
1Image spoof
2Video spoof
3Too close
4Too far
5Close to right edge
6Close to left edge
7Close to top edge
8Close to bottom edge
9Too blurry
10Eye glasses detected
11Facemask detected
12Chin too far left
13Chin too far right
14Chin too far up
15Chin too far down
16Image too dim
17Image too bright
18Face low confidence value
19Invalid face background
20Eyes closed
21Mouth open
22Face tilted right
23Face tilted left

Liveness check 7 possible coded results: | Property | Description | |----------|----------------------------| | -100 | Invalid Image | | -4 | Invalid Face | | -3 | Face Too Close To Edge | | -2 | Mobile Phone Detected | | -1 | No Face Detected | | 0 | Real | | 1 | Spoof Detected |

Predict Age

Perform an age estimation using predictAge function on all detected faces from image or camera.

The function takes 4 parameters | Property | Description | |---------------|--------------------------------------------------------------| | callback | The callback function to handle predictAge results. | | config | Internal configurable settings (optional) | | element | The element ID of the video to be used. (optional) | | imageData | ImageData to perform the agePrediction on (optional) |

import { predictAge } from '@privateid/cryptonets-web-sdk';

await predictAge(predictAgeCallback);

Enroll

Perform a new enrollment (register a new user) using the enroll1FA functio. The function will need 10 concecutive valid faces to be able to enroll. We would need to pass the same enroll_token on success using configuration. If enroll_token changes that means we had an invalid image for enroll and started again from the beginning. (Note: Concecutive 10 face needed.) When enrollment is successful after 10 concecutive valid faces, enroll1FA is returning one enrollment image that can be use for document mugshot comparison, etc.

The function takes 3 parameters | Property | Description | |---------------|--------------------------------------------------------------| | callback | The callback function to handle enroll results. | | config | Internal configurable settings (optional) | | element | The element ID of the video to be used. (optional) |

import { enroll1FA } from '@privateid/cryptonets-web-sdk';

const image: ImageData | null = enroll1FA(callback, {enroll_token:"token"});

Predict

Perform predict (authenticate a user) using the predict1FA function

The function takes 3 parameters | Property | Description | |---------------|--------------------------------------------------------------| | callback | The callback function to handle enroll results. | | config | Internal configurable settings (optional) | | element | The element ID of the video to be used. (optional) |

import { predict1FA } from '@privateid/cryptonets-web-sdk';

await predict1FA(callback)

Face Login

Perform Face Login (authenticate a user) using the faceLogin function. Face login performs a more restrictive prediction of face.

The function takes 3 parameters | Property | Description | |---------------|--------------------------------------------------------------| | callback | The callback function to handle enroll results. | | config | Internal configurable settings (optional) | | element | The element ID of the video to be used. (optional) |

import { faceLogin } from '@privateid/cryptonets-web-sdk';

await faceLogin(callback)

Continuous Authentication

Perform continuous user prediction (authentication) using the continuousAuthentication function. This provides the same status updates as Predict.

import { continuousAuthentication } from '@privateid/cryptonets-web-sdk';

continuousAuthentication(callback, configuration, element)

The continuousAuthentication function takes 4 parameters

PropertyDescription
callbackThe callback to be executed on each status
configurationPlease use recommended: { input_image_format: "rgba" }
element(Optional) Element ID of the video tag where the camera is open.

isValidPhotoID

This function finds, crops, align and validate, front and back of the photoID, and returns back a valid cropped and aligned image of the photoID

import { isValidPhotoID } from '@privateid/cryptonets-web-sdk';

//Front of DL scan 
const { imageData, croppedDocument, croppedMugshot } = isValidPhotoID("PHOTO_ID_FRONT", documentCallback);

// Back of DL barcode scan
const { croppedBarcode, croppedDocument } = isValidPhotoID("PHOTO_ID_BACK", callback)

The isValidPhotoID function takes 3 parameters

PropertyDescription
docTypeit can be either PHOTO_ID_BACK (back of the photo ID) or PHOTO_ID_FRONT (front of the photo ID)
callbackreturns the uuid of the portrait on the Front of the Photo ID

The function returns:

Front Document Scan (PHOTO_ID_FRONT) imageData: ImageData datatype of the input image croppedDocument: Uint8ClampedArray convertable to base64String of the cropped document. If document scan is unsuccessful, this will return null croppedMugshot: Uint8ClampedArray convertable to base64String of the cropped face. If document scan is unsuccessful, this will return null (Note: Please use utilty function below for converting images to base64 string.)

Front DL Callback Data returns:

{
    "error": number,
    "payload_type": "face_id",
    "image_width": number,
    "image_height": number,
    "doc_center_x": number,
    "doc_center_y": number,
    "doc_x1": number,
    "doc_y1": number,
    "doc_x2": number,
    "doc_y2": number,
    "doc_x3": number,
    "doc_y3": number,
    "doc_x4": number,
    "doc_y4": number,
    "conf_level": number,
    "cropped_doc_width": number,
    "cropped_doc_height": number,
    "cropped_doc_channels": number,
    "doc_validation_status": number,
    "op_message": string,
    "predict_status": number,
    "face_valid": number,
    "op_status": number,
    "cropped_face_width": number,
    "cropped_face_height": number,
    "cropped_face_size": number,
    "cropped_face_channels": number,
    "status_message": string
}

Front DL Callback Op Status equivalent: | Property | Description | |----------|---------------------------------------| | -2 | SYSTEM ERROR. Please try again later. | | -1 | MOVE CLOSER | | 0 | Success | | 3 | ALMOST DONE . . . | | 4 | MOVE JUST A LITTLE CLOSER | | 9 | TOO BLURRY | | 18 | SHOW FRONT OF DOCUMENT |

Back Document Scan (PHOTO_ID_BACK) inputImage: Uint8ClampedArray convertable to base64String of the cropped document. croppedDocument:: Uint8ClampedArray convertable to base64String of the cropped document. If barcode scan is unsuccessful, this will return null croppedBarcode:: Uint8ClampedArray convertable to base64String of the cropped barcode. If barcode scan is unsuccessful, this will return null

Back DL Callback sample return value: Note: Variables might change depending on the barcode data.

{
    "op_status": number,
    "op_message": "",
    "payload_type": "barcode",
    "image_width": number,
    "image_height": number,
    "barcode_conf_score": number,
    "barcode_c_x0": number,
    "barcode_c_y0": number,
    "barcode_x1": number,
    "barcode_y1": number,
    "barcode_x2": number,
    "barcode_y2": number,
    "barcode_x3": number,
    "barcode_y3": number,
    "barcode_x4": number,
    "barcode_y4": number,
    "crop_img_topleft_x": number,
    "crop_img_topleft_y": number,
    "crop_img_botright_x": number,
    "crop_img_botright_y": number,
    "crop_doc_width": number,
    "crop_doc_height": number,
    "crop_doc_bytes": number,
    "crop_doc_channels": number,
    "crop_barcode_width": number,
    "crop_barcode_height": number,
    "crop_barcode_bytes": number,
    "crop_barcode_channels": number,
    "type": string,
    "format": string,
    "documentId": string,
    "customerId": string,
    "firstName": string,
    "lastName": string,
    "middleName": string,
    "expirationDate": string,
    "issueDate": string,
    "dateOfBirth": string,
    "gender": string,
    "eyeColor": string,
    "hairColor": string,
    "height": string,
    "streetAddress1": string,
    "streetAddress2": string,
    "RestStreetAddress1": string,
    "RestStreetAddress2": string,
    "city": string,
    "state": string,
    "postCode": string,
    "issuingCountry": string,
    "firstNameTruncation": string,
    "placeOfBirth": string,
    "auditInformation": string,
    "inventoryControlNumber": string,
    "lastNameAlias": string,
    "firstNameAlias": string,
    "suffixAlias": string,
    "nameSuffix": string,
    "namePrefix": string,
    "barcode_key_string": string,
    "barcode_key_string_encoding": string,
    "barcodeHash64_string": string,
    "barcodeHash128_string": string,
    "status_message": string
}

Back DL Callback Op Status equivalent: | Property | Description | |----------|---------------------------------------| | -2 | SYSTEM ERROR. Please try again later. | | -1 | MOVE CLOSER | | 0 | Success | | 3 | ALMOST DONE . . . | | 4 | MOVE JUST A LITTLE CLOSER | | 9 | TOO BLURRY | | 10 | MOVE CLOSER TO BARCODE | | 18 | PRESENT BARCODE IN BOX |

Utility function for convertion of image returned by front and back dl scan

convertCroppedImage()

This is a utility function that helps for converting returned image from FRONT DL SCAN and BACK DL SCAN

import { convertCroppedImage } from '@privateid/cryptonets-web-sdk';

// FRONT DL SCAN and BACK DL SCAN
// For converting InputImage returned data FRONT DL SCAN and from BACK DL SCAN.
const InputImageBase64String = convertCroppedImage(inputImage, image_height, image_width);

// FRONT DL SCAN
// For converting croppedDocument returned data from FRONT DL SCAN.
// (Note: We would need other variables that is returned in the callback data. crop_doc_width, crop_doc_height)
const FrontCroppedDocumentBase64String = convertCroppedImage(croppedDocument, crop_doc_width, crop_doc_height);

// For converting croppedMugshot returned data from FRONT DL SCAN.
// (Note: We would need other variables that is returned in the callback data. cropped_face_width and cropped_face_height)
const FrontCroppedMugshotBase64String = convertCroppedImage(croppedMugshot, cropped_face_width and cropped_face_height);

// BACK DL SCAN
// For converting croppedBarcode returned data from BACK DL SCAN.
// (Note: We would need other variables that is returned in the callback data. crop_barcode_width and crop_barcode_width)
const CroppedBarcodeBase64String = convertCroppedImage(croppedBarcode, crop_barcode_width, crop_barcode_height);

// For converting croppedDocument returned data from BACK DL SCAN.
// (Note: We would need other variables that is returned in the callback data. crop_doc_width and crop_doc_height)
const CroppedDocumentBase64String = convertCroppedImage(croppedDocument, crop_doc_width, crop_doc_height);

faceCompareLocal

This function compares 2 faces if they are matching. In the callback it is returning a conf_score (recommended threshold for faceCompare is 0.25)

import { faceCompareLocal } from '@privateid/cryptonets-web-sdk';

faceCompareLocal(callback, imageData1, imageData2, { input_image_format: "rgba" });

The faceCompareLocal function takes 4 parameters | Property | Description | | -------- | ----------------------------------------------------------------------------------------------- | | callback | a function that will handle the result of compare returned | | imageData1 | imageData datatype of the first image | | imageData2 | imageData datatype of second image | | config | Additional configuration. Please enter { input_image_format: "rgba" } as a default |

Sample returned data in callback:

{
    "error": number,
    "distance_max": number,
    "distance_mean": number,
    "distance_min": number,
    "conf_score": number,
    "face_thresholds_count": number,
    "face_thresholds": [
        number,
        number,
        number
    ],
    "result": number,
    "valid_flag_a": number,
    "valid_flag_b": number
}

Licensing Restriction: This product is not licensed for use in regulated gaming. To license in this market, please contact CentralAMS.

deleteUser

This function is used for deleting user with the uuid

import { deleteUser } from "@privateid/cryptonets-web-sdk";

deleteUser(uuid, callback)

Note: Please use Predict to get the user UUID you want to delete and pass it in

The function returns: result: status of the validation of the document

StatusDescription
0deletion is successful
-1deletion is unsuccessful

messege: deletion messege

checkPackageSupport

This function checks if the web browser supports WASM based on: https://www.lambdatest.com/web-technologies/wasm And also checks if WebRTC is supported based on: https://caniuse.com/?search=getusermedia

import { checkPackageSupport } from "@privateid/cryptonets-web-sdk";

checkPackageSupport();

The function returns: status: status is a boolean when "True" the browser supports WASM and "False" browser does not support WASM messege: Messege of the checking of package support.

API Utils

createUser

This function accepts { token (CID or GAN Unique ID/PlayerID), phone, email, ... } and creates user.

import { createUser } from '@privateid/cryptonets-web-sdk';

createUser(parmas)

params = {
    id?: string; // (CID or GAN Unique ID/PlayerID)
    guid?: string;
    phone: string;
    phoneVerified?: boolean;
    email?: string;
    emailVerified?: boolean;
    ssn4?: string;
    ssn9?: string;
    userConsent: boolean;
    userConsentDate: string;
    userFaceEnrollConsent?: boolean;
    consentVersion: string;
    portrait?: string;
};

sendEnrollSms

This function sends SMS to user's phone with a link to acquire front & back of Driver License from mobile. (also enroll face if faceEnrollConsent is true).
From the redirect link in SMS, you can find query string code. You can pass it through verifyToken function as a verification code to get user information.
You can use it if the webcam is lower than 2MP.

import { sendEnrollSms } from '@privateid/cryptonets-web-sdk';

sendEnrollSms({ id })

{
    id: string; // (CID or GAN Unique ID/PlayerID)
}

verifyToken

This function gets the verification code as parameter and return the user information if it's valid code.

import { verifyToken } from '@privateid/cryptonets-web-sdk';

verifyToken({ code, type })

{
    code: string; // verification code
    type: ['phone', 'email']; 
}

uploadPortrait

This function uploads user portrait image.

import { uploadPortrait } from '@privateid/cryptonets-web-sdk';

uploadPortrait({ id, portrait })

{
    id: string; // (CID or GAN Unique ID/PlayerID)
    portrait: string // Base64 
}

uploadDL

This function uploads front & back of Driver Licence image.

import { uploadDL } from '@privateid/cryptonets-web-sdk';

// Uploading Front DL images
uploadDl({ id, type, image })
	id: string //Required
	type: "frontDLoriginal", "frontDLheadshot", "frontDLcropped"
	image: string // Base64 //Require
 
// Uploading Back DL image
uploadDl({ id, type, image })
	id: string //Required
	type: "backDLoriginal", "backDLbarcode"
	image: string // Base64 //Required 
 
// Uploading Back DL barcode JSON
uploadDl({ id, type, barcode})
	id : string //Required
	type:  "barcodeJson"
	barcode: string //Required
ParameterDescription
idId to be set for customerID. (Required)
type"frontDLoriginal", "frontDLheadshot", "frontDLcropped", "backDLoriginal", "backDLbarcode" , "barcodeJson". (required)
imagebase64 string of image. (Required for all type exept 'barcodeJson')
barcodeJSON string of the barcode data. (Required for type 'barcodeJson')

updateUser

This function update user preferred data.
i.e. address, city, state, country, postalCode, etc.
This information will be stored in preferred field of User object in DB.

import { updateUser } from '@privateid/cryptonets-web-sdk';

updateUser({ id, attributes })

{
    id: string; // (CID or GAN Unique ID/PlayerID)
    attributes: {...}; // 
}

getUserStatus

This function will return the status of user.

import { getUserStatus } from '@privateid/cryptonets-web-sdk';

getUserStatus({ id  })

{
    id: string; // (CID or GAN Unique ID/PlayerID)
}

Response

NameValueDescription
userRegisteredtrue, falsetrue if all user information provided for createUser function
emailVerifiedtrue, falseEmail verified for user
phoneVerifiedtrue, falsePhone number verified for user
manualPIIEntrytrue, falsetrue for manual data entry (no Scan ID)
userScanIDtrue, falsetrue Approved Scan ID

validateSecurityToken

This function will validate the returned securityToken.

Note: Token are only valid for 5 minutes starting from the creation of token. After 5 minutes the token will be invalid.

import { validateSecurityToken } from '@privateid/cryptonets-web-sdk';

validateSecurityToken({ uuid, token })

{
    puid: string; // UUID of the user
    token: string; // Token from the api call i.e. enroll1Fa/predict1Fa
}

Response | Name | Value | Description | | ----------- | ------------ | ------------------ | | securityToken | string | The securityToken passed in the API call. | | securityTokenStatus | '1','0' | '1' being TRUE means securityToken is valid. '0' being FALSE means securityToken is invalid. |

clearCache

This is a utility function that will clear the cache data.

import { clearCache } from '@privateid/cryptonets-web-sdk';

clearCache();

generatePasskey

The generatePasskey function is used to generate a passkey based on a UUID.

import { generatePasskey } from '@privateid/cryptonets-web-sdk';

generatePasskey(uuid);

{
    uuid: string; // The UUID for which you want to generate a passkey (Required)
}

authenticatePasskey

The authenticatePasskey function is used to authenticate a generated passkey.

import { authenticatePasskey } from '@privateid/cryptonets-web-sdk';

authenticatePasskey(uuid);

{
    uuid: string; // The UUID for which you want to authenticate a passkey (Required)
}

deletePasskey

The deletePasskey function is used to delete the generated passkey.

import { deletePasskey } from '@privateid/cryptonets-web-sdk';

deletePasskey(uuid);

{
    uuid: string; // The UUID for which you want to delete the passkey (Required)
}
3.3.5

21 days ago

3.3.4

2 months ago

3.3.3

2 months ago

3.3.2

3 months ago

3.3.1

3 months ago

3.3.0

4 months ago

3.2.2

5 months ago

3.2.1

5 months ago

3.2.0

5 months ago

3.0.10

6 months ago

3.0.11

6 months ago

3.2.6

5 months ago

3.2.5

5 months ago

3.2.4

5 months ago

3.2.3

5 months ago

2.1.24

8 months ago

3.2.9

4 months ago

3.2.8

5 months ago

3.2.7

5 months ago

3.1.3

5 months ago

3.1.2

5 months ago

3.1.1

5 months ago

3.1.0

6 months ago

3.1.7

5 months ago

3.1.6

5 months ago

3.1.5

5 months ago

3.1.4

5 months ago

3.1.9

5 months ago

3.1.8

5 months ago

3.0.4

6 months ago

3.0.3

7 months ago

3.0.2

7 months ago

3.0.1

7 months ago

3.0.8

6 months ago

3.0.7

6 months ago

3.0.6

6 months ago

3.0.5

6 months ago

3.0.0

7 months ago

3.0.9

6 months ago

2.0.100-alpha

1 year ago

2.1.9

11 months ago

2.1.14

11 months ago

2.1.12

11 months ago

2.1.13

11 months ago

2.1.10

11 months ago

2.1.11

11 months ago

2.1.18

10 months ago

2.1.19

10 months ago

2.1.23

9 months ago

2.1.21

9 months ago

2.1.22

9 months ago

2.1.20

10 months ago

2.0.104-alpha

1 year ago

2.0.101-alpha

1 year ago

2.0.103-alpha

1 year ago

2.0.108

1 year ago

2.0.107

1 year ago

2.0.106

1 year ago

2.0.105

1 year ago

2.0.102-alpha

1 year ago

2.1.2

12 months ago

2.1.1

1 year ago

2.0.15-beta

11 months ago

2.1.4

12 months ago

2.1.3

12 months ago

2.1.6

12 months ago

2.1.5

12 months ago

2.1.8

11 months ago

2.1.7

12 months ago

2.1.0

1 year ago

2.0.16-beta

11 months ago

2.0.17-beta

10 months ago

2.0.97-alpha

1 year ago

2.0.98-alpha

1 year ago

2.0.91-alpha

1 year ago

2.0.92-alpha

1 year ago

2.0.87-alpha

1 year ago

2.0.89-alpha

1 year ago

2.0.94-alpha

1 year ago

2.0.95-alpha

1 year ago

2.0.88-alpha

1 year ago

2.0.99-alpha

1 year ago

2.0.90-alpha

1 year ago

2.0.93-alpha

1 year ago

2.0.96-alpha

1 year ago

2.0.86-alpha

1 year ago

2.0.74-alpha

1 year ago

2.0.82-alpha

1 year ago

2.0.77-alpha

1 year ago

2.0.85-alpha

1 year ago

2.0.75-alpha

1 year ago

2.0.81-alpha

1 year ago

2.0.71-alpha

1 year ago

2.0.78-alpha

1 year ago

2.0.79-alpha

1 year ago

2.0.84-alpha

1 year ago

2.0.72-alpha

1 year ago

2.0.80-alpha

1 year ago

2.0.70-alpha

1 year ago

2.0.76-alpha

1 year ago

2.0.73-alpha

1 year ago

2.0.83-alpha

1 year ago

2.0.49-alpha

1 year ago

2.0.29-alpha

1 year ago

2.0.69-alpha

1 year ago

2.0.54-alpha

1 year ago

2.0.51-alpha

1 year ago

2.0.31-alpha

1 year ago

2.0.26-alpha

1 year ago

2.0.66-alpha

1 year ago

2.0.46-alpha

1 year ago

2.0.11-alpha

1 year ago

2.0.42-alpha

1 year ago

2.0.37-alpha

1 year ago

2.0.22-alpha

1 year ago

2.0.57-alpha

1 year ago

2.0.34-alpha

1 year ago

2.0.14-alpha

1 year ago

2.0.62-alpha

1 year ago

2.0.55-alpha

1 year ago

2.0.15-alpha

1 year ago

2.0.45-alpha

1 year ago

2.0.25-alpha

1 year ago

2.0.38-alpha

1 year ago

2.0.35-alpha

1 year ago

2.0.18-alpha

1 year ago

2.0.28-alpha

1 year ago

2.0.65-alpha

1 year ago

2.0.68-alpha

1 year ago

2.0.61-alpha

1 year ago

2.0.48-alpha

1 year ago

2.0.58-alpha

1 year ago

2.0.59-alpha

1 year ago

2.0.39-alpha

1 year ago

2.0.19-alpha

1 year ago

2.0.64-alpha

1 year ago

2.0.44-alpha

1 year ago

2.0.41-alpha

1 year ago

2.0.36-alpha

1 year ago

2.0.56-alpha

1 year ago

2.0.21-alpha

1 year ago

2.0.27-alpha

1 year ago

2.0.52-alpha

1 year ago

2.0.47-alpha

1 year ago

2.0.12-alpha

1 year ago

2.0.67-alpha

1 year ago

2.0.16-alpha

1 year ago

2.0.32-alpha

1 year ago

2.0.24-alpha

1 year ago

2.0.50-alpha

1 year ago

2.0.30-alpha

1 year ago

2.0.60-alpha

1 year ago

2.0.20-alpha

1 year ago

2.0.40-alpha

1 year ago

2.0.17-alpha

1 year ago

2.0.23-alpha

1 year ago

2.0.13-alpha

1 year ago

2.0.63-alpha

1 year ago

2.0.53-alpha

1 year ago

2.0.33-alpha

1 year ago

2.0.43-alpha

1 year ago

2.0.10-alpha

1 year ago

2.0.9-alpha

1 year ago

2.0.8-alpha

2 years ago

2.0.7-alpha

2 years ago

2.0.6-alpha

2 years ago

2.0.5-alpha

2 years ago