GithubHelp home page GithubHelp logo

scalar-labs / scalardl-web-client-sdk Goto Github PK

View Code? Open in Web Editor NEW
25.0 16.0 2.0 2.81 MB

This is a library for web applications by which the applications can interact with a Scalar DL network.

License: Other

HTML 3.08% JavaScript 96.11% Java 0.81%

scalardl-web-client-sdk's Introduction

Caution

The docs folder has been moved to the centralized documentation repository, docs-internal. Please update this documentation in that repository instead.

To view the ScalarDL documentation, visit ScalarDL Documentation.

Scalar DL Web Client SDK

This is a library for web applications by which the applications can interact with a Scalar DL network.

Node version used for development and testing

This package has been developed and tested using Node LTS v14.16.0. named "fermium". This means we cannot guarantee the package nominal behaviour when using other Node versions.

Install

We can use package manager to install this library. For example, to install with NPM:

NPM

npm install @scalar-labs/scalardl-web-client-sdk

You can also find a bundle scalardl-web-client-sdk.bundle.js which can be imported statically in @scalar-labs/scalardl-web-client-sdk/dist.

HOWTO

Create ClientService instance

ClientService class is the main class of this package. It provides following functions to request Scalar DL network.

Name Use
registerCertificate To register a client's certificate to a Scalar DL network
registerContract To register the contracts to the registered client of the Scalar DL network
listContracts To list all registered contracts of the client
executeContract To execute a registered contract of the client
validateLedger To validate an asset of the Scalar DL network to determine if it is tampered

If an error occurs when executing one of the above methods, a ClientError will be thrown. The ClientError.statusCode provides additional context. Please refer to the Runtime error section below for the status code specification.

Use the code snippet below to create a ClientService instance.

import { ClientService } from '@scalar-labs/scalardl-web-client-sdk';
const clientService = new ClientService(clientProperties);

Or, if you use the static release, try following

<head>
    <meta charset="utf-8">
    <script src="scalardl-web-client-sdk.bundle.js"></script>
</head>

<script>
    const clientService = new Scalar.ClientService(clientProperties);
</script>

The clientProperties argument is mandatory for the constructor. This is a properties example that a user [email protected] would use to try to connect to the server scalardl.example.com:50051 of the Scalar DL network.

{
    'scalar.dl.client.server.host': 'scalardl.example.com',
    'scalar.dl.client.server.port': 50051,
    'scalar.dl.client.server.privileged_port': 50052,
    'scalar.dl.client.cert_holder_id': '[email protected]',
    'scalar.dl.client.private_key_pem': "-----BEGIN EC PRIVATE KEY-----\nMHc...",
    'scalar.dl.client.cert_pem': "-----BEGIN CERTIFICATE-----\nMIICjTCCAj...n",
    'scalar.dl.client.cert_version': 1,
    'scalar.dl.client.tls.enabled': false,
}

If the auditor capability is enabled on the Scalar DL network, specify additional properties like the following example. In this example, the client interacts with the auditor scalardl-auditor.example.com and detects Byzantine faults including data tampering when executing contracts.

{
    'scalar.dl.client.auditor.enabled': true,
    'scalar.dl.client.auditor.host': 'scalardl-auditor.example.com',
    'scalar.dl.client.auditor.port': 40051,
    'scalar.dl.client.auditor.privileged_port': 40052,
}

In what follows assume that we have a clientService instance.

Register the certificate

Use the registerCertificate function to register a certificate on the Scalar DL network.

await clientService.registerCertificate();

Please refer to the Status code section below for the details of status.

Register contracts

Use the registerContract function to register a contract.

await clientService.registerContract('contractId', 'com.example.contract.contractName', contractUint8Array, propertiesObject);

Register functions

Use the registerFunction function to register a function.

