undedoloremque
Version:
Green Field JS SDK
450 lines (390 loc) • 13.1 kB
text/typescript
import { encodePath, HTTPHeaderUserAddress } from '../clients/spclient/auth';
import {
getListGroupMetaInfo,
parseListGroupsResponse,
} from '../clients/spclient/spApis/listGroups';
import { parseListGroupsMembersResponse } from '../clients/spclient/spApis/listGroupsMembers';
import { parseListUserGroupsResponse } from '../clients/spclient/spApis/listUserGroups';
import { parseListUserOwnedGroupsResponse } from '../clients/spclient/spApis/listUserOwnedGroups';
import { parseError } from '../clients/spclient/spApis/parseError';
import { parseVerifyPermissionResponse } from '../clients/spclient/spApis/verifyPermission';
import { SpClient } from '../clients/spclient/spClient';
import { METHOD_GET, NORMAL_ERROR_CODE } from '../constants/http';
import { ListUserOwnedGroupsResponse } from '../types/sp/ListUserOwnedGroups';
import { actionTypeFromJSON } from '@bnb-chain/greenfield-cosmos-types/greenfield/permission/common';
import {
QueryGlobalSpStorePriceByTimeRequest,
QueryGlobalSpStorePriceByTimeResponse,
QueryParamsResponse,
QuerySpStoragePriceRequest,
QuerySpStoragePriceResponse,
QueryStorageProviderByOperatorAddressRequest,
QueryStorageProviderByOperatorAddressResponse,
QueryStorageProviderMaintenanceRecordsRequest,
QueryStorageProviderMaintenanceRecordsResponse,
} from '@bnb-chain/greenfield-cosmos-types/greenfield/sp/query';
import { Status, StorageProvider } from '@bnb-chain/greenfield-cosmos-types/greenfield/sp/types';
import { container, injectable } from 'tsyringe';
import type {
ListGroupsMembersRequest,
ListGroupsMembersResponse,
ListGroupsResponse,
ListGroupsResquest,
ListUserGroupsResponse,
ListUserGroupsResquest,
ListUserOwnedGroupsRequest,
SpResponse,
VerifyPermissionRequest,
VerifyPermissionResponse,
} from '..';
import { RpcQueryClient } from '../clients/queryclient';
import { Bucket } from './bucket';
import { VirtualGroup } from './virtualGroup';
export interface ISp {
/**
* return the storage provider info on chain
isInService indicates if only display the sp with STATUS_IN_SERVICE status
*/
getStorageProviders(): Promise<StorageProvider[]>;
/**
* return the sp info with the sp chain address
*/
getStorageProviderInfo(spId: number): Promise<StorageProvider | undefined>;
/**
* get the latest storage price of specific sp
*/
getQuerySpStoragePrice(request: QuerySpStoragePriceRequest): Promise<QuerySpStoragePriceResponse>;
/**
* get global store price by time
*/
getQueryGlobalSpStorePriceByTime(
request: QueryGlobalSpStorePriceByTimeRequest,
): Promise<QueryGlobalSpStorePriceByTimeResponse>;
/**
* Queries a StorageProvider by specify operator address.
*/
getStorageProviderByOperatorAddress(
request: QueryStorageProviderByOperatorAddressRequest,
): Promise<QueryStorageProviderByOperatorAddressResponse>;
/**
* Queries a StorageProvider by specify operator address.
*/
getStorageProviderMaintenanceRecordsByOperatorAddress(
request: QueryStorageProviderMaintenanceRecordsRequest,
): Promise<QueryStorageProviderMaintenanceRecordsResponse>;
params(): Promise<QueryParamsResponse>;
listGroups(params: ListGroupsResquest): Promise<SpResponse<ListGroupsResponse>>;
listGroupsMembers(
params: ListGroupsMembersRequest,
): Promise<SpResponse<ListGroupsMembersResponse>>;
listUserGroups(params: ListUserGroupsResquest): Promise<SpResponse<ListUserGroupsResponse>>;
listUserOwnedGroups(
params: ListUserOwnedGroupsRequest,
): Promise<SpResponse<ListUserOwnedGroupsResponse>>;
getSPUrlByBucket(bucketName: string): Promise<string>;
getSPUrlByPrimaryAddr(parimaryAddr: string): Promise<string>;
getSPUrlById(primaryId: number): Promise<string>;
verifyPermission(params: VerifyPermissionRequest): Promise<SpResponse<VerifyPermissionResponse>>;
}
()
export class Sp implements ISp {
private bucket = container.resolve(Bucket);
private queryClient = container.resolve(RpcQueryClient);
private virtualGroup = container.resolve(VirtualGroup);
private spClient = container.resolve(SpClient);
public async getStorageProviders() {
const rpc = await this.queryClient.getSpQueryClient();
const res = await rpc.StorageProviders();
return res.sps;
}
public async getStorageProviderInfo(spId: number) {
const rpc = await this.queryClient.getSpQueryClient();
const res = await rpc.StorageProvider({
id: spId,
});
return res.storageProvider;
}
public async getQuerySpStoragePrice(request: QuerySpStoragePriceRequest) {
const rpc = await this.queryClient.getSpQueryClient();
return await rpc.QuerySpStoragePrice(request);
}
public async getQueryGlobalSpStorePriceByTime(request: QueryGlobalSpStorePriceByTimeRequest) {
const rpc = await this.queryClient.getSpQueryClient();
return await rpc.QueryGlobalSpStorePriceByTime(request);
}
public async getStorageProviderByOperatorAddress(
request: QueryStorageProviderByOperatorAddressRequest,
) {
const rpc = await this.queryClient.getSpQueryClient();
return await rpc.StorageProviderByOperatorAddress(request);
}
public async getStorageProviderMaintenanceRecordsByOperatorAddress(
request: QueryStorageProviderMaintenanceRecordsRequest,
) {
const rpc = await this.queryClient.getSpQueryClient();
return await rpc.StorageProviderMaintenanceRecordsByOperatorAddress(request);
}
public async getSPUrlById(primaryId: number) {
const spList = await this.getStorageProviders();
return spList.filter((sp) => sp.id === primaryId)[0].endpoint;
}
public async getSPUrlByBucket(bucketName: string) {
const { bucketInfo } = await this.bucket.headBucket(bucketName);
if (!bucketInfo) throw new Error('Get bucket info error');
const familyResp = await this.virtualGroup.getGlobalVirtualGroupFamily({
familyId: bucketInfo.globalVirtualGroupFamilyId,
});
const spList = await this.getStorageProviders();
const spId = familyResp.globalVirtualGroupFamily?.primarySpId;
return spList.filter((sp) => sp.id === spId)[0].endpoint;
}
public async getSPUrlByPrimaryAddr(parimaryAddr: string) {
const sps = await this.getStorageProviders();
return sps.filter((sp) => sp.operatorAddress === parimaryAddr)[0].endpoint;
}
public async params() {
const rpc = await this.queryClient.getSpQueryClient();
return await rpc.Params();
}
public async getInServiceSP() {
const sps = await this.getStorageProviders();
const spList = sps.filter((sp) => sp.status === Status.STATUS_IN_SERVICE);
if (spList.length === 0) throw new Error('No storage provider found');
return spList[0];
}
public async listGroups(params: ListGroupsResquest) {
try {
const { name, prefix } = params;
let res: ListGroupsResponse = {
GfSpGetGroupListResponse: {
Groups: [],
Count: 0,
},
};
if (name === '' || prefix === '') {
return {
code: 0,
message: 'success',
body: res,
};
}
const sp = await this.getInServiceSP();
const { url } = getListGroupMetaInfo(sp.endpoint, params);
const result = await this.spClient.callApi(
url,
{
headers: {},
method: METHOD_GET,
},
3000,
);
const { status } = result;
if (!result.ok) {
const xmlError = await result.text();
const { code, message } = await parseError(xmlError);
throw {
code: code || -1,
message: message || 'error',
statusCode: status,
};
}
const xmlData = await result.text();
res = await parseListGroupsResponse(xmlData);
return {
code: 0,
message: 'success',
statusCode: status,
body: res,
};
} catch (error: any) {
return {
code: -1,
message: error.message,
statusCode: error?.statusCode || NORMAL_ERROR_CODE,
};
}
}
public async verifyPermission(params: VerifyPermissionRequest) {
try {
const { action, bucketName, objectName, operator } = params;
const sp = await this.getInServiceSP();
let url = `${sp.endpoint}/permission/${operator}/${bucketName}/${actionTypeFromJSON(action)}`;
if (objectName) {
url += `?object=${encodePath(objectName)}`;
}
const result = await this.spClient.callApi(
url,
{
headers: {},
method: METHOD_GET,
},
3000,
);
const { status } = result;
if (!result.ok) {
const xmlError = await result.text();
const { code, message } = await parseError(xmlError);
throw {
code: code || -1,
message: message || 'error',
statusCode: status,
};
}
const xmlData = await result.text();
const res = await parseVerifyPermissionResponse(xmlData);
return {
code: 0,
message: 'success',
statusCode: status,
body: res,
};
} catch (error: any) {
return {
code: -1,
message: error.message,
statusCode: error?.statusCode || NORMAL_ERROR_CODE,
};
}
}
public async listGroupsMembers(params: ListGroupsMembersRequest) {
try {
const { groupId, limit, startAfter } = params;
const sp = await this.getInServiceSP();
let url = `${sp.endpoint}?group-members&group-id=${groupId}`;
if (limit) {
url += `&limit=${limit}`;
}
if (startAfter) {
url += `&start-after=${startAfter}`;
}
const result = await this.spClient.callApi(
url,
{
headers: {},
method: METHOD_GET,
},
3000,
);
const { status } = result;
if (!result.ok) {
const xmlError = await result.text();
const { code, message } = await parseError(xmlError);
throw {
code: code || -1,
message: message || 'error',
statusCode: status,
};
}
const xmlData = await result.text();
const res = await parseListGroupsMembersResponse(xmlData);
return {
code: 0,
message: 'success',
statusCode: status,
body: res,
};
} catch (error: any) {
return {
code: -1,
message: error.message,
statusCode: error?.statusCode || NORMAL_ERROR_CODE,
};
}
}
public async listUserGroups(params: ListUserGroupsResquest) {
try {
const { address, limit, startAfter } = params;
const sp = await this.getInServiceSP();
let url = `${sp.endpoint}?user-groups`;
if (limit) {
url += `&limit=${limit}`;
}
if (startAfter) {
url += `&start-after=${startAfter}`;
}
const headers = new Headers({
[HTTPHeaderUserAddress]: address,
});
const result = await this.spClient.callApi(
url,
{
headers,
method: METHOD_GET,
},
3000,
);
const { status } = result;
if (!result.ok) {
const xmlError = await result.text();
const { code, message } = await parseError(xmlError);
throw {
code: code || -1,
message: message || 'error',
statusCode: status,
};
}
const xmlData = await result.text();
const res = await parseListUserGroupsResponse(xmlData);
return {
code: 0,
message: 'success',
statusCode: status,
body: res,
};
} catch (error: any) {
return {
code: -1,
message: error.message,
statusCode: error?.statusCode || NORMAL_ERROR_CODE,
};
}
}
public async listUserOwnedGroups(params: ListUserOwnedGroupsRequest) {
try {
const { address, limit, startAfter } = params;
const sp = await this.getInServiceSP();
let url = `${sp.endpoint}?owned-groups`;
if (limit) {
url += `&limit=${limit}`;
}
if (startAfter) {
url += `&start-after=${startAfter}`;
}
const headers = new Headers({
[HTTPHeaderUserAddress]: address,
});
const result = await this.spClient.callApi(
url,
{
headers,
method: METHOD_GET,
},
3000,
);
const { status } = result;
if (!result.ok) {
const xmlError = await result.text();
const { code, message } = await parseError(xmlError);
throw {
code: code || -1,
message: message || 'error',
statusCode: status,
};
}
const xmlData = await result.text();
const res = await parseListUserOwnedGroupsResponse(xmlData);
return {
code: 0,
message: 'success',
statusCode: status,
body: res,
};
} catch (error: any) {
return {
code: -1,
message: error.message,
statusCode: error?.statusCode || NORMAL_ERROR_CODE,
};
}
}
}