@idos-network/issuer-sdk-js v0.0.4
idOS Issuer JavaScript SDK
Installing
Get our NPM package and its dependencies with pnpm or the equivalent of your package manager of choice:
pnpm add @idos-network/issuer-sdk-jsBefore you start
When using this package, you're going to need to be familiar with how a dApp works with the idOS. Make sure you read idos-sdk-js's README before you proceed.
Setting up
Create an issuer config with your secret key. This config will be used to interact with the idOS.
// issuer-config.js
import { createIssuerConfig } from "@idos-network/issuer-sdk-js";
const signingKeyPair = nacl.sign.keyPair.fromSecretKey(ISSUER_SIGNING_SECRET_KEY);
const issuerConfig = await createIssuerConfig({
// To use a non-prod environment, pass in "nodes.playground.idos.network".
nodeUrl: "https://nodes.idos.network/",
signingKeyPair,
});Creating a user profile
This procedure can only be done by a Permissioned Issuer. Get in touch with us at engineering@idos.network if you're interested in being one.
To create a user profile in idOS, you need: 1. A wallet address associated with the user. 2. A public encryption key derived from either a password or a passkey chosen by the user in the idOS enclave app.
User Creation Process
Step 1: Decide on a user id
Deciding on a user id for a user is an issuer decision. You can use whichever you want, as long as it's an UUID.
// Server side
const userId = crypto.randomUUID();
// Remember it on your database
session.user.update({ userId })
// Return it to the front-end to be used in the next step
return { userId }Step 2: Derive the Public Key
Use the idos.discoverUserEncryptionPublicKey function to derive a public key for the user. This key will be used to encrypt and decrypt user's credential content.
// Client side
import { idOS } from "@idos-network/idos-sdk-js";
// Arguments are described on idos-sdk-js's README. Be sure to read it.
// Note: make sure to set mode to "new" since you're creating a new idOS profile
const initParams = { ...YOUR_IDOS_INIT_PARAMS, mode: "new" };
const idos = await idOS.init(...);
// Get userId associated with this user from your server
const { userId } = await yourServer.getIdosInformation();
// Discover user encryption key
const { userEncryptionPublicKey } = await idos.discoverUserEncryptionPublicKey(userId);
// Report it back to your server
await yourServer.reportIdosEncryptionPublicKey(userEncryptionPublicKey);Step 3: Creating a User Profile
Once the public key is derived, you can create the user profile in idOS by passing it to the createUser function alongside with user id and the wallet the user's going to use to drive their idOS profile.
// Server side
import { createUser } from "@idos-network/issuer-sdk-js";
import issuerConfig from "./issuer-config.js";
// Get this from the user's request, and remember it
const currentPublicKey = request.params['userEncryptionPublicKey']
session.user.currentPublicKey = currentPublicKey
// Get the stored user id
const userId = session.user.userId
// Build the user object
const user = {
id: userId,
recipient_encryption_public_key: currentPublicKey,
}
// Build the wallet object
const walletPayload = {
// The user's wallet address (e.g., an Ethereum address)
address: "0x0",
// The type of user wallet (e.g., "EVM", "NEAR")
wallet_type: "EVM",
// The message that was signed by the address
message: "app wants you to sign this message...",
// The derived signature for the message, created with the user wallet
signature: "0x3fda8a9fef767d974ceb481d606587b17c...",
// The user wallet's public key
public_key: "RxG8ByhoFYA6fL5X3qw2Ar9wpblWtmPp5MKtlmBsl0c=",
}
// Create the user on idOS nodes, and get some information back.
const [profile, wallet] = await createUser(issuerConfig, user, walletPayload);Writing credentials
In order to write a credential to idOS, the issuer needs to obtain permission from the user. This can be done in two ways: using Write Grants, or using Permissioned Credential Creation. Below are the two methods for writing credentials.
Using Write Grants
The first method involves getting permission from the user via a Write Grant.
A Write Grant is a permission given by the user that allows a specific grantee to perform a few operations on their behalf. This is particularly relevant to not require the user to come back to your website if you want to add data to their profile.
To do this, you must first create a Write Grant using the idOS SDK. Here's an example of creating a write grant, by calling the idos.data.addWriteGrant:
// Client side
import { idOS } from "@idos-network/idos-sdk-js";
import * as Utf8Codec from "@stablelib/utf8";
// Arguments are described on idos-sdk-js's README. Be sure to read it.
const idos = await idOS.init(...);
// This is a placeholder for your signer's address. You could get it from
// some endpoint you expose. But, to keep it simple, we're using a constant.
const ISSUER_SIGNER_ADDRESS = "0xc00ffeec00ffeec00ffeec00ffeec00ffeec00ff";
// Ask the user for a Write Grant
await idos.data.addWriteGrant(ISSUER_SIGNER_ADDRESS);Now that the user has created a Write Grant for us, the issuer, we can create a credential for the user:
// Server side
import { createCredentialByGrant, encryptionPublicKey } from "@idos-network/issuer-sdk-js";
import issuerConfig from "./issuer-config.js";
const publicNotesId = crypto.randomUUID();
const credentialsPublicNotes = {
// `id` is required to make `editCredential` work.
id: publicNotesId,
type: "human",
level: "human",
status: "approved",
// make yourself discoverable by dApps.
issuer: "MyCoolIssuer",
}
const credentialContent = JSON.stringify({
"@context": [
"https://www.w3.org/2018/credentials/v1",
],
id: "uuid:087b9cf0-a968-471d-a4e8-a805a05357ed",
type: ["VerifiableCredential"],
issuer: "https://vc-issuers.cool-issuer.id/",
level: "human",
credentialSubject: {
id: "uuid:33ce045b-19f8-4f5a-89d9-4575f66f4d40",
name: "John Doe",
email: "johndoe@example.com",
country: "USA",
},
issuanceDate: "2022-06-01T12:00:00Z",
expirationDate: "2022-06-30T12:00:00Z",
proof: {
type: "Ed25519Signature2020",
created: "2022-06-01T12:00:00Z",
verificationMethod: "https://vc-issuers.fractal.id/idos/keys/1",
proofPurpose: "assertionMethod",
proofValue: "z22DAdBQgJXUh69e4y9a7t7n9f6c7m7b8a6v6w5z4x3y2x1w",
},
})
const credentialPayload = {
id: crypto.randomUUID(),
// user id of the user who is creating the credential.
user_id: session.user.userId,
// The verifiable credential content should be passed as it's seen in the example at https://verifiablecredentials.dev/ usually a stringfied JSON object.
// credential content is encrypted, using the Issuer's secret encryption key, along with the receiver's public encryption key.
// plaintextContent should be passed as a Uint8Array.
plaintextContent: Utf8Codec.encode(credentialContent),
// The public encryption key of the user who is creating the credential. also passed as a Uint8Array.
receiverEncryptionPublicKey: Utf8Codec.encode(session.user.userEncryptionPublicKey),
// These notes will be publicly disclosed and accessible without needing to decrypt the credential.
publicNotes: JSON.stringify(credentialsPublicNotes),
}
const credential = await createCredentialByGrant(issuerConfig, credentialPayload);This will create a credential in the idOS for the given user id.
⚠️ Notice
The credential content should be passed as is. It will be encrypted for the recipient before being stored on the idOS.
Using Permissioned Credential Creation
The second method allows the issuer, by virtue of being a Permissioned Issuer, to create a credential without a Write Grant. Get in touch with us at engineering@idos.network if you're interested in being one.
For this method, use the createCredentialPermissioned function to write the credential with the necessary encryption.
Example:
// Server side
import { createCredentialPermissioned } from "@idos-network/issuer-sdk-js";
import issuerConfig from "./issuer-config.js";
// See the previous example for more details on these fields
await createCredentialPermissioned(issuerConfig, credentialPayload);Sharing credentials
The SDK provides issuer to share credentials with other grantees. This function is called shareCredentialByGrant.
// Server side
import issuerConfig from "./issuer-config.js";
await shareCredentialByGrant(issuerConfig,{
...credentialPayload,
grantee: "GRANTEE_WALLET_ADDRESS",
lockedUntil: Math.floor(Date.now() / 1000) + 1000,
originalCredentialId: credentialPayload.id,
});Editing credentials
The editCredential function allows issuers to update the public notes associated with a credential in the idOS. This is useful for actions like marking credentials as revoked or updating metadata.
In order for editCredential to work, the credential's public_notes field needs to be a valid JSON object with an id field, and the public_notes_id argument needs to have that value.
⚠️ Warning
If the new
public_notesvalue doesn't have anidfield, you'll stop being able to edit that credential.
// Server side
import issuerConfig from "./issuer-config.js";
const public_notes_id = crypto.randomUUID();
await editCredential(issuerConfig, {
public_notes_id: publicNotesId,
public_notes: JSON.stringify({
...credentialsPublicNotes,
status: "revoked",
}),
});Revoking a credential
A previously created credential can be revoked by the issuer by calling the editCredential function. When creating a credential, the publicNotes field needs to have an id field that will be used to identify the credential to be revoked. Pass this id to the editCredential function to revoke the credential.
// Server side
import { editCredential } from "@idos-network/issuer-sdk-js";
import issuerConfig from "./issuer-config.js";
await editCredential(issuer, {
publicNotesId: id, // the `id` of the credential to be revoked that is stored in the `publicNotes` field.
publicNotes: JSON.stringify({
...publicNotes,
status: "revoked" // updating the credential status to revoked
}),
});Developing the SDK locally
Run:
pnpm devThis will start the compiler in watch mode that will rebuild every time any of the source files are changed.
You can also create a production build by running the following command in the root folder of the SDK package:
pnpm build