Legacy

All content here will be functional for v2 of the sdk (If you need to use the wasm-pemFile model).

Current version is v3

Introduction to KleverChain SDK

Introduction to develop and start integration with KleverChain main methods

The SDK module provides a quick and easy way to make contract calls directly to the Klever blockchain directly.

Installation

$ npm install @klever/sdk

or

$ yarn add @klever/sdk

Setup

Web App

After installation, the KleverSDK folder will automatically appear inside your public, assets or static folder (according to the framework used).

To load the KleverSDK WASM file into your DOM you just need to import the loader script in your index.html or app.html:

You can achieve this placing one of the script tags below:

//If you're using React:
<script src="%PUBLIC_URL%/kleverSDK/kleverSDKLoader.js"></script>
//If you're using Vue or Svelte:
<script src="/kleverSDK/kleverSDKLoader.js"></script>
//If you're using Sveltekit:
<script src="%sveltekit.assets%/kleverSDK/kleverSDKLoader.js"></script>
//If you're using Angular:
<script src="assets/kleverSDK/kleverSDKLoader.js"></script>
//If you're using NextJS:
import Script from "next/script";

<Script
  src="/kleverSDK/kleverSDKLoader.js"
  strategy="beforeInteractive"
/>

You can use any framework you like.

NodeJS

NodeJS version 18+ is required, since we rely on the newly implemented fetch API.

Just require the kleverSDKLoader that appeared on the root level of your project after installation.

//CommonJS
require("./kleverSDK/kleverSDKLoader");
...

How to use KleverChain SDK

Getting started with the KleverChain SDK

Basic usage

There are _two ways t_o make a contract call: you can call only one method passing the user data plus the contract data or you can create an instance of an account.

Sender address and private key is required in all transactions.

With a simple call:

import { sendTransaction, TransactionType } from "@klever/sdk";

const transactionType = TransactionType.Transfer;
const transactionPayload = {
  sender: "address",
  privateKey: "privateKey",
  receiver: "receiver",
  amount: 100,
};

sendTransaction(transactionType, transactionPayload);

With an account instance:

import { Account } from "@klever/sdk";

const account = new Account("address", "privateKey");
const transactionPayload = {
  receiver: "receiver",
  amount: 100,
};

account.sendTransfer(transactionPayload);

Transactions

All available transactions:

IDType
0Transfer
1Create Asset
2Create Validator
3Validator Config
4Freeze
5Unfreeze
6Delegate
7Undelegate
8Withdraw
9Claim
10Unjail
11Asset Trigger
12Set Account Name
13Proposal
14Vote
15Config ITO Prices
16Set ITO Prices
17Buy
18Sell
19Cancel Market Order
20Create Marketplace
21Config Marketplace
22Update Account Permission

Usage Inside a Context

If you want a global instance of your account to use throughout your app, you can create a custom hook to help you with that.

Using React as an example, you can create a MyCustomHook.tsx file and create your provider as follows:

import { useState, createContext, useContext } from 'react';
import { Account, core } from '@klever/sdk';

interface ISdkContext {
  isLoaded(): Promise<boolean>;
  getAccount(): Account | null;
  setAccount(account: Account): void;
}

const SdkContext = createContext({} as ISdkContext);

const SdkProvider: React.FC = ({ children }) => {
  const [acc, setAcc] = useState<Account | null>(null);

  const values: ISdkContext = {
    isLoaded: () => core.isSDKLoaded(),
    getAccount: () => acc,
    setAccount: account => setAcc(account),
  };
  return <SdkContext.Provider value={values}>{children}</SdkContext.Provider>;
};

const useSdk = () => useContext(SdkContext);

export { SdkContext, SdkProvider, useSdk };

And wrap your entire App.tsx in it:

import { SdkProvider } from './MyCustomHook';
...
  <SdkProvider>
    ...
  </SdkProvider>
...

With that, you can use it on any child component you want, without the need to instantiate an account every time:

import { useSdk } from './MyCustomHook';
...
const sdk = useSdk();
const account = sdk.getAccount();
...
await account.sendTransfer(payload)
...

The same pattern of global provider can be achieved in any framework you want, not only React.

Optional Params

How to send more than one contract per transaction and how to send metadata

When using the SDK you may have the need to send more than one contract per transaction or to send metadata within the transaction.

Both these things are achieved passing an additional param to either sendTransaction or to the account.sendContract`` methods.

The second parameter is a "props" object that contains these parameters:

  • metadata
  • autobroadcast
  • previousTX

Sending Metadata

Sending metadata will cause additional fee charges to be applied for every byte.

To add metadata to a transaction, just add a string to the metadata prop.

Ex:

const metadata = "this text will be sent in the blockchain transaction"

await account.sendTransfer(payload, {metadata})

Autobroadcast

Autobroadcast is on by default, meaning that if you call a send transaction method, it will be sent to the blockchain with the parameters you called, but you can disable this option with the autobroadcast prop.

In this way, you can get the raw transaction and contracts info that are built inside the SDK before the transaction is sent to be processed by the blockchain. You can get some useful info, like the fees you/the user will be paying for that transaction.

If you disable the autobroadcast, you can manually broadcast the transaction using the broadcast() method. Ex:

const rawTransaction: ITransactionResponse = await account.sendTransfer(
transferPayload, {
    autobroadcast: false
})

