npm install @tuum-tech/identify@1.5.0
or
yarn add @tuum-tech/identify@1.5.0
It's optional but recommended to automate the MetaMask installation for users, as this enhances their experience. The choice is up to developers on how they want to handle this aspect of the integration.
async function isMetamaskInstalled() {
// Check if the `window.ethereum` property exists on the window object
return typeof window.ethereum !== 'undefined' && window.ethereum.isMetaMask;
}
Check out Snap RPC APIs to learn about how to interact with the Identify Snap from your website.
Note that before users can interact with the Identify Snap, it needs to first be installed on the Metamask itself so you can have a button on your website that lets users do exactly this.
// Get permissions to interact with and install the Identify Snap
async function connect() {
console.log("snap id", snapId);
const isMetamaskDetected = await isMetamaskInstalled();
if (!isMetamaskDetected ) {
console.error(
"You need to install Metamask for this demo to work. You can install it at https://metamask.io"
);
alert(
"You need to install Metamask for this demo to work. You can install it at https://metamask.io"
);
}
let snaps = await window.ethereum.request({
method: "wallet_getSnaps"
});
console.log("Installed snaps...", snaps);
try {
if (!(snapId in snaps)) {
console.log("Identify Snap is not yet installed. Installing now...");
const result = await ethereum.request({
method: "wallet_requestSnaps",
params: {
[snapId]: { version: "latest" }
}
});
console.log("result: ", result);
snaps = await window.ethereum.request({
method: "wallet_getSnaps"
});
}
} catch (e) {
console.log(
`Failed to obtain installed snap: ${JSON.stringify(e, null, 4)}`
);
alert(`Failed to obtain installed snap: ${JSON.stringify(e, null, 4)}`);
}
if (snapId in snaps) {
console.log("Connected successfully!");
alert("Connected successfully!");
} else {
console.log("Could not connect successfully. Please try again!");
alert("Could not connect successfully. Please try again!");
}
}
import { OnRpcRequestHandler } from '@metamask/snaps-types';
import { heading, text } from '@metamask/snaps-ui';
import { Account, ExternalAccount, IdentitySnapParams } from './interfaces';
import { getAccountInfo } from './rpc/account/getAccountInfo';
import { getAvailableDIDMethods } from './rpc/did/getAvailableDIDMethods';
import { getCurrentDIDMethod } from './rpc/did/getCurrentDIDMethod';
import { resolveDID } from './rpc/did/resolveDID';
import { switchDIDMethod } from './rpc/did/switchDIDMethod';
import { configureGoogleAccount } from './rpc/gdrive/configureGoogleAccount';
import { createNewHederaAccount } from './rpc/hedera/createNewHederaAccount';
import { togglePopups } from './rpc/snap/togglePopups';
import { createVC } from './rpc/vc/createVC';
import { createVP } from './rpc/vc/createVP';
import { deleteAllVCs } from './rpc/vc/deleteAllVCs';
import { getSupportedProofFormats } from './rpc/vc/getSupportedProofFormats';
import { getVCs } from './rpc/vc/getVCs';
import { removeVC } from './rpc/vc/removeVC';
import { saveVC } from './rpc/vc/saveVC';
import { syncGoogleVCs } from './rpc/vc/syncGoogleVCs';
import { verifyVC } from './rpc/vc/verifyVC';
import { verifyVP } from './rpc/vc/verifyVP';
import { getCurrentAccount } from './snap/account';
import { generateCommonPanel } from './snap/dialog';
import { getSnapStateUnchecked } from './snap/state';
import { CreateNewHederaAccountRequestParams } from './types/params';
import { init } from './utils/init';
import {
isExternalAccountFlagSet,
isValidConfigueGoogleRequest,
isValidCreateNewHederaAccountParams,
isValidCreateVCRequest,
isValidCreateVPRequest,
isValidDeleteAllVCsRequest,
isValidGetVCsRequest,
isValidMetamaskAccountParams,
isValidRemoveVCRequest,
isValidResolveDIDRequest,
isValidSaveVCRequest,
isValidSwitchMethodRequest,
isValidVerifyVCRequest,
isValidVerifyVPRequest,
} from './utils/params';
/**
* Handle incoming JSON-RPC requests, sent through `wallet_invokeSnap`.
*
* @param args - The request handler args as object.
* @param args.request - A validated JSON-RPC request object.
* @param args.origin - Origin of the request.
* @returns `null` if the request succeeded.
* @throws If the request method is not valid for this snap.
*/
export const onRpcRequest: OnRpcRequestHandler = async ({
origin,
request,
}) => {
console.log('Request:', JSON.stringify(request, null, 4));
console.log('Origin:', origin);
console.log('-------------------------------------------------------------');
console.log(
'request.params=========',
JSON.stringify(request.params, null, 4),
);
let state = await getSnapStateUnchecked(snap);
if (state === null) {
state = await init(snap);
}
console.log('state:', JSON.stringify(state, null, 4));
let isExternalAccount: boolean;
let extraData: unknown;
if (isExternalAccountFlagSet(request.params)) {
isExternalAccount = true;
extraData = (request.params as ExternalAccount).externalAccount.data;
} else {
isExternalAccount = false;
isValidMetamaskAccountParams(request.params);
}
const account: Account = await getCurrentAccount(
state,
request.params,
isExternalAccount,
);
account.extraData = extraData;
console.log(`Current account: ${JSON.stringify(account, null, 4)}`);
const identitySnapParams: IdentitySnapParams = {
origin,
snap,
state,
metamask: ethereum,
account,
};
switch (request.method) {
case 'hello': {
return snap.request({
method: 'snap_dialog',
params: {
/*
Type can be one of the following:
- 'alert': for displaying information.
- 'confirmation': for accepting or rejecting some action.
- 'prompt': for inputting some information.
*/
type: 'alert',
content: await generateCommonPanel(origin, [
heading('Hello from Identify Snap!'),
text('This custom alert is just for display purposes.'),
]),
},
});
}
case 'togglePopups': {
return await togglePopups(identitySnapParams);
}
case 'getAccountInfo': {
return await getAccountInfo(identitySnapParams);
}
case 'createNewHederaAccount': {
isValidCreateNewHederaAccountParams(request.params);
return await createNewHederaAccount(
identitySnapParams,
request.params as CreateNewHederaAccountRequestParams,
);
}
case 'resolveDID': {
isValidResolveDIDRequest(request.params);
return await resolveDID(identitySnapParams, request.params.did);
}
case 'getVCs': {
isValidGetVCsRequest(request.params);
return await getVCs(identitySnapParams, request.params);
}
case 'saveVC': {
isValidSaveVCRequest(request.params);
return await saveVC(identitySnapParams, request.params);
}
case 'createVC': {
isValidCreateVCRequest(request.params);
return await createVC(identitySnapParams, request.params);
}
case 'verifyVC': {
isValidVerifyVCRequest(request.params);
return await verifyVC(
identitySnapParams,
request.params.verifiableCredential,
);
}
case 'removeVC': {
isValidRemoveVCRequest(request.params);
return await removeVC(identitySnapParams, request.params);
}
case 'deleteAllVCs': {
isValidDeleteAllVCsRequest(request.params);
return await deleteAllVCs(identitySnapParams, request.params);
}
case 'createVP': {
isValidCreateVPRequest(request.params);
return await createVP(identitySnapParams, request.params);
}
case 'verifyVP': {
isValidVerifyVPRequest(request.params);
return await verifyVP(
identitySnapParams,
request.params.verifiablePresentation,
);
}
case 'getAvailableMethods': {
return getAvailableDIDMethods();
}
case 'getCurrentDIDMethod': {
return getCurrentDIDMethod(identitySnapParams);
}
case 'switchDIDMethod': {
isValidSwitchMethodRequest(request.params);
return await switchDIDMethod(
identitySnapParams,
request.params.didMethod,
);
}
case 'getSupportedProofFormats': {
return getSupportedProofFormats();
}
case 'configureGoogleAccount': {
isValidConfigueGoogleRequest(request.params);
return await configureGoogleAccount(identitySnapParams, request.params);
}
case 'syncGoogleVCs': {
return await syncGoogleVCs(identitySnapParams);
}
default: {
console.error('Method not found');
throw new Error('Method not found');
}
}
};