Skip to content

Commit 8db146e

Browse files
authored
Update Server.getLatestLedger response fields (#1389)
* add missing fields to rpc Server.getLatestLedger response and update tests
1 parent da2f95b commit 8db146e

6 files changed

Lines changed: 91 additions & 5 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ A breaking change will get clearly marked in this log.
3131
* `AccountResponse` constructor now uses explicit field-by-field assignment instead of `Object.entries` dynamic assignment for type safety ([#1373](https://github.com/stellar/js-stellar-sdk/pull/1373)).
3232
* Added `transactions` collection to `Api.AccountRecord` and `AccountResponse` ([#1373](https://github.com/stellar/js-stellar-sdk/pull/1373)).
3333
* Added range checks for U32/I32 values in `Spec`: bigint values are now validated against min/max bounds before conversion, throwing a `RangeError` instead of silently truncating ([#1373](https://github.com/stellar/js-stellar-sdk/pull/1373)).
34+
* `rpc.Server.getLatestLedger()` now includes `closeTime`, `headerXdr`, and `metadataXdr` in the typed response, with `headerXdr`/`metadataXdr` parsed into XDR objects instead of raw base64 strings ([#1389
35+
](https://github.com/stellar/js-stellar-sdk/pull/1389)).
3436

3537
### Deprecated
3638
* `BalanceResponse.revocable` is deprecated in favor of `authorizedToMaintainLiabilities`, which correctly reflects the trustline flag semantics ([#1372](https://github.com/stellar/js-stellar-sdk/pull/1372)).

src/rpc/api.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,20 @@ export namespace Api {
5353
id: string;
5454
sequence: number;
5555
protocolVersion: string;
56+
closeTime: string;
57+
headerXdr: xdr.LedgerHeader;
58+
metadataXdr: xdr.LedgerCloseMeta;
59+
}
60+
61+
export interface RawGetLatestLedgerResponse {
62+
id: string;
63+
sequence: number;
64+
protocolVersion: string;
65+
closeTime: string;
66+
/** a base-64 encoded {@link xdr.LedgerHeader} instance */
67+
headerXdr: string;
68+
/** a base-64 encoded {@link xdr.LedgerCloseMeta} instance */
69+
metadataXdr: string;
5670
}
5771

5872
export enum GetTransactionStatus {

src/rpc/parsers.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,3 +295,32 @@ export function parseRawLedger(raw: Api.RawLedgerResponse): Api.LedgerResponse {
295295
headerXdr,
296296
};
297297
}
298+
299+
export function parseRawLatestLedger(
300+
raw: Api.RawGetLatestLedgerResponse,
301+
): Api.GetLatestLedgerResponse {
302+
const headerXdr = xdr.LedgerHeader.fromXDR(raw.headerXdr, "base64");
303+
const metadataXdr = xdr.LedgerCloseMeta.fromXDR(raw.metadataXdr, "base64");
304+
let missingFields;
305+
if (!raw.metadataXdr && !raw.headerXdr) {
306+
missingFields = "metadataXdr and headerXdr";
307+
} else if (!raw.metadataXdr) {
308+
missingFields = "metadataXdr";
309+
} else if (!raw.headerXdr) {
310+
missingFields = "headerXdr";
311+
}
312+
if (missingFields) {
313+
throw new TypeError(
314+
`invalid getLatestLedger response missing fields: ${missingFields}`,
315+
);
316+
}
317+
318+
return {
319+
id: raw.id,
320+
sequence: raw.sequence,
321+
protocolVersion: raw.protocolVersion,
322+
closeTime: raw.closeTime,
323+
headerXdr,
324+
metadataXdr,
325+
};
326+
}

src/rpc/server.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import {
3030
parseRawTransactions,
3131
parseTransactionInfo,
3232
parseRawLedger,
33+
parseRawLatestLedger,
3334
} from "./parsers";
3435
import { Utils } from "../utils";
3536
import { HttpClient } from "../http-client";
@@ -954,8 +955,11 @@ export class RpcServer {
954955
* console.log("protocolVersion:", response.protocolVersion);
955956
* });
956957
*/
957-
958958
public async getLatestLedger(): Promise<Api.GetLatestLedgerResponse> {
959+
return this._getLatestLedger().then(parseRawLatestLedger);
960+
}
961+
962+
public async _getLatestLedger(): Promise<Api.RawGetLatestLedgerResponse> {
959963
return jsonrpc.postObject(
960964
this.httpClient,
961965
this.serverURL.toString(),

test/unit/server/soroban/get_classic_entries.test.ts

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,25 @@ function expectLedgerEntryFound(
2929
},
3030
},
3131
};
32-
mockPost.mockResolvedValue(mockResponse);
32+
mockPost.mockImplementation((_: any, body: any) => {
33+
if (body && body.method === "getLatestLedger") {
34+
return Promise.resolve({
35+
data: {
36+
result: {
37+
id: "hashed_id",
38+
sequence: 123,
39+
protocolVersion: "20",
40+
closeTime: "124",
41+
headerXdr:
42+
"AAAAGrP0s/PGggfZROfm4UrD2ul0kjwslx8W5YhzlGrP1kmlLqJv3aMl3XEf5FOicCD8tDOT0RNfC5huOz82oO+R2lYAAAAAaeEr4gAAAAAAAAABAAAAALVdELK7fShO1cA6R6XhtZDJD1eDVUccxFB7voIE0jyLAAAAQEMyjPK8bIfQbIrUCHW40CP4+YvCImxg16wuSIjEl43NwDbpsGwu3wQmbi/u8WIZsL6MSTLMXlyXYJDZsRM1pQVU05gS2Au4O3vlO2eyFYdtVS8dCHe0xpQYHXySoXVMo7cVZULv/3jAlcjIvlsAn9k0QMOkSYl3lWBCxEKVK785AB+dnA3gtrOnZAAAAAABMFvNhVUAAAAAAAAAAAABiJMAAABkAExLQAAAAMgQFSWR4kocJqxbAsjAStNr1C1FPlc8QXXsjTfs9IydXFT0EtE8W/9jSNRWmLdX985erJs28eCPXUKZpEvoEx+1H5C0OqNqUACzQFS756EBZ0pgw/b3mKoBb8yYOXC9yWGOFIykqWNbxH+1ZyiD369YvoPJhDkeL1vb0PUdGO+NuAAAAAA=",
43+
metadataXdr:
44+
"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",
45+
},
46+
},
47+
});
48+
}
49+
return Promise.resolve(mockResponse);
50+
});
3351

3452
return call().then((entry: any) => {
3553
expect(entry).toBeInstanceOf(expectedType);
@@ -58,7 +76,12 @@ function expectLedgerEntryNotFound(
5876
},
5977
},
6078
};
61-
mockPost.mockResolvedValue(mockResponse);
79+
mockPost.mockImplementation((url: any, body: any) => {
80+
if (body && body.method === "getLatestLedger") {
81+
return Promise.resolve({ data: { result: { latestLedger: 0 } } });
82+
}
83+
return Promise.resolve(mockResponse);
84+
});
6285

6386
return call()
6487
.then(() => Promise.reject(new Error("Expected rejection")))

test/unit/server/soroban/get_latest_ledger.test.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { StellarSdk } from "../../../test-utils/stellar-sdk-import";
44
import { serverUrl } from "../../../constants";
55

66
const { Server } = StellarSdk.rpc;
7+
const { xdr } = StellarSdk;
78

89
describe("Server#getLatestLedger", () => {
910
let server: any;
@@ -22,13 +23,26 @@ describe("Server#getLatestLedger", () => {
2223
const result = {
2324
id: "hashed_id",
2425
sequence: 123,
25-
protocolVersion: 20,
26+
protocolVersion: "20",
27+
closeTime: "124",
28+
headerXdr:
29+
"AAAAGrP0s/PGggfZROfm4UrD2ul0kjwslx8W5YhzlGrP1kmlLqJv3aMl3XEf5FOicCD8tDOT0RNfC5huOz82oO+R2lYAAAAAaeEr4gAAAAAAAAABAAAAALVdELK7fShO1cA6R6XhtZDJD1eDVUccxFB7voIE0jyLAAAAQEMyjPK8bIfQbIrUCHW40CP4+YvCImxg16wuSIjEl43NwDbpsGwu3wQmbi/u8WIZsL6MSTLMXlyXYJDZsRM1pQVU05gS2Au4O3vlO2eyFYdtVS8dCHe0xpQYHXySoXVMo7cVZULv/3jAlcjIvlsAn9k0QMOkSYl3lWBCxEKVK785AB+dnA3gtrOnZAAAAAABMFvNhVUAAAAAAAAAAAABiJMAAABkAExLQAAAAMgQFSWR4kocJqxbAsjAStNr1C1FPlc8QXXsjTfs9IydXFT0EtE8W/9jSNRWmLdX985erJs28eCPXUKZpEvoEx+1H5C0OqNqUACzQFS756EBZ0pgw/b3mKoBb8yYOXC9yWGOFIykqWNbxH+1ZyiD369YvoPJhDkeL1vb0PUdGO+NuAAAAAA=",
30+
metadataXdr:
31+
"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",
32+
};
33+
const expectedResponse = {
34+
id: result.id,
35+
sequence: result.sequence,
36+
protocolVersion: result.protocolVersion,
37+
closeTime: result.closeTime,
38+
headerXdr: xdr.LedgerHeader.fromXDR(result.headerXdr, "base64"),
39+
metadataXdr: xdr.LedgerCloseMeta.fromXDR(result.metadataXdr, "base64"),
2640
};
2741
const mockResponse = { data: { result } };
2842
mockPost.mockResolvedValue(mockResponse);
2943

3044
const response = await server.getLatestLedger();
31-
expect(response).toEqual(result);
45+
expect(response).toEqual(expectedResponse);
3246
expect(mockPost).toHaveBeenCalledWith(serverUrl, {
3347
jsonrpc: "2.0",
3448
id: 1,

0 commit comments

Comments
 (0)