diff --git a/examples/get-usage/index.ts b/examples/get-usage/index.ts new file mode 100644 index 00000000..0fb5d621 --- /dev/null +++ b/examples/get-usage/index.ts @@ -0,0 +1,18 @@ +require('dotenv').config(); + +const { AccountClient } = require('@openzeppelin/defender-account-client'); + +async function main() { + const creds = { apiKey: process.env.ADMIN_API_KEY, apiSecret: process.env.ADMIN_API_SECRET }; + + const client = new AccountClient(creds); + + // List Account Usage + const usage = await client.getUsage(); + + console.log(usage); +} + +if (require.main === module) { + main().catch(console.error); +} diff --git a/examples/get-usage/package.json b/examples/get-usage/package.json new file mode 100644 index 00000000..5456b2bd --- /dev/null +++ b/examples/get-usage/package.json @@ -0,0 +1,15 @@ +{ + "name": "get-usage", + "version": "1.49.0", + "private": true, + "main": "index.js", + "author": "Zeljko Markovic ", + "license": "MIT", + "scripts": { + "start": "node index.js" + }, + "dependencies": { + "@openzeppelin/defender-base-client": "1.49.0", + "dotenv": "^8.2.0" + } +} diff --git a/lerna.json b/lerna.json index 85508c99..a6ba5a27 100644 --- a/lerna.json +++ b/lerna.json @@ -8,6 +8,7 @@ "packages/kvstore", "packages/relay", "packages/sentinel", + "packages/account", "examples/*" ], "useNx": true, diff --git a/packages/account/README.md b/packages/account/README.md new file mode 100644 index 00000000..e1c31c3f --- /dev/null +++ b/packages/account/README.md @@ -0,0 +1,52 @@ +# Defender Account Client + +Defender Account acts as an interface to manage your account. + +## Install + +```bash +npm install @openzeppelin/defender-account-client +``` + +```bash +yarn add @openzeppelin/defender-account-client +``` + +## Usage + +Start by creating a new _Team API Key_ in Defender, and granting it the capability to create new proposals. Use the newly created API key to initialize an instance of the Account client. + +```js +const { AccountClient } = require('@openzeppelin/defender-account-client'); +const client = new AccountClient({ apiKey: API_KEY, apiSecret: API_SECRET }); +``` + +### Account Usage + +To get account usages `getUsage` method can be used: + +```js +await client.getUsage(); +``` + +You can optionally set date to get usage for past period. When date is set only subset of quotas connected to the monthly usage is returned. + +```js +await client.getUsage({ + date: '2023-10-01' +}); +``` + +You can also optionally set quotas list to get usage only for desired quotas. + +```js +await client.getUsage({ + quotas: ['relayers', 'relayerTxPerHour'] +}); +``` + +## FAQ + +**Can I use this package in a browser?** + +This package is not designed to be used in a browser environment. Using this package requires sensitive API KEYS that should not be exposed publicly. diff --git a/packages/account/jest.config.js b/packages/account/jest.config.js new file mode 100644 index 00000000..990bd442 --- /dev/null +++ b/packages/account/jest.config.js @@ -0,0 +1 @@ +module.exports = require('../../jest.config'); diff --git a/packages/account/package.json b/packages/account/package.json new file mode 100644 index 00000000..8ed51b42 --- /dev/null +++ b/packages/account/package.json @@ -0,0 +1,31 @@ +{ + "name": "@openzeppelin/defender-account-client", + "version": "1.50.0-rc.0", + "description": "", + "main": "./lib/index.js", + "types": "./lib/index.d.ts", + "scripts": { + "build": "rm -rf lib && tsc", + "test": "yarn test:unit", + "test:unit": "jest --verbose --passWithNoTests", + "watch": "tsc -w", + "prepare": "yarn build" + }, + "files": [ + "lib", + "!*.test.js", + "!*.test.js.map", + "!*.test.d.ts", + "!*__mocks__" + ], + "author": "Zeljko Markovic ", + "license": "MIT", + "dependencies": { + "@openzeppelin/defender-base-client": "1.50.0-rc.0", + "axios": "^1.4.0" + }, + "publishConfig": { + "access": "public" + }, + "gitHead": "a7c4808dd11e708df42d110de230c264061c72c3" +} diff --git a/packages/account/src/api.ts b/packages/account/src/api.ts new file mode 100644 index 00000000..33bf3e55 --- /dev/null +++ b/packages/account/src/api.ts @@ -0,0 +1,29 @@ +import { BaseApiClient, ApiVersion } from '@openzeppelin/defender-base-client'; + +import { AccountUsageResponse } from './models/account'; + +export class AccountClient extends BaseApiClient { + protected getPoolId(): string { + return process.env.DEFENDER_ADMIN_POOL_ID ?? 'us-west-2_94f3puJWv'; + } + + protected getPoolClientId(): string { + return process.env.DEFENDER_ADMIN_POOL_CLIENT_ID ?? '40e58hbc7pktmnp9i26hh5nsav'; + } + + protected getApiUrl(v: ApiVersion = 'v1'): string { + if (v === 'v2') { + return process.env.DEFENDER_API_V2_URL ?? 'https://defender-api.openzeppelin.com/v2/'; + } + return process.env.DEFENDER_ADMIN_API_URL ?? 'https://defender-api.openzeppelin.com/admin/'; + } + + public async getUsage(params?: { date?: string | Date; quotas: string[] }): Promise { + const searchParams = new URLSearchParams({ + ...(params?.quotas && { quotas: params.quotas.join(',') }), + ...(params?.date && { date: new Date(params.date).toISOString() }), + }); + + return this.apiCall(async (api) => api.get(`/account/usage?${searchParams.toString()}`)); + } +} diff --git a/packages/account/src/index.ts b/packages/account/src/index.ts new file mode 100644 index 00000000..36400f11 --- /dev/null +++ b/packages/account/src/index.ts @@ -0,0 +1,5 @@ +export { AccountClient } from './api'; +export { AccountUsageResponse } from './models/account'; + +// eslint-disable-next-line @typescript-eslint/no-var-requires +export const VERSION = require('../package.json').version; diff --git a/packages/account/src/models/account.ts b/packages/account/src/models/account.ts new file mode 100644 index 00000000..fc9f9156 --- /dev/null +++ b/packages/account/src/models/account.ts @@ -0,0 +1,16 @@ +type AccountUsage = + | { + name: string; + description: string; + used: number; + limit: number; + overage?: number; + remaining: number; + period: 'hour' | 'month' | 'total'; + } + | { + name: string; + error: string; + }; + +export type AccountUsageResponse = Record; diff --git a/packages/account/tsconfig.json b/packages/account/tsconfig.json new file mode 100644 index 00000000..4d5d6974 --- /dev/null +++ b/packages/account/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "code-style/tsconfig.json", + "compilerOptions": { + "declaration": true, + "outDir": "./lib", + "skipLibCheck": true, + "sourceMap": false + }, + "include": ["./src"] +} diff --git a/packages/base/src/utils/network.ts b/packages/base/src/utils/network.ts index d96485f9..94781784 100644 --- a/packages/base/src/utils/network.ts +++ b/packages/base/src/utils/network.ts @@ -84,7 +84,7 @@ export const Networks: Network[] = [ 'x-dfk-avax-chain', 'x-dfk-avax-chain-test', 'mantle', - 'scroll-sepolia' + 'scroll-sepolia', ]; export function isValidNetwork(text: string): text is Network { return (Networks as string[]).includes(text);