Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

solution: sierra project and org api #45

Merged
merged 1 commit into from
Dec 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion api-definitions
108 changes: 91 additions & 17 deletions packages/core/src/typesSierra.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,41 @@
import * as sierra_stat_message_pb from './generated/sierra.stat.message_pb';
import * as sierra_message_pb from './generated/sierra.message_pb';
import { DataMapper } from './Publisher';
import { UUID } from "./typesCommon";
import { MessageFactory } from './typesConvert';

export interface Project {
orgId: UUID;
projectId: UUID;
name: string;
description: string;
createdAt: Date;
}

export interface Org {
orgId: UUID;
name: UUID;
description: string;
createdAt: Date;
}

export interface CreateProjectRequest {
orgId: UUID;
name: string;
description: string;
}

export interface CreateProjectResponse {
projectId: UUID;
}

export interface ListProjectsRequest {
orgId: UUID;
}

export interface GetOrgRequest {
orgId: UUID;
}

export enum Granularity {
UNSPECIFIED = 0,
SECOND = 1,
Expand All @@ -17,14 +51,15 @@ export enum GroupBy {
SERVICE = 1,
PROJECT = 2,
}

export interface GetRequestCountRequest {
orgId: string;
orgId: UUID;
timestampFrom?: Date;
timestampTo?: Date;
projectIds?: string[];
projectIds?: UUID[];
services?: string[];
granularity?: Granularity;
GroupBy?: GroupBy;
groupBy?: GroupBy;
}

export interface RequestCount {
Expand All @@ -37,7 +72,7 @@ export interface GroupService {
}

export interface GroupProjectId {
projectId: string;
projectId: UUID;
}

export interface GroupRequestCount {
Expand All @@ -46,12 +81,12 @@ export interface GroupRequestCount {
}

export interface GetTokenStatRequest {
orgId: string;
tokenIds?: string[];
orgId: UUID;
tokenIds?: UUID[];
}

export interface TokenStat {
tokenId: string;
tokenId: UUID;
lastTimestamp: Date;
}

Expand All @@ -62,8 +97,28 @@ export class ConvertSierra {
this.factory = factory;
}

public getRequestCountRequest(request: GetRequestCountRequest): sierra_stat_message_pb.GetRequestCountRequest {
const result: sierra_stat_message_pb.GetRequestCountRequest = this.factory('sierra_stat_message_pb.GetRequestCountRequest');
public createProjectRequest(request: CreateProjectRequest): sierra_message_pb.CreateProjectRequest {
const result: sierra_message_pb.CreateProjectRequest = this.factory('sierra_message_pb.CreateProjectRequest');
result.setOrgId(request.orgId);
result.setName(request.name);
result.setDescription(request.description);
return result;
}

public listProjectsRequest(request: ListProjectsRequest): sierra_message_pb.ListProjectsRequest {
const result: sierra_message_pb.ListProjectsRequest = this.factory('sierra_message_pb.ListProjectsRequest');
result.setOrgId(request.orgId);
return result;
}

public getOrgRequest(request: GetOrgRequest): sierra_message_pb.GetOrgRequest {
const result: sierra_message_pb.GetOrgRequest = this.factory('sierra_message_pb.GetOrgRequest');
result.setOrgId(request.orgId);
return result;
}

public getRequestCountRequest(request: GetRequestCountRequest): sierra_message_pb.GetRequestCountRequest {
const result: sierra_message_pb.GetRequestCountRequest = this.factory('sierra_message_pb.GetRequestCountRequest');
result.setOrgId(request.orgId)
if (request.timestampFrom) {
result.setTimestampFrom(request.timestampFrom.getTime());
Expand All @@ -80,20 +135,39 @@ export class ConvertSierra {
if (request.granularity) {
result.setGranularity(request.granularity.valueOf())
}
if (request.GroupBy) {
result.setGroupBy(request.GroupBy.valueOf());
if (request.groupBy) {
result.setGroupBy(request.groupBy.valueOf());
}
return result;
}

public requestCount(): DataMapper<sierra_stat_message_pb.RequestCount, RequestCount> {
public project(): DataMapper<sierra_message_pb.Project, Project> {
return (response) => ({
orgId: response.getOrgId(),
projectId: response.getProjectId(),
name: response.getName(),
description: response.getDescription(),
createdAt: new Date(response.getCreatedAt()),
});
}

public org(): DataMapper<sierra_message_pb.Org, Org> {
return (response) => ({
orgId: response.getOrgId(),
name: response.getName(),
description: response.getDescription(),
createdAt: new Date(response.getCreatedAt()),
});
}

public requestCount(): DataMapper<sierra_message_pb.RequestCount, RequestCount> {
return (response) => ({
timestamp: new Date(response.getTimestamp()),
count: response.getCount(),
});
}

public groupRequestCount(): DataMapper<sierra_stat_message_pb.GroupRequestCount, GroupRequestCount> {
public groupRequestCount(): DataMapper<sierra_message_pb.GroupRequestCount, GroupRequestCount> {
return (response) => {
let group: GroupService | GroupProjectId;
if (response.hasService()) {
Expand All @@ -112,16 +186,16 @@ export class ConvertSierra {
};
}

public getTokenStatRequest(request: GetTokenStatRequest): sierra_stat_message_pb.GetTokenStatRequest {
const result: sierra_stat_message_pb.GetTokenStatRequest = this.factory('sierra_stat_message_pb.GetTokenStatRequest');
public getTokenStatRequest(request: GetTokenStatRequest): sierra_message_pb.GetTokenStatRequest {
const result: sierra_message_pb.GetTokenStatRequest = this.factory('sierra_message_pb.GetTokenStatRequest');
result.setOrgId(request.orgId);
if (request.tokenIds) {
result.setTokenIdsList(request.tokenIds);
}
return result;
}

public tokenStat(): DataMapper<sierra_stat_message_pb.TokenStat, TokenStat> {
public tokenStat(): DataMapper<sierra_message_pb.TokenStat, TokenStat> {
return (response) => {
return {
tokenId: response.getTokenId(),
Expand Down
28 changes: 17 additions & 11 deletions packages/node/src/EmeraldApi.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { ChannelCredentials } from '@grpc/grpc-js';
import { emeraldCredentials } from './credentials';
import { AddressClient } from './wrapped/AddressClient';
import { BlockchainClient } from './wrapped/BlockchainClient';
import { MarketClient } from './wrapped/MarketClient';
import { MonitoringClient } from './wrapped/MonitoringClient';
import { TokenClient } from './wrapped/TokenClient';
import { TransactionClient } from './wrapped/TransactionClient';
import {SecretToken} from "@emeraldpay/api/lib/typesAuth";
import {SecretToken} from "@emeraldpay/api";
import {ChannelCredentials} from '@grpc/grpc-js';
import {emeraldCredentials} from './credentials';
import {AddressClient} from './wrapped/AddressClient';
import {AuthClient} from "./wrapped/Auth";
import {BlockchainClient} from './wrapped/BlockchainClient';
import {MarketClient} from './wrapped/MarketClient';
import {MonitoringClient} from './wrapped/MonitoringClient';
import {SierraProjectClient} from "./wrapped/SierraProjectClient";
import {TokenClient} from './wrapped/TokenClient';
import {TransactionClient} from './wrapped/TransactionClient';

export class EmeraldApi {
private readonly agents: string[] = ['test-client/0.0.0'];
Expand All @@ -22,13 +23,13 @@ export class EmeraldApi {

static devApi(token?: SecretToken | undefined, credentials?: ChannelCredentials): EmeraldApi {
// a dev token with access only from the internal network
let devToken = token ?? 'emrld_8ntrHbZN67DF8TWKgCMO1I9nSaMG0cpoMhj3GP';
const devToken = token ?? 'emrld_8ntrHbZN67DF8TWKgCMO1I9nSaMG0cpoMhj3GP';
return new EmeraldApi('api.emeraldpay.dev:443', devToken, credentials);
}

static localApi(port = 50051, credentials?: ChannelCredentials): EmeraldApi {
// just a random token, doesn't exist
let noToken = 'emrld_yKb3jXMKRJLUWFzL7wPrktkherocZCBy7W6qZH';
const noToken = 'emrld_yKb3jXMKRJLUWFzL7wPrktkherocZCBy7W6qZH';
return new EmeraldApi(`localhost:${port}`, noToken, credentials);
}

Expand Down Expand Up @@ -63,4 +64,9 @@ export class EmeraldApi {
auth(): AuthClient {
return new AuthClient(this.hostname, this.credentials, this.agents);
}

sierraProject(): SierraProjectClient {
return new SierraProjectClient(this.hostname, this.credentials, this.agents);
}

}
45 changes: 45 additions & 0 deletions packages/node/src/__integration-tests__/sierraProject.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import {EmeraldApi} from "../EmeraldApi";

jest.setTimeout(35000);

describe("SierraProjectClient", () => {
let api: EmeraldApi;

beforeAll(() => {
// a dev token with user id: bada55a1-0000-4000-a000-000000000000
api = EmeraldApi.devApi("emrld_fU88aIafXsCClerhyWtflBp1hH6h112ckzpSfP");
});

test('createProject permission denied for the user', async () => {
const client = api.sierraProject();

try {
await client.createProject({
orgId: "cafe0000-0000-4000-a000-000000000000",
name: "Test Project",
description: "Project for using in tests",
})
} catch (e) {
console.log("createProject error: ", e)
expect(e.code).toEqual(7); // 7: PERMISSION_DENIED
}
});

test('listProjects', (done) => {
const client = api.sierraProject();

const call = client.listProjects({
orgId: "cafe0000-0000-4000-a000-000000000000",
})
call
.onData((data) => {
console.log("listProjects", data);
done();
})
.onError((error) => {
console.log("cancel: ", error.message);
done(error);
})
});

});
11 changes: 9 additions & 2 deletions packages/node/src/wrapped/Factory.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { MessageFactory } from '@emeraldpay/api';
import {MessageFactory} from '@emeraldpay/api';
import * as address_message_pb from '../generated/address.message_pb';
import * as auth_message_pb from '../generated/auth_pb';
import * as blockchain_pb from '../generated/blockchain_pb';
import * as common_pb from '../generated/common_pb';
import * as market_pb from '../generated/market_pb';
import * as sierra_message_pb from "../generated/sierra.message_pb";
import * as token_message_pb from '../generated/token.message_pb';
import * as transaction_message_pb from '../generated/transaction.message_pb';
import * as auth_message_pb from '../generated/auth_pb';

export const classFactory: MessageFactory = (id: string) => {
switch (id) {
Expand Down Expand Up @@ -70,6 +71,12 @@ export const classFactory: MessageFactory = (id: string) => {
return new transaction_message_pb.GetTransactionsRequest();
case 'transaction_message_pb.SubscribeTransactionsRequest':
return new transaction_message_pb.SubscribeTransactionsRequest();
// Sierra
case 'sierra_message_pb.CreateProjectRequest':
return new sierra_message_pb.CreateProjectRequest();
case 'sierra_message_pb.ListProjectsRequest':
return new sierra_message_pb.ListProjectsRequest();

default:
throw Error(`Unsupported type: ${id}`);
}
Expand Down
46 changes: 46 additions & 0 deletions packages/node/src/wrapped/SierraProjectClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import {ConnectionListener, Publisher, publishToPromise, readOnce, sierra,} from '@emeraldpay/api';
import {ChannelCredentials} from '@grpc/grpc-js';
import {NativeChannel, callSingle, callStream} from '../channel';
import {ProjectClient} from '../generated/sierra_grpc_pb';
import {classFactory} from './Factory';
// eslint-disable-next-line @typescript-eslint/no-var-requires
const { version: clientVersion } = require('../../package.json');

export class SierraProjectClient {
readonly client: ProjectClient;
readonly channel: NativeChannel;
readonly credentials: ChannelCredentials;
readonly retries: number;

private readonly convert: sierra.ConvertSierra = new sierra.ConvertSierra(classFactory);

constructor(address: string, credentials: ChannelCredentials, agents: string[], retries = 3) {
const agent = [...agents, `emerald-client-node/${clientVersion}`].join(' ');

this.client = new ProjectClient(address, credentials, { 'grpc.primary_user_agent': agent });
this.channel = new NativeChannel(this.client);
this.credentials = credentials;
this.retries = retries;
}

public setConnectionListener(listener: ConnectionListener): void {
this.channel.setListener(listener);
}

public createProject(request: sierra.CreateProjectRequest): Promise<sierra.Project> {
const req = this.convert.createProjectRequest(request);
const mapper = this.convert.project();

const call = callSingle(this.client.createProject.bind(this.client), mapper);
// disable retries for create
return publishToPromise(readOnce(this.channel, call, req, 1));
}

public listProjects(request: sierra.ListProjectsRequest): Publisher<sierra.Project> {
const req = this.convert.listProjectsRequest(request);
const mapper = this.convert.project();

const call = callStream(this.client.listProjects.bind(this.client), mapper);
return readOnce(this.channel, call, req, this.retries);
}
}
12 changes: 11 additions & 1 deletion packages/web/src/EmeraldApi.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import {SecretToken} from "@emeraldpay/api";
import {WebChannel} from "./channel";
import {CredentialsContext, emeraldCredentials} from "./credentials";
import {AuthClient} from "./wrapped/AuthClient";
import {BlockchainClient} from "./wrapped/BlockchainClient";
import {InsightsClient} from "./wrapped/InsightsClient";
import {MarketClient} from "./wrapped/MarketClient";
import {SierraOrgClient} from "./wrapped/SierraOrgClient";
import {SierraProjectClient} from "./wrapped/SierraProjectClient";
import {SierraStatClient} from "./wrapped/SierraStatClient";
import {AuthClient} from "./wrapped/AuthClient";

export class EmeraldApi {
private readonly hostname: string;
Expand Down Expand Up @@ -43,6 +45,14 @@ export class EmeraldApi {
return new MarketClient(this.hostname, this.channel, this.credentials);
}

get sierraProject(): SierraProjectClient {
return new SierraProjectClient(this.hostname, this.channel, this.credentials);
}

get sierraOrg(): SierraOrgClient {
return new SierraOrgClient(this.hostname, this.channel, this.credentials);
}

get sierraStat(): SierraStatClient {
return new SierraStatClient(this.hostname, this.channel, this.credentials);
}
Expand Down
Loading
Loading