Kwil JS Overview
Below is a quick overview of how to use the Kwil JS SDK. For more detailed information, see the API Reference.
Installation
The Kwil JS SDK can be installed using npm.
npm install @kwilteam/kwil-js@beta ethers
Initialize
Kwil has different initialization logic for Browser and NodeJS
- Browser
- NodeJS
import { WebKwil } from '@kwilteam/kwil-js';
const kwil = new WebKwil({
kwilProvider: "kwil_provider_endpoint",
chainId: "your_kwil_chain_id"
});
import { NodeKwil } from '@kwilteam/kwil-js';
const kwil = new kwiljs.NodeKwil({
kwilProvider: "kwil_provider_endpoint",
chainId: "your_kwil_chain_id"
});
Optional Configuration
The WebKwil
and NodeKwil
constructors take a configuration object. The only required fields are kwilProvider
and chainId
; however, there are additional configuration options available:
import { WebKwil, Utils } from '@kwilteam/kwil-js';
const kwil = new WebKwil({
kwilProvider: 'http://localhost:8484';
chainId: 'kwil-testnet';
// optional configuration
autoAuthenticate?: boolean; // automatically authenticate with Kwil Gateway / Kwild private RPC, default true
unconfirmedNonce?: boolean; // sends transactions and returns getAccount with unconfirmed nonce, default false
timeout?: number; // timeout for requests, default 30000
logging?: boolean; // enable logging, default false
logger?: Function // custom logger, default console.log
});
To verify you have the correct chainId
, you can use the chainInfo()
method.
Identifiers
Account Identifiers
In Kwil, accounts are identified by the signer(s) that are used on the Kwil Network. Kwil natively supports two types of signers: Secp256k1 (EVM) and ED25519.
Secp256k1 signers use Ethereum wallet addresses as account identifiers. ED25519 signers use the ED25519 public key as account identifiers.
Signers
Certain operations in Kwil require signature authentication from the user (e.g. execute action, INSERT/UPDATE/DELETE/CREATE/DROP, transfer funds, etc).
To manage signing, Kwil-JS uses a KwilSigner
class. Out of the box, Kwil-JS supports signers from ethers.js (v5 and v6). You can also pass a custom signing callback function (see below).
- Browser
- NodeJS
import { KwilSigner } from '@kwilteam/kwil-js';
import { BrowserProvider } from 'ethers';
// get ethers signer
const provider = new BrowserProvider(window.ethereum)
const signer = await provider.getSigner();
// get ethereum address
const identifier = await signer.getAddress();
// create kwil signer
const kwilSigner = new KwilSigner(signer, identifier);
import { KwilSigner } from '@kwilteam/kwil-js';
import { Wallet } from 'ethers';
// create ethers signer
const signer = new Wallet("my_ethereum_private_key");
// get eth address
const identifier = await signer.getAddress();
// create kwil signer
const kwilSigner = new KwilSigner(signer, identifier);
Custom Signers
If you wish to sign with something other than an ethers signer, you may pass a callback function that accepts and returns a Uint8Array()
and the enumerator for the signature type used.
Currently, Kwil supports two signature types:
Type | Identifier | Enumerator | Description |
---|---|---|---|
Secp256k1 | Ethereum Wallet Address | secp256k1 | The Kwil Signer will use a secp256k1 elliptic curve signature, which is the same signature used in Ethereum's personal sign. |
ED25519 | ED25519 Public Key | ed25519 | The Kwil Signer will use an ED25519 signature. |
To use an ed25519 signature:
import nacl from "tweetnacl";
import { KwilSigner } from "@kwilteam/kwil-js";
// create keypair and signer
const keys = nacl.sign.keyPair();
const customSigner = (msg) => nacl.sign.detached(msg, keys.secretKey);
const kwilSigner = new KwilSigner(customSigner, keys.publicKey, "ed25519");
Writing Data
To write data on Kwil, you can (1) execute an ad-hoc SQL query or (2) execute an action.
Ad-Hoc SQL
If the signer has the required permissions, they can execute ad-hoc SQL queries on the database.
const res = await kwil.execSql(
'INSERT INTO users (name, age) VALUES ($name, $age)',
{
$name: "John Doe",
$age: 30
},
kwilSigner,
true // set to true to wait for the transaction to be confirmed
)
/*
res.data = {
tx_hash: "hash",
}
*/
Executing Actions
Actions are pre-defined operations that can be executed on the database.
You can bulk execute an action by passing an array of objects to the inputs
field (to name each parameter), or an array of tuples (for unnamed parameters).
To execute an action once, pass only one tuple to the inputs array.
const res = await kwil.execute(
{
namespace: 'db_namespace' // e.g., 'main',
name: 'action_name', // e.g., 'create_user',
// execute the same action two times:
inputs: [
['iter_1_value_1', 'iter_1_value_2', 'iter_1_value_3'],
['iter_2_value_1', 'iter_2_value_2', 'iter_2_value_3'],
],
description: 'Click sign to execute'
},
kwilSigner,
true // set to true to wait for the transaction to be confirmed
)
/*
res.data = {
tx_hash: "hash",
}
*/
If using TypeScript, you can import interfaces for each API from the types
namespace.
import { Types } from '@kwilteam/kwil-js'
const actionBody: Types.ActionBody = {...}
const callBody: Types.CallBody = { ... }
Reading Data
To read data on Kwil, you can (1) execute ad-hoc SELECT queries or (2) call view actions.
Ad-Hoc SELECT Queries
const res = await kwil.selectQuery(
'SELECT * FROM users WHERE age > $age',
{
$age: 30
}
)
/*
res.data = [
...
]
*/
View Actions
View actions are read-only actions that return data without having to wait for a transaction to be mined on Kwil.
If the view
action uses a @caller
contextual variable, you must pass a KwilSigner
as the second argument to the kwil.call()
method to identify the caller.
const res = await kwil.call(
{
namespace: 'db_namespace',
name: 'action_name',
inputs: ['input_value_1', 'input_value_2']
},
kwilSigner
)
/*
res.data = {
result: [ query results ],
}
*/
Network Info
ChainID and Status
To verify that you are using the correct chainId
, as well as the latest block height and block hash on your chain, you can call the .chainInfo()
method.
const res = await kwil.chainInfo()
/*
res.data = {
chain_id: "your_chain_id",
height: "latest_block_height",
hash: "latest_block_hash"
}
*/
Get Account
You can get the nonce and balance of an account by using the .getAccount()
method. .getAccount()
takes an account identifier, either in hex format or bytes (Uint8Array).
If you are using a custom signer, you should pass the signer's enumerator as the second argument.
// using secp256k1 (Ethereum) signer or ed25519 signer
const res = await kwil.getAccount("account_identifier")
// using custom signer
const res = await kwil.getAccount("account_identifier", "custom_signer_enumerator")
/*
res.data = {
identifier: Uint8Array,
balance: "some_balance",
nonce: "some_nonce"
}
*/
Read Access Control
Private Mode
Private RPC is a server-side configuration in kwild that enforces user authentication for each call request. Learn more about private mode here.
const body: CallBody = {
namespace,
name: 'your_action_name',
inputs: ['input_value_1', 'input_value_2']
};
// pass body AND kwilSigner if in Private Mode
const res = await kwil.call(body, kwilSigner);
Kwil Gateway Authentication
Kwil Gateway is an optional service on Kwil networks that allows for authenticating users with their signatures for read queries / view procedures.
Advanced read access control is under development. Please check back soon for updates.
The Kwil Gateway is in private beta. If you would like access, please contact our team.
// pass KwilSigner to the call method
const res = await kwil.call(body, kwilSigner);
/*
res.data = {
result: [ query results ],
}
*/
Gateway logout
To log out of the Kwil Gateway, you can call the kwil.auth.logoutKGW()
method. This is useful if you want to switch accounts or remove the authentication cookie.
await kwil.auth.logoutKGW();