await clientService.registerFunction('functionId, 'com.example.function.functionName', functionUint8Array);

List registered contracts

Use listContracts function to list all registered contracts.

const constracts = await clientService.listContracts();

Execute a contract

Use executeContract function to execute a registered contract. It will also execute a function if _functions_ is given in the argument.

const response = await clientService.executeContract('contractId', argumentObject);
const executionResult = response.getResult();
const proofsList = response.getProofs();
const response = await clientService.executeContract('contractId', { 'arg1': 'a', '_functions_': [functionId] }, { 'arg2': 'b' });

{ 'arg1': 'a', will be passed via contractArgument, while { 'arg2': 'b' } will be passed via functionArgument.

Validate an asset

Use the validateLedger function to validate an asset in the Scalar DL network.

const response = await clientService.validateLedger('assetId');
const status = response.getCode();
const proof = response.getProof();

Validate an asset linearizably

The default ledger validation in a Auditor-enabled Scalar DL network is non-linearizable; i.e., there might be cases where Ledger and Auditor look inconsistent temporarily. Scalar DL supports linearizable ledger validation. To use it, we can configure the properties as follows

{
    'scalar.dl.client.auditor.enabled': true,
    ...
    'scalar.dl.client.auditor.linearizable_validation.enabled': true,
    'scalar.dl.client.auditor.linearizable_validation.contract_id': '<choose a contract ID>',
}

and, register the ValidateLedger contract as the contract ID we specified in the properties. Then, the ClientService.validateLedger function can provide linearizable ledger validation.

Runtime error

Error thrown by the client present a status code.

try {
    await clientService.registerCertificate();
} catch (clientError) {
    const message = clientError.message;
    const statusCode = clientError.code;
}

Enumeration StatusCode enumerates all the possible status.

StatusCode = {
  OK: 200,
  INVALID_HASH: 300,
  INVALID_PREV_HASH: 301,
  INVALID_CONTRACT: 302,
  INVALID_OUTPUT: 303,
  INVALID_NONCE: 304,
  INCONSISTENT_STATES: 305,
  INVALID_SIGNATURE: 400,
  UNLOADABLE_KEY: 401,
  UNLOADABLE_CONTRACT: 402,
  CERTIFICATE_NOT_FOUND: 403,
  CONTRACT_NOT_FOUND: 404,
  CERTIFICATE_ALREADY_REGISTERED: 405,
  CONTRACT_ALREADY_REGISTERED: 406,
  INVALID_REQUEST: 407,
  CONTRACT_CONTEXTUAL_ERROR: 408,
  ASSET_NOT_FOUND: 409,
  FUNCTION_NOT_FOUND: 410,
  UNLOADABLE_FUNCTION: 411,
  INVALID_FUNCTION: 412,
  DATABASE_ERROR: 500,
  UNKNOWN_TRANSACTION_STATUS: 501,
  RUNTIME_ERROR: 502,
  CLIENT_IO_ERROR: 600,
  CLIENT_DATABASE_ERROR: 601,
  CLIENT_RUNTIME_ERROR: 602,
};

IndexedDB support

This library supports storing private keys in the browsers' IndexedDB. To use the feature, please decorate ClientService object with ClientServiceWithIndexedDb as follows.

const clientService = await new ClientServiceWithIndexedDb(new ClientService(properties));

ClientServiceWithIndexedDb stores a private key in IndexedDB if the key is specified in client properties and reads a private key from the IndexedDB if the key is not specified in client properties.

Based on the behavior, it is recommended to use it as follows. If a private key is not found, IndexedDbKeyNotFoundError will be thrown and the application needs to get a private key from an external service.

let properties = {
    'scalar.dl.client.cert_holder_id': '[email protected]',
    'scalar.dl.client.cert_version': 1,
    ...
}; // Not specify 'scalar.dl.client.private_key_pem' or 'scalar.dl.client.private_key_cryptokey'

let clientService;
try {
    // It tries to read a private key from IndexedDB
    clientService = await new ClientServiceWithIndexedDb(new ClientService(properties));
} catch (err) {
    if (err instanceof IndexedDbKeyNotFoundError) {
        properties['scalar.dl.client.private_key_pem'] = /* from some place */
        // This time, it stores the specified private key in IndexedDB
        clientService = await new ClientServiceWithIndexedDb(new ClientService(properties));
    } else {
        throw err; // How to handle the error should be decided by application side
    }
}

deleteIndexedDb

deleteIndexedDb removes a private key in IndexedDB according to scalar.dl.client.cert_holder_id and scalar.dl.client.cert_version in client properties.

clientService = await new ClientServiceWithIndexedDb(new ClientService(properties));
clientService.deleteIndexedDb(); // Remove stored key in indexedDb

Envoy configuration

Scalar DLT server (grpc) uses a custom header called rpc.status-bin to share error metadata with the client. This means envoy needs to be configured to expose the header to clients. More specifically, rpc.status-bin needs to be added to the expose-headers field of the cors configuration.

Contributing

This library is mainly maintained by the Scalar Engineering Team, but of course we appreciate any help.

  • For asking questions, finding answers and helping other users, please go to stackoverflow and use scalardl tag.
  • For filing bugs, suggesting improvements, or requesting new features, help us out by opening an issue.

License

Scalar DL client SDK is dual-licensed under both the AGPL (found in the LICENSE file in the root directory) and a commercial license. You may select, at your option, one of the above-listed licenses. Regarding the commercial license, please contact us for more information.

scalardl-web-client-sdk's People

Contributors

dependabot[bot] avatar feeblefakie avatar jnmt avatar josh-wong avatar moon004 avatar scalar-boney avatar scalarindetail avatar supl avatar tei-k avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

scalardl-web-client-sdk's Issues

Importing EC private keys into CryptoKey with PKCS#8 format doesn't work on Firefox

We found that this code snippet doesn't work on Firefox.

const ecdsaPKCS8 = "-----BEGIN PRIVATE KEY-----\n" +
        "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQghsSVj9WzmcShUawd\n" +
        "nwb2JzFlyxGVPYNwch/EU2RmucehRANCAAT9PMYRxgk1zB7l34GU+7G7CIiEyEqk\n" +
        "ylMxkz3gv5tGEM8WficyKBwKKOV7LuqE5/CmVWtO2c0tM0wPza23CdHu\n" +
        "-----END PRIVATE KEY-----\n";

console.log(await window.crypto.subtle.importKey(
        'pkcs8',
        hextoArrayBuffer(b64utohex(ecdsaPKCS8.replace('-----BEGIN PRIVATE KEY-----', '').replace('-----END PRIVATE KEY-----', '').replace(/\r\n/g, ''))),
        {
            name: 'ECDSA',
            namedCurve: 'P-256',
        },
        false,
        ['sign'],
));

This makes Scalar DL Web SDK can't work on Firefox because the current implementation uses PKCS#8 format to import private keys into CryptoKey.

According to this bug report https://bugzilla.mozilla.org/show_bug.cgi?id=1048931
it seems that we can only import EC private key with JWK (JSON Web Key) format.

We should consider using JWK as the input to import private keys instead of PKCS#8.

NPM install missing distribution directory

I think npm install @scalar-labs/scalardl-web-client-sdk should include the scalardl-web-client-sdk.bundle.js. The current included files required a webpack enabled project which might not always be the case.

I suggest the make dist output should be included in the npm bundle.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.