diff --git a/.gitignore b/.gitignore index a489e5ab..b27a7346 100644 --- a/.gitignore +++ b/.gitignore @@ -13,4 +13,5 @@ dist .DS_Store tmp .pnpm-store +session.json .nx diff --git a/examples/auth-caching-relay-signer/auth.js b/examples/auth-caching-relay-signer/auth.js new file mode 100644 index 00000000..0032c1df --- /dev/null +++ b/examples/auth-caching-relay-signer/auth.js @@ -0,0 +1,24 @@ +require('dotenv').config(); + +const { Defender } = require('@openzeppelin/defender-sdk'); +const fs = require('fs'); + +async function main() { + const creds = { + relayerApiKey: process.env.RELAYER_API_KEY, + relayerApiSecret: process.env.RELAYER_API_SECRET, + }; + const client = new Defender(creds); + + const relayerApiKey = client.relaySigner.getApiKey(); + const accessToken = await client.relaySigner.getAccessToken(); + + // writes session.json with apiKey and accessToken + fs.writeFileSync('session.json', JSON.stringify({ relayerApiKey, accessToken }, null, 2)); + + console.log('Done! ✅'); +} + +if (require.main === module) { + main().catch(console.error); +} diff --git a/examples/auth-caching-relay-signer/index.js b/examples/auth-caching-relay-signer/index.js new file mode 100644 index 00000000..ca2cb016 --- /dev/null +++ b/examples/auth-caching-relay-signer/index.js @@ -0,0 +1,29 @@ +require('dotenv').config(); + +const { Defender } = require('@openzeppelin/defender-sdk'); +const fs = require('fs'); + +async function main() { + let cachedCredentials = {}; + + try { + cachedCredentials = JSON.parse(fs.readFileSync('session.json')); + } catch (e) { + console.error('❌ No credentials found. Please run "auth" command first.'); + return; + } + + try { + const client = new Defender(cachedCredentials); + const info = await client.relaySigner.getRelayerStatus(); + console.log('relayerStatus', JSON.stringify(info, null, 2)); + } catch (e) { + if (e.response?.status === 401) { + console.error('❌ Access token expired. Please run "auth" command again.'); + } + } +} + +if (require.main === module) { + main().catch(console.error); +} diff --git a/examples/auth-caching-relay-signer/package.json b/examples/auth-caching-relay-signer/package.json new file mode 100644 index 00000000..dc4052d0 --- /dev/null +++ b/examples/auth-caching-relay-signer/package.json @@ -0,0 +1,16 @@ +{ + "name": "@openzeppelin/defender-sdk-example-auth-caching", + "version": "1.13.1", + "private": true, + "main": "index.js", + "author": "Marcos Carlomagno ", + "license": "MIT", + "scripts": { + "auth": "node auth.js", + "start": "node index.js" + }, + "dependencies": { + "@openzeppelin/defender-sdk": "1.13.1", + "dotenv": "^16.3.1" + } +} diff --git a/packages/account/src/api/index.ts b/packages/account/src/api/index.ts index ff5a4b71..5b73736e 100644 --- a/packages/account/src/api/index.ts +++ b/packages/account/src/api/index.ts @@ -17,6 +17,14 @@ export class AccountClient extends BaseApiClient { return process.env.DEFENDER_API_URL ?? 'https://defender-api.openzeppelin.com/'; } + public getApiKey(): string { + return this.getKey(); + } + + public getAccessToken(): Promise { + return this.getToken(); + } + public async getUsage(params?: { date?: string | Date; quotas: string[] }): Promise { const searchParams = new URLSearchParams({ ...(params?.quotas && { quotas: params.quotas.join(',') }), diff --git a/packages/action/src/api.ts b/packages/action/src/api.ts index eadbb197..456cfab3 100644 --- a/packages/action/src/api.ts +++ b/packages/action/src/api.ts @@ -36,6 +36,14 @@ export class ActionClient extends BaseApiClient { return process.env.DEFENDER_API_URL || 'https://defender-api.openzeppelin.com/'; } + public getApiKey(): string { + return this.getKey(); + } + + public getAccessToken(): Promise { + return this.getToken(); + } + public async list(): Promise { return this.apiCall(async (api) => { return await api.get(`/actions`); diff --git a/packages/base/src/api/client.ts b/packages/base/src/api/client.ts index a38e8f76..5e9fe0dd 100644 --- a/packages/base/src/api/client.ts +++ b/packages/base/src/api/client.ts @@ -23,10 +23,12 @@ type ApiFunction = (api: AxiosInstance) => Promise; export abstract class BaseApiClient { private api: AxiosInstance | undefined; private session: CognitoUserSession | undefined; + private sessionV2: { accessToken: string; refreshToken: string } | undefined; - private apiSecret: string; + private apiSecret: string | undefined; private httpsAgent?: https.Agent; private retryConfig: RetryConfig; + private accessToken: string | undefined; private authConfig: AuthConfig; protected apiKey: string; @@ -35,30 +37,38 @@ export abstract class BaseApiClient { protected abstract getApiUrl(type?: AuthType): string; public constructor(params: { - apiKey: string; - apiSecret: string; + apiKey?: string; + apiSecret?: string; httpsAgent?: https.Agent; retryConfig?: Partial; + accessToken?: string; authConfig?: AuthConfig; }) { if (!params.apiKey) throw new Error(`API key is required`); - if (!params.apiSecret) throw new Error(`API secret is required`); + if (!params.apiSecret && !params.accessToken) throw new Error(`API secret or access token is required`); this.apiKey = params.apiKey; this.apiSecret = params.apiSecret; + this.accessToken = params.accessToken; this.httpsAgent = params.httpsAgent; this.retryConfig = { retries: 3, retryDelay: exponentialDelay, ...params.retryConfig }; this.authConfig = params.authConfig ?? { useCredentialsCaching: true, type: 'admin' }; } - private async getAccessToken(): Promise { + public async getAccessToken(): Promise { + if (this.accessToken) return this.accessToken; + if (!this.apiSecret) throw new Error('Cannot authenticate without API secret.'); + const userPass = { Username: this.apiKey, Password: this.apiSecret }; const poolData = { UserPoolId: this.getPoolId(), ClientId: this.getPoolClientId() }; const auth = await authenticate(userPass, poolData); return auth.getAccessToken().getJwtToken(); } - private async getAccessTokenV2(): Promise { + public async getAccessTokenV2(): Promise { + if (this.accessToken) return this.accessToken; + if (!this.apiSecret) throw new Error('Cannot authenticate without API secret.'); + if (!this.authConfig.type) throw new Error('Auth type is required to authenticate in auth v2'); const credentials = { apiKey: this.apiKey, @@ -71,6 +81,7 @@ export abstract class BaseApiClient { private async refreshSession(): Promise { if (!this.session) return this.getAccessToken(); + if (!this.apiSecret) throw new Error('Cannot authenticate without API secret.'); const userPass = { Username: this.apiKey, Password: this.apiSecret }; const poolData = { UserPoolId: this.getPoolId(), ClientId: this.getPoolClientId() }; this.session = await refreshSession(userPass, poolData, this.session); @@ -80,6 +91,7 @@ export abstract class BaseApiClient { private async refreshSessionV2(): Promise { if (!this.authConfig.type) throw new Error('Auth type is required to refresh session in auth v2'); if (!this.sessionV2) return this.getAccessTokenV2(); + if (!this.apiSecret) throw new Error('Cannot authenticate without API secret.'); const credentials = { apiKey: this.apiKey, secretKey: this.apiSecret, @@ -90,6 +102,20 @@ export abstract class BaseApiClient { return auth.accessToken; } + protected getKey(): string { + return this.apiKey; + } + + protected async getToken(): Promise { + if (this.accessToken) return this.accessToken; + if (!this.apiSecret) throw new Error('Cannot authenticate without API secret.'); + + const userPass = { Username: this.apiKey, Password: this.apiSecret }; + const poolData = { UserPoolId: this.getPoolId(), ClientId: this.getPoolClientId() }; + this.session = await authenticate(userPass, poolData); + return this.session.getAccessToken().getJwtToken(); + } + protected async init(): Promise { if (!this.api) { const accessToken = this.authConfig.useCredentialsCaching @@ -105,6 +131,9 @@ export abstract class BaseApiClient { if (!this.session && !this.sessionV2) { return this.init(); } + if (!this.apiSecret) { + throw new Error('Cannot refresh session without API secret.'); + } try { const accessToken = this.authConfig.useCredentialsCaching ? await this.refreshSessionV2() @@ -139,6 +168,9 @@ export abstract class BaseApiClient { // this means ID token has expired so we'll recreate session and try again if (isAuthenticationError(error)) { + // if using custom access token, throw error. + if (this.accessToken) throw error; + this.api = undefined; const api = await this.refresh(); diff --git a/packages/base/src/utils/network.ts b/packages/base/src/utils/network.ts index 4effaaba..ca7c34ed 100644 --- a/packages/base/src/utils/network.ts +++ b/packages/base/src/utils/network.ts @@ -20,8 +20,8 @@ export type PublicNetwork = | 'fantomtest' | 'fuji' | 'fuse' - | 'geist-polter' | 'geist-mainnet' + | 'geist-polter' | 'hedera' | 'hederatest' | 'holesky' @@ -73,8 +73,8 @@ export const Networks: Network[] = [ 'fantomtest', 'fuji', 'fuse', - 'geist-polter', 'geist-mainnet', + 'geist-polter', 'hedera', 'hederatest', 'holesky', @@ -140,8 +140,8 @@ export const chainIds: { [key in Network]: number } = { 'fantomtest': 4002, 'fuji': 43113, 'fuse': 122, - 'geist-polter': 631571, 'geist-mainnet': 63157, + 'geist-polter': 631571, 'hedera': 295, 'hederatest': 296, 'holesky': 17000, diff --git a/packages/defender-sdk/src/index.ts b/packages/defender-sdk/src/index.ts index 08611f6f..ccc9f356 100644 --- a/packages/defender-sdk/src/index.ts +++ b/packages/defender-sdk/src/index.ts @@ -27,6 +27,7 @@ export interface DefenderOptions { apiSecret?: string; relayerApiKey?: string; relayerApiSecret?: string; + accessToken?: string; credentials?: ActionRelayerParams; relayerARN?: string; httpsAgent?: https.Agent; @@ -41,7 +42,7 @@ function getClient(Client: Newable, credentials: Partial | A !isApiCredentials(credentials) && !isActionKVStoreCredentials(credentials) ) { - throw new Error(`API key and secret are required`); + throw new Error(`API authentication credentials required`); } return new Client(credentials); @@ -52,6 +53,7 @@ export class Defender { private apiSecret: string | undefined; private relayerApiKey: string | undefined; private relayerApiSecret: string | undefined; + private accessToken: string | undefined; private actionCredentials: ActionRelayerParams | undefined; private actionRelayerArn: string | undefined; private actionKVStoreArn: string | undefined; @@ -64,6 +66,7 @@ export class Defender { this.apiSecret = options.apiSecret; this.relayerApiKey = options.relayerApiKey; this.relayerApiSecret = options.relayerApiSecret; + this.accessToken = options.accessToken; // support for using relaySigner from Defender Actions this.actionCredentials = options.credentials; this.actionRelayerArn = options.relayerARN; @@ -189,6 +192,7 @@ export class Defender { ...(this.actionRelayerArn ? { relayerARN: this.actionRelayerArn } : undefined), ...(this.relayerApiKey ? { apiKey: this.relayerApiKey } : undefined), ...(this.relayerApiSecret ? { apiSecret: this.relayerApiSecret } : undefined), + ...(this.accessToken ? { accessToken: this.accessToken } : undefined), }); } diff --git a/packages/defender-sdk/src/utils.ts b/packages/defender-sdk/src/utils.ts index e18be111..c929802f 100644 --- a/packages/defender-sdk/src/utils.ts +++ b/packages/defender-sdk/src/utils.ts @@ -16,7 +16,7 @@ export function isActionRelayerCredentials(credentials: Partial | } export function isApiCredentials(credentials: Partial | ActionRelayerParams): boolean { - return 'apiKey' in credentials && 'apiSecret' in credentials; + return 'apiKey' in credentials && ('accessToken' in credentials || 'apiSecret' in credentials); } export function isActionKVStoreCredentials(credentials: Partial | ActionRelayerParams): boolean { diff --git a/packages/deploy/src/api/index.ts b/packages/deploy/src/api/index.ts index 4d7ff665..e318dcd6 100644 --- a/packages/deploy/src/api/index.ts +++ b/packages/deploy/src/api/index.ts @@ -32,6 +32,14 @@ export class DeployClient extends BaseApiClient { return process.env.DEFENDER_API_URL || 'https://defender-api.openzeppelin.com/'; } + public getApiKey(): string { + return this.getKey(); + } + + public getAccessToken(): Promise { + return this.getToken(); + } + public async deployContract(params: DeployContractRequest): Promise { if (isEmpty(params.artifactUri) && isEmpty(params.artifactPayload)) throw new Error( diff --git a/packages/monitor/src/api/index.ts b/packages/monitor/src/api/index.ts index 52c29ece..fabbb16f 100644 --- a/packages/monitor/src/api/index.ts +++ b/packages/monitor/src/api/index.ts @@ -34,6 +34,14 @@ export class MonitorClient extends BaseApiClient { return process.env.DEFENDER_API_URL || 'https://defender-api.openzeppelin.com/v2/'; } + public getApiKey(): string { + return this.getKey(); + } + + public getAccessToken(): Promise { + return this.getToken(); + } + public async list(): Promise { return this.apiCall(async (api) => { return await api.get(`/monitors`); diff --git a/packages/network/src/api/index.ts b/packages/network/src/api/index.ts index 1b453f98..13f7edfa 100644 --- a/packages/network/src/api/index.ts +++ b/packages/network/src/api/index.ts @@ -25,6 +25,14 @@ export class NetworkClient extends BaseApiClient { return process.env.DEFENDER_API_URL || 'https://defender-api.openzeppelin.com/'; } + public getApiKey(): string { + return this.getKey(); + } + + public getAccessToken(): Promise { + return this.getToken(); + } + public async listSupportedNetworks(params?: ListNetworkRequestOptions): Promise { return this.apiCall(async (api) => { return await api.get(params && params.networkType ? `${PATH}?type=${params.networkType}` : `${PATH}`); diff --git a/packages/notification-channel/src/api/index.ts b/packages/notification-channel/src/api/index.ts index a52b6ae0..37175e49 100644 --- a/packages/notification-channel/src/api/index.ts +++ b/packages/notification-channel/src/api/index.ts @@ -24,6 +24,14 @@ export class NotificationChannelClient extends BaseApiClient { return process.env.DEFENDER_API_URL || 'https://defender-api.openzeppelin.com/v2/'; } + public getApiKey(): string { + return this.getKey(); + } + + public getAccessToken(): Promise { + return this.getToken(); + } + public async create(notification: CreateNotificationRequest): Promise { return this.apiCall(async (api) => { return await api.post(`${PATH}/${notification.type}`, notification); diff --git a/packages/proposal/src/api/index.ts b/packages/proposal/src/api/index.ts index c9806b87..403fd716 100644 --- a/packages/proposal/src/api/index.ts +++ b/packages/proposal/src/api/index.ts @@ -30,6 +30,14 @@ export class ProposalClient extends BaseApiClient { return process.env.DEFENDER_API_URL || 'https://defender-api.openzeppelin.com/'; } + public getApiKey(): string { + return this.getKey(); + } + + public getAccessToken(): Promise { + return this.getToken(); + } + public async addContract(contract: Contract): Promise { return this.apiCall(async (api) => { return (await api.put('/contracts', contract)) as Contract; diff --git a/packages/relay-signer/src/action/index.ts b/packages/relay-signer/src/action/index.ts index 6462d135..b625647e 100644 --- a/packages/relay-signer/src/action/index.ts +++ b/packages/relay-signer/src/action/index.ts @@ -48,6 +48,14 @@ export class ActionRelayer extends BaseActionClient implements IRelayer { this.jsonRpcRequestNextId = 0; } + public getApiKey(): string { + throw new Error('Method not available for action relayers.'); + } + + public getAccessToken(): Promise { + throw new Error('Method not available for action relayers.'); + } + public async sendTransaction(payload: RelayerTransactionPayload): Promise { return this.execute({ action: 'send-tx', payload }); } diff --git a/packages/relay-signer/src/api/index.ts b/packages/relay-signer/src/api/index.ts index fd647d95..920e6442 100644 --- a/packages/relay-signer/src/api/index.ts +++ b/packages/relay-signer/src/api/index.ts @@ -48,6 +48,14 @@ export class RelaySignerClient extends BaseApiClient implements IRelayer { return getApiUrl(); } + public getApiKey(): string { + return this.getKey(); + } + + public getToken(): Promise { + return this.getAccessToken(); + } + public async getRelayer(): Promise { return this.apiCall(async (api) => { return (await api.get('/relayers/self')) as RelayerGetResponse | RelayerGroupResponse; diff --git a/packages/relay-signer/src/ethers/utils.ts b/packages/relay-signer/src/ethers/utils.ts index 4b9aa930..50fe7b74 100644 --- a/packages/relay-signer/src/ethers/utils.ts +++ b/packages/relay-signer/src/ethers/utils.ts @@ -17,7 +17,7 @@ export function isActionCredentials( export function isApiCredentials(credentials: ActionRelayerParams | ApiRelayerParams): credentials is ApiRelayerParams { const apiCredentials = credentials as ApiRelayerParams; - return !!apiCredentials.apiKey && !!apiCredentials.apiSecret; + return !!apiCredentials.apiKey && !!(apiCredentials.apiSecret || apiCredentials.accessToken); } export function validatePayload(payload: RelayerTransactionPayload) { diff --git a/packages/relay-signer/src/models/relayer.ts b/packages/relay-signer/src/models/relayer.ts index 1d968b84..61a58a1b 100644 --- a/packages/relay-signer/src/models/relayer.ts +++ b/packages/relay-signer/src/models/relayer.ts @@ -16,7 +16,14 @@ export type Address = string; export type BigUInt = string | number; export type RelayerParams = ApiRelayerParams | ActionRelayerParams; -export type ApiRelayerParams = { apiKey: string; apiSecret: string; httpsAgent?: https.Agent; authConfig: AuthConfig }; + +export type ApiRelayerParams = { + apiKey: string; + apiSecret?: string; + accessToken?: string; + httpsAgent?: https.Agent; + authConfig: AuthConfig; +}; export type ActionRelayerParams = { credentials: string; relayerARN: string; @@ -156,4 +163,6 @@ export interface IRelayer { sign(payload: SignMessagePayload): Promise; signTypedData(payload: SignTypedDataPayload): Promise; call(params: { method: string; params: string[] }): Promise; + getApiKey(): string; + getAccessToken(): Promise; } diff --git a/packages/relay-signer/src/relayer.ts b/packages/relay-signer/src/relayer.ts index a099bba1..5400faec 100644 --- a/packages/relay-signer/src/relayer.ts +++ b/packages/relay-signer/src/relayer.ts @@ -70,11 +70,19 @@ export class Relayer implements IRelayer { }); } else { throw new Error( - `Missing credentials for creating a Relayer instance. If you are running this code in an Action, make sure you pass the "credentials" parameter from the handler to the Relayer constructor. If you are running this on your own process, then pass an object with the "apiKey" and "apiSecret" generated by the relayer.`, + `Missing credentials for creating a Relayer instance. If you are running this code in an Action, make sure you pass the "credentials" parameter from the handler to the Relayer constructor. If you are running this on your own process, then pass an object with the "apiKey" and "apiSecret" or "accessToken" generated by the relayer.`, ); } } + public getApiKey(): string { + return this.relayer.getApiKey(); + } + + public getAccessToken(): Promise { + return this.relayer.getAccessToken(); + } + public getRelayer(): Promise { return this.relayer.getRelayer(); } diff --git a/packages/relay/src/api/index.ts b/packages/relay/src/api/index.ts index 46de4b1d..16f6b4cc 100644 --- a/packages/relay/src/api/index.ts +++ b/packages/relay/src/api/index.ts @@ -23,6 +23,14 @@ export class RelayClient extends BaseApiClient { return process.env.DEFENDER_API_URL || 'https://defender-api.openzeppelin.com/'; } + public getApiKey(): string { + return this.getKey(); + } + + public getAccessToken(): Promise { + return this.getToken(); + } + public async get(id: string): Promise { return this.apiCall(async (api) => { return await api.get(`/relayers/${id}`); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0f3af38f..938465ea 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -113,6 +113,15 @@ importers: specifier: ^16.3.1 version: 16.4.5 + examples/auth-caching-relay-signer: + dependencies: + '@openzeppelin/defender-sdk': + specifier: 1.13.1 + version: 1.13.1(bufferutil@4.0.8)(utf-8-validate@5.0.10)(web3-core@4.7.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))(web3-utils@4.3.2)(web3@4.14.0(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8)) + dotenv: + specifier: ^16.3.1 + version: 16.4.5 + examples/create-action: dependencies: '@openzeppelin/defender-sdk': @@ -1481,6 +1490,44 @@ packages: cpu: [x64] os: [win32] + '@openzeppelin/defender-sdk-account-client@1.15.2': + resolution: {integrity: sha512-lhYf1rBtac1MBbKP/ALgkjUhVulqo45RtaemTP9xI6BwUCCb4nq2SSKM82UN5sOE2I+VXSbPXf8w91bao5Mmmg==} + + '@openzeppelin/defender-sdk-action-client@1.15.2': + resolution: {integrity: sha512-PpVFKaDU9jBNIoJWfwIA5/9I+qse/4rzEY3CqPvH1z7qGsUjKmImTcQA6SpEzbbvLFOjBY/cuHz6vaf/Vdttcg==} + hasBin: true + + '@openzeppelin/defender-sdk-base-client@1.15.2': + resolution: {integrity: sha512-N3ZTeH8TXyklL7yNPMLUv0dxQwT78DTkOEDhzMS2/QE2FxbXrclSseoeeXxl6UYI61RBtZKn+okbSsbwiB5QWQ==} + + '@openzeppelin/defender-sdk-deploy-client@1.15.2': + resolution: {integrity: sha512-zspzMqh+OC8arXAkgBqTUDVO+NfCkt54UrsmQHbA3UAjr5TiDXKycBKU5ORb01hE+2gAmoPwEpDW9uS2VLg33A==} + + '@openzeppelin/defender-sdk-monitor-client@1.15.2': + resolution: {integrity: sha512-SW+je3RvfAbS43gFtyPcPfloFiAj0VJJZpXsYpolA28j94pEBz5EdYczfNwq/QqyK5adAvASdHobCU9ywVlokw==} + + '@openzeppelin/defender-sdk-network-client@1.15.2': + resolution: {integrity: sha512-9r9pegc1aR7xzP9fmj1zvkk0OXMRJE10JabxxiJzAQQgmNXDeTGI6W5bFgrNJfxzcImNGqddJ3K4weKdLyL21A==} + + '@openzeppelin/defender-sdk-notification-channel-client@1.15.2': + resolution: {integrity: sha512-42c9rpQdFS9vQgwOetrsnMbnLPeQnD680Ex6jSvOK497NI7RNP8eFI4vHgzNBhCQYdlMj+oEY7gIhD7Vs0kUow==} + + '@openzeppelin/defender-sdk-proposal-client@1.15.2': + resolution: {integrity: sha512-Ib2pHGbgtEEnLagWIzW1eesbzGqIc0QKyHVyM1aIqcCJpvKZU9TKCgT7FMqo8m/g2HdJNY74qW3964j9/6ehbw==} + + '@openzeppelin/defender-sdk-relay-client@1.15.2': + resolution: {integrity: sha512-QqqprIcVcSS/xlos1gRtW2RIh5AtsOzY9vGnJ2jo5YcutUQrfUCICBigkn+BbeSHesleUxk/zGJInPKol9ir0g==} + + '@openzeppelin/defender-sdk-relay-signer-client@1.15.2': + resolution: {integrity: sha512-AqQOAkqOdpO7J+n1hzUWHVRvsb93t8Nb3wQEXJN+/UMcWfoKTOLSYOvjOMQ4PbEUmM8aI+YcQxJL5VfJlIXngQ==} + peerDependencies: + web3: ^4.14.0 + web3-core: ^4.7.0 + web3-utils: ^4.3.2 + + '@openzeppelin/defender-sdk@1.13.1': + resolution: {integrity: sha512-GC3pCqtuG82z4cfGo8ze3sAFM2gwWv/1Do/HPtH4f+a8jTbNXpHqWIQXQ+9Utsq36reVsC60pBeQHUuHvumpyg==} + '@pkgjs/parseargs@0.11.0': resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} @@ -5391,6 +5438,138 @@ snapshots: '@nx/nx-win32-x64-msvc@19.5.1': optional: true + '@openzeppelin/defender-sdk-account-client@1.15.2': + dependencies: + '@openzeppelin/defender-sdk-base-client': 1.15.2 + axios: 1.7.2 + lodash: 4.17.21 + transitivePeerDependencies: + - debug + - encoding + + '@openzeppelin/defender-sdk-action-client@1.15.2': + dependencies: + '@openzeppelin/defender-sdk-base-client': 1.15.2 + axios: 1.7.2 + dotenv: 16.4.5 + glob: 11.0.0 + jszip: 3.10.1 + lodash: 4.17.21 + transitivePeerDependencies: + - debug + - encoding + + '@openzeppelin/defender-sdk-base-client@1.15.2': + dependencies: + amazon-cognito-identity-js: 6.3.6 + async-retry: 1.3.3 + transitivePeerDependencies: + - encoding + + '@openzeppelin/defender-sdk-deploy-client@1.15.2': + dependencies: + '@openzeppelin/defender-sdk-base-client': 1.15.2 + axios: 1.7.2 + lodash: 4.17.21 + transitivePeerDependencies: + - debug + - encoding + + '@openzeppelin/defender-sdk-monitor-client@1.15.2(bufferutil@4.0.8)(utf-8-validate@5.0.10)': + dependencies: + '@openzeppelin/defender-sdk-base-client': 1.15.2 + axios: 1.7.2 + ethers: 6.9.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) + lodash: 4.17.21 + transitivePeerDependencies: + - bufferutil + - debug + - encoding + - utf-8-validate + + '@openzeppelin/defender-sdk-network-client@1.15.2': + dependencies: + '@openzeppelin/defender-sdk-base-client': 1.15.2 + axios: 1.7.2 + lodash: 4.17.21 + transitivePeerDependencies: + - debug + - encoding + + '@openzeppelin/defender-sdk-notification-channel-client@1.15.2': + dependencies: + '@openzeppelin/defender-sdk-base-client': 1.15.2 + axios: 1.7.2 + lodash: 4.17.21 + transitivePeerDependencies: + - debug + - encoding + + '@openzeppelin/defender-sdk-proposal-client@1.15.2(bufferutil@4.0.8)(utf-8-validate@5.0.10)': + dependencies: + '@openzeppelin/defender-sdk-base-client': 1.15.2 + axios: 1.7.2 + ethers: 6.9.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) + lodash: 4.17.21 + transitivePeerDependencies: + - bufferutil + - debug + - encoding + - utf-8-validate + + '@openzeppelin/defender-sdk-relay-client@1.15.2': + dependencies: + '@openzeppelin/defender-sdk-base-client': 1.15.2 + axios: 1.7.2 + lodash: 4.17.21 + transitivePeerDependencies: + - debug + - encoding + + '@openzeppelin/defender-sdk-relay-signer-client@1.15.2(bufferutil@4.0.8)(utf-8-validate@5.0.10)(web3-core@4.7.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))(web3-utils@4.3.2)(web3@4.14.0(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))': + dependencies: + '@ethersproject/bignumber': 5.7.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/logger': 5.7.0 + '@ethersproject/networks': 5.7.1 + '@ethersproject/properties': 5.7.0 + '@ethersproject/providers': 5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10) + '@ethersproject/strings': 5.7.0 + '@openzeppelin/defender-sdk-base-client': 1.15.2 + amazon-cognito-identity-js: 6.3.6 + axios: 1.7.2 + ethers: 6.9.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) + lodash: 4.17.21 + web3: 4.14.0(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8) + web3-core: 4.7.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) + web3-utils: 4.3.2 + transitivePeerDependencies: + - bufferutil + - debug + - encoding + - utf-8-validate + + '@openzeppelin/defender-sdk@1.13.1(bufferutil@4.0.8)(utf-8-validate@5.0.10)(web3-core@4.7.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))(web3-utils@4.3.2)(web3@4.14.0(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))': + dependencies: + '@openzeppelin/defender-sdk-account-client': 1.15.2 + '@openzeppelin/defender-sdk-action-client': 1.15.2 + '@openzeppelin/defender-sdk-base-client': 1.15.2 + '@openzeppelin/defender-sdk-deploy-client': 1.15.2 + '@openzeppelin/defender-sdk-monitor-client': 1.15.2(bufferutil@4.0.8)(utf-8-validate@5.0.10) + '@openzeppelin/defender-sdk-network-client': 1.15.2 + '@openzeppelin/defender-sdk-notification-channel-client': 1.15.2 + '@openzeppelin/defender-sdk-proposal-client': 1.15.2(bufferutil@4.0.8)(utf-8-validate@5.0.10) + '@openzeppelin/defender-sdk-relay-client': 1.15.2 + '@openzeppelin/defender-sdk-relay-signer-client': 1.15.2(bufferutil@4.0.8)(utf-8-validate@5.0.10)(web3-core@4.7.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))(web3-utils@4.3.2)(web3@4.14.0(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8)) + transitivePeerDependencies: + - bufferutil + - debug + - encoding + - utf-8-validate + - web3 + - web3-core + - web3-utils + '@pkgjs/parseargs@0.11.0': optional: true