Skip to content

Commit

Permalink
authKey is no longer stored in client and added getAddresses test cases
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisli30 committed Nov 1, 2024
1 parent 7c9f6c5 commit 3c61392
Show file tree
Hide file tree
Showing 7 changed files with 170 additions and 88 deletions.
17 changes: 10 additions & 7 deletions dist/index.d.mts
Original file line number Diff line number Diff line change
Expand Up @@ -1458,8 +1458,11 @@ declare class AggregatorClient extends grpc.Client implements IAggregatorClient

type Environment = "production" | "development" | "staging";
declare const AUTH_KEY_HEADER = "authKey";
interface RequestOptions {
authKey: string;
}
interface GetKeyResponse {
key: string;
authKey: string;
}
interface ClientOption {
endpoint: string;
Expand Down Expand Up @@ -1493,16 +1496,16 @@ declare class BaseClient {
readonly rpcClient: AggregatorClient;
protected metadata: Metadata;
constructor(opts: ClientOption);
setAuthKey(key: string): void;
getAuthKey(): string | undefined;
isAuthenticated(): boolean;
isAuthKeyValid(key: string): boolean;
authWithAPIKey(apiKey: string, expiredAtEpoch: number): Promise<GetKeyResponse>;
authWithSignature(address: string, signature: string, expiredAtEpoch: number): Promise<GetKeyResponse>;
protected _callRPC<TResponse, TRequest>(method: string, request: TRequest | any): Promise<TResponse>;
protected _callRPC<TResponse, TRequest>(method: string, request: TRequest | any, options?: RequestOptions): Promise<TResponse>;
}
declare class Client extends BaseClient {
constructor(config: ClientOption);
getAddresses(address: string): Promise<GetAddressesResponse>;
getAddresses(address: string, { authKey }: {
authKey: string;
}): Promise<GetAddressesResponse>;
createTask({ address, oracleContract, tokenContract, }: {
address: string;
tokenContract: string;
Expand All @@ -1514,4 +1517,4 @@ declare class Client extends BaseClient {
deleteTask(id: string): Promise<boolean>;
}

export { AUTH_KEY_HEADER, type BalanceResp, type ClientOption, type CreateTaskResponse, type Environment, type GetAddressesResponse, type GetKeyResponse, type ListTasksResponse, type Task, type TransactionResp, Client as default, getKeyRequestMessage };
export { AUTH_KEY_HEADER, type BalanceResp, type ClientOption, type CreateTaskResponse, type Environment, type GetAddressesResponse, type GetKeyResponse, type ListTasksResponse, type RequestOptions, type Task, type TransactionResp, Client as default, getKeyRequestMessage };
17 changes: 10 additions & 7 deletions dist/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1458,8 +1458,11 @@ declare class AggregatorClient extends grpc.Client implements IAggregatorClient

type Environment = "production" | "development" | "staging";
declare const AUTH_KEY_HEADER = "authKey";
interface RequestOptions {
authKey: string;
}
interface GetKeyResponse {
key: string;
authKey: string;
}
interface ClientOption {
endpoint: string;
Expand Down Expand Up @@ -1493,16 +1496,16 @@ declare class BaseClient {
readonly rpcClient: AggregatorClient;
protected metadata: Metadata;
constructor(opts: ClientOption);
setAuthKey(key: string): void;
getAuthKey(): string | undefined;
isAuthenticated(): boolean;
isAuthKeyValid(key: string): boolean;
authWithAPIKey(apiKey: string, expiredAtEpoch: number): Promise<GetKeyResponse>;
authWithSignature(address: string, signature: string, expiredAtEpoch: number): Promise<GetKeyResponse>;
protected _callRPC<TResponse, TRequest>(method: string, request: TRequest | any): Promise<TResponse>;
protected _callRPC<TResponse, TRequest>(method: string, request: TRequest | any, options?: RequestOptions): Promise<TResponse>;
}
declare class Client extends BaseClient {
constructor(config: ClientOption);
getAddresses(address: string): Promise<GetAddressesResponse>;
getAddresses(address: string, { authKey }: {
authKey: string;
}): Promise<GetAddressesResponse>;
createTask({ address, oracleContract, tokenContract, }: {
address: string;
tokenContract: string;
Expand All @@ -1514,4 +1517,4 @@ declare class Client extends BaseClient {
deleteTask(id: string): Promise<boolean>;
}

export { AUTH_KEY_HEADER, type BalanceResp, type ClientOption, type CreateTaskResponse, type Environment, type GetAddressesResponse, type GetKeyResponse, type ListTasksResponse, type Task, type TransactionResp, Client as default, getKeyRequestMessage };
export { AUTH_KEY_HEADER, type BalanceResp, type ClientOption, type CreateTaskResponse, type Environment, type GetAddressesResponse, type GetKeyResponse, type ListTasksResponse, type RequestOptions, type Task, type TransactionResp, Client as default, getKeyRequestMessage };
35 changes: 13 additions & 22 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4529,25 +4529,14 @@ var BaseClient = class {
);
this.metadata = new import_grpc_js.Metadata();
}
setAuthKey(key) {
this.metadata.add(AUTH_KEY_HEADER, key);
}
getAuthKey() {
const authKey = this.metadata.get(AUTH_KEY_HEADER);
return authKey?.[0]?.toString();
}
isAuthenticated() {
const authKey = this.getAuthKey();
if (!authKey) {
return false;
}
isAuthKeyValid(key) {
try {
const [, payload] = authKey.split(".");
const [, payload] = key.split(".");
const decodedPayload = JSON.parse(atob(payload));
const currentTimestamp = Math.floor(Date.now() / 1e3);
return decodedPayload.exp > currentTimestamp;
} catch (error) {
console.error("Error validating JWT token:", error);
console.error("Error validating auth key:", error);
return false;
}
}
Expand All @@ -4557,8 +4546,7 @@ var BaseClient = class {
request.setExpiredAt(expiredAtEpoch);
request.setSignature(apiKey);
const result = await this._callRPC("getKey", request);
this.setAuthKey(result.getKey());
return { key: result.getKey() };
return { authKey: result.getKey() };
}
// This flow can be used where the signature is generate from outside, such as in front-end and pass in
async authWithSignature(address, signature, expiredAtEpoch) {
Expand All @@ -4570,14 +4558,17 @@ var BaseClient = class {
"getKey",
request
);
this.setAuthKey(result.getKey());
return { key: result.getKey() };
return { authKey: result.getKey() };
}
_callRPC(method, request) {
_callRPC(method, request, options) {
const metadata = import_lodash.default.cloneDeep(this.metadata);
if (options?.authKey) {
metadata.set(AUTH_KEY_HEADER, options.authKey);
}
return new Promise((resolve, reject) => {
this.rpcClient[method].bind(this.rpcClient)(
request,
this.metadata,
metadata,
(error, response) => {
if (error) reject(error);
else resolve(response);
Expand All @@ -4590,10 +4581,10 @@ var Client = class extends BaseClient {
constructor(config) {
super(config);
}
async getAddresses(address) {
async getAddresses(address, { authKey }) {
const request = new AddressRequest();
request.setOwner(address);
const result = await this._callRPC("getSmartAccountAddress", request);
const result = await this._callRPC("getSmartAccountAddress", request, { authKey });
return {
owner: address,
smart_account_address: result.getSmartAccountAddress()
Expand Down
35 changes: 13 additions & 22 deletions dist/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4517,25 +4517,14 @@ var BaseClient = class {
);
this.metadata = new Metadata();
}
setAuthKey(key) {
this.metadata.add(AUTH_KEY_HEADER, key);
}
getAuthKey() {
const authKey = this.metadata.get(AUTH_KEY_HEADER);
return authKey?.[0]?.toString();
}
isAuthenticated() {
const authKey = this.getAuthKey();
if (!authKey) {
return false;
}
isAuthKeyValid(key) {
try {
const [, payload] = authKey.split(".");
const [, payload] = key.split(".");
const decodedPayload = JSON.parse(atob(payload));
const currentTimestamp = Math.floor(Date.now() / 1e3);
return decodedPayload.exp > currentTimestamp;
} catch (error) {
console.error("Error validating JWT token:", error);
console.error("Error validating auth key:", error);
return false;
}
}
Expand All @@ -4545,8 +4534,7 @@ var BaseClient = class {
request.setExpiredAt(expiredAtEpoch);
request.setSignature(apiKey);
const result = await this._callRPC("getKey", request);
this.setAuthKey(result.getKey());
return { key: result.getKey() };
return { authKey: result.getKey() };
}
// This flow can be used where the signature is generate from outside, such as in front-end and pass in
async authWithSignature(address, signature, expiredAtEpoch) {
Expand All @@ -4558,14 +4546,17 @@ var BaseClient = class {
"getKey",
request
);
this.setAuthKey(result.getKey());
return { key: result.getKey() };
return { authKey: result.getKey() };
}
_callRPC(method, request) {
_callRPC(method, request, options) {
const metadata = _.cloneDeep(this.metadata);
if (options?.authKey) {
metadata.set(AUTH_KEY_HEADER, options.authKey);
}
return new Promise((resolve, reject) => {
this.rpcClient[method].bind(this.rpcClient)(
request,
this.metadata,
metadata,
(error, response) => {
if (error) reject(error);
else resolve(response);
Expand All @@ -4578,10 +4569,10 @@ var Client = class extends BaseClient {
constructor(config) {
super(config);
}
async getAddresses(address) {
async getAddresses(address, { authKey }) {
const request = new AddressRequest();
request.setOwner(address);
const result = await this._callRPC("getSmartAccountAddress", request);
const result = await this._callRPC("getSmartAccountAddress", request, { authKey });
return {
owner: address,
smart_account_address: result.getSmartAccountAddress()
Expand Down
51 changes: 22 additions & 29 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { AggregatorClient } from "../grpc_codegen/avs_grpc_pb";
import * as avs_pb from "../grpc_codegen/avs_pb";
import { BoolValue } from "google-protobuf/google/protobuf/wrappers_pb";
import Task from "./task";
import { AUTH_KEY_HEADER } from "./types";
import { AUTH_KEY_HEADER, RequestOptions } from "./types";

// Move interfaces to a separate file, e.g., types.ts
import {
Expand All @@ -18,7 +18,6 @@ import {
ListTasksResponse,
} from "./types";


class BaseClient {
readonly endpoint: string;

Expand All @@ -35,32 +34,17 @@ class BaseClient {
this.metadata = new Metadata();
}

public setAuthKey(key: string): void {
this.metadata.add(AUTH_KEY_HEADER, key);
}

public getAuthKey(): string | undefined {
const authKey = this.metadata.get(AUTH_KEY_HEADER);
return authKey?.[0]?.toString();
}

public isAuthenticated(): boolean {
const authKey = this.getAuthKey();

if (!authKey) {
return false;
}

public isAuthKeyValid(key: string): boolean {
try {
// Decode the JWT token (without verifying the signature)
const [, payload] = authKey.split(".");
const [, payload] = key.split(".");
const decodedPayload = JSON.parse(atob(payload));

// Check if the token has expired
const currentTimestamp = Math.floor(Date.now() / 1000);
return decodedPayload.exp > currentTimestamp;
} catch (error) {
console.error("Error validating JWT token:", error);
console.error("Error validating auth key:", error);
return false;
}
}
Expand All @@ -80,8 +64,7 @@ class BaseClient {
avs_pb.GetKeyReq
>("getKey", request);

this.setAuthKey(result.getKey());
return { key: result.getKey() };
return { authKey: result.getKey() };
}

// This flow can be used where the signature is generate from outside, such as in front-end and pass in
Expand All @@ -101,19 +84,26 @@ class BaseClient {
request
);

this.setAuthKey(result.getKey());

return { key: result.getKey() };
return { authKey: result.getKey() };
}

protected _callRPC<TResponse, TRequest>(
method: string,
request: TRequest | any
request: TRequest | any,
options?: RequestOptions
): Promise<TResponse> {
// Clone the existing metadata from the client
const metadata = _.cloneDeep(this.metadata);

// Add the auth key to the metadata as a header
if (options?.authKey) {
metadata.set(AUTH_KEY_HEADER, options.authKey);
}

return new Promise((resolve, reject) => {
(this.rpcClient as any)[method].bind(this.rpcClient)(
request,
this.metadata,
metadata,
(error: any, response: TResponse) => {
if (error) reject(error);
else resolve(response);
Expand All @@ -128,14 +118,17 @@ export default class Client extends BaseClient {
super(config);
}

async getAddresses(address: string): Promise<GetAddressesResponse> {
async getAddresses(
address: string,
{ authKey }: { authKey: string }
): Promise<GetAddressesResponse> {
const request = new avs_pb.AddressRequest();
request.setOwner(address);

const result = await this._callRPC<
avs_pb.AddressResp,
avs_pb.AddressRequest
>("getSmartAccountAddress", request);
>("getSmartAccountAddress", request, { authKey });

return {
owner: address,
Expand Down
6 changes: 5 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@ export type Environment = "production" | "development" | "staging";

export const AUTH_KEY_HEADER = "authKey";

export interface RequestOptions {
authKey: string;
}

export interface GetKeyResponse {
key: string;
authKey: string;
}

export interface ClientOption {
Expand Down
Loading

0 comments on commit 3c61392

Please sign in to comment.