# Using Trinsic + Kwil
This document proposes an approach for an identity application using [Trinsic](https://trinsic.id/) to integrate with a decentralized database on [Kwil](https://www.kwil.com/). The proposed system uses Trinsic for credential issuance and verification and Kwil for decentralized storage and management.
## Reading / Writing Credentials
When a user accepts a Trinsic credential, the same service can encrypt and store the credential on Kwil. For example, using Kwil's and Trinsic's APIs:
```javascript
import { TrinsicService } from "@trinsic/trinsic";
import { WebKwil, KwilSigner } from "@kwilteam/kwil-js";
async function acceptAndStoreCredential(
trinsic: TrinsicService,
credential: string,
kwil: WebKwil,
signer: KwilSigner
) {
// accept credential on Trinsic
const acceptCredentialResponse = await trinsic.credential().acceptCredential({
documentJson: credential,
})
//** add credential encryption */
// store credential on Kwil
return await kwil.execute({
dbid: "some_dbid",
name: "store_credential",
inputs: [{
$item_id: acceptCredentialResponse.itemId,
$credential_json: acceptCredentialResponse.documentJson // or encrypted credential
}]
}, signer)
}
```
Similarily, credentials are read from Kwil and verified with Trinsic:
```javascript
import { TrinsicService } from "@trinsic/trinsic";
import { WebKwil, KwilSigner } from "@kwilteam/kwil-js";
async function retrieveAndGenerateProof(
trinsic: TrinsicService,
kwil: WebKwil,
itemId: string
) {
// retrieve credential from kwil
const { data } = await kwil.call({
dbid: "some_dbid",
name: "retrieve_credential",
inputs: [{
$item_id: itemId
}]
})
const credential = data?.result[0].credential_json
/** decrypt credential and do something */
// generate and return proof
return await trinsic.credential().createProof({
documentJson: credential,
itemId
})
}
```
## Kwil Key Management
Writing data to Kwil requires a Secp256k1 key pair. The identity application can generate and custody a key for the user or use an admin key to write data on behalf of the user.
### Generate Key for User
Generate a new wallet with a key that is custodied by the identity platform. The identity platform can use most key custody solutions (e.g. [AWS KMS](https://aws.amazon.com/blogs/database/make-eoa-private-keys-compatible-with-aws-kms/)).
```javascript
import { Wallet } from 'ethers'
import { KwilSigner } from '@kwilteam/kwil-js'
function generateUserSigner(private_key: string) {
const ethereumWallet = new Wallet(private_key)
return new KwilSigner(ethereumWallet, ethereumWallet.address)
}
```
### Use Admin Key
Use an admin private key (owned and managed by the identity application) to sign transactions on behalf of the user:
```javascript
import { Wallet } from 'ethers'
import { KwilSigner } from '@kwilteam/kwil-js'
function generateAdminSigner() {
const adminWallet = new Wallet("admin_private_key")
return new KwilSigner(adminWallet, adminWallet.address)
}
```
## Launching a Multi-node Network
The third component is launching a multi-node database network. - **[Tutorial Here](https://docs.kwil.com/docs/node/tutorial)**
The Kwil Team can set up the network, run validators, run RPC nodes, and enable other stakeholders to run validators in the network (customers, investors, etc).
The network will also need a database schema, which is defined using Kwil's [SQL smart contract language](https://docs.kwil.com/docs/kuneiform/introduction). A basic example schema is included below.
### Example Identity Schema
This schema can be tested at admin.kwil.com.
```javascript
database identity;
// credentials stored encrypted verifiable credentials, tied to a user
table credentials {
item_id uuid primary key,
credential_json text not null,
submitted_by text not null
}
// regiser credential allows a user to add a credential to the database
// if the credential already exists, it will error
procedure store_credential ($item_id uuid, $credential_json text) public {
// store credential
INSERT INTO credentials (item_id, credential_json, submitted_by)
VALUES ($item_id, $credential_json, @caller);
}
// retrieve credential gets a credential from the database
procedure retrieve_credential ($item_id uuid) public view returns table(item_id uuid, credential_json text){
return SELECT item_id, credential_json
FROM credentials
WHERE item_id = $item_id;
}
// delete credential allows a user to remove a credential from the database
// only the wallet that submitted the credential can remove it
procedure delete_credential($item_id uuid) public {
$record_owner text;
// get the owner for the selected record
for $owner in SELECT submitted_by FROM credentials WHERE item_id = $item_id {
$record_owner := $owner.submitted_by;
}
// check if the person calling the action is the owner
if $record_owner != @caller {
error('you cannot delete a credential you do not own!');
}
// delete the record
DELETE FROM credentials WHERE item_id = $item_id;
}
```