console.log({rawTransaction})
//insert any rawTX treatment, like confirming the fees

const broadcastResponse: IBroadcastResponse = await broadcast(JSON.stringify(rawTransaction))

Sending multiple contracts per transaction

By default when you use a "send" method, it automatically broadcasts the transaction to the blockchain.

So if you want to send multiple contracts, disable this option with the autobroadcast prop, then chain-build (using the previousTX prop) the contracts you want to broadcast. After that, broadcast the transaction containing all the contracts.

Ex:

const transferContract: ITransactionResponse = await account.sendTransfer(
transferPayload, {
    autobroadcast: false
})

const freezeAndTransferContract: IBroadcastResponse = await account.sendTransfer(
freezePayload, {
    previousTX: transferContract,
}) // this will autobroadcast the multi-contract TX

Sign Message/Verify Signature

Usage of the sign/verify flow

As of 30/Aug the verifySignature method is only supported by the legacy pem-file method

When using the main methods for generating transactions, the user signs them with their private key automatically upon sending them.

However any message can be signed with the private key and the signature can be verified using the public key and comparing, which can be useful for authentication of contracts of any sort between users.

For KleverChain regular accounts, the public key is the address of the account.

Usage example:

import { core } from '@klever/sdk';

const message = 'hello world';

// sign the message "hello world"
const { signature } = await core.signMessage(
        message,
        privateKey,
      );
//signature is a cipher not decryptable with just the message content, but verifiable

//"valid" is a boolean, which is the return of the verifySignature promise
const { valid } = await core.verifySignature(
        message,
        signature,
        walletAddress,
      );

console.log(valid);
// should log true if the message/signature and privateKey/walletAddress
// combinations are compatible

Raw Functions

The KleverChain SDK provides an easy way to interact with the blockchain by introducing a TypeScript interface to the webassembly(wasm) underlying functions, this functions, however, are still acessible via the global object interface, inside the kleverWeb object.

Ex for using in the browser:

window.kleverWeb.sendTransaction(transactionType, payload, props)

Ex for using in Node.js:

globalThis.kleverWeb.sendTransaction(transactionType, payload, props)

Note that as you are calling raw wasm functions, there will be no type interface unless you enforce it in your own code.

Wasm Functions

All the following functions that can be called this way:

- getAccount(address)
- createAccount()
- getAddressFromPrivateKey(privateKey)
- generateMnemonic()
- parsePemFileData(pemString)
- decodePEM(cipheredPem, password)
- signMessage(JSON.stringify({message, privatekey}))
- verifySignature(JSON.stringify({message, signature, publicKey}))
- setApiUrl(newApiUrl)
- setNodeUrl(newNodeUrl)
- sendTransaction(transactionType, payload, props)
- signTx(JSON.stringify({ rawTx, privateKey }))
- broadcast(JSON.stringify(signedTx))

All the functions above return a promise, so be sure to use "await" or other promise treatment.

Raw Transaction Broadcast Flow

This is automatically managed by the extension, but if you choose to use the raw functions, please note that there are some underlying steps.

The base flow is sendTransaction -> signTx -> broadcast.

"Send" in this case means converting the payload in a object that can be read by the blockchain, which we will call "raw TX"

Example flow:


const rawTx = await globalThis.kleverWeb.sendTransaction(
    transactionType,
    JSON.stringify(payload),
    JSON.stringify(props)
  );

 const { signature } = await globalThis.kleverWeb.signTx(JSON.stringify({
    rawTx,
    privateKey
}))

const signedTx = { ...rawTx,
    Signature: signature
    }

const broadcastResponse = await globalThis.kleverWeb.broadcast(JSON.stringify(signedTx))

console.log(broadcastResponse)

sendTransaction payload and props

payload:

The payload is a stringified object that will always need a sender and nonce properties, and additional ones depending on the contract type.

Ex:

const payload = JSON.stringify({
  receiver,
  amount,
  asset,
  sender,
  nonce
})

const rawTx = await globalThis.kleverWeb.sendTransaction(0,payload)
// The first argument can be either 0, "0" or "TransferContractType"

console.log(rawTx)

props:

The props is a stringified object that is optional, it has two independent properties: metadata and previousTX.

Metadata can be any string that will be stored in the transaction when it is in the blockchain, notably used when storing metadata in a NFT through the update metadata asset trigger. If you store metadata in a transaction, be sure to store it's hash.

Storing data in a TX will increase the bandwidth fee

Ex:

const props = JSON.stringify({
    metadata: "this string will be stored in the blockchain upon broadcast"
})

const rawTx = await globalThis.kleverWeb.sendTransaction(0,payload, props)

console.log(rawTx)

PreviousTX is a way of chaining transactions, so you can create a multi-contract transaction.

Multi-contract flow: sendTransaction -> ... -> sendTransaction -> signTx -> broadcast

Ex:

const singleContractTx = await globalThis.kleverWeb.sendTransaction(0,payload)

const props = JSON.stringify({
    previousTX: singleContractTx[0],
})

const multiContractTx = await globalThis.kleverWeb.sendTransaction(2,payload2,props)

console.log(multiContractTx)

If you want to chain contracts with metadata, use both props, each metadata will be assigned to the respective contract, they are related by the data array index.

Was this page helpful?