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

example of types #2677

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
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
20 changes: 8 additions & 12 deletions packages/xrpl/src/client/RequestManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,11 +171,8 @@ export default class RequestManager {
* @param response - The response to handle.
* @throws ResponseFormatError if the response format is invalid, RippledError if rippled returns an error.
*/
public handleResponse(response: Partial<Response | ErrorResponse>): void {
if (
response.id == null ||
!(typeof response.id === 'string' || typeof response.id === 'number')
) {
public handleResponse(response: Response | ErrorResponse): void {
if (!(typeof response.id === 'string' || typeof response.id === 'number')) {
throw new ResponseFormatError('valid id not found in response', response)
}
if (!this.promisesAwaitingResponse.has(response.id)) {
Expand All @@ -185,12 +182,11 @@ export default class RequestManager {
const error = new ResponseFormatError('Response has no status')
this.reject(response.id, error)
}
if (response.status === 'error') {
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- We know this must be true
const errorResponse = response as Partial<ErrorResponse>
// Error response type
if (!('result' in response)) {
const error = new RippledError(
errorResponse.error_message ?? errorResponse.error,
errorResponse,
response.error_message ?? response.error,
response,
)
this.reject(response.id, error)
return
Expand All @@ -205,8 +201,8 @@ export default class RequestManager {
}
// status no longer needed because error is thrown if status is not "success"
delete response.status
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Must be a valid Response here
this.resolve(response.id, response as unknown as Response)

this.resolve(response.id, response)
}

/**
Expand Down
31 changes: 23 additions & 8 deletions packages/xrpl/src/client/connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import {
ConnectionError,
XrplError,
} from '../errors'
import type { RequestResponseMap } from '../models'
import { ErrorResponse } from '../models'
import type { RequestResponseMap, Response } from '../models'
import { BaseRequest } from '../models/methods/baseMethod'

import ConnectionManager from './ConnectionManager'
Expand Down Expand Up @@ -323,26 +324,40 @@ export class Connection extends EventEmitter {
*
* @param message - The message received from the server.
*/
private onMessage(message): void {
// eslint-disable-next-line complexity -- It is fine to have a high complexity here.
private onMessage(message: string): void {
this.trace('receive', message)
let data: Record<string, unknown>
let data: Response | ErrorResponse | null = null

// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Typeguard function
function isResponseOrError(obj: any): obj is Response | ErrorResponse {
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access -- Made it safe with ?
return 'result' in obj || obj?.status === 'error'
}
try {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- Must be a JSON dictionary
data = JSON.parse(message)
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- Only away to do a typeguard
const parsed = JSON.parse(message)

if (isResponseOrError(parsed)) {
data = parsed
}
} catch (error) {
if (error instanceof Error) {
this.emit('error', 'badMessage', error.message, message)
}
return
}
if (data.type == null && data.error) {
if (data === null) {
this.emit('error', 'badMessage', 'Invalid JSON', message)
return
}
if (!('result' in data) && data.type == null && data.error) {
// e.g. slowDown
this.emit('error', data.error, data.error_message, data)
return
}
if (data.type) {
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Should be true
this.emit(data.type as string, data)
this.emit(data.type, data)
}
if (data.type === 'response') {
try {
Expand Down
13 changes: 7 additions & 6 deletions packages/xrpl/src/client/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ import {
import type {
RequestResponseMap,
RequestAllResponseMap,
MarkerRequest,
MarkerResponse,
SubmitResponse,
} from '../models/methods'
Expand Down Expand Up @@ -437,10 +436,11 @@ class Client extends EventEmitter<EventTypes> {
* const allResponses = await client.requestAll({ command: 'transaction_data' });
* console.log(allResponses);
*/
public async requestAll<
T extends MarkerRequest,
U = RequestAllResponseMap<T>,
>(request: T, collect?: string): Promise<U[]> {

public async requestAll<T extends Request, U = RequestAllResponseMap<T>>(
request: T,
collect?: string,
): Promise<U[]> {
/*
* The data under collection is keyed based on the command. Fail if command
* not recognized and collection key not provided.
Expand All @@ -453,7 +453,8 @@ class Client extends EventEmitter<EventTypes> {
* If limit is not provided, fetches all data over multiple requests.
* NOTE: This may return much more than needed. Set limit when possible.
*/
const countTo: number = request.limit == null ? Infinity : request.limit
const countTo: number =
typeof request.limit === 'number' ? request.limit : Infinity
let count = 0
let marker: unknown = request.marker
const results: U[] = []
Expand Down
40 changes: 38 additions & 2 deletions packages/xrpl/src/models/methods/accountInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ export interface AccountInfoAccountFlags {
*
* @category Responses
*/
export interface AccountInfoResponse extends BaseResponse {
export interface BaseAccountInfoResponse extends BaseResponse {
result: {
/**
* The AccountRoot ledger object with this account's information, as stored
Expand All @@ -148,7 +148,7 @@ export interface AccountInfoResponse extends BaseResponse {
* at most one SignerList, this array must have exactly one member if it is
* present.
*/
account_data: AccountRoot & { signer_lists?: SignerList[] }
account_data: AccountRoot

/**
* A map of account flags parsed out. This will only be available for rippled nodes 1.11.0 and higher.
Expand Down Expand Up @@ -180,3 +180,39 @@ export interface AccountInfoResponse extends BaseResponse {
validated?: boolean
}
}

export interface AccountInfoV1Response extends BaseAccountInfoResponse {
result: BaseAccountInfoResponse['result'] & {
/**
* The AccountRoot ledger object with this account's information, as stored
* in the ledger.
* If requested, also includes Array of SignerList ledger objects
* associated with this account for Multi-Signing. Since an account can own
* at most one SignerList, this array must have exactly one member if it is
* present.
*/
account_data: BaseAccountInfoResponse['result']['account_data'] & {
/**
* Array of SignerList ledger objects associated with this account for Multi-Signing.
* Since an account can own at most one SignerList, this array must have exactly one
* member if it is present.
* Quirk: In API version 1, this field is nested under account_data. For this method,
* Clio implements the API version 2 behavior where is field is not nested under account_data.
*/
signer_lists?: SignerList[]
}
}
}

export interface AccountInfoV2Response extends BaseAccountInfoResponse {
result: BaseAccountInfoResponse['result'] & {
/**
* Array of SignerList ledger objects associated with this account for Multi-Signing.
* Since an account can own at most one SignerList, this array must have exactly one
* member if it is present.
* Quirk: In API version 1, this field is nested under account_data. For this method,
* Clio implements the API version 2 behavior where is field is not nested under account_data.
*/
signer_lists?: SignerList[]
}
}
10 changes: 5 additions & 5 deletions packages/xrpl/src/models/methods/baseMethod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ export interface ResponseWarning {
}

export interface BaseResponse {
id: number | string
status?: 'success' | string
type: 'response' | string
id: number | string | null
status?: 'success' | string | null
type: 'response' | string | null
result: unknown
warning?: 'load'
warnings?: ResponseWarning[]
Expand All @@ -47,9 +47,9 @@ export interface BaseResponse {
* @category Responses
*/
export interface ErrorResponse {
id: number | string
id: number | string | null
status: 'error'
type: 'response' | string
type: 'response' | string | null
error: string
error_code?: string
error_message?: string
Expand Down
Loading
Loading