From c94444e7fd0cabc34a882980c47c8516798f2fc8 Mon Sep 17 00:00:00 2001 From: Damjan Date: Wed, 20 Nov 2024 14:50:05 +0100 Subject: [PATCH 1/3] Implement RPC module and RPC Api Key model --- packages/sdk/src/lib/apillon.ts | 11 ++++ .../cloud-functions/cloud-functions.ts | 7 +- packages/sdk/src/modules/rpc/rpc-api-key.ts | 44 +++++++++++++ packages/sdk/src/modules/rpc/rpc.ts | 63 ++++++++++++++++++ packages/sdk/src/tests/rpc.test.ts | 66 +++++++++++++++++++ packages/sdk/src/types/cloud-functions.ts | 11 ---- packages/sdk/src/types/rpc.ts | 17 +++++ 7 files changed, 204 insertions(+), 15 deletions(-) create mode 100644 packages/sdk/src/modules/rpc/rpc-api-key.ts create mode 100644 packages/sdk/src/modules/rpc/rpc.ts create mode 100644 packages/sdk/src/tests/rpc.test.ts create mode 100644 packages/sdk/src/types/rpc.ts diff --git a/packages/sdk/src/lib/apillon.ts b/packages/sdk/src/lib/apillon.ts index 866e0af..91a65b5 100644 --- a/packages/sdk/src/lib/apillon.ts +++ b/packages/sdk/src/lib/apillon.ts @@ -30,6 +30,17 @@ export interface ApillonConfig { debug?: boolean; } +export interface ICreateApillonModel { + /** + * Name of the model object + */ + name: string; + /** + * Description of the model object + */ + description: string; +} + export class ApillonModule { protected config: ApillonConfig; diff --git a/packages/sdk/src/modules/cloud-functions/cloud-functions.ts b/packages/sdk/src/modules/cloud-functions/cloud-functions.ts index b1d2ca4..535391b 100644 --- a/packages/sdk/src/modules/cloud-functions/cloud-functions.ts +++ b/packages/sdk/src/modules/cloud-functions/cloud-functions.ts @@ -1,8 +1,7 @@ -import { ApillonModule } from '../../lib/apillon'; +import { ApillonModule, ICreateApillonModel } from '../../lib/apillon'; import { ApillonApi } from '../../lib/apillon-api'; import { constructUrlWithQueryParams } from '../../lib/common'; import { IApillonList, IApillonPagination } from '../../types/apillon'; -import { ICreateCloudFunction } from '../../types/cloud-functions'; import { CloudFunction } from './cloud-function'; import { CloudFunctionJob } from './cloud-function-job'; @@ -38,11 +37,11 @@ export class CloudFunctions extends ApillonModule { /** * Creates a new cloud function based on the provided data. - * @param {ICreateCloudFunction} data Data for creating the cloud function. + * @param {ICreateApillonModel} data Data for creating the cloud function. * @returns {CloudFunction} Newly created cloud function. */ public async createCloudFunction( - data: ICreateCloudFunction, + data: ICreateApillonModel, ): Promise { const cloudFunction = await ApillonApi.post< CloudFunction & { functionUuid: string } diff --git a/packages/sdk/src/modules/rpc/rpc-api-key.ts b/packages/sdk/src/modules/rpc/rpc-api-key.ts new file mode 100644 index 0000000..f158edf --- /dev/null +++ b/packages/sdk/src/modules/rpc/rpc-api-key.ts @@ -0,0 +1,44 @@ +import { ApillonModel } from '../../lib/apillon'; + +export class RpcApiKey extends ApillonModel { + /** + * Unique identifier of the RPC API key. + */ + public id: number = null; + + /** + * Name of the RPC API key. + */ + public name: string = null; + + /** + * Description of the RPC API key. + */ + public description: string = null; + + /** + * Unique identifier of the project. + */ + public projectUuid: string = null; + + /** + * Unique identifier of the RPC API key, used for RPC calls. + */ + public uuid: string = null; + + /** + * Array of favorite URLs for the RPC API key. + */ + public urls: string[] = []; + + /** + * Constructor which should only be called via Rpc class. + * @param id Unique identifier of the RPC API key. + * @param data Data to populate RPC API key with. + */ + constructor(id: number, data?: Partial) { + super(id.toString()); + this.API_PREFIX = `/rpc/api-key/${id}`; + this.populate(data); + } +} diff --git a/packages/sdk/src/modules/rpc/rpc.ts b/packages/sdk/src/modules/rpc/rpc.ts new file mode 100644 index 0000000..3657529 --- /dev/null +++ b/packages/sdk/src/modules/rpc/rpc.ts @@ -0,0 +1,63 @@ +import { ApillonModule, ICreateApillonModel } from '../../lib/apillon'; +import { ApillonApi } from '../../lib/apillon-api'; +import { constructUrlWithQueryParams } from '../../lib/common'; +import { IApillonList, IApillonPagination } from '../../types/apillon'; +import { RpcEndpoint } from '../../types/rpc'; +import { RpcApiKey } from './rpc-api-key'; + +export class Rpc extends ApillonModule { + /** + * API URL for RPC module. + */ + private API_PREFIX = '/rpc'; + + /** + * List all API keys for RPC. + * @param {IApillonPagination} params - The query parameters for filtering API keys. + * @returns The list of API keys. + */ + public async listApiKeys( + params?: IApillonPagination, + ): Promise> { + const url = constructUrlWithQueryParams( + `${this.API_PREFIX}/api-key`, + params, + ); + + const data = await ApillonApi.get>(url); + + return { + ...data, + items: data.items.map((apiKey) => new RpcApiKey(apiKey.id, apiKey)), + }; + } + + /** + * Create a new API key for RPC module. + * @param {ApillonApiCreateRpcApiKeyDto} data - The data for creating an API key. + * @returns The created API key. + */ + public async createApiKey(data: ICreateApillonModel): Promise { + const apiKey = await ApillonApi.post( + `${this.API_PREFIX}/api-key`, + data, + ); + return new RpcApiKey(apiKey.uuid, apiKey); + } + + /** + * Get all available endpoints for the RPC service. + * @returns The list of endpoints. + */ + public async listEndpoints(): Promise { + return await ApillonApi.get(`${this.API_PREFIX}/endpoints`); + } + + /** + * @param id Unique API key identifier. + * @returns An empty instance of RpcApiKey. + */ + public apiKey(id: number): RpcApiKey { + return new RpcApiKey(id, null); + } +} diff --git a/packages/sdk/src/tests/rpc.test.ts b/packages/sdk/src/tests/rpc.test.ts new file mode 100644 index 0000000..cf24be0 --- /dev/null +++ b/packages/sdk/src/tests/rpc.test.ts @@ -0,0 +1,66 @@ +import { Rpc } from '../modules/rpc/rpc'; +import { RpcApiKey } from '../modules/rpc/rpc-api-key'; +import { getConfig } from './helpers/helper'; + +describe('Rpc Module tests', () => { + let rpc: Rpc; + let apiKeyId: number; + + beforeAll(() => { + rpc = new Rpc(getConfig()); + }); + + test('Create new API key', async () => { + const apiKeyData = { + name: 'Test API Key', + description: 'Test Description', + }; + const apiKey = await rpc.createApiKey(apiKeyData); + + expect(apiKey).toBeInstanceOf(RpcApiKey); + expect(apiKey.name).toEqual(apiKeyData.name); + expect(apiKey.description).toEqual(apiKeyData.description); + expect(apiKey.uuid).toBeTruthy(); + expect(apiKey.id).toBeTruthy(); + + apiKeyId = apiKey.id; + }); + + test('List API keys', async () => { + const { items } = await rpc.listApiKeys(); + + expect(items.length).toBeGreaterThanOrEqual(0); + items.forEach((apiKey) => { + expect(apiKey).toBeInstanceOf(RpcApiKey); + expect(apiKey.name).toBeTruthy(); + expect(apiKey.uuid).toBeTruthy(); + expect(apiKey.id).toBeTruthy(); + }); + }); + + test('Get specific API key', async () => { + const apiKey = await rpc.apiKey(apiKeyId).get(); + + expect(apiKey).toBeInstanceOf(RpcApiKey); + expect(apiKey.id).toEqual(apiKeyId); + }); + + test('List endpoints', async () => { + const endpoints = await rpc.listEndpoints(); + + expect(Array.isArray(endpoints)).toBeTruthy(); + expect(endpoints.length).toBeGreaterThanOrEqual(0); + + endpoints.forEach((endpoint) => { + expect(endpoint).toMatchObject({ + id: expect.any(Number), + name: expect.any(String), + imageUrl: expect.any(String), + type: expect.any(String), + version: expect.any(String), + networkName: expect.any(String), + networkId: expect.any(Number), + }); + }); + }); +}); diff --git a/packages/sdk/src/types/cloud-functions.ts b/packages/sdk/src/types/cloud-functions.ts index 426294f..a4c2bc5 100644 --- a/packages/sdk/src/types/cloud-functions.ts +++ b/packages/sdk/src/types/cloud-functions.ts @@ -1,14 +1,3 @@ -export interface ICreateCloudFunction { - /** - * Name of the cloud function. - */ - name: string; - /** - * Description of the cloud function. - */ - description: string; -} - /** * Interface for creating a cloud function job. */ diff --git a/packages/sdk/src/types/rpc.ts b/packages/sdk/src/types/rpc.ts new file mode 100644 index 0000000..7683967 --- /dev/null +++ b/packages/sdk/src/types/rpc.ts @@ -0,0 +1,17 @@ +export type RpcEndpoint = { + id: number; + name: string; + imageUrl: string; + type: string; + version: string; + nodes: Array<{ + id: number; + https: string; + wss: string; + nodeType: string; + type: string; + version: string; + }>; + networkName: string; + networkId: number; +}; From 46989e2fdb1175698d32a36cd8c4c17809dc0c79 Mon Sep 17 00:00:00 2001 From: Damjan Date: Wed, 20 Nov 2024 14:51:25 +0100 Subject: [PATCH 2/3] Add docs, upgrade SDK version --- package-lock.json | 27 +++++++++++---------- packages/sdk/README.md | 37 +++++++++++++++++++++++++++++ packages/sdk/package.json | 2 +- packages/sdk/src/modules/rpc/rpc.ts | 2 +- 4 files changed, 53 insertions(+), 15 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1d2a899..c746000 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2920,9 +2920,10 @@ "dev": true }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -3057,9 +3058,9 @@ "dev": true }, "node_modules/elliptic": { - "version": "6.5.7", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.7.tgz", - "integrity": "sha512-ESVCtTwiA+XhY3wyh24QqRGBoP3rEdDUl3EDUUo9tft074fi19IrdpH7hLCMMP3CIj7jb3W96rn8lt/BqIlt5Q==", + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.1.tgz", + "integrity": "sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==", "license": "MIT", "dependencies": { "bn.js": "^4.11.9", @@ -7119,7 +7120,7 @@ }, "packages/sdk": { "name": "@apillon/sdk", - "version": "3.5.0", + "version": "3.6.0", "license": "MIT", "dependencies": { "@polkadot/util-crypto": "^12.6.2", @@ -9573,9 +9574,9 @@ "dev": true }, "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "requires": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -9665,9 +9666,9 @@ "dev": true }, "elliptic": { - "version": "6.5.7", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.7.tgz", - "integrity": "sha512-ESVCtTwiA+XhY3wyh24QqRGBoP3rEdDUl3EDUUo9tft074fi19IrdpH7hLCMMP3CIj7jb3W96rn8lt/BqIlt5Q==", + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.1.tgz", + "integrity": "sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==", "requires": { "bn.js": "^4.11.9", "brorand": "^1.1.0", diff --git a/packages/sdk/README.md b/packages/sdk/README.md index 0588dce..cf9a34c 100644 --- a/packages/sdk/README.md +++ b/packages/sdk/README.md @@ -383,6 +383,7 @@ async function validatePolkadotWalletSignature() { } ``` + ## Computing The Computing module provides functionalities for managing computing contracts, including creating contracts, listing contracts, and interacting with specific contracts for operations like encryption and ownership transfer. @@ -435,6 +436,42 @@ console.log( ); ``` +## RPCs + +The RPC module provides functionalities for managing RPC API keys and listing available endpoints. This module is essential for interacting with the Apillon platform's RPC services dynamically. + +### Usage example + +```typescript +import { Rpc } from '@apillon/sdk'; +import { getConfig } from './helpers/helper'; + +// Initialize the RPC module +const rpc = new Rpc({ + key: 'yourApiKey', + secret: 'yourApiSecret', +}); + +// Create a new API key +const apiKey = await rpc.createApiKey({ + name: 'Test API Key', + description: 'Test Description', +}); +console.log('API Key created:', apiKey.name); + +// List all API keys +const { items } = await rpc.listApiKeys(); +console.log('Total API Keys:', items.length); + +// Get a specific API key by ID +const apiKey = await rpc.apiKey(apiKeyId).get(); +console.log('API Key UUID:', apiKey.uuid); + +// List all available endpoints +const endpoints = await rpc.listEndpoints(); +console.log('Total Endpoints:', endpoints.length); +``` + ## Social The Social module provides functionalities for managing social hubs and channels within the Apillon platform. This includes creating, listing, and interacting with hubs and channels. In the background it utilizes Grill.chat, a mobile-friendly, anonymous chat application powered by Subsocial. diff --git a/packages/sdk/package.json b/packages/sdk/package.json index f893a0d..67a8b1e 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -1,7 +1,7 @@ { "name": "@apillon/sdk", "description": "▶◀ Apillon SDK for NodeJS ▶◀", - "version": "3.5.0", + "version": "3.6.0", "author": "Apillon", "license": "MIT", "main": "./dist/index.js", diff --git a/packages/sdk/src/modules/rpc/rpc.ts b/packages/sdk/src/modules/rpc/rpc.ts index 3657529..d20a4ef 100644 --- a/packages/sdk/src/modules/rpc/rpc.ts +++ b/packages/sdk/src/modules/rpc/rpc.ts @@ -37,7 +37,7 @@ export class Rpc extends ApillonModule { * @param {ApillonApiCreateRpcApiKeyDto} data - The data for creating an API key. * @returns The created API key. */ - public async createApiKey(data: ICreateApillonModel): Promise { + public async createApiKey(data: ICreateApillonModel): Promise { const apiKey = await ApillonApi.post( `${this.API_PREFIX}/api-key`, data, From 711160d394a5fd4da459c91fa19bdef918bc51e5 Mon Sep 17 00:00:00 2001 From: Damjan Date: Wed, 20 Nov 2024 14:58:32 +0100 Subject: [PATCH 3/3] Update SDK exports --- packages/sdk/src/docs-index.ts | 6 ++++++ packages/sdk/src/index.ts | 7 ++++++- packages/sdk/src/types/indexer.ts | 4 ++-- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/packages/sdk/src/docs-index.ts b/packages/sdk/src/docs-index.ts index 426a920..2c4b721 100644 --- a/packages/sdk/src/docs-index.ts +++ b/packages/sdk/src/docs-index.ts @@ -5,6 +5,10 @@ export * from './types/storage'; export * from './types/identity'; export * from './types/computing'; export * from './types/social'; +export * from './types/cloud-functions'; +export * from './types/indexer'; +export * from './types/rpc'; + export * from './lib/apillon'; export * from './modules/storage/storage'; export * from './modules/storage/storage-bucket'; @@ -28,3 +32,5 @@ export * from './modules/cloud-functions/cloud-function'; export * from './modules/cloud-functions/cloud-function-job'; export * from './modules/indexing/indexing'; export * from './modules/indexing/indexer'; +export * from './modules/rpc/rpc'; +export * from './modules/rpc/rpc-api-key'; diff --git a/packages/sdk/src/index.ts b/packages/sdk/src/index.ts index f4f3584..d74f81e 100644 --- a/packages/sdk/src/index.ts +++ b/packages/sdk/src/index.ts @@ -4,8 +4,13 @@ export * from './types/hosting'; export * from './types/storage'; export * from './types/identity'; export * from './types/social'; +export * from './types/cloud-functions'; +export * from './types/indexer'; +export * from './types/rpc'; + export * from './lib/apillon'; export * from './lib/common'; + export * from './modules/storage/storage'; export * from './modules/hosting/hosting'; export * from './modules/nft/nft'; @@ -15,4 +20,4 @@ export * from './modules/social/social'; export * from './modules/project/project'; export * from './modules/cloud-functions/cloud-functions'; export * from './modules/indexing/indexing'; -export * from './modules/indexing/indexer'; \ No newline at end of file +export * from './modules/rpc/rpc'; diff --git a/packages/sdk/src/types/indexer.ts b/packages/sdk/src/types/indexer.ts index 50c7dc0..e63b183 100644 --- a/packages/sdk/src/types/indexer.ts +++ b/packages/sdk/src/types/indexer.ts @@ -12,7 +12,7 @@ export enum DeploymentType { SET_TAG = 'SET_TAG', REMOVE_TAG = 'REMOVE_TAG', } -export enum DeploymentStatus { +export enum IndexerDeploymentStatus { UNPACKING = 'UNPACKING', IMAGE_BUILDING = 'IMAGE_BUILDING', RESETTING = 'RESETTING', @@ -57,7 +57,7 @@ export interface IDeployIndexer { */ id: number; type: DeploymentType; - status: DeploymentStatus; + status: IndexerDeploymentStatus; failed: DeploymentFailed; }; }