Adding and Removing Auth Methods
Configure auth methods for your PKP using the @lit-protocol/contracts-sdk
package.
To write to the blockchain, the LitContracts
instance must be created with a ethers.Signer
that is authorized to sign transactions using the PKP. The @lit-protocol/pkp-ethers
package provides a convenient class, PKPEthersWallet
, which can be used as a signer.
Initialize PKPEthersWallet
PKPEthersWallet
must be instantiated with an AuthSig
, AuthenticationProps
or a SessionSig
in order to authorize signing requests. To learn how to generate these signatures, refer to the Authentication section.
Ideally you would want to pass AuthenticationProps
as it will update SessionSigs
for you based on current conditions while retaining the benefits of sessions.
You can only pass one of the three. If you pass more than one, PKPEthersWallet
will throw an exception when constructing or trying to use it.
import { LitNodeClient } from "@lit-protocol/lit-node-client";
import { LitAbility, LitActionResource } from '@lit-protocol/auth-helpers';
import { PKPEthersWallet } from "@lit-protocol/pkp-ethers";
import { LIT_RPC, LitNetwork } from "@lit-protocol/constants";
// If you haven't done before, create a LitNodeClient instance
const litNodeClient = new LitNodeClient({
litNetwork: LitNetwork.DatilDev,
});
await litNodeClient.connect();
// Prepare needed params for authContext
const resourceAbilities = [
{
resource: new LitActionResource("*"),
ability: LitAbility.PKPSigning,
},
];
const authNeededCallback = async (params: AuthCallbackParams) => {
const response = await litNodeClient.signSessionKey({
statement: params.statement,
authMethods: [authMethod],
expiration: params.expiration,
resources: params.resources,
chainId: 1,
});
return response.authSig;
};
const pkpWallet = new PKPEthersWallet({
authContext: {
client: litNodeClient,
getSessionSigsProps: {
chain: 'ethereum',
expiration: new Date(Date.now() + 60_000 * 60).toISOString(),
resourceAbilityRequests: resourceAbilities,
authNeededCallback,
},
},
// controllerAuthSig: authSig,
// controllerSessionSigs: sesionSigs, // (deprecated)
pkpPubKey: "<Your PKP public key>",
rpc: LIT_RPC.CHRONICLE_YELLOWSTONE,
});
await pkpWallet.init();
To view more constructor options for PKPEthersWallet
, check out the API docs.
Initialize LitContracts
Create an instance of LitContracts
and pass in your PKPEthersWallet
.
import { LitContracts } from "@lit-protocol/contracts-sdk";
const litContracts = new LitContracts({
signer: pkpWallet,
});
await litContracts.connect();
To view more constructor options for LitContracts
, check out the API docs.
Construct the AuthMethod
Object
To add an auth method, you must pass an authMethod
object, which should have the following properties:
authMethodType
: A number representing the type of auth method you want to add. Refer to the supported auth methods table here.id
: Bytes that represent a hash of a string that uniquely identifies the auth methoduserPubkey
: Public key of a WebAuthn credential (only required when using WebAuthn as an auth method)
The auth method ID should be a hash of a string that uniquely identifies the auth method. For example, if adding Discord as an auth method, the auth method ID could be a hash of the Discord user ID and your Discord client ID.
import { utils } from "ethers";
// You can fetch the Discord user ID by calling the Discord API: https://discord.com/developers/docs/resources/user
const userId = "<Discord user ID>";
// Upon creating a Discord application, you will be given a client ID: https://discord.com/developers/docs/topics/oauth2
const clientId = "<Discord client ID>";
// The id can be a hash of the Discord user ID and the Discord client ID
const authMethodId = utils.keccak256(
utils.toUtf8Bytes(`${user.id}:${this.clientId}`)
);
Add an Auth Method
Auth methods can be modified by interacting with the PKPPermissions contract. To add an auth method, call the addPermittedAuthMethod
function on the PKPPermissions
contract.
const transaction =
await litContracts.pkpPermissionsContract.write.addPermittedAuthMethod(
"<The token ID of the PKP you want to add an auth method to>",
"<The auth method object you want to add>",
[],
{ gasPrice: utils.parseUnits("0.001", "gwei"), gasLimit: 400000 }
);
const result = await transaction.wait();
The addPermittedAuthMethod
function takes the following arguments:
tokenId
: The token ID of the PKP you want to add an auth method toauthMethod
: The auth method you want to addoverrides
: An optional object that allows you to customize certain parameters of the transaction (e.g,gasPrice
,gasLimit
)
Note: Here, we have specified a hardcoded gasLimit
of 400000
. Users should note that this gasLimit
is a number which is dependent on the authentication methods being added. For estimating the gasLimit
specific to your use case, please visit Estimating Gas section.
Alternatively, you can set a sufficiently high gasLimit
fee based on your testing and requirements.
Remove an Auth Method
To remove an auth method, call the removePermittedAuthMethod
function on the PKPPermissions
contract.
const transaction =
await litContracts.pkpPermissionsContract.write.removePermittedAuthMethod(
"<The token ID of your PKP>",
"<The auth method type",
"<The auth method ID>",
{ gasPrice: utils.parseUnits("0.001", "gwei"), gasLimit: 400000 }
);
The removePermittedAuthMethod
function takes the following arguments:
tokenId
: The token ID of the PKP you want to remove an auth method fromauthMethodType
: A number representing the type of auth method you want to remove. Refer to the supported auth methods table here.id
: Bytes that represent a hash of a string that uniquely identifies the auth method you want to removeoverrides
: An optional object that allows you to customize certain parameters of the transaction (e.g,gasPrice
,gasLimit
)
Note: Here, we have specified a hardcoded gasLimit
of 400000
. Users should note that this gasLimit
is a number which is dependent on the authentication methods being added. For estimating the gasLimit
specific to your use case, please visit Estimating Gas section.
Alternatively, you can set a sufficiently high gasLimit
fee based on your testing and requirements.
Estimating Gas
To estimate of the amount of gas that would be required to add and remove auth methods, you can first mock the transaction using populateTransaction
to create an unsigned transaction and then call estimateGas
on the unsigned transaction.
// First, mock the transaction to add an auth method
const mockTransaction =
await litContracts.pkpPermissionsContract.write.populateTransaction.addPermittedAuthMethod(
"<The token ID of the PKP you want to add an auth method to>",
"<The auth method object you want to add>",
[]
);
// Then, estimate gas on the unsigned transaction
const gas = await litContracts.signer.estimateGas(mockTransaction);
// Now, you can use the gas value to set the gas limit
const transaction =
await litContracts.pkpPermissionsContract.write.addPermittedAuthMethod(
"<The token ID of the PKP you want to add an auth method to>",
"<The auth method object you want to add>",
[],
{ gasLimit: gas }
);
Fetch Auth Methods
To check that the auth method was added or removed successfully, call the getPermittedAuthMethods
function on the PKPPermissions
contract.
const authMethods =
await litContracts.pkpPermissionsContract.read.getPermittedAuthMethods(
"<The token ID of your PKP>"
);
The getPermittedAuthMethods
function returns an array of authMethod
objects, each of which will include authMethodType
, id
, and userPubkey
values.
Not finding the answer you're looking for? Share your feedback on these docs by creating an issue in our GitHub Issues and Reports repository or get support by visiting our Support page.