From b48fd1eadb2d35a845738b2a07832fb185e6620d Mon Sep 17 00:00:00 2001 From: Ansonhkg Date: Thu, 9 Nov 2023 19:09:44 +0000 Subject: [PATCH 1/8] mint by auth method --- ...rite-mint-a-pkp-and-set-scope-1-2-easy.mjs | 71 ++++++++++ ...te-mint-a-pkp-and-set-scope-1-advanced.mjs | 78 +++++++++++ ...acts-write-mint-a-pkp-then-set-scope-1.mjs | 98 +++++++++++++ ...t-a-pkp-with-a-pkp-with-no-permissions.mjs | 96 +++++++++++++ ...s-write-mint-a-pkp-with-no-permissions.mjs | 44 ++++++ ...th-session-sigs-eth-wallet-auth-method.mjs | 1 + .../contracts-sdk/src/lib/contracts-sdk.ts | 131 +++++++++++++++++- .../src/lib/providers/AppleProvider.ts | 3 + .../src/lib/providers/DiscordProvider.ts | 27 ++++ .../src/lib/providers/EthWalletProvider.ts | 4 + .../src/lib/providers/GoogleProvider.ts | 4 + .../src/lib/providers/StytchOtpProvider.ts | 10 +- .../src/lib/providers/WebAuthnProvider.ts | 8 +- 13 files changed, 568 insertions(+), 7 deletions(-) create mode 100644 e2e-nodejs/group-contracts/test-contracts-write-mint-a-pkp-and-set-scope-1-2-easy.mjs create mode 100644 e2e-nodejs/group-contracts/test-contracts-write-mint-a-pkp-and-set-scope-1-advanced.mjs create mode 100644 e2e-nodejs/group-contracts/test-contracts-write-mint-a-pkp-then-set-scope-1.mjs create mode 100644 e2e-nodejs/group-contracts/test-contracts-write-mint-a-pkp-with-a-pkp-with-no-permissions.mjs create mode 100644 e2e-nodejs/group-contracts/test-contracts-write-mint-a-pkp-with-no-permissions.mjs diff --git a/e2e-nodejs/group-contracts/test-contracts-write-mint-a-pkp-and-set-scope-1-2-easy.mjs b/e2e-nodejs/group-contracts/test-contracts-write-mint-a-pkp-and-set-scope-1-2-easy.mjs new file mode 100644 index 0000000000..c5fd898680 --- /dev/null +++ b/e2e-nodejs/group-contracts/test-contracts-write-mint-a-pkp-and-set-scope-1-2-easy.mjs @@ -0,0 +1,71 @@ +import path from 'path'; +import { success, fail, testThis } from '../../tools/scripts/utils.mjs'; +import LITCONFIG from '../../lit.config.json' assert { type: 'json' }; +import { LitContracts } from '@lit-protocol/contracts-sdk'; +import { ethers } from 'ethers'; +import { AuthMethodType } from '@lit-protocol/constants'; + +export async function main() { + // ========== Controller Setup =========== + const provider = new ethers.providers.JsonRpcProvider( + LITCONFIG.CHRONICLE_RPC + ); + + const controllerWallet = new ethers.Wallet( + LITCONFIG.CONTROLLER_PRIVATE_KEY, + provider + ); + + // ==================== LitContracts Setup ==================== + const contractClient = new LitContracts({ + signer: controllerWallet, + }); + + await contractClient.connect(); + + // ==================== Test Logic ==================== + const mintInfo = await contractClient.mint({ + authMethod: { + authMethodType: AuthMethodType.EthWallet, + accessToken: JSON.stringify(LITCONFIG.CONTROLLER_AUTHSIG), + }, + scopes: [1, 2], + }); + + if (!mintInfo.tx.transactionHash) { + return fail(`failed to mint a PKP`); + } + + // ==================== Post-Validation ==================== + // -- get the scopes + const scopes = + await contractClient.pkpPermissionsContract.read.getPermittedAuthMethodScopes( + mintInfo.pkp.tokenId, + AuthMethodType.EthWallet, + LITCONFIG.CONTROLLER_AUTHSIG.address, // auth id + 3 // we only offer 2 scopes atm. and index 0 doesn't exist, so either 1 = sign anything or 2 = only sign messages + ); + + const signAnythingScope = scopes[1]; + const onlySignMessagesScope = scopes[2]; + + if (!signAnythingScope) { + return fail(`signAnythingScope should be true`); + } + + if (!onlySignMessagesScope) { + return fail(`onlySignMessagesScope should be true`); + } + + // ==================== Success ==================== + return success(`ContractsSDK mints a PKP and set scope 1 and 2 +Logs: +--- +tokenId: ${mintInfo.pkp.tokenId} +transactionHash: ${mintInfo.tx.transactionHash} +signAnythingScope: ${signAnythingScope} +onlySignMessagesScope: ${onlySignMessagesScope} +`); +} + +await testThis({ name: path.basename(import.meta.url), fn: main }); diff --git a/e2e-nodejs/group-contracts/test-contracts-write-mint-a-pkp-and-set-scope-1-advanced.mjs b/e2e-nodejs/group-contracts/test-contracts-write-mint-a-pkp-and-set-scope-1-advanced.mjs new file mode 100644 index 0000000000..2a4a00bb13 --- /dev/null +++ b/e2e-nodejs/group-contracts/test-contracts-write-mint-a-pkp-and-set-scope-1-advanced.mjs @@ -0,0 +1,78 @@ +import path from 'path'; +import { success, fail, testThis } from '../../tools/scripts/utils.mjs'; +import LITCONFIG from '../../lit.config.json' assert { type: 'json' }; +import { LitContracts } from '@lit-protocol/contracts-sdk'; +import { ethers } from 'ethers'; +import { AuthMethodType } from '@lit-protocol/constants'; + +export async function main() { + // ========== Controller Setup =========== + const provider = new ethers.providers.JsonRpcProvider( + LITCONFIG.CHRONICLE_RPC + ); + + const controllerWallet = new ethers.Wallet( + LITCONFIG.CONTROLLER_PRIVATE_KEY, + provider + ); + + // ==================== LitContracts Setup ==================== + const contractClient = new LitContracts({ + signer: controllerWallet, + }); + + await contractClient.connect(); + + // ==================== Test Logic ==================== + const mintCost = await contractClient.pkpNftContract.read.mintCost(); + + // -- minting a PKP + const mintTx = + await contractClient.pkpHelperContract.write.mintNextAndAddAuthMethods( + 2, + [AuthMethodType.EthWallet], + [LITCONFIG.CONTROLLER_AUTHSIG.address], // auth id + ['0x'], // only for web3auth atm + [[1]], + true, // addPkpEthAddressAsPermittedAddress, + true, // sendPkpToItself, + { + value: mintCost, + } + ); + + const mintTxReceipt = await mintTx.wait(); + + const tokenId = mintTxReceipt.events[0].topics[1]; + console.log('tokenId', tokenId); + + // -- get the scopes + const scopes = + await contractClient.pkpPermissionsContract.read.getPermittedAuthMethodScopes( + tokenId, + AuthMethodType.EthWallet, + LITCONFIG.CONTROLLER_AUTHSIG.address, // auth id + 3 // we only offer 2 scopes atm. and index 0 doesn't exist, so either 1 = sign anything or 2 = only sign messages + ); + + // ==================== Post-Validation ==================== + if (mintCost === undefined || mintCost === null) { + return fail('mintCost should not be empty'); + } + + if (scopes[1] !== true) { + return fail('scope 1 (sign anything) should be true'); + } + + // ==================== Success ==================== + return success(`ContractsSDK mints a PKP +Logs: +--- +mintHash: ${mintTxReceipt.transactionHash} +tokenId: ${tokenId} +scope 1 (sign anything): ${scopes[1]} +scope 2 (only sign messages): ${scopes[2]} +`); +} + +await testThis({ name: path.basename(import.meta.url), fn: main }); diff --git a/e2e-nodejs/group-contracts/test-contracts-write-mint-a-pkp-then-set-scope-1.mjs b/e2e-nodejs/group-contracts/test-contracts-write-mint-a-pkp-then-set-scope-1.mjs new file mode 100644 index 0000000000..933736ad46 --- /dev/null +++ b/e2e-nodejs/group-contracts/test-contracts-write-mint-a-pkp-then-set-scope-1.mjs @@ -0,0 +1,98 @@ +import path from 'path'; +import { success, fail, testThis } from '../../tools/scripts/utils.mjs'; +import LITCONFIG from '../../lit.config.json' assert { type: 'json' }; +import { LitContracts } from '@lit-protocol/contracts-sdk'; +import { ethers } from 'ethers'; +import { AuthMethodType } from '@lit-protocol/constants'; + +export async function main() { + // ========== Controller Setup =========== + const provider = new ethers.providers.JsonRpcProvider( + LITCONFIG.CHRONICLE_RPC + ); + + const controllerWallet = new ethers.Wallet( + LITCONFIG.CONTROLLER_PRIVATE_KEY, + provider + ); + + // ==================== LitContracts Setup ==================== + const contractClient = new LitContracts({ + signer: controllerWallet, + }); + + await contractClient.connect(); + + // ==================== Test Logic ==================== + const mintCost = await contractClient.pkpNftContract.read.mintCost(); + + // -- minting a PKP using a PKP + const mintTx = await contractClient.pkpNftContract.write.mintNext(2, { + value: mintCost, + }); + + const mintTxReceipt = await mintTx.wait(); + + const tokenId = mintTxReceipt.events[0].topics[1]; + console.log('tokenId', tokenId); + + // -- get the scopes + const scopes = + await contractClient.pkpPermissionsContract.read.getPermittedAuthMethodScopes( + tokenId, + AuthMethodType.EthWallet, + LITCONFIG.CONTROLLER_AUTHSIG.address, // auth id + 3 // we only offer 2 scopes atm. and index 0 doesn't exist, so either 1 = sign anything or 2 = only sign messages + ); + + // -- validate both scopes should be false + if (scopes[1] !== false) { + return fail('scope 1 (sign anything) should be false'); + } + + if (scopes[2] !== false) { + return fail('scope 2 (only sign messages) should be false'); + } + + // -- set the scope + const setScopeTx = + await contractClient.pkpPermissionsContract.write.addPermittedAuthMethodScope( + tokenId, + AuthMethodType.EthWallet, + LITCONFIG.CONTROLLER_AUTHSIG.address, // auth id + 1 // sign anything + ); + + const setScopeTxReceipt = await setScopeTx.wait(); + + // -- check the scopes again + const scopes2 = + await contractClient.pkpPermissionsContract.read.getPermittedAuthMethodScopes( + tokenId, + AuthMethodType.EthWallet, + LITCONFIG.CONTROLLER_AUTHSIG.address, // auth id + 3 // we only offer 2 scopes atm. and index 0 doesn't exist, so either 1 = sign anything or 2 = only sign messages + ); + + // ==================== Post-Validation ==================== + if (mintCost === undefined || mintCost === null) { + return fail('mintCost should not be empty'); + } + + if (scopes2[1] !== true) { + return fail('scope 1 (sign anything) should be true'); + } + + // ==================== Success ==================== + return success(`ContractsSDK mints a PKP +Logs: +--- +mintHash: ${mintTxReceipt.transactionHash} +tokenId: ${tokenId} +setScopeHash: ${setScopeTxReceipt.transactionHash} +scope 1 (sign anything): ${scopes2[1]} +scope 2 (only sign messages): ${scopes2[2]} +`); +} + +await testThis({ name: path.basename(import.meta.url), fn: main }); diff --git a/e2e-nodejs/group-contracts/test-contracts-write-mint-a-pkp-with-a-pkp-with-no-permissions.mjs b/e2e-nodejs/group-contracts/test-contracts-write-mint-a-pkp-with-a-pkp-with-no-permissions.mjs new file mode 100644 index 0000000000..f41ffba251 --- /dev/null +++ b/e2e-nodejs/group-contracts/test-contracts-write-mint-a-pkp-with-a-pkp-with-no-permissions.mjs @@ -0,0 +1,96 @@ +import path from 'path'; +import { success, fail, testThis } from '../../tools/scripts/utils.mjs'; +import LITCONFIG from '../../lit.config.json' assert { type: 'json' }; +import { LitContracts } from '@lit-protocol/contracts-sdk'; +import { PKPEthersWallet } from '@lit-protocol/pkp-ethers'; +import { ethers } from 'ethers'; + +async function getFundsFromPKPController() { + // ========== Controller Setup =========== + const provider = new ethers.providers.JsonRpcProvider( + LITCONFIG.CHRONICLE_RPC + ); + + const controllerWallet = new ethers.Wallet( + LITCONFIG.CONTROLLER_PRIVATE_KEY, + provider + ); + + // get the fund + console.log( + 'Controller Balance:', + (await controllerWallet.getBalance()).toString() + ); + + // send some funds to the pkp + const amount = '0.0000001'; + + const tx = await controllerWallet.sendTransaction({ + to: LITCONFIG.PKP_ETH_ADDRESS, + value: ethers.utils.parseEther(amount), + }); + + await tx.wait(); + + console.log( + 'New Controller Balance:', + (await controllerWallet.getBalance()).toString() + ); + console.log(`Sent ${amount} ETH to ${LITCONFIG.PKP_ETH_ADDRESS}`); +} + +export async function main() { + // ========== PKP WALLET SETUP =========== + const pkpWallet = new PKPEthersWallet({ + pkpPubKey: LITCONFIG.PKP_PUBKEY, + controllerAuthSig: LITCONFIG.CONTROLLER_AUTHSIG, + rpc: LITCONFIG.CHRONICLE_RPC, + }); + + await pkpWallet.init(); + + const pkpBalance = parseFloat(await pkpWallet.getBalance()); + + if (pkpBalance <= 0) { + console.log( + `PKP Balance is ${pkpBalance}. Getting funds from controller...` + ); + await getFundsFromPKPController(); + console.log('New PKP Balance:', (await pkpWallet.getBalance()).toString()); + } + + if (pkpWallet._isSigner !== true) { + return fail('pkpWallet should be signer'); + } + + // ==================== LitContracts Setup ==================== + const contractClient = new LitContracts({ + signer: pkpWallet, + }); + + await contractClient.connect(); + + // ==================== Test Logic ==================== + const mintCost = await contractClient.pkpNftContract.read.mintCost(); + + // -- minting a PKP using a PKP + const mintTx = + await contractClient.pkpNftContract.write.populateTransaction.mintNext(2, { + value: mintCost, + }); + + const signedMintTx = await pkpWallet.signTransaction(mintTx); + + const sentTx = await pkpWallet.sendTransaction(signedMintTx); + + // ==================== Post-Validation ==================== + if (mintCost === undefined || mintCost === null) { + return fail('mintCost should not be empty'); + } + + // ==================== Success ==================== + return success(`ContractsSDK mint a PKP using PKP Ethers wallet +hash: ${sentTx.hash}`); +} + +await testThis({ name: path.basename(import.meta.url), fn: main }); diff --git a/e2e-nodejs/group-contracts/test-contracts-write-mint-a-pkp-with-no-permissions.mjs b/e2e-nodejs/group-contracts/test-contracts-write-mint-a-pkp-with-no-permissions.mjs new file mode 100644 index 0000000000..c93fd1e6e5 --- /dev/null +++ b/e2e-nodejs/group-contracts/test-contracts-write-mint-a-pkp-with-no-permissions.mjs @@ -0,0 +1,44 @@ +import path from 'path'; +import { success, fail, testThis } from '../../tools/scripts/utils.mjs'; +import LITCONFIG from '../../lit.config.json' assert { type: 'json' }; +import { LitContracts } from '@lit-protocol/contracts-sdk'; +import { ethers } from 'ethers'; + +export async function main() { + // ========== Controller Setup =========== + const provider = new ethers.providers.JsonRpcProvider( + LITCONFIG.CHRONICLE_RPC + ); + + const controllerWallet = new ethers.Wallet( + LITCONFIG.CONTROLLER_PRIVATE_KEY, + provider + ); + + // ==================== LitContracts Setup ==================== + const contractClient = new LitContracts({ + signer: controllerWallet, + }); + + await contractClient.connect(); + + // ==================== Test Logic ==================== + const mintCost = await contractClient.pkpNftContract.read.mintCost(); + + // -- minting a PKP using a PKP + const mintTx = await contractClient.pkpNftContract.write.mintNext(2, { + value: mintCost, + }); + + const mintTxReceipt = await mintTx.wait(); + + // ==================== Post-Validation ==================== + if (mintCost === undefined || mintCost === null) { + return fail('mintCost should not be empty'); + } + + // ==================== Success ==================== + return success(`ContractsSDK mints a PKP ${mintTxReceipt.transactionHash}`); +} + +await testThis({ name: path.basename(import.meta.url), fn: main }); diff --git a/e2e-nodejs/group-pkp-session-sigs/test-pkp-sign-with-session-sigs-eth-wallet-auth-method.mjs b/e2e-nodejs/group-pkp-session-sigs/test-pkp-sign-with-session-sigs-eth-wallet-auth-method.mjs index 844cd8ae7f..88af01d64f 100644 --- a/e2e-nodejs/group-pkp-session-sigs/test-pkp-sign-with-session-sigs-eth-wallet-auth-method.mjs +++ b/e2e-nodejs/group-pkp-session-sigs/test-pkp-sign-with-session-sigs-eth-wallet-auth-method.mjs @@ -17,6 +17,7 @@ export async function main() { const litAuthClient = new LitAuthClient({ litRelayConfig: { + relayUrl: 'http://localhost:6380', relayApiKey: '67e55044-10b1-426f-9247-bb680e5fe0c8_relayer', }, version: 'V3', diff --git a/packages/contracts-sdk/src/lib/contracts-sdk.ts b/packages/contracts-sdk/src/lib/contracts-sdk.ts index 2dd6264b70..5e8cbe1e57 100644 --- a/packages/contracts-sdk/src/lib/contracts-sdk.ts +++ b/packages/contracts-sdk/src/lib/contracts-sdk.ts @@ -1,7 +1,8 @@ -import { BytesLike, ethers } from 'ethers'; +import { BigNumberish, BytesLike, ethers } from 'ethers'; import { hexToDec, decToHex } from './hex2dec'; import bs58 from 'bs58'; import { isBrowser, isNode } from '@lit-protocol/misc'; +import { DiscordProvider, EthWalletProvider, GoogleProvider, WebAuthnProvider } from '@lit-protocol/lit-auth-client'; let CID: any; try { @@ -39,6 +40,8 @@ import * as stakingContract from '../abis/Staking.sol/Staking'; import { TokenInfo, derivedAddresses } from './addresses'; import { IPubkeyRouter } from '../abis/PKPNFT.sol/PKPNFT'; import { computeAddress } from 'ethers/lib/utils'; +import { AuthMethod } from '@lit-protocol/types'; +import { AuthMethodType } from '@lit-protocol/constants'; const DEFAULT_RPC = 'https://chain-rpc.litprotocol.com/http'; const BLOCK_EXPLORER = 'https://chain.litprotocol.com/'; @@ -488,6 +491,128 @@ export class LitContracts { this.connected = true; }; + mint = async ({ authMethod, scopes, pubkey }: { + authMethod: AuthMethod, + scopes: string[] | number[] | BigNumberish[], + pubkey?: string + }) => { + + // -- validate + if (!this.connected) { + throw new Error( + 'Contracts are not connected. Please call connect() first' + ); + } + + if (!this.pkpNftContract) { + throw new Error('Contract is not available'); + } + + if (authMethod && !authMethod?.authMethodType) { + throw new Error('authMethodType is required'); + } + + if (authMethod && !authMethod?.accessToken) { + throw new Error('accessToken is required'); + } + + if (scopes.length <= 0) { + throw new Error(`❌ Permission scopes are required! +[0] No Permissions +[1] Sign Anything +[2] Only Sign Messages +Read more here: +https://developer.litprotocol.com/v3/sdk/wallets/auth-methods/#auth-method-scopes + `); + } + + // -- prepare + const _pubkey = pubkey ?? '0x'; + + // if scopes are list of strings, turn them into numbers + scopes = scopes.map((scope) => { + if (typeof scope === 'string') { + return ethers.BigNumber.from(scope) + } + if (typeof scope === 'number') { + return ethers.BigNumber.from(scope.toString()) + } + return scope; + }); + + let authId; + + switch (authMethod.authMethodType) { + case AuthMethodType.EthWallet: + authId = await EthWalletProvider.authMethodId(authMethod); + break; + case AuthMethodType.Discord: + authId = await DiscordProvider.authMethodId(authMethod); + break; + case AuthMethodType.WebAuthn: + authId = await WebAuthnProvider.authMethodId(authMethod); + break; + case AuthMethodType.Google: + authId = await GoogleProvider.authMethodId(authMethod); + break; + case AuthMethodType.StytchOtp: + authId = await GoogleProvider.authMethodId(authMethod); + break; + default: + throw new Error(`Unsupported auth method type: ${authMethod.authMethodType}`); + } + + // -- go + const mintCost = await this.pkpNftContract.read.mintCost(); + + // -- start minting + const tx = await this.pkpHelperContract.write.mintNextAndAddAuthMethods( + 2, // key type + [authMethod.authMethodType], + [authId], + [_pubkey], + [[...scopes]], + true, + true, + { + value: mintCost + } + ); + + const receipt = await tx.wait(); + + let events = 'events' in receipt ? receipt.events : receipt.logs; + + if (!events) { + throw new Error('No events found in receipt'); + } + + let tokenId; + + tokenId = events[0].topics[1]; + console.warn('tokenId:', tokenId); + + let publicKey = await this.pkpNftContract.read.getPubkey( + tokenId + ); + + if (publicKey.startsWith('0x')) { + publicKey = publicKey.slice(2); + } + + const pubkeyBuffer = Buffer.from(publicKey, 'hex'); + + const ethAddress = computeAddress(pubkeyBuffer); + + return { + pkp: { + tokenId, + publicKey, + ethAddress, + }, + tx: receipt, + }; + } // getRandomPrivateKeySignerProvider = () => { // const privateKey = ethers.utils.hexlify(ethers.utils.randomBytes(32)); @@ -764,7 +889,7 @@ export class LitContracts { let tokenIdFromEvent; - tokenIdFromEvent = events[1].topics[1]; + tokenIdFromEvent = events[0].topics[1]; console.warn('tokenIdFromEvent:', tokenIdFromEvent); let publicKey = await this.pkpNftContract.read.getPubkey( @@ -1393,7 +1518,7 @@ export class LitContracts { const res: any = await tx.wait(); - const tokenIdFromEvent = res.events[0].topics[3]; + const tokenIdFromEvent = res.events[0].topics[1]; return { tx, tokenId: tokenIdFromEvent }; }, diff --git a/packages/lit-auth-client/src/lib/providers/AppleProvider.ts b/packages/lit-auth-client/src/lib/providers/AppleProvider.ts index 3f3d5e27f7..25a73a5476 100644 --- a/packages/lit-auth-client/src/lib/providers/AppleProvider.ts +++ b/packages/lit-auth-client/src/lib/providers/AppleProvider.ts @@ -104,6 +104,9 @@ export default class AppleProvider extends BaseProvider { * @returns {Promise} - Auth method id */ public async getAuthMethodId(authMethod: AuthMethod): Promise { + return AppleProvider.authMethodId(authMethod); + } + public static async authMethodId(authMethod: AuthMethod): Promise { const tokenPayload = jose.decodeJwt(authMethod.accessToken); const userId: string = tokenPayload['sub'] as string; const audience: string = tokenPayload['aud'] as string; diff --git a/packages/lit-auth-client/src/lib/providers/DiscordProvider.ts b/packages/lit-auth-client/src/lib/providers/DiscordProvider.ts index e924e154b2..d240e01a86 100644 --- a/packages/lit-auth-client/src/lib/providers/DiscordProvider.ts +++ b/packages/lit-auth-client/src/lib/providers/DiscordProvider.ts @@ -115,6 +115,33 @@ export default class DiscordProvider extends BaseProvider { return authMethodId; } + public static async authMethodId(authMethod: AuthMethod, clientId?: string): Promise { + + const _clientId = clientId || '1052874239658692668'; + + // -- get user id from access token + let userId; + const meResponse = await fetch('https://discord.com/api/users/@me', { + method: 'GET', + headers: { + authorization: `Bearer ${authMethod.accessToken}`, + }, + }); + if (meResponse.ok) { + const user = await meResponse.json(); + userId = user.id; + } else { + throw new Error('Unable to verify Discord account'); + } + + // -- get auth method id + const authMethodId = ethers.utils.keccak256( + ethers.utils.toUtf8Bytes(`${userId}:${_clientId}`) + ); + + return authMethodId; + } + /** * Fetch Discord user ID * diff --git a/packages/lit-auth-client/src/lib/providers/EthWalletProvider.ts b/packages/lit-auth-client/src/lib/providers/EthWalletProvider.ts index e9888887f0..07a0983828 100644 --- a/packages/lit-auth-client/src/lib/providers/EthWalletProvider.ts +++ b/packages/lit-auth-client/src/lib/providers/EthWalletProvider.ts @@ -110,6 +110,10 @@ export default class EthWalletProvider extends BaseProvider { * @returns {Promise} - Auth method id */ public async getAuthMethodId(authMethod: AuthMethod): Promise { + return EthWalletProvider.authMethodId(authMethod); + } + + public static async authMethodId(authMethod: AuthMethod): Promise { let address: string; try { diff --git a/packages/lit-auth-client/src/lib/providers/GoogleProvider.ts b/packages/lit-auth-client/src/lib/providers/GoogleProvider.ts index e27db144ee..e4791c97b4 100644 --- a/packages/lit-auth-client/src/lib/providers/GoogleProvider.ts +++ b/packages/lit-auth-client/src/lib/providers/GoogleProvider.ts @@ -104,6 +104,10 @@ export default class GoogleProvider extends BaseProvider { * @returns {Promise} - Auth method id */ public async getAuthMethodId(authMethod: AuthMethod): Promise { + return GoogleProvider.authMethodId(authMethod); + } + + public static async authMethodId(authMethod: AuthMethod): Promise { const tokenPayload = jose.decodeJwt(authMethod.accessToken); const userId: string = tokenPayload['sub'] as string; const audience: string = tokenPayload['aud'] as string; diff --git a/packages/lit-auth-client/src/lib/providers/StytchOtpProvider.ts b/packages/lit-auth-client/src/lib/providers/StytchOtpProvider.ts index 22af52e00c..f6e1d72c10 100644 --- a/packages/lit-auth-client/src/lib/providers/StytchOtpProvider.ts +++ b/packages/lit-auth-client/src/lib/providers/StytchOtpProvider.ts @@ -49,7 +49,7 @@ export class StytchOtpProvider extends BaseProvider { ); } - const parsedToken: StytchToken = this._parseJWT(accessToken); + const parsedToken: StytchToken = StytchOtpProvider._parseJWT(accessToken); const audience = (parsedToken['aud'] as string[])[0]; if (audience != this._params.appId) { reject(new Error('Parsed application id does not match parameters')); @@ -93,7 +93,11 @@ export class StytchOtpProvider extends BaseProvider { * @returns {Promise} - Auth method id */ public async getAuthMethodId(authMethod: AuthMethod): Promise { - const tokenBody = this._parseJWT(authMethod.accessToken); + return StytchOtpProvider.authMethodId(authMethod); + } + + public static async authMethodId(authMethod: AuthMethod): Promise { + const tokenBody = StytchOtpProvider._parseJWT(authMethod.accessToken); const userId = tokenBody['sub'] as string; const orgId = (tokenBody['aud'] as string[])[0]; const authMethodId = ethers.utils.keccak256( @@ -107,7 +111,7 @@ export class StytchOtpProvider extends BaseProvider { * @param jwt token to parse * @returns {string}- userId contained within the token message */ - private _parseJWT(jwt: string): StytchToken { + public static _parseJWT(jwt: string): StytchToken { const parts = jwt.split('.'); if (parts.length !== 3) { throw new Error('Invalid token length'); diff --git a/packages/lit-auth-client/src/lib/providers/WebAuthnProvider.ts b/packages/lit-auth-client/src/lib/providers/WebAuthnProvider.ts index ebbdc54854..7044ee7f61 100644 --- a/packages/lit-auth-client/src/lib/providers/WebAuthnProvider.ts +++ b/packages/lit-auth-client/src/lib/providers/WebAuthnProvider.ts @@ -153,8 +153,14 @@ export default class WebAuthnProvider extends BaseProvider { * @returns {Promise} - Auth method id */ public async getAuthMethodId(authMethod: AuthMethod): Promise { + return WebAuthnProvider.authMethodId(authMethod, this.rpName); + } + + public static async authMethodId(authMethod: AuthMethod, rpName?: string): Promise { let credentialId: string; + const rpNameToUse = rpName || 'lit'; + try { credentialId = JSON.parse(authMethod.accessToken).rawId; } catch (err) { @@ -164,7 +170,7 @@ export default class WebAuthnProvider extends BaseProvider { } const authMethodId = ethers.utils.keccak256( - ethers.utils.toUtf8Bytes(`${credentialId}:${this.rpName}`) + ethers.utils.toUtf8Bytes(`${credentialId}:${rpNameToUse}`) ); return authMethodId; } From fdb17ae62f3aa284b57adeec4dbf8f2740ba7bb4 Mon Sep 17 00:00:00 2001 From: Ansonhkg Date: Thu, 9 Nov 2023 19:16:40 +0000 Subject: [PATCH 2/8] remove url --- .../test-pkp-sign-with-session-sigs-eth-wallet-auth-method.mjs | 1 - 1 file changed, 1 deletion(-) diff --git a/e2e-nodejs/group-pkp-session-sigs/test-pkp-sign-with-session-sigs-eth-wallet-auth-method.mjs b/e2e-nodejs/group-pkp-session-sigs/test-pkp-sign-with-session-sigs-eth-wallet-auth-method.mjs index 88af01d64f..844cd8ae7f 100644 --- a/e2e-nodejs/group-pkp-session-sigs/test-pkp-sign-with-session-sigs-eth-wallet-auth-method.mjs +++ b/e2e-nodejs/group-pkp-session-sigs/test-pkp-sign-with-session-sigs-eth-wallet-auth-method.mjs @@ -17,7 +17,6 @@ export async function main() { const litAuthClient = new LitAuthClient({ litRelayConfig: { - relayUrl: 'http://localhost:6380', relayApiKey: '67e55044-10b1-426f-9247-bb680e5fe0c8_relayer', }, version: 'V3', From ab03b1766b31765d0c0452e099e62b97d5bdcb01 Mon Sep 17 00:00:00 2001 From: Ansonhkg Date: Thu, 9 Nov 2023 19:29:15 +0000 Subject: [PATCH 3/8] feat: fix authmethod type 6 --- packages/contracts-sdk/src/lib/contracts-sdk.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/contracts-sdk/src/lib/contracts-sdk.ts b/packages/contracts-sdk/src/lib/contracts-sdk.ts index 5e8cbe1e57..cf0febb130 100644 --- a/packages/contracts-sdk/src/lib/contracts-sdk.ts +++ b/packages/contracts-sdk/src/lib/contracts-sdk.ts @@ -552,7 +552,7 @@ https://developer.litprotocol.com/v3/sdk/wallets/auth-methods/#auth-method-scope case AuthMethodType.WebAuthn: authId = await WebAuthnProvider.authMethodId(authMethod); break; - case AuthMethodType.Google: + case AuthMethodType.GoogleJwt: authId = await GoogleProvider.authMethodId(authMethod); break; case AuthMethodType.StytchOtp: From 0024a86723d8cc7039cfd9477d7b05595d9915d2 Mon Sep 17 00:00:00 2001 From: Ansonhkg Date: Thu, 9 Nov 2023 19:32:06 +0000 Subject: [PATCH 4/8] add a note --- .../test-contracts-write-mint-a-pkp-and-set-scope-1-2-easy.mjs | 1 + 1 file changed, 1 insertion(+) diff --git a/e2e-nodejs/group-contracts/test-contracts-write-mint-a-pkp-and-set-scope-1-2-easy.mjs b/e2e-nodejs/group-contracts/test-contracts-write-mint-a-pkp-and-set-scope-1-2-easy.mjs index c5fd898680..f84be6136a 100644 --- a/e2e-nodejs/group-contracts/test-contracts-write-mint-a-pkp-and-set-scope-1-2-easy.mjs +++ b/e2e-nodejs/group-contracts/test-contracts-write-mint-a-pkp-and-set-scope-1-2-easy.mjs @@ -37,6 +37,7 @@ export async function main() { } // ==================== Post-Validation ==================== + // NOTE: When using other auth methods, you might need to wait for a block to be mined before you can read the scopes // -- get the scopes const scopes = await contractClient.pkpPermissionsContract.read.getPermittedAuthMethodScopes( From e48dd4c540e95f41d2014b135ca12662db17999c Mon Sep 17 00:00:00 2001 From: Ansonhkg Date: Thu, 9 Nov 2023 19:47:06 +0000 Subject: [PATCH 5/8] feat: add enums --- ...st-contracts-write-mint-a-pkp-and-set-scope-1-2-easy.mjs | 4 ++-- packages/constants/src/lib/enums.ts | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/e2e-nodejs/group-contracts/test-contracts-write-mint-a-pkp-and-set-scope-1-2-easy.mjs b/e2e-nodejs/group-contracts/test-contracts-write-mint-a-pkp-and-set-scope-1-2-easy.mjs index f84be6136a..b9cdfad4ac 100644 --- a/e2e-nodejs/group-contracts/test-contracts-write-mint-a-pkp-and-set-scope-1-2-easy.mjs +++ b/e2e-nodejs/group-contracts/test-contracts-write-mint-a-pkp-and-set-scope-1-2-easy.mjs @@ -3,7 +3,7 @@ import { success, fail, testThis } from '../../tools/scripts/utils.mjs'; import LITCONFIG from '../../lit.config.json' assert { type: 'json' }; import { LitContracts } from '@lit-protocol/contracts-sdk'; import { ethers } from 'ethers'; -import { AuthMethodType } from '@lit-protocol/constants'; +import { AuthMethodType, AuthMethodScope } from '@lit-protocol/constants'; export async function main() { // ========== Controller Setup =========== @@ -29,7 +29,7 @@ export async function main() { authMethodType: AuthMethodType.EthWallet, accessToken: JSON.stringify(LITCONFIG.CONTROLLER_AUTHSIG), }, - scopes: [1, 2], + scopes: [AuthMethodScope.SignAnything, AuthMethodScope.OnlySignMessages], }); if (!mintInfo.tx.transactionHash) { diff --git a/packages/constants/src/lib/enums.ts b/packages/constants/src/lib/enums.ts index cf040ee1c2..1d84b61cb7 100644 --- a/packages/constants/src/lib/enums.ts +++ b/packages/constants/src/lib/enums.ts @@ -37,6 +37,12 @@ export enum AuthMethodType { StytchTotpFactorOtp = 13, } +export declare enum AuthMethodScope { + NoPermissions = 0, + SignAnything = 1, + OnlySignMessages = 2, +} + /** * Supported provider types */ From 017979cb954a19e4de678f1b386bbfb91dc99da0 Mon Sep 17 00:00:00 2001 From: Ansonhkg Date: Thu, 9 Nov 2023 19:49:58 +0000 Subject: [PATCH 6/8] remove declare --- packages/constants/src/lib/enums.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/constants/src/lib/enums.ts b/packages/constants/src/lib/enums.ts index 1d84b61cb7..e13a1c24a0 100644 --- a/packages/constants/src/lib/enums.ts +++ b/packages/constants/src/lib/enums.ts @@ -37,7 +37,7 @@ export enum AuthMethodType { StytchTotpFactorOtp = 13, } -export declare enum AuthMethodScope { +export enum AuthMethodScope { NoPermissions = 0, SignAnything = 1, OnlySignMessages = 2, From 972ac5ef3bba57b83fe8604c9b7f140e585398d1 Mon Sep 17 00:00:00 2001 From: Ansonhkg Date: Fri, 10 Nov 2023 13:56:06 +0000 Subject: [PATCH 7/8] rename from 'mint' to 'mintWithAuth' for better clarity --- ...test-contracts-write-mint-a-pkp-and-set-scope-1-2-easy.mjs | 2 +- packages/contracts-sdk/src/lib/contracts-sdk.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/e2e-nodejs/group-contracts/test-contracts-write-mint-a-pkp-and-set-scope-1-2-easy.mjs b/e2e-nodejs/group-contracts/test-contracts-write-mint-a-pkp-and-set-scope-1-2-easy.mjs index b9cdfad4ac..7cacdf893e 100644 --- a/e2e-nodejs/group-contracts/test-contracts-write-mint-a-pkp-and-set-scope-1-2-easy.mjs +++ b/e2e-nodejs/group-contracts/test-contracts-write-mint-a-pkp-and-set-scope-1-2-easy.mjs @@ -24,7 +24,7 @@ export async function main() { await contractClient.connect(); // ==================== Test Logic ==================== - const mintInfo = await contractClient.mint({ + const mintInfo = await contractClient.mintWithAuth({ authMethod: { authMethodType: AuthMethodType.EthWallet, accessToken: JSON.stringify(LITCONFIG.CONTROLLER_AUTHSIG), diff --git a/packages/contracts-sdk/src/lib/contracts-sdk.ts b/packages/contracts-sdk/src/lib/contracts-sdk.ts index cf0febb130..ebf8f66d97 100644 --- a/packages/contracts-sdk/src/lib/contracts-sdk.ts +++ b/packages/contracts-sdk/src/lib/contracts-sdk.ts @@ -491,10 +491,10 @@ export class LitContracts { this.connected = true; }; - mint = async ({ authMethod, scopes, pubkey }: { + mintWithAuth = async ({ authMethod, scopes, pubkey }: { authMethod: AuthMethod, scopes: string[] | number[] | BigNumberish[], - pubkey?: string + pubkey?: string // only applies to webauthn auth method }) => { // -- validate From 0e8c8fe86153616b7e39ed4be211500c9466a8b9 Mon Sep 17 00:00:00 2001 From: Ansonhkg Date: Fri, 10 Nov 2023 14:02:43 +0000 Subject: [PATCH 8/8] fix: ignore_dirs --- e2e-nodejs/index.mjs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/e2e-nodejs/index.mjs b/e2e-nodejs/index.mjs index 02a6cb499c..de608ea72b 100644 --- a/e2e-nodejs/index.mjs +++ b/e2e-nodejs/index.mjs @@ -99,6 +99,11 @@ async function main() { const group = file.split('/')[file.split('/').length - 2]; // Assuming group is the second last part of the file path + // skip the for loop if group is in IGNORE_DIRS + if (IGNORE_DIRS.includes(group)) { + continue; + } + if (group !== currentGroup) { console.log(`\nRunning tests in ${group}`); currentGroup = group;