Skip to content

Commit

Permalink
Merge f1c419b into 98aa53e
Browse files Browse the repository at this point in the history
  • Loading branch information
nazarhussain authored Jan 19, 2023
2 parents 98aa53e + f1c419b commit ab4f5db
Show file tree
Hide file tree
Showing 131 changed files with 1,952 additions and 699 deletions.
12 changes: 10 additions & 2 deletions packages/api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ Typescript REST client for the [Ethereum Consensus API spec](https://github.com/

## Usage

We use more typesafe approach for the API client, where all the errors are returned not thrown. This approach is more easy to document and better to handle all possible error cases.

```typescript
import {getClient} from "@lodestar/api";
import {getClient, HttpError} from "@lodestar/api";
import {config} from "@lodestar/config/default";

const api = getClient({baseUrl: "http://localhost:9596"}, {config});
Expand All @@ -22,7 +24,13 @@ api.beacon
"head",
"0x933ad9491b62059dd065b560d256d8957a8c402cc6e8d8ee7290ae11e8f7329267a8811c397529dac52ae1342ba58c95"
)
.then((res) => console.log("Your balance is:", res.data.balance));
.then((res) => {
if(res.ok) {
console.log("Your balance is:", res.response.data.balance, res.ok, res.status);
} else {
console.error(res.status, res.error.code, res.error.message);
}
});
```

## Prerequisites
Expand Down
8 changes: 7 additions & 1 deletion packages/api/src/beacon/client/beacon.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {IChainForkConfig} from "@lodestar/config";
import {Api, ReqTypes, routesData, getReqSerializers, getReturnTypes} from "../routes/beacon/index.js";
import {IHttpClient, generateGenericJsonClient} from "../../utils/client/index.js";
import {ReturnTypes} from "../../utils/types.js";

/**
* REST HTTP client for beacon routes
Expand All @@ -9,5 +10,10 @@ export function getClient(config: IChainForkConfig, httpClient: IHttpClient): Ap
const reqSerializers = getReqSerializers(config);
const returnTypes = getReturnTypes();
// All routes return JSON, use a client auto-generator
return generateGenericJsonClient<Api, ReqTypes>(routesData, reqSerializers, returnTypes, httpClient);
return generateGenericJsonClient<Api, ReqTypes>(
routesData,
reqSerializers,
returnTypes as ReturnTypes<Api>,
httpClient
);
}
12 changes: 9 additions & 3 deletions packages/api/src/beacon/client/config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {IChainForkConfig} from "@lodestar/config";
import {Api, ReqTypes, routesData, getReqSerializers, getReturnTypes} from "../routes/config.js";
import {IHttpClient, generateGenericJsonClient} from "../../utils/client/index.js";
import {generateGenericJsonClient, IHttpClient} from "../../utils/client/index.js";
import {ReturnTypes} from "../../utils/types.js";
import {Api, getReqSerializers, getReturnTypes, ReqTypes, routesData} from "../routes/config.js";

/**
* REST HTTP client for config routes
Expand All @@ -9,5 +10,10 @@ export function getClient(config: IChainForkConfig, httpClient: IHttpClient): Ap
const reqSerializers = getReqSerializers();
const returnTypes = getReturnTypes();
// All routes return JSON, use a client auto-generator
return generateGenericJsonClient<Api, ReqTypes>(routesData, reqSerializers, returnTypes, httpClient);
return generateGenericJsonClient<Api, ReqTypes>(
routesData,
reqSerializers,
returnTypes as ReturnTypes<Api>,
httpClient
);
}
45 changes: 33 additions & 12 deletions packages/api/src/beacon/client/debug.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import {IChainForkConfig} from "@lodestar/config";
import {Api, ReqTypes, routesData, getReqSerializers, getReturnTypes, StateFormat} from "../routes/debug.js";
import {IHttpClient, getFetchOptsSerializers, generateGenericJsonClient} from "../../utils/client/index.js";
import {ApiClientResponse} from "../../interfaces.js";
import {HttpStatusCode} from "../../utils/client/httpStatusCode.js";
import {generateGenericJsonClient, getFetchOptsSerializers, IHttpClient} from "../../utils/client/index.js";
import {ReturnTypes} from "../../utils/types.js";
import {StateId} from "../routes/beacon/state.js";
import {Api, getReqSerializers, getReturnTypes, ReqTypes, routesData, StateFormat} from "../routes/debug.js";

// As Jul 2022, it takes up to 3 mins to download states so make this 5 mins for reservation
const GET_STATE_TIMEOUT_MS = 5 * 60 * 1000;
Expand All @@ -12,38 +16,55 @@ export function getClient(_config: IChainForkConfig, httpClient: IHttpClient): A
const reqSerializers = getReqSerializers();
const returnTypes = getReturnTypes();
// Some routes return JSON, use a client auto-generator
const client = generateGenericJsonClient<Api, ReqTypes>(routesData, reqSerializers, returnTypes, httpClient);
const client = generateGenericJsonClient<Api, ReqTypes>(
routesData,
reqSerializers,
returnTypes as ReturnTypes<Api>,
httpClient
);
// For `getState()` generate request serializer
const fetchOptsSerializers = getFetchOptsSerializers<Api, ReqTypes>(routesData, reqSerializers);

return {
...client,

// TODO: Debug the type issue
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
async getState(stateId: string, format?: StateFormat) {
if (format === "ssz") {
const buffer = await httpClient.arrayBuffer({
const res = await httpClient.arrayBuffer({
...fetchOptsSerializers.getState(stateId, format),
timeoutMs: GET_STATE_TIMEOUT_MS,
});
// Casting to any otherwise Typescript doesn't like the multi-type return
// eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-explicit-any
return new Uint8Array(buffer) as any;
} else {
return client.getState(stateId, format);
return {
ok: true,
response: new Uint8Array(res.body),
status: res.status,
} as ApiClientResponse<{[HttpStatusCode.OK]: Uint8Array}>;
}
return client.getState(stateId, format);
},
async getStateV2(stateId: string, format?: StateFormat) {

// TODO: Debug the type issue
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
async getStateV2(stateId: StateId, format?: StateFormat) {
if (format === "ssz") {
const buffer = await httpClient.arrayBuffer({
const res = await httpClient.arrayBuffer({
...fetchOptsSerializers.getStateV2(stateId, format),
timeoutMs: GET_STATE_TIMEOUT_MS,
});
// Casting to any otherwise Typescript doesn't like the multi-type return
// eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-explicit-any
return new Uint8Array(buffer) as any;
} else {
return client.getStateV2(stateId, format);
return {ok: true, response: new Uint8Array(res.body), status: res.status} as ApiClientResponse<{
[HttpStatusCode.OK]: Uint8Array;
}>;
}

return client.getStateV2(stateId, format);
},
};
}
3 changes: 3 additions & 0 deletions packages/api/src/beacon/client/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {IChainForkConfig} from "@lodestar/config";
import {Api, BeaconEvent, routesData, getEventSerdes} from "../routes/events.js";
import {stringifyQuery} from "../../utils/client/format.js";
import {getEventSource} from "../../utils/client/eventSource.js";
import {HttpStatusCode} from "../../utils/client/httpStatusCode.js";

/**
* REST HTTP client for events routes
Expand Down Expand Up @@ -50,6 +51,8 @@ export function getClient(_config: IChainForkConfig, baseUrl: string): Api {
} finally {
eventSource.close();
}

return {ok: true, response: undefined, status: HttpStatusCode.OK};
},
};
}
Expand Down
8 changes: 7 additions & 1 deletion packages/api/src/beacon/client/lightclient.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {IChainForkConfig} from "@lodestar/config";
import {Api, ReqTypes, routesData, getReqSerializers, getReturnTypes} from "../routes/lightclient.js";
import {IHttpClient, generateGenericJsonClient} from "../../utils/client/index.js";
import {ReturnTypes} from "../../utils/types.js";

/**
* REST HTTP client for lightclient routes
Expand All @@ -9,5 +10,10 @@ export function getClient(_config: IChainForkConfig, httpClient: IHttpClient): A
const reqSerializers = getReqSerializers();
const returnTypes = getReturnTypes();
// All routes return JSON, use a client auto-generator
return generateGenericJsonClient<Api, ReqTypes>(routesData, reqSerializers, returnTypes, httpClient);
return generateGenericJsonClient<Api, ReqTypes>(
routesData,
reqSerializers,
returnTypes as ReturnTypes<Api>,
httpClient
);
}
8 changes: 7 additions & 1 deletion packages/api/src/beacon/client/lodestar.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {IChainForkConfig} from "@lodestar/config";
import {Api, ReqTypes, routesData, getReqSerializers, getReturnTypes} from "../routes/lodestar.js";
import {IHttpClient, generateGenericJsonClient} from "../../utils/client/index.js";
import {ReturnTypes} from "../../utils/types.js";

/**
* REST HTTP client for lodestar routes
Expand All @@ -9,5 +10,10 @@ export function getClient(_config: IChainForkConfig, httpClient: IHttpClient): A
const reqSerializers = getReqSerializers();
const returnTypes = getReturnTypes();
// All routes return JSON, use a client auto-generator
return generateGenericJsonClient<Api, ReqTypes>(routesData, reqSerializers, returnTypes, httpClient);
return generateGenericJsonClient<Api, ReqTypes>(
routesData,
reqSerializers,
returnTypes as ReturnTypes<Api>,
httpClient
);
}
4 changes: 2 additions & 2 deletions packages/api/src/beacon/client/node.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {IChainForkConfig} from "@lodestar/config";
import {Api, ReqTypes, routesData, getReqSerializers, getReturnTypes} from "../routes/node.js";
import {IHttpClient, generateGenericJsonClient} from "../../utils/client/index.js";
import {generateGenericJsonClient, IHttpClient} from "../../utils/client/index.js";
import {Api, getReqSerializers, getReturnTypes, ReqTypes, routesData} from "../routes/node.js";

/**
* REST HTTP client for beacon routes
Expand Down
21 changes: 17 additions & 4 deletions packages/api/src/beacon/client/proof.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import {IChainForkConfig} from "@lodestar/config";
import {deserializeProof} from "@chainsafe/persistent-merkle-tree";
import {Api, ReqTypes, routesData, getReqSerializers} from "../routes/proof.js";
import {IHttpClient, getFetchOptsSerializers} from "../../utils/client/index.js";
import {IHttpClient, getFetchOptsSerializers, HttpError} from "../../utils/client/index.js";
import {HttpStatusCode} from "../../utils/client/httpStatusCode.js";

/**
* REST HTTP client for lightclient routes
Expand All @@ -14,9 +15,21 @@ export function getClient(_config: IChainForkConfig, httpClient: IHttpClient): A

return {
async getStateProof(stateId, paths) {
const buffer = await httpClient.arrayBuffer(fetchOptsSerializers.getStateProof(stateId, paths));
const proof = deserializeProof(new Uint8Array(buffer));
return {data: proof};
try {
const res = await httpClient.arrayBuffer(fetchOptsSerializers.getStateProof(stateId, paths));
const proof = deserializeProof(new Uint8Array(res.body));

return {ok: true, response: {data: proof}, status: HttpStatusCode.OK};
} catch (err) {
if (err instanceof HttpError) {
return {
ok: false,
error: {code: err.status, message: err.message, operationId: "proof.getStateProof"},
status: err.status,
};
}
throw err;
}
},
};
}
8 changes: 7 additions & 1 deletion packages/api/src/beacon/client/validator.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {IChainForkConfig} from "@lodestar/config";
import {Api, ReqTypes, routesData, getReqSerializers, getReturnTypes} from "../routes/validator.js";
import {IHttpClient, generateGenericJsonClient} from "../../utils/client/index.js";
import {ReturnTypes} from "../../utils/types.js";

/**
* REST HTTP client for validator routes
Expand All @@ -9,5 +10,10 @@ export function getClient(_config: IChainForkConfig, httpClient: IHttpClient): A
const reqSerializers = getReqSerializers();
const returnTypes = getReturnTypes();
// All routes return JSON, use a client auto-generator
return generateGenericJsonClient<Api, ReqTypes>(routesData, reqSerializers, returnTypes, httpClient);
return generateGenericJsonClient<Api, ReqTypes>(
routesData,
reqSerializers,
returnTypes as ReturnTypes<Api>,
httpClient
);
}
Loading

0 comments on commit ab4f5db

Please sign in to comment.