mirror of
https://github.com/Xahau/xahau.js.git
synced 2025-11-04 21:15:47 +00:00
feat: add rippled API v2 support and use as default (#2656)
* add apiVersion support to requests and AccountInfoResponse v1/v2 types * fix submitAndWait signature * update docker container README * update tests * fix apiVersion param in wrong position of Client.request * add integ tests * update HISTORY.md * fix request.api_version * update RIPPLED_DOCKER_IMAGE to use v2.1.0 * refactor Client.request signature * update rippled docker image * fix Client.requestAll * update rippled docker image to use v2.1.1 * update README * use import type * fix faucet; unrelated to PR * add api_version v2 support and set as default while providing support for v1 * refactor: add apiVersion to Client * resolve errors * use DeliverMax for isPartialPayment check * update fixtures * resolve lint errors * add API v1 support for isPartialPayment * update CONTRIBUTING * update accountTx JSDoc * revert deleted JSDoc comments in accountTx * update JSDoc for account_info response * only use client.apiVersion in Client.request() * add ledger_hash * remove API v1 comment from v2 model * update meta_blob JSDoc * delete second AccountTxRequest matching * add close_time_iso * set close_time_iso as optional field * add meta_blob to BaseResponse * Revert "add meta_blob to BaseResponse" This reverts commit 89794c629dc515915e28752d7c2552bfeab266a3. * use DEFAULT_API_VERSION throughout call stack * improve JSDoc explanation of ledger_index * remove this.apiVersion from getLedgerIndex * refactor Client.request() * refactor RequestManger.resolve() * add TODO to fix TxResponse type assertion * use @category ResponsesV1 for API v1 types * refactor accountTxHasPartialPayment() * remove TODO
This commit is contained in:
@@ -5,8 +5,12 @@ Subscribe to [the **xrpl-announce** mailing list](https://groups.google.com/g/xr
|
||||
## Unreleased
|
||||
* Remove references to the Hooks testnet faucet in the xrpl.js code repository.
|
||||
|
||||
### BREAKING CHANGES
|
||||
* Use rippled api_version v2 as default while maintaining support for v1.
|
||||
|
||||
### Added
|
||||
* Add `nfts_by_issuer` clio-only API definition
|
||||
|
||||
## 3.1.0 (2024-06-03)
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
@@ -56,7 +56,7 @@ async function claimPayChannel(): Promise<void> {
|
||||
Channel: hashes.hashPaymentChannel(
|
||||
wallet1.classicAddress,
|
||||
wallet2.classicAddress,
|
||||
paymentChannelResponse.result.Sequence ?? 0,
|
||||
paymentChannelResponse.result.tx_json.Sequence ?? 0,
|
||||
),
|
||||
Amount: '100',
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ async function sendEscrow(): Promise<void> {
|
||||
TransactionType: 'EscrowFinish',
|
||||
Account: wallet1.classicAddress,
|
||||
Owner: wallet1.classicAddress,
|
||||
OfferSequence: Number(createEscrowResponse.result.Sequence),
|
||||
OfferSequence: Number(createEscrowResponse.result.tx_json.Sequence),
|
||||
}
|
||||
|
||||
await client.submit(finishTx, {
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
TimeoutError,
|
||||
XrplError,
|
||||
} from '../errors'
|
||||
import type { APIVersion } from '../models'
|
||||
import { Response, RequestResponseMap } from '../models/methods'
|
||||
import { BaseRequest, ErrorResponse } from '../models/methods/baseMethod'
|
||||
|
||||
@@ -35,10 +36,10 @@ export default class RequestManager {
|
||||
* @param timer - The timer associated with the promise.
|
||||
* @returns A promise that resolves to the specified generic type.
|
||||
*/
|
||||
public async addPromise<R extends BaseRequest, T = RequestResponseMap<R>>(
|
||||
newId: string | number,
|
||||
timer: ReturnType<typeof setTimeout>,
|
||||
): Promise<T> {
|
||||
public async addPromise<
|
||||
R extends BaseRequest,
|
||||
T = RequestResponseMap<R, APIVersion>,
|
||||
>(newId: string | number, timer: ReturnType<typeof setTimeout>): Promise<T> {
|
||||
return new Promise<T>((resolve, reject) => {
|
||||
this.promisesAwaitingResponse.set(newId, {
|
||||
resolve,
|
||||
@@ -55,7 +56,10 @@ export default class RequestManager {
|
||||
* @param response - Response to return.
|
||||
* @throws Error if no existing promise with the given ID.
|
||||
*/
|
||||
public resolve(id: string | number, response: Response): void {
|
||||
public resolve(
|
||||
id: string | number,
|
||||
response: Partial<Response<APIVersion>>,
|
||||
): void {
|
||||
const promise = this.promisesAwaitingResponse.get(id)
|
||||
if (promise == null) {
|
||||
throw new XrplError(`No existing promise with id ${id}`, {
|
||||
@@ -111,10 +115,10 @@ export default class RequestManager {
|
||||
* @returns Request ID, new request form, and the promise for resolving the request.
|
||||
* @throws XrplError if request with the same ID is already pending.
|
||||
*/
|
||||
public createRequest<R extends BaseRequest, T = RequestResponseMap<R>>(
|
||||
request: R,
|
||||
timeout: number,
|
||||
): [string | number, string, Promise<T>] {
|
||||
public createRequest<
|
||||
R extends BaseRequest,
|
||||
T = RequestResponseMap<R, APIVersion>,
|
||||
>(request: R, timeout: number): [string | number, string, Promise<T>] {
|
||||
let newId: string | number
|
||||
if (request.id == null) {
|
||||
newId = this.nextId
|
||||
@@ -171,7 +175,9 @@ 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 {
|
||||
public handleResponse(
|
||||
response: Partial<Response<APIVersion> | ErrorResponse>,
|
||||
): void {
|
||||
if (
|
||||
response.id == null ||
|
||||
!(typeof response.id === 'string' || typeof response.id === 'number')
|
||||
@@ -205,8 +211,7 @@ 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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
ConnectionError,
|
||||
XrplError,
|
||||
} from '../errors'
|
||||
import type { RequestResponseMap } from '../models'
|
||||
import type { APIVersion, RequestResponseMap } from '../models'
|
||||
import { BaseRequest } from '../models/methods/baseMethod'
|
||||
|
||||
import ConnectionManager from './ConnectionManager'
|
||||
@@ -267,6 +267,7 @@ export class Connection extends EventEmitter {
|
||||
|
||||
/**
|
||||
* Disconnect the websocket, then connect again.
|
||||
*
|
||||
*/
|
||||
public async reconnect(): Promise<void> {
|
||||
/*
|
||||
@@ -287,10 +288,10 @@ export class Connection extends EventEmitter {
|
||||
* @returns The response from the rippled server.
|
||||
* @throws NotConnectedError if the Connection isn't connected to a server.
|
||||
*/
|
||||
public async request<R extends BaseRequest, T = RequestResponseMap<R>>(
|
||||
request: R,
|
||||
timeout?: number,
|
||||
): Promise<T> {
|
||||
public async request<
|
||||
R extends BaseRequest,
|
||||
T = RequestResponseMap<R, APIVersion>,
|
||||
>(request: R, timeout?: number): Promise<T> {
|
||||
if (!this.shouldBeConnected || this.ws == null) {
|
||||
throw new NotConnectedError(JSON.stringify(request), request)
|
||||
}
|
||||
@@ -468,6 +469,7 @@ export class Connection extends EventEmitter {
|
||||
|
||||
/**
|
||||
* Starts a heartbeat to check the connection with the server.
|
||||
*
|
||||
*/
|
||||
private startHeartbeatInterval(): void {
|
||||
this.clearHeartbeatInterval()
|
||||
|
||||
@@ -9,7 +9,12 @@ import {
|
||||
ValidationError,
|
||||
XrplError,
|
||||
} from '../errors'
|
||||
import type { LedgerIndex, Balance } from '../models/common'
|
||||
import {
|
||||
APIVersion,
|
||||
LedgerIndex,
|
||||
Balance,
|
||||
DEFAULT_API_VERSION,
|
||||
} from '../models/common'
|
||||
import {
|
||||
Request,
|
||||
// account methods
|
||||
@@ -213,6 +218,12 @@ class Client extends EventEmitter<EventTypes> {
|
||||
*/
|
||||
public buildVersion: string | undefined
|
||||
|
||||
/**
|
||||
* API Version used by the server this client is connected to
|
||||
*
|
||||
*/
|
||||
public apiVersion: APIVersion = DEFAULT_API_VERSION
|
||||
|
||||
/**
|
||||
* Creates a new Client with a websocket connection to a rippled server.
|
||||
*
|
||||
@@ -307,7 +318,6 @@ class Client extends EventEmitter<EventTypes> {
|
||||
* additional request body parameters.
|
||||
*
|
||||
* @category Network
|
||||
*
|
||||
* @param req - Request to send to the server.
|
||||
* @returns The response from the server.
|
||||
*
|
||||
@@ -320,16 +330,20 @@ class Client extends EventEmitter<EventTypes> {
|
||||
* console.log(response)
|
||||
* ```
|
||||
*/
|
||||
public async request<R extends Request, T = RequestResponseMap<R>>(
|
||||
req: R,
|
||||
): Promise<T> {
|
||||
const response = await this.connection.request<R, T>({
|
||||
public async request<
|
||||
R extends Request,
|
||||
V extends APIVersion = typeof DEFAULT_API_VERSION,
|
||||
T = RequestResponseMap<R, V>,
|
||||
>(req: R): Promise<T> {
|
||||
const request = {
|
||||
...req,
|
||||
account: req.account
|
||||
? // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Must be string
|
||||
ensureClassicAddress(req.account as string)
|
||||
account:
|
||||
typeof req.account === 'string'
|
||||
? ensureClassicAddress(req.account)
|
||||
: undefined,
|
||||
})
|
||||
api_version: req.api_version ?? this.apiVersion,
|
||||
}
|
||||
const response = await this.connection.request<R, T>(request)
|
||||
|
||||
// mutates `response` to add warnings
|
||||
handlePartialPayment(req.command, response)
|
||||
@@ -438,9 +452,10 @@ 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>,
|
||||
U = RequestAllResponseMap<T, APIVersion>,
|
||||
>(request: T, collect?: string): Promise<U[]> {
|
||||
/*
|
||||
* The data under collection is keyed based on the command. Fail if command
|
||||
@@ -468,7 +483,7 @@ class Client extends EventEmitter<EventTypes> {
|
||||
// eslint-disable-next-line no-await-in-loop -- Necessary for this, it really has to wait
|
||||
const singleResponse = await this.connection.request(repeatProps)
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Should be true
|
||||
const singleResult = (singleResponse as MarkerResponse).result
|
||||
const singleResult = (singleResponse as MarkerResponse<APIVersion>).result
|
||||
if (!(collectKey in singleResult)) {
|
||||
throw new XrplError(`${collectKey} not in result`)
|
||||
}
|
||||
|
||||
@@ -2,13 +2,16 @@ import BigNumber from 'bignumber.js'
|
||||
import { decode } from 'ripple-binary-codec'
|
||||
|
||||
import type {
|
||||
AccountTxResponse,
|
||||
TransactionEntryResponse,
|
||||
TransactionStream,
|
||||
TxResponse,
|
||||
} from '..'
|
||||
import type { Amount } from '../models/common'
|
||||
import type { RequestResponseMap } from '../models/methods'
|
||||
import type { Amount, APIVersion, DEFAULT_API_VERSION } from '../models/common'
|
||||
import type {
|
||||
AccountTxTransaction,
|
||||
RequestResponseMap,
|
||||
} from '../models/methods'
|
||||
import { AccountTxVersionResponseMap } from '../models/methods/accountTx'
|
||||
import { BaseRequest, BaseResponse } from '../models/methods/baseMethod'
|
||||
import { PaymentFlags, Transaction } from '../models/transactions'
|
||||
import type { TransactionMetadata } from '../models/transactions/metadata'
|
||||
@@ -63,7 +66,10 @@ function isPartialPayment(
|
||||
}
|
||||
|
||||
const delivered = meta.delivered_amount
|
||||
const amount = tx.Amount
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment -- DeliverMax is a valid field on Payment response
|
||||
// @ts-expect-error -- DeliverMax is a valid field on Payment response
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- DeliverMax is a valid field on Payment response
|
||||
const amount = tx.DeliverMax
|
||||
|
||||
if (delivered === undefined) {
|
||||
return false
|
||||
@@ -73,23 +79,36 @@ function isPartialPayment(
|
||||
}
|
||||
|
||||
function txHasPartialPayment(response: TxResponse): boolean {
|
||||
return isPartialPayment(response.result, response.result.meta)
|
||||
return isPartialPayment(response.result.tx_json, response.result.meta)
|
||||
}
|
||||
|
||||
function txEntryHasPartialPayment(response: TransactionEntryResponse): boolean {
|
||||
return isPartialPayment(response.result.tx_json, response.result.metadata)
|
||||
}
|
||||
|
||||
function accountTxHasPartialPayment(response: AccountTxResponse): boolean {
|
||||
function accountTxHasPartialPayment<
|
||||
Version extends APIVersion = typeof DEFAULT_API_VERSION,
|
||||
>(response: AccountTxVersionResponseMap<Version>): boolean {
|
||||
const { transactions } = response.result
|
||||
const foo = transactions.some((tx) => isPartialPayment(tx.tx, tx.meta))
|
||||
const foo = transactions.some((tx) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access -- required to check API version model
|
||||
if (tx.tx_json != null) {
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- use API v2 model
|
||||
const transaction = tx as AccountTxTransaction
|
||||
return isPartialPayment(transaction.tx_json, transaction.meta)
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- use API v1 model
|
||||
const transaction = tx as AccountTxTransaction<1>
|
||||
return isPartialPayment(transaction.tx, transaction.meta)
|
||||
})
|
||||
return foo
|
||||
}
|
||||
|
||||
function hasPartialPayment<R extends BaseRequest, T = RequestResponseMap<R>>(
|
||||
command: string,
|
||||
response: T,
|
||||
): boolean {
|
||||
function hasPartialPayment<
|
||||
R extends BaseRequest,
|
||||
V extends APIVersion = typeof DEFAULT_API_VERSION,
|
||||
T = RequestResponseMap<R, V>,
|
||||
>(command: string, response: T): boolean {
|
||||
/* eslint-disable @typescript-eslint/consistent-type-assertions -- Request type is known at runtime from command */
|
||||
switch (command) {
|
||||
case 'tx':
|
||||
@@ -97,7 +116,9 @@ function hasPartialPayment<R extends BaseRequest, T = RequestResponseMap<R>>(
|
||||
case 'transaction_entry':
|
||||
return txEntryHasPartialPayment(response as TransactionEntryResponse)
|
||||
case 'account_tx':
|
||||
return accountTxHasPartialPayment(response as AccountTxResponse)
|
||||
return accountTxHasPartialPayment(
|
||||
response as AccountTxVersionResponseMap<V>,
|
||||
)
|
||||
default:
|
||||
return false
|
||||
}
|
||||
@@ -112,7 +133,7 @@ function hasPartialPayment<R extends BaseRequest, T = RequestResponseMap<R>>(
|
||||
*/
|
||||
export function handlePartialPayment<
|
||||
R extends BaseRequest,
|
||||
T = RequestResponseMap<R>,
|
||||
T = RequestResponseMap<R, APIVersion>,
|
||||
>(command: string, response: T): void {
|
||||
if (hasPartialPayment(command, response)) {
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- We are checking dynamically and safely.
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
export const RIPPLED_API_V1 = 1
|
||||
export const RIPPLED_API_V2 = 2
|
||||
export const DEFAULT_API_VERSION = RIPPLED_API_V2
|
||||
export type APIVersion = typeof RIPPLED_API_V1 | typeof RIPPLED_API_V2
|
||||
export type LedgerIndex = number | ('validated' | 'closed' | 'current')
|
||||
|
||||
export interface XRP {
|
||||
@@ -104,6 +108,10 @@ export interface ResponseOnlyTxInfo {
|
||||
* The sequence number of the ledger that included this transaction.
|
||||
*/
|
||||
ledger_index?: number
|
||||
/**
|
||||
* The hash of the ledger included this transaction.
|
||||
*/
|
||||
ledger_hash?: string
|
||||
/**
|
||||
* @deprecated Alias for ledger_index.
|
||||
*/
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { APIVersion, DEFAULT_API_VERSION, RIPPLED_API_V1 } from '../common'
|
||||
import { Transaction, TransactionMetadata } from '../transactions'
|
||||
|
||||
import { LedgerEntry } from './LedgerEntry'
|
||||
|
||||
/**
|
||||
* A ledger is a block of transactions and shared state data. It has a unique
|
||||
* header that describes its contents using cryptographic hashes.
|
||||
* Common properties for ledger entries.
|
||||
*
|
||||
* @category Ledger Entries
|
||||
*/
|
||||
export default interface Ledger {
|
||||
interface BaseLedger {
|
||||
/** The SHA-512Half of this ledger's state tree information. */
|
||||
account_hash: string
|
||||
/** All the state information in this ledger. Admin only. */
|
||||
@@ -38,11 +38,6 @@ export default interface Ledger {
|
||||
* for this ledger and all its contents.
|
||||
*/
|
||||
ledger_hash: string
|
||||
/**
|
||||
* The ledger index of the ledger. Some API methods display this as a quoted
|
||||
* integer; some display it as a native JSON number.
|
||||
*/
|
||||
ledger_index: string
|
||||
/** The approximate time at which the previous ledger was closed. */
|
||||
parent_close_time: number
|
||||
/**
|
||||
@@ -63,3 +58,40 @@ export default interface Ledger {
|
||||
*/
|
||||
transactions?: Array<Transaction & { metaData?: TransactionMetadata }>
|
||||
}
|
||||
|
||||
/**
|
||||
* A ledger is a block of transactions and shared state data. It has a unique
|
||||
* header that describes its contents using cryptographic hashes.
|
||||
*
|
||||
* @category Ledger Entries
|
||||
*/
|
||||
export interface Ledger extends BaseLedger {
|
||||
/**
|
||||
* The ledger index of the ledger. Represented as a number.
|
||||
*/
|
||||
ledger_index: number
|
||||
}
|
||||
|
||||
/**
|
||||
* A ledger is a block of transactions and shared state data. It has a unique
|
||||
* header that describes its contents using cryptographic hashes. This is used
|
||||
* in api_version 1.
|
||||
*
|
||||
* @category Ledger Entries
|
||||
*/
|
||||
export interface LedgerV1 extends BaseLedger {
|
||||
/**
|
||||
* The ledger index of the ledger. Some API methods display this as a quoted
|
||||
* integer; some display it as a number.
|
||||
*/
|
||||
ledger_index: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Type to map between the API version and the Ledger type.
|
||||
*
|
||||
* @category Responses
|
||||
*/
|
||||
export type LedgerVersionMap<
|
||||
Version extends APIVersion = typeof DEFAULT_API_VERSION,
|
||||
> = Version extends typeof RIPPLED_API_V1 ? LedgerV1 : Ledger
|
||||
|
||||
@@ -15,7 +15,7 @@ import FeeSettings, {
|
||||
FeeSettingsPostAmendmentFields,
|
||||
FEE_SETTINGS_ID,
|
||||
} from './FeeSettings'
|
||||
import Ledger from './Ledger'
|
||||
import { Ledger, LedgerV1 } from './Ledger'
|
||||
import { LedgerEntry, LedgerEntryFilter } from './LedgerEntry'
|
||||
import LedgerHashes from './LedgerHashes'
|
||||
import NegativeUNL, { NEGATIVE_UNL_ID } from './NegativeUNL'
|
||||
@@ -48,6 +48,7 @@ export {
|
||||
FeeSettingsPreAmendmentFields,
|
||||
FeeSettingsPostAmendmentFields,
|
||||
Ledger,
|
||||
LedgerV1,
|
||||
LedgerEntryFilter,
|
||||
LedgerEntry,
|
||||
LedgerHashes,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { APIVersion, DEFAULT_API_VERSION, RIPPLED_API_V1 } from '../common'
|
||||
import { AccountRoot, SignerList } from '../ledger'
|
||||
|
||||
import { BaseRequest, BaseResponse, LookupByLedgerRequest } from './baseMethod'
|
||||
@@ -133,23 +134,13 @@ export interface AccountInfoAccountFlags {
|
||||
allowTrustLineClawback: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Response expected from an {@link AccountInfoRequest}.
|
||||
*
|
||||
* @category Responses
|
||||
*/
|
||||
export interface AccountInfoResponse extends BaseResponse {
|
||||
interface BaseAccountInfoResponse extends BaseResponse {
|
||||
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: 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.
|
||||
*/
|
||||
@@ -180,3 +171,58 @@ export interface AccountInfoResponse extends BaseResponse {
|
||||
validated?: boolean
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Response expected from a {@link AccountInfoRequest}.
|
||||
*
|
||||
* @category Responses
|
||||
*/
|
||||
export interface AccountInfoResponse extends BaseAccountInfoResponse {
|
||||
result: BaseAccountInfoResponse['result'] & {
|
||||
/**
|
||||
* If requested, 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.
|
||||
*/
|
||||
signer_lists?: SignerList[]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Response expected from a {@link AccountInfoRequest} using API version 1.
|
||||
*
|
||||
* @category ResponsesV1
|
||||
*/
|
||||
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[]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Type to map between the API version and the response type.
|
||||
*
|
||||
* @category Responses
|
||||
*/
|
||||
export type AccountInfoVersionResponseMap<
|
||||
Version extends APIVersion = typeof DEFAULT_API_VERSION,
|
||||
> = Version extends typeof RIPPLED_API_V1
|
||||
? AccountInfoV1Response
|
||||
: AccountInfoResponse
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
import { ResponseOnlyTxInfo } from '../common'
|
||||
import {
|
||||
APIVersion,
|
||||
DEFAULT_API_VERSION,
|
||||
RIPPLED_API_V1,
|
||||
RIPPLED_API_V2,
|
||||
ResponseOnlyTxInfo,
|
||||
} from '../common'
|
||||
import { Transaction, TransactionMetadata } from '../transactions'
|
||||
|
||||
import { BaseRequest, BaseResponse, LookupByLedgerRequest } from './baseMethod'
|
||||
@@ -49,7 +55,9 @@ export interface AccountTxRequest extends BaseRequest, LookupByLedgerRequest {
|
||||
marker?: unknown
|
||||
}
|
||||
|
||||
export interface AccountTxTransaction {
|
||||
export interface AccountTxTransaction<
|
||||
Version extends APIVersion = typeof DEFAULT_API_VERSION,
|
||||
> {
|
||||
/** The ledger index of the ledger version that included this transaction. */
|
||||
ledger_index: number
|
||||
/**
|
||||
@@ -58,7 +66,15 @@ export interface AccountTxTransaction {
|
||||
*/
|
||||
meta: string | TransactionMetadata
|
||||
/** JSON object defining the transaction. */
|
||||
tx?: Transaction & ResponseOnlyTxInfo
|
||||
tx_json?: Version extends typeof RIPPLED_API_V2
|
||||
? Transaction & ResponseOnlyTxInfo
|
||||
: never
|
||||
/** JSON object defining the transaction in rippled API v1. */
|
||||
tx?: Version extends typeof RIPPLED_API_V1
|
||||
? Transaction & ResponseOnlyTxInfo
|
||||
: never
|
||||
/** The hash of the transaction. */
|
||||
hash?: Version extends typeof RIPPLED_API_V2 ? string : never
|
||||
/** Unique hashed String representing the transaction. */
|
||||
tx_blob?: string
|
||||
/**
|
||||
@@ -69,11 +85,11 @@ export interface AccountTxTransaction {
|
||||
}
|
||||
|
||||
/**
|
||||
* Expected response from an {@link AccountTxRequest}.
|
||||
*
|
||||
* @category Responses
|
||||
* Base interface for account transaction responses.
|
||||
*/
|
||||
export interface AccountTxResponse extends BaseResponse {
|
||||
interface AccountTxResponseBase<
|
||||
Version extends APIVersion = typeof DEFAULT_API_VERSION,
|
||||
> extends BaseResponse {
|
||||
result: {
|
||||
/** Unique Address identifying the related account. */
|
||||
account: string
|
||||
@@ -98,7 +114,7 @@ export interface AccountTxResponse extends BaseResponse {
|
||||
* Array of transactions matching the request's criteria, as explained
|
||||
* below.
|
||||
*/
|
||||
transactions: AccountTxTransaction[]
|
||||
transactions: Array<AccountTxTransaction<Version>>
|
||||
/**
|
||||
* If included and set to true, the information in this response comes from
|
||||
* a validated ledger version. Otherwise, the information is subject to
|
||||
@@ -107,3 +123,28 @@ export interface AccountTxResponse extends BaseResponse {
|
||||
validated?: boolean
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Expected response from an {@link AccountTxRequest}.
|
||||
*
|
||||
* @category Responses
|
||||
*/
|
||||
export type AccountTxResponse = AccountTxResponseBase
|
||||
|
||||
/**
|
||||
* Expected response from an {@link AccountTxRequest} with `api_version` set to 1.
|
||||
*
|
||||
* @category ResponsesV1
|
||||
*/
|
||||
export type AccountTxV1Response = AccountTxResponseBase<typeof RIPPLED_API_V1>
|
||||
|
||||
/**
|
||||
* Type to map between the API version and the response type.
|
||||
*
|
||||
* @category Responses
|
||||
*/
|
||||
export type AccountTxVersionResponseMap<
|
||||
Version extends APIVersion = typeof DEFAULT_API_VERSION,
|
||||
> = Version extends typeof RIPPLED_API_V1
|
||||
? AccountTxV1Response
|
||||
: AccountTxResponse
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
/* eslint-disable no-inline-comments -- Necessary for important note */
|
||||
/* eslint-disable max-lines -- There is a lot to export */
|
||||
import type { APIVersion, DEFAULT_API_VERSION } from '../common'
|
||||
|
||||
import {
|
||||
AccountChannelsRequest,
|
||||
AccountChannelsResponse,
|
||||
@@ -13,6 +15,8 @@ import {
|
||||
AccountInfoAccountFlags,
|
||||
AccountInfoRequest,
|
||||
AccountInfoResponse,
|
||||
AccountInfoV1Response,
|
||||
AccountInfoVersionResponseMap,
|
||||
AccountQueueData,
|
||||
AccountQueueTransaction,
|
||||
} from './accountInfo'
|
||||
@@ -40,6 +44,8 @@ import {
|
||||
import {
|
||||
AccountTxRequest,
|
||||
AccountTxResponse,
|
||||
AccountTxV1Response,
|
||||
AccountTxVersionResponseMap,
|
||||
AccountTxTransaction,
|
||||
} from './accountTx'
|
||||
import { AMMInfoRequest, AMMInfoResponse } from './ammInfo'
|
||||
@@ -76,11 +82,13 @@ import {
|
||||
LedgerQueueData,
|
||||
LedgerRequest,
|
||||
LedgerResponse,
|
||||
LedgerV1Response,
|
||||
LedgerRequestExpandedTransactionsOnly,
|
||||
LedgerResponseExpanded,
|
||||
LedgerRequestExpandedAccountsAndTransactions,
|
||||
LedgerRequestExpandedAccountsOnly,
|
||||
LedgerRequestExpandedTransactionsBinary,
|
||||
LedgerVersionResponseMap,
|
||||
} from './ledger'
|
||||
import { LedgerClosedRequest, LedgerClosedResponse } from './ledgerClosed'
|
||||
import { LedgerCurrentRequest, LedgerCurrentResponse } from './ledgerCurrent'
|
||||
@@ -136,6 +144,8 @@ import { SubmitRequest, SubmitResponse } from './submit'
|
||||
import {
|
||||
SubmitMultisignedRequest,
|
||||
SubmitMultisignedResponse,
|
||||
SubmitMultisignedV1Response,
|
||||
SubmitMultisignedVersionResponseMap,
|
||||
} from './submitMultisigned'
|
||||
import {
|
||||
BooksSnapshot,
|
||||
@@ -156,7 +166,7 @@ import {
|
||||
TransactionEntryRequest,
|
||||
TransactionEntryResponse,
|
||||
} from './transactionEntry'
|
||||
import { TxRequest, TxResponse } from './tx'
|
||||
import { TxRequest, TxResponse, TxV1Response, TxVersionResponseMap } from './tx'
|
||||
import {
|
||||
UnsubscribeBook,
|
||||
UnsubscribeRequest,
|
||||
@@ -222,27 +232,27 @@ type Request =
|
||||
/**
|
||||
* @category Responses
|
||||
*/
|
||||
type Response =
|
||||
type Response<Version extends APIVersion = typeof DEFAULT_API_VERSION> =
|
||||
// account methods
|
||||
| AccountChannelsResponse
|
||||
| AccountCurrenciesResponse
|
||||
| AccountInfoResponse
|
||||
| AccountInfoVersionResponseMap<Version>
|
||||
| AccountLinesResponse
|
||||
| AccountNFTsResponse
|
||||
| AccountObjectsResponse
|
||||
| AccountOffersResponse
|
||||
| AccountTxResponse
|
||||
| AccountTxVersionResponseMap<Version>
|
||||
| GatewayBalancesResponse
|
||||
| NoRippleCheckResponse
|
||||
// ledger methods
|
||||
| LedgerResponse
|
||||
| LedgerVersionResponseMap<Version>
|
||||
| LedgerClosedResponse
|
||||
| LedgerCurrentResponse
|
||||
| LedgerDataResponse
|
||||
| LedgerEntryResponse
|
||||
// transaction methods
|
||||
| SubmitResponse
|
||||
| SubmitMultisignedResponse
|
||||
| SubmitMultisignedVersionResponseMap<Version>
|
||||
| TransactionEntryResponse
|
||||
| TxResponse
|
||||
// path and order book methods
|
||||
@@ -276,12 +286,15 @@ type Response =
|
||||
// Price Oracle methods
|
||||
| GetAggregatePriceResponse
|
||||
|
||||
export type RequestResponseMap<T> = T extends AccountChannelsRequest
|
||||
export type RequestResponseMap<
|
||||
T,
|
||||
Version extends APIVersion = typeof DEFAULT_API_VERSION,
|
||||
> = T extends AccountChannelsRequest
|
||||
? AccountChannelsResponse
|
||||
: T extends AccountCurrenciesRequest
|
||||
? AccountCurrenciesResponse
|
||||
: T extends AccountInfoRequest
|
||||
? AccountInfoResponse
|
||||
? AccountInfoVersionResponseMap<Version>
|
||||
: T extends AccountLinesRequest
|
||||
? AccountLinesResponse
|
||||
: T extends AccountNFTsRequest
|
||||
@@ -291,7 +304,7 @@ export type RequestResponseMap<T> = T extends AccountChannelsRequest
|
||||
: T extends AccountOffersRequest
|
||||
? AccountOffersResponse
|
||||
: T extends AccountTxRequest
|
||||
? AccountTxResponse
|
||||
? AccountTxVersionResponseMap<Version>
|
||||
: T extends AMMInfoRequest
|
||||
? AMMInfoResponse
|
||||
: T extends GatewayBalancesRequest
|
||||
@@ -357,15 +370,15 @@ export type RequestResponseMap<T> = T extends AccountChannelsRequest
|
||||
// then we'd get the wrong response type, LedgerResponse, instead of
|
||||
// LedgerResponseExpanded.
|
||||
T extends LedgerRequestExpandedTransactionsBinary
|
||||
? LedgerResponse
|
||||
? LedgerVersionResponseMap<Version>
|
||||
: T extends LedgerRequestExpandedAccountsAndTransactions
|
||||
? LedgerResponseExpanded
|
||||
? LedgerResponseExpanded<Version>
|
||||
: T extends LedgerRequestExpandedTransactionsOnly
|
||||
? LedgerResponseExpanded
|
||||
? LedgerResponseExpanded<Version>
|
||||
: T extends LedgerRequestExpandedAccountsOnly
|
||||
? LedgerResponseExpanded
|
||||
? LedgerResponseExpanded<Version>
|
||||
: T extends LedgerRequest
|
||||
? LedgerResponse
|
||||
? LedgerVersionResponseMap<Version>
|
||||
: T extends LedgerClosedRequest
|
||||
? LedgerClosedResponse
|
||||
: T extends LedgerCurrentRequest
|
||||
@@ -377,11 +390,11 @@ export type RequestResponseMap<T> = T extends AccountChannelsRequest
|
||||
: T extends SubmitRequest
|
||||
? SubmitResponse
|
||||
: T extends SubmitMultisignedRequest
|
||||
? SubmitMultisignedResponse
|
||||
? SubmitMultisignedVersionResponseMap<Version>
|
||||
: T extends TransactionEntryRequest
|
||||
? TransactionEntryResponse
|
||||
: T extends TxRequest
|
||||
? TxResponse
|
||||
? TxVersionResponseMap<Version>
|
||||
: T extends BookOffersRequest
|
||||
? BookOffersResponse
|
||||
: T extends DepositAuthorizedRequest
|
||||
@@ -420,20 +433,25 @@ export type RequestResponseMap<T> = T extends AccountChannelsRequest
|
||||
? NFTsByIssuerResponse
|
||||
: T extends NFTHistoryRequest
|
||||
? NFTHistoryResponse
|
||||
: Response
|
||||
: Response<Version>
|
||||
|
||||
export type MarkerRequest = Request & {
|
||||
limit?: number
|
||||
marker?: unknown
|
||||
}
|
||||
|
||||
export type MarkerResponse = Response & {
|
||||
export type MarkerResponse<
|
||||
Version extends APIVersion = typeof DEFAULT_API_VERSION,
|
||||
> = Response<Version> & {
|
||||
result: {
|
||||
marker?: unknown
|
||||
}
|
||||
}
|
||||
|
||||
export type RequestAllResponseMap<T> = T extends AccountChannelsRequest
|
||||
export type RequestAllResponseMap<
|
||||
T,
|
||||
Version extends APIVersion = typeof DEFAULT_API_VERSION,
|
||||
> = T extends AccountChannelsRequest
|
||||
? AccountChannelsResponse
|
||||
: T extends AccountLinesRequest
|
||||
? AccountLinesResponse
|
||||
@@ -442,14 +460,12 @@ export type RequestAllResponseMap<T> = T extends AccountChannelsRequest
|
||||
: T extends AccountOffersRequest
|
||||
? AccountOffersResponse
|
||||
: T extends AccountTxRequest
|
||||
? AccountTxResponse
|
||||
? AccountTxVersionResponseMap<Version>
|
||||
: T extends LedgerDataRequest
|
||||
? LedgerDataResponse
|
||||
: T extends AccountTxRequest
|
||||
? AccountTxResponse
|
||||
: T extends BookOffersRequest
|
||||
? BookOffersResponse
|
||||
: MarkerResponse
|
||||
: MarkerResponse<Version>
|
||||
|
||||
export {
|
||||
// Allow users to define their own requests and responses. This is useful for releasing experimental versions
|
||||
@@ -467,6 +483,7 @@ export {
|
||||
AccountInfoAccountFlags,
|
||||
AccountInfoRequest,
|
||||
AccountInfoResponse,
|
||||
AccountInfoV1Response,
|
||||
AccountQueueData,
|
||||
AccountQueueTransaction,
|
||||
AccountLinesRequest,
|
||||
@@ -484,6 +501,7 @@ export {
|
||||
AccountOffersResponse,
|
||||
AccountTxRequest,
|
||||
AccountTxResponse,
|
||||
AccountTxV1Response,
|
||||
AccountTxTransaction,
|
||||
GatewayBalance,
|
||||
GatewayBalancesRequest,
|
||||
@@ -495,6 +513,7 @@ export {
|
||||
// ledger methods
|
||||
LedgerRequest,
|
||||
LedgerResponse,
|
||||
LedgerV1Response,
|
||||
LedgerQueueData,
|
||||
LedgerBinary,
|
||||
LedgerModifiedOfferCreateTransaction,
|
||||
@@ -514,10 +533,12 @@ export {
|
||||
SubmitResponse,
|
||||
SubmitMultisignedRequest,
|
||||
SubmitMultisignedResponse,
|
||||
SubmitMultisignedV1Response,
|
||||
TransactionEntryRequest,
|
||||
TransactionEntryResponse,
|
||||
TxRequest,
|
||||
TxResponse,
|
||||
TxV1Response,
|
||||
// path and order book methods with types
|
||||
BookOffersRequest,
|
||||
BookOffer,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Ledger } from '../ledger'
|
||||
import { APIVersion, DEFAULT_API_VERSION, RIPPLED_API_V1 } from '../common'
|
||||
import { Ledger, LedgerV1, LedgerVersionMap } from '../ledger/Ledger'
|
||||
import { LedgerEntryFilter } from '../ledger/LedgerEntry'
|
||||
import { Transaction, TransactionAndMetadata } from '../transactions'
|
||||
import { TransactionMetadata } from '../transactions/metadata'
|
||||
@@ -207,6 +208,12 @@ export interface LedgerBinary
|
||||
transactions?: string[]
|
||||
}
|
||||
|
||||
export interface LedgerBinaryV1
|
||||
extends Omit<Omit<LedgerV1, 'transactions'>, 'accountState'> {
|
||||
accountState?: string[]
|
||||
transactions?: string[]
|
||||
}
|
||||
|
||||
interface LedgerResponseBase {
|
||||
/** Unique identifying hash of the entire ledger. */
|
||||
ledger_hash: string
|
||||
@@ -231,6 +238,11 @@ interface LedgerResponseResult extends LedgerResponseBase {
|
||||
ledger: LedgerBinary
|
||||
}
|
||||
|
||||
interface LedgerV1ResponseResult extends LedgerResponseBase {
|
||||
/** The complete header data of this {@link Ledger}. */
|
||||
ledger: LedgerBinaryV1
|
||||
}
|
||||
|
||||
/**
|
||||
* Response expected from a {@link LedgerRequest}.
|
||||
* This is the default request response, triggered when `expand` and `binary` are both false.
|
||||
@@ -241,9 +253,31 @@ export interface LedgerResponse extends BaseResponse {
|
||||
result: LedgerResponseResult
|
||||
}
|
||||
|
||||
interface LedgerResponseExpandedResult extends LedgerResponseBase {
|
||||
/**
|
||||
* Response expected from a {@link LedgerRequest}.
|
||||
* This is the default request response, triggered when `expand` and `binary` are both false.
|
||||
* This is the response for API version 1.
|
||||
*
|
||||
* @category ResponsesV1
|
||||
*/
|
||||
export interface LedgerV1Response extends BaseResponse {
|
||||
result: LedgerV1ResponseResult
|
||||
}
|
||||
|
||||
/**
|
||||
* Type to map between the API version and the response type.
|
||||
*
|
||||
* @category Responses
|
||||
*/
|
||||
export type LedgerVersionResponseMap<
|
||||
Version extends APIVersion = typeof DEFAULT_API_VERSION,
|
||||
> = Version extends typeof RIPPLED_API_V1 ? LedgerV1Response : LedgerResponse
|
||||
|
||||
interface LedgerResponseExpandedResult<
|
||||
Version extends APIVersion = typeof DEFAULT_API_VERSION,
|
||||
> extends LedgerResponseBase {
|
||||
/** The complete header data of this {@link Ledger}. */
|
||||
ledger: Ledger
|
||||
ledger: LedgerVersionMap<Version>
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -254,6 +288,8 @@ interface LedgerResponseExpandedResult extends LedgerResponseBase {
|
||||
*
|
||||
* @category Responses
|
||||
*/
|
||||
export interface LedgerResponseExpanded extends BaseResponse {
|
||||
result: LedgerResponseExpandedResult
|
||||
export interface LedgerResponseExpanded<
|
||||
Version extends APIVersion = typeof DEFAULT_API_VERSION,
|
||||
> extends BaseResponse {
|
||||
result: LedgerResponseExpandedResult<Version>
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { APIVersion, DEFAULT_API_VERSION, RIPPLED_API_V1 } from '../common'
|
||||
import { Transaction } from '../transactions'
|
||||
|
||||
import { BaseRequest, BaseResponse } from './baseMethod'
|
||||
@@ -25,12 +26,11 @@ export interface SubmitMultisignedRequest extends BaseRequest {
|
||||
}
|
||||
|
||||
/**
|
||||
* Response expected from a {@link SubmitMultisignedRequest}.
|
||||
* Common properties for multisigned transaction responses.
|
||||
*
|
||||
* @category Responses
|
||||
*/
|
||||
export interface SubmitMultisignedResponse extends BaseResponse {
|
||||
result: {
|
||||
interface BaseSubmitMultisignedResult {
|
||||
/**
|
||||
* Code indicating the preliminary result of the transaction, for example.
|
||||
* `tesSUCCESS`.
|
||||
@@ -46,6 +46,38 @@ export interface SubmitMultisignedResponse extends BaseResponse {
|
||||
/** The complete transaction in hex string format. */
|
||||
tx_blob: string
|
||||
/** The complete transaction in JSON format. */
|
||||
tx_json: Transaction
|
||||
}
|
||||
|
||||
/**
|
||||
* Response expected from a {@link SubmitMultisignedRequest}.
|
||||
*
|
||||
* @category Responses
|
||||
*/
|
||||
export interface SubmitMultisignedResponse extends BaseResponse {
|
||||
result: BaseSubmitMultisignedResult & {
|
||||
hash?: string
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Response expected from a {@link SubmitMultisignedRequest} using api_version 1.
|
||||
*
|
||||
* @category ResponsesV1
|
||||
*/
|
||||
export interface SubmitMultisignedV1Response extends BaseResponse {
|
||||
result: BaseSubmitMultisignedResult & {
|
||||
tx_json: Transaction & { hash?: string }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Type to map between the API version and the response type.
|
||||
*
|
||||
* @category Responses
|
||||
*/
|
||||
export type SubmitMultisignedVersionResponseMap<
|
||||
Version extends APIVersion = typeof DEFAULT_API_VERSION,
|
||||
> = Version extends typeof RIPPLED_API_V1
|
||||
? SubmitMultisignedV1Response
|
||||
: SubmitMultisignedResponse
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
import {
|
||||
APIVersion,
|
||||
DEFAULT_API_VERSION,
|
||||
RIPPLED_API_V1,
|
||||
RIPPLED_API_V2,
|
||||
} from '../common'
|
||||
import { Transaction, TransactionMetadata } from '../transactions'
|
||||
import { BaseTransaction } from '../transactions/common'
|
||||
|
||||
@@ -42,13 +48,14 @@ export interface TxRequest extends BaseRequest {
|
||||
}
|
||||
|
||||
/**
|
||||
* Response expected from a {@link TxRequest}.
|
||||
* Common properties of transaction responses.
|
||||
*
|
||||
* @category Responses
|
||||
*/
|
||||
export interface TxResponse<T extends BaseTransaction = Transaction>
|
||||
extends BaseResponse {
|
||||
result: {
|
||||
interface BaseTxResult<
|
||||
Version extends APIVersion = typeof DEFAULT_API_VERSION,
|
||||
T extends BaseTransaction = Transaction,
|
||||
> {
|
||||
/** The SHA-512 hash of the transaction. */
|
||||
hash: string
|
||||
/**
|
||||
@@ -57,6 +64,12 @@ export interface TxResponse<T extends BaseTransaction = Transaction>
|
||||
ctid?: string
|
||||
/** The ledger index of the ledger that includes this transaction. */
|
||||
ledger_index?: number
|
||||
/** Unique hashed string Transaction metadata blob, which describes the results of the transaction.
|
||||
* Can be undefined if a transaction has not been validated yet. This field is omitted if binary
|
||||
* binary format is not requested. */
|
||||
meta_blob?: Version extends typeof RIPPLED_API_V2
|
||||
? TransactionMetadata<T> | string
|
||||
: never
|
||||
/** Transaction metadata, which describes the results of the transaction.
|
||||
* Can be undefined if a transaction has not been validated yet. */
|
||||
meta?: TransactionMetadata<T> | string
|
||||
@@ -65,11 +78,24 @@ export interface TxResponse<T extends BaseTransaction = Transaction>
|
||||
* Set to false, this data is not final.
|
||||
*/
|
||||
validated?: boolean
|
||||
/**
|
||||
* The time the transaction was closed, in seconds since the Ripple Epoch.
|
||||
*/
|
||||
close_time_iso?: string
|
||||
/**
|
||||
* This number measures the number of seconds since the "Ripple Epoch" of January 1, 2000 (00:00 UTC)
|
||||
*/
|
||||
date?: number
|
||||
} & T
|
||||
}
|
||||
|
||||
/**
|
||||
* Response expected from a {@link TxRequest}.
|
||||
*
|
||||
* @category Responses
|
||||
*/
|
||||
export interface TxResponse<T extends BaseTransaction = Transaction>
|
||||
extends BaseResponse {
|
||||
result: BaseTxResult<typeof RIPPLED_API_V2, T> & { tx_json: T }
|
||||
/**
|
||||
* If true, the server was able to search all of the specified ledger
|
||||
* versions, and the transaction was in none of them. If false, the server did
|
||||
@@ -78,3 +104,29 @@ export interface TxResponse<T extends BaseTransaction = Transaction>
|
||||
*/
|
||||
searched_all?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Response expected from a {@link TxRequest} using API version 1.
|
||||
*
|
||||
* @category ResponsesV1
|
||||
*/
|
||||
export interface TxV1Response<T extends BaseTransaction = Transaction>
|
||||
extends BaseResponse {
|
||||
result: BaseTxResult<typeof RIPPLED_API_V1, T> & T
|
||||
/**
|
||||
* If true, the server was able to search all of the specified ledger
|
||||
* versions, and the transaction was in none of them. If false, the server did
|
||||
* not have all of the specified ledger versions available, so it is not sure.
|
||||
* If one of them might contain the transaction.
|
||||
*/
|
||||
searched_all?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Type to map between the API version and the response type.
|
||||
*
|
||||
* @category Responses
|
||||
*/
|
||||
export type TxVersionResponseMap<
|
||||
Version extends APIVersion = typeof DEFAULT_API_VERSION,
|
||||
> = Version extends typeof RIPPLED_API_V1 ? TxV1Response : TxResponse
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import BigNumber from 'bignumber.js'
|
||||
import { xAddressToClassicAddress, isValidXAddress } from 'ripple-address-codec'
|
||||
|
||||
import type { Client } from '..'
|
||||
import { type Client } from '..'
|
||||
import { ValidationError, XrplError } from '../errors'
|
||||
import { AccountInfoRequest, AccountObjectsRequest } from '../models/methods'
|
||||
import { Transaction } from '../models/transactions'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import BigNumber from 'bignumber.js'
|
||||
|
||||
import type { Client } from '..'
|
||||
import { type Client } from '..'
|
||||
import { XrplError } from '../errors'
|
||||
|
||||
const NUM_DECIMAL_PLACES = 6
|
||||
@@ -20,8 +20,11 @@ export default async function getFeeXrp(
|
||||
): Promise<string> {
|
||||
const feeCushion = cushion ?? client.feeCushion
|
||||
|
||||
const serverInfo = (await client.request({ command: 'server_info' })).result
|
||||
.info
|
||||
const serverInfo = (
|
||||
await client.request({
|
||||
command: 'server_info',
|
||||
})
|
||||
).result.info
|
||||
|
||||
const baseFee = serverInfo.validated_ledger?.base_fee_xrp
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import type {
|
||||
} from '..'
|
||||
import { ValidationError, XrplError } from '../errors'
|
||||
import { Signer } from '../models/common'
|
||||
import { TxRequest, TxResponse } from '../models/methods'
|
||||
import { TxResponse } from '../models/methods'
|
||||
import { BaseTransaction } from '../models/transactions/common'
|
||||
|
||||
/** Approximate time for a ledger to close, in milliseconds */
|
||||
@@ -129,7 +129,7 @@ export async function waitForFinalTransactionOutcome<
|
||||
}
|
||||
|
||||
const txResponse = await client
|
||||
.request<TxRequest, TxResponse<T>>({
|
||||
.request({
|
||||
command: 'tx',
|
||||
transaction: txHash,
|
||||
})
|
||||
@@ -153,7 +153,9 @@ export async function waitForFinalTransactionOutcome<
|
||||
})
|
||||
|
||||
if (txResponse.result.validated) {
|
||||
return txResponse
|
||||
// TODO: resolve the type assertion below
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- we know that txResponse is of type TxResponse
|
||||
return txResponse as TxResponse<T>
|
||||
}
|
||||
|
||||
return waitForFinalTransactionOutcome<T>(
|
||||
|
||||
@@ -8,8 +8,9 @@ import BigNumber from 'bignumber.js'
|
||||
import { decode, encode } from 'ripple-binary-codec'
|
||||
|
||||
import { ValidationError, XrplError } from '../../errors'
|
||||
import type { Ledger } from '../../models/ledger'
|
||||
import { APIVersion } from '../../models'
|
||||
import { LedgerEntry } from '../../models/ledger'
|
||||
import { LedgerVersionMap } from '../../models/ledger/Ledger'
|
||||
import { Transaction, TransactionMetadata } from '../../models/transactions'
|
||||
|
||||
import HashPrefix from './HashPrefix'
|
||||
@@ -99,7 +100,9 @@ export function hashSignedTx(tx: Transaction | string): string {
|
||||
* @returns The hash of the ledger.
|
||||
* @category Utilities
|
||||
*/
|
||||
export function hashLedgerHeader(ledgerHeader: Ledger): string {
|
||||
export function hashLedgerHeader(
|
||||
ledgerHeader: LedgerVersionMap<APIVersion>,
|
||||
): string {
|
||||
const prefix = HashPrefix.LEDGER.toString(HEX).toUpperCase()
|
||||
|
||||
const ledger =
|
||||
@@ -158,7 +161,7 @@ export function hashStateTree(entries: LedgerEntry[]): string {
|
||||
}
|
||||
|
||||
function computeTransactionHash(
|
||||
ledger: Ledger,
|
||||
ledger: LedgerVersionMap<APIVersion>,
|
||||
options: HashLedgerHeaderOptions,
|
||||
): string {
|
||||
const { transaction_hash } = ledger
|
||||
@@ -188,7 +191,7 @@ function computeTransactionHash(
|
||||
}
|
||||
|
||||
function computeStateHash(
|
||||
ledger: Ledger,
|
||||
ledger: LedgerVersionMap<APIVersion>,
|
||||
options: HashLedgerHeaderOptions,
|
||||
): string {
|
||||
const { account_hash } = ledger
|
||||
@@ -222,7 +225,7 @@ function computeStateHash(
|
||||
* @category Utilities
|
||||
*/
|
||||
function hashLedger(
|
||||
ledger: Ledger,
|
||||
ledger: LedgerVersionMap<APIVersion>,
|
||||
options: {
|
||||
computeTreeHashes?: boolean
|
||||
} = {},
|
||||
|
||||
@@ -23,6 +23,7 @@ import {
|
||||
} from 'ripple-binary-codec'
|
||||
import { verify as verifyKeypairSignature } from 'ripple-keypairs'
|
||||
|
||||
import type { APIVersion } from '../models'
|
||||
import { LedgerEntry } from '../models/ledger'
|
||||
import { Response } from '../models/methods'
|
||||
import { PaymentChannelClaim } from '../models/transactions/paymentChannelClaim'
|
||||
@@ -157,7 +158,7 @@ function isValidAddress(address: string): boolean {
|
||||
* @returns Whether the response has more pages of data.
|
||||
* @category Utilities
|
||||
*/
|
||||
function hasNextPage(response: Response): boolean {
|
||||
function hasNextPage(response: Response<APIVersion>): boolean {
|
||||
// eslint-disable-next-line @typescript-eslint/dot-notation -- only checking if it exists
|
||||
return Boolean(response.result['marker'])
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any -- required for formatting transactions */
|
||||
import { expect } from 'chai'
|
||||
import cloneDeep from 'lodash/cloneDeep'
|
||||
|
||||
@@ -24,7 +23,7 @@ describe('client handling of tfPartialPayments', function () {
|
||||
testContext.mockRippled!.addResponse('tx', rippled.tx.Payment)
|
||||
const resp = await testContext.client.request({
|
||||
command: 'tx',
|
||||
transaction: rippled.tx.Payment.result.hash,
|
||||
transaction: rippled.tx.Payment.result.tx_json.hash,
|
||||
})
|
||||
|
||||
expect(resp.warnings).to.equal(undefined)
|
||||
@@ -35,7 +34,7 @@ describe('client handling of tfPartialPayments', function () {
|
||||
testContext.mockRippled!.addResponse('tx', mockResponse)
|
||||
const resp = await testContext.client.request({
|
||||
command: 'tx',
|
||||
transaction: mockResponse.result.hash,
|
||||
transaction: mockResponse.result.tx_json.hash,
|
||||
})
|
||||
|
||||
expect(resp.warnings).to.deep.equal([
|
||||
@@ -51,7 +50,7 @@ describe('client handling of tfPartialPayments', function () {
|
||||
testContext.mockRippled!.addResponse('tx', mockResponse)
|
||||
const resp = await testContext.client.request({
|
||||
command: 'tx',
|
||||
transaction: mockResponse.result.hash,
|
||||
transaction: mockResponse.result.tx_json.hash,
|
||||
})
|
||||
|
||||
expect(resp.warnings).to.deep.equal([
|
||||
@@ -82,8 +81,10 @@ describe('client handling of tfPartialPayments', function () {
|
||||
}
|
||||
const mockResponse = rippled.account_tx.normal
|
||||
mockResponse.result.transactions.push({
|
||||
tx: partial.result,
|
||||
tx_json: partial.result.tx_json,
|
||||
meta: partial.result.meta,
|
||||
validated: true,
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- we are mocking the response
|
||||
} as any)
|
||||
|
||||
testContext.mockRippled!.addResponse('account_tx', mockResponse)
|
||||
@@ -105,8 +106,10 @@ describe('client handling of tfPartialPayments', function () {
|
||||
const partial = { ...rippled.tx.Payment, result: partialPaymentXRP }
|
||||
const mockResponse = rippled.account_tx.normal
|
||||
mockResponse.result.transactions.push({
|
||||
tx: partial.result,
|
||||
tx_json: partial.result.tx_json,
|
||||
meta: partial.result.meta,
|
||||
validated: true,
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- we are mocking the response
|
||||
} as any)
|
||||
|
||||
testContext.mockRippled!.addResponse('account_tx', mockResponse)
|
||||
@@ -138,7 +141,7 @@ describe('client handling of tfPartialPayments', function () {
|
||||
|
||||
it('transaction_entry with XRP tfPartialPayment', async function () {
|
||||
const mockResponse = cloneDeep(rippled.transaction_entry)
|
||||
mockResponse.result.tx_json.Amount = '1000'
|
||||
mockResponse.result.tx_json.DeliverMax = '1000'
|
||||
testContext.mockRippled!.addResponse('transaction_entry', mockResponse)
|
||||
const resp = await testContext.client.request({
|
||||
command: 'transaction_entry',
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
"TransactionIndex": 12,
|
||||
"TransactionResult": "tesSUCCESS"
|
||||
},
|
||||
"tx": {
|
||||
"tx_json": {
|
||||
"Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"Destination": "ra5nK24KXen9AHvsdFTKHSANinZseWnPcX",
|
||||
"DestinationTag": 13,
|
||||
@@ -169,7 +169,7 @@
|
||||
"TransactionIndex": 59,
|
||||
"TransactionResult": "tesSUCCESS"
|
||||
},
|
||||
"tx": {
|
||||
"tx_json": {
|
||||
"Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"Authorize": "ra5nK24KXen9AHvsdFTKHSANinZseWnPcX",
|
||||
"Fee": "10",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"tx_json": {
|
||||
"Account": "rGFuMiw48HdbnrUbkRYuitXTmfrDBNTCnX",
|
||||
"Amount": {
|
||||
"DeliverMax": {
|
||||
"currency": "USD",
|
||||
"issuer": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B",
|
||||
"value": "10"
|
||||
@@ -12,7 +13,8 @@
|
||||
"SigningPubKey": "02B205F4B92351AC0EEB04254B636F4C49EF922CFA3CAAD03C6477DA1E04E94B53",
|
||||
"TransactionType": "Payment",
|
||||
"TxnSignature": "3045022100FAF247A836D601DE74A515B2AADE31186D8B0DA9C23DE489E09753F5CF4BB81F0220477C5B5BC3AC89F2347744F9E00CCA62267E198489D747578162C4C7D156211D",
|
||||
"hash": "A0A074D10355223CBE2520A42F93A52E3CC8B4D692570EB4841084F9BBB39F7A",
|
||||
"hash": "A0A074D10355223CBE2520A42F93A52E3CC8B4D692570EB4841084F9BBB39F7A"
|
||||
},
|
||||
"meta": {
|
||||
"AffectedNodes": [
|
||||
{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"tx_json": {
|
||||
"Account": "rGFuMiw48HdbnrUbkRYuitXTmfrDBNTCnX",
|
||||
"Amount": "2000000",
|
||||
"DeliverMax": "2000000",
|
||||
"Destination": "rNNuQMuExCiEjeZ4h9JJnj5PSWypdMXDj4",
|
||||
"Fee": "10000",
|
||||
"Flags": 131072,
|
||||
@@ -8,7 +9,8 @@
|
||||
"SigningPubKey": "02B205F4B92351AC0EEB04254B636F4C49EF922CFA3CAAD03C6477DA1E04E94B53",
|
||||
"TransactionType": "Payment",
|
||||
"TxnSignature": "3045022100FAF247A836D601DE74A515B2AADE31186D8B0DA9C23DE489E09753F5CF4BB81F0220477C5B5BC3AC89F2347744F9E00CCA62267E198489D747578162C4C7D156211D",
|
||||
"hash": "A0A074D10355223CBE2520A42F93A52E3CC8B4D692570EB4841084F9BBB39F7A",
|
||||
"hash": "A0A074D10355223CBE2520A42F93A52E3CC8B4D692570EB4841084F9BBB39F7A"
|
||||
},
|
||||
"meta": {
|
||||
"AffectedNodes": [
|
||||
{
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
},
|
||||
"tx_json": {
|
||||
"Account": "rLSn6Z3T8uCxbcd1oxwfGQN1Fdn5CyGujK",
|
||||
"Amount": "104169972",
|
||||
"DeliverMax": "104169972",
|
||||
"Destination": "rEb8TK3gBgk5auZkwc6sHnwrGVJH8DuaLh",
|
||||
"DestinationTag": 109735445,
|
||||
"Fee": "6000",
|
||||
|
||||
@@ -3,8 +3,9 @@
|
||||
"status": "success",
|
||||
"type": "response",
|
||||
"result": {
|
||||
"tx_json": {
|
||||
"Account": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59",
|
||||
"Amount": {
|
||||
"DeliverMax": {
|
||||
"currency": "USD",
|
||||
"issuer": "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM",
|
||||
"value": "0.001"
|
||||
@@ -35,9 +36,10 @@
|
||||
"TransactionType": "Payment",
|
||||
"TxnSignature": "304502204EE3E9D1B01D8959B08450FCA9E22025AF503DEF310E34A93863A85CAB3C0BC5022100B61F5B567F77026E8DEED89EED0B7CAF0E6C96C228A2A65216F0DC2D04D52083",
|
||||
"date": 416447810,
|
||||
"hash": "F4AB442A6D4CBB935D66E1DA7309A5FC71C7143ED4049053EC14E3875B0CF9BF",
|
||||
"inLedger": 348860,
|
||||
"ledger_index": 348860,
|
||||
"hash": "F4AB442A6D4CBB935D66E1DA7309A5FC71C7143ED4049053EC14E3875B0CF9BF"
|
||||
},
|
||||
"meta": {
|
||||
"AffectedNodes": [
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
To run integration tests:
|
||||
1. Run rippled in standalone node, either in a docker container (preferred) or by installing rippled.
|
||||
* Go to the top-level of the `xrpl.js` repo, just above the `packages` folder.
|
||||
* With docker, run `docker run -p 6006:6006 --interactive -t --volume $PWD/.ci-config:/config/ xrpllabsofficial/1.12.0-b1 -a --start`
|
||||
* With docker, run `docker run -p 6006:6006 --interactive -t --volume $PWD/.ci-config:/opt/ripple/etc/ --platform linux/amd64 rippleci/rippled:2.2.0-b3 /opt/ripple/bin/rippled -a --conf /opt/ripple/etc/rippled.cfg`
|
||||
* Or [download and build rippled](https://xrpl.org/install-rippled.html) and run `./rippled -a --start`
|
||||
* If you'd like to use the latest rippled amendments, you should modify your `rippled.cfg` file to enable amendments in the `[amendments]` section. You can view `.ci-config/rippled.cfg` in the top level folder as an example of this.
|
||||
2. Run `npm run test:integration` or `npm run test:browser`
|
||||
|
||||
@@ -80,4 +80,105 @@ describe('account_info', function () {
|
||||
},
|
||||
TIMEOUT,
|
||||
)
|
||||
|
||||
it(
|
||||
'uses api_version 1',
|
||||
async () => {
|
||||
const request: AccountInfoRequest = {
|
||||
command: 'account_info',
|
||||
account: testContext.wallet.classicAddress,
|
||||
strict: true,
|
||||
ledger_index: 'validated',
|
||||
api_version: 1,
|
||||
}
|
||||
const response = await testContext.client.request(request)
|
||||
const expected = {
|
||||
id: 0,
|
||||
result: {
|
||||
account_data: {
|
||||
Account: testContext.wallet.classicAddress,
|
||||
Balance: '400000000',
|
||||
Flags: 0,
|
||||
LedgerEntryType: 'AccountRoot',
|
||||
OwnerCount: 0,
|
||||
PreviousTxnID:
|
||||
'19A8211695785A3A02C1C287D93C2B049E83A9CD609825E721052D63FF4F0EC8',
|
||||
PreviousTxnLgrSeq: 582,
|
||||
Sequence: 283,
|
||||
index:
|
||||
'BD4815E6EB304136E6044F778FB68D4E464CC8DFC59B8F6CC93D90A3709AE194',
|
||||
},
|
||||
ledger_hash:
|
||||
'F0DEEC46A7185BBB535517EE38CF2025973022D5B0532B36407F492521FDB0C6',
|
||||
ledger_index: 582,
|
||||
validated: true,
|
||||
},
|
||||
type: 'response',
|
||||
}
|
||||
assert.equal(response.type, expected.type)
|
||||
assert.equal(response.result.validated, expected.result.validated)
|
||||
assert.equal(typeof response.result.ledger_index, 'number')
|
||||
assert.equal(typeof response.result.account_data.PreviousTxnID, 'string')
|
||||
assert.equal(typeof response.result.account_data.index, 'string')
|
||||
assert.equal(
|
||||
typeof response.result.account_data.PreviousTxnLgrSeq,
|
||||
'number',
|
||||
)
|
||||
assert.equal(typeof response.result.account_data.Sequence, 'number')
|
||||
assert.deepEqual(
|
||||
omit(response.result.account_data, [
|
||||
'PreviousTxnID',
|
||||
'PreviousTxnLgrSeq',
|
||||
'Sequence',
|
||||
'index',
|
||||
]),
|
||||
omit(expected.result.account_data, [
|
||||
'PreviousTxnID',
|
||||
'PreviousTxnLgrSeq',
|
||||
'Sequence',
|
||||
'index',
|
||||
]),
|
||||
)
|
||||
},
|
||||
TIMEOUT,
|
||||
)
|
||||
|
||||
it(
|
||||
'signer_list using api_version 1',
|
||||
async () => {
|
||||
const request: AccountInfoRequest = {
|
||||
command: 'account_info',
|
||||
account: testContext.wallet.classicAddress,
|
||||
strict: true,
|
||||
ledger_index: 'validated',
|
||||
signer_lists: true,
|
||||
api_version: 1,
|
||||
}
|
||||
const response = await testContext.client.request<AccountInfoRequest, 1>(
|
||||
request,
|
||||
)
|
||||
expect(response.result.account_data.signer_lists).toEqual([])
|
||||
// @ts-expect-error -- signer_lists is expected to be undefined
|
||||
expect(response.result.signer_lists).toBeUndefined()
|
||||
},
|
||||
TIMEOUT,
|
||||
)
|
||||
|
||||
it(
|
||||
'signer_list using api_version 2',
|
||||
async () => {
|
||||
const request: AccountInfoRequest = {
|
||||
command: 'account_info',
|
||||
account: testContext.wallet.classicAddress,
|
||||
strict: true,
|
||||
ledger_index: 'validated',
|
||||
signer_lists: true,
|
||||
}
|
||||
const response = await testContext.client.request(request)
|
||||
// @ts-expect-error -- signer_lists is expected to be undefined
|
||||
expect(response.result.account_data.signer_lists).toBeUndefined()
|
||||
expect(response.result.signer_lists).toEqual([])
|
||||
},
|
||||
TIMEOUT,
|
||||
)
|
||||
})
|
||||
|
||||
@@ -32,6 +32,102 @@ describe('account_tx', function () {
|
||||
ledger_index: 'validated',
|
||||
}
|
||||
const response = await testContext.client.request(request)
|
||||
const expected = {
|
||||
result: {
|
||||
account: testContext.wallet.classicAddress,
|
||||
limit: 400,
|
||||
transactions: [
|
||||
{
|
||||
tx_json: {
|
||||
Account: 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh',
|
||||
DeliverMax: '400000000',
|
||||
Destination: testContext.wallet.classicAddress,
|
||||
Fee: '12',
|
||||
Flags: 0,
|
||||
LastLedgerSequence: 1753,
|
||||
Sequence: 843,
|
||||
SigningPubKey:
|
||||
'0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020',
|
||||
TransactionType: 'Payment',
|
||||
TxnSignature:
|
||||
'30440220693D244BC13967E3DA67BDC974096784ED03DD4ACE6F36645E5176988452AFCF02200F8AB172432913899F27EC5523829AEDAD00CC2445690400E294EDF652A85945',
|
||||
date: 685747005,
|
||||
hash: '2E68BC15813B4A836FAC4D80E42E6FDA6410E99AB973937DEA5E6C2E9A116BAB',
|
||||
ledger_index: 1734,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
type: 'response',
|
||||
}
|
||||
assert.equal(response.type, expected.type)
|
||||
assert.equal(response.result.account, expected.result.account)
|
||||
assert.equal(
|
||||
(response.result.transactions[0].meta as TransactionMetadata<Payment>)
|
||||
.TransactionResult,
|
||||
'tesSUCCESS',
|
||||
)
|
||||
assert.equal(
|
||||
typeof response.result.transactions[0].tx_json?.LastLedgerSequence,
|
||||
'number',
|
||||
)
|
||||
assert.equal(
|
||||
typeof response.result.transactions[0].tx_json?.Sequence,
|
||||
'number',
|
||||
)
|
||||
assert.equal(
|
||||
typeof response.result.transactions[0].tx_json?.SigningPubKey,
|
||||
'string',
|
||||
)
|
||||
assert.equal(
|
||||
typeof response.result.transactions[0].tx_json?.TxnSignature,
|
||||
'string',
|
||||
)
|
||||
assert.equal(
|
||||
typeof response.result.transactions[0].tx_json?.Fee,
|
||||
'string',
|
||||
)
|
||||
assert.equal(typeof response.result.transactions[0].hash, 'string')
|
||||
assert.equal(
|
||||
typeof response.result.transactions[0].tx_json?.ledger_index,
|
||||
'number',
|
||||
)
|
||||
|
||||
const responseTx = response.result.transactions[0].tx_json as Payment
|
||||
const expectedTx = expected.result.transactions[0].tx_json
|
||||
assert.deepEqual(
|
||||
[
|
||||
responseTx.Flags,
|
||||
responseTx.TransactionType,
|
||||
responseTx.Account,
|
||||
// @ts-expect-error -- DeliverMax is a valid field on Payment response
|
||||
responseTx.DeliverMax,
|
||||
responseTx.Destination,
|
||||
],
|
||||
[
|
||||
expectedTx.Flags,
|
||||
expectedTx.TransactionType,
|
||||
expectedTx.Account,
|
||||
expectedTx.DeliverMax,
|
||||
expectedTx.Destination,
|
||||
],
|
||||
)
|
||||
},
|
||||
TIMEOUT,
|
||||
)
|
||||
|
||||
it(
|
||||
'uses api_version 1',
|
||||
async () => {
|
||||
const request: AccountTxRequest = {
|
||||
command: 'account_tx',
|
||||
account: testContext.wallet.classicAddress,
|
||||
ledger_index: 'validated',
|
||||
api_version: 1,
|
||||
}
|
||||
const response = await testContext.client.request<AccountTxRequest, 1>(
|
||||
request,
|
||||
)
|
||||
const expected = {
|
||||
result: {
|
||||
account: testContext.wallet.classicAddress,
|
||||
|
||||
@@ -35,6 +35,7 @@ describe('book_offers', function () {
|
||||
const response = await testContext.client.request(bookOffer)
|
||||
|
||||
const expectedResponse: BookOffersResponse = {
|
||||
api_version: 2,
|
||||
id: response.id,
|
||||
type: 'response',
|
||||
result: {
|
||||
|
||||
@@ -35,6 +35,7 @@ describe('channel_verify', function () {
|
||||
const response = await testContext.client.request(channelVerify)
|
||||
|
||||
const expectedResponse: ChannelVerifyResponse = {
|
||||
api_version: 2,
|
||||
id: response.id,
|
||||
type: 'response',
|
||||
result: {
|
||||
|
||||
@@ -36,6 +36,7 @@ describe('deposit_authorized', function () {
|
||||
const response = await testContext.client.request(depositAuthorized)
|
||||
|
||||
const expectedResponse: DepositAuthorizedResponse = {
|
||||
api_version: 2,
|
||||
id: response.id,
|
||||
type: 'response',
|
||||
result: {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { assert } from 'chai'
|
||||
|
||||
import { LedgerRequest, LedgerResponse } from '../../../src'
|
||||
import { Ledger } from '../../../src/models/ledger'
|
||||
import { LedgerRequest } from '../../../src'
|
||||
import { Ledger, LedgerV1 } from '../../../src/models/ledger'
|
||||
import serverUrl from '../serverUrl'
|
||||
import {
|
||||
setupClient,
|
||||
@@ -29,6 +29,7 @@ describe('ledger', function () {
|
||||
}
|
||||
|
||||
const expected = {
|
||||
api_version: 2,
|
||||
id: 0,
|
||||
result: {
|
||||
ledger: {
|
||||
@@ -45,7 +46,68 @@ describe('ledger', function () {
|
||||
type: 'response',
|
||||
}
|
||||
|
||||
const ledgerResponse: LedgerResponse = await testContext.client.request(
|
||||
const ledgerResponse = await testContext.client.request(ledgerRequest)
|
||||
|
||||
assert.equal(ledgerResponse.type, expected.type)
|
||||
|
||||
assert.equal(ledgerResponse.result.validated, expected.result.validated)
|
||||
assert.typeOf(ledgerResponse.result.ledger_hash, 'string')
|
||||
assert.typeOf(ledgerResponse.result.ledger_index, 'number')
|
||||
|
||||
const ledger = ledgerResponse.result.ledger as Ledger & {
|
||||
accepted: boolean
|
||||
hash: string
|
||||
seqNum: string
|
||||
}
|
||||
assert.equal(ledger.closed, true)
|
||||
const stringTypes = [
|
||||
'account_hash',
|
||||
'close_time_human',
|
||||
'ledger_hash',
|
||||
'parent_hash',
|
||||
'total_coins',
|
||||
'transaction_hash',
|
||||
]
|
||||
stringTypes.forEach((strType) => assert.typeOf(ledger[strType], 'string'))
|
||||
const numTypes = [
|
||||
'close_flags',
|
||||
'close_time',
|
||||
'close_time_resolution',
|
||||
'ledger_index',
|
||||
'parent_close_time',
|
||||
]
|
||||
numTypes.forEach((numType) => assert.typeOf(ledger[numType], 'number'))
|
||||
},
|
||||
TIMEOUT,
|
||||
)
|
||||
|
||||
it(
|
||||
'uses api_version 1',
|
||||
async () => {
|
||||
const ledgerRequest: LedgerRequest = {
|
||||
command: 'ledger',
|
||||
ledger_index: 'validated',
|
||||
api_version: 1,
|
||||
}
|
||||
|
||||
const expected = {
|
||||
id: 0,
|
||||
result: {
|
||||
ledger: {
|
||||
accepted: true,
|
||||
account_hash: 'string',
|
||||
close_flags: 0,
|
||||
close_time: 0,
|
||||
close_time_human: 'string',
|
||||
},
|
||||
ledger_hash: 'string',
|
||||
ledger_index: 1,
|
||||
validated: true,
|
||||
},
|
||||
type: 'response',
|
||||
}
|
||||
|
||||
const ledgerResponse = await testContext.client.request<LedgerRequest, 1>(
|
||||
ledgerRequest,
|
||||
)
|
||||
|
||||
@@ -55,7 +117,7 @@ describe('ledger', function () {
|
||||
assert.typeOf(ledgerResponse.result.ledger_hash, 'string')
|
||||
assert.typeOf(ledgerResponse.result.ledger_index, 'number')
|
||||
|
||||
const ledger = ledgerResponse.result.ledger as Ledger & {
|
||||
const ledger = ledgerResponse.result.ledger as LedgerV1 & {
|
||||
accepted: boolean
|
||||
hash: string
|
||||
seqNum: string
|
||||
|
||||
@@ -40,6 +40,7 @@ describe('ledger_entry', function () {
|
||||
)
|
||||
|
||||
const expectedResponse: LedgerEntryResponse = {
|
||||
api_version: 2,
|
||||
id: ledgerEntryResponse.id,
|
||||
type: 'response',
|
||||
result: {
|
||||
|
||||
@@ -41,6 +41,7 @@ describe('path_find', function () {
|
||||
const response = await testContext.client.request(pathFind)
|
||||
|
||||
const expectedResponse: PathFindResponse = {
|
||||
api_version: 2,
|
||||
id: response.id,
|
||||
type: 'response',
|
||||
result: {
|
||||
@@ -98,6 +99,7 @@ describe('path_find', function () {
|
||||
const response = await testContext.client.request(pathFind)
|
||||
|
||||
const expectedResponse: PathFindResponse = {
|
||||
api_version: 2,
|
||||
id: response.id,
|
||||
type: 'response',
|
||||
result: {
|
||||
|
||||
@@ -35,6 +35,7 @@ describe('ripple_path_find', function () {
|
||||
const response = await testContext.client.request(ripplePathFind)
|
||||
|
||||
const expectedResponse: RipplePathFindResponse = {
|
||||
api_version: 2,
|
||||
id: response.id,
|
||||
type: 'response',
|
||||
result: {
|
||||
|
||||
@@ -54,6 +54,7 @@ describe('submit', function () {
|
||||
)
|
||||
|
||||
const expectedResponse: SubmitResponse = {
|
||||
api_version: 2,
|
||||
id: submitResponse.id,
|
||||
type: 'response',
|
||||
result: {
|
||||
|
||||
@@ -8,6 +8,8 @@ import {
|
||||
Transaction,
|
||||
SubmitMultisignedResponse,
|
||||
hashes,
|
||||
SubmitMultisignedRequest,
|
||||
SubmitMultisignedV1Response,
|
||||
} from '../../../src'
|
||||
import { convertStringToHex } from '../../../src/utils'
|
||||
import { multisign } from '../../../src/Wallet/signer'
|
||||
@@ -88,6 +90,81 @@ describe('submit_multisigned', function () {
|
||||
await verifySubmittedTransaction(testContext.client, multisigned)
|
||||
|
||||
const expectedResponse: SubmitMultisignedResponse = {
|
||||
api_version: 2,
|
||||
id: submitResponse.id,
|
||||
type: 'response',
|
||||
result: {
|
||||
engine_result: 'tesSUCCESS',
|
||||
engine_result_code: 0,
|
||||
engine_result_message:
|
||||
'The transaction was applied. Only final in a validated ledger.',
|
||||
tx_blob: multisigned,
|
||||
tx_json: {
|
||||
...(decode(multisigned) as unknown as Transaction),
|
||||
},
|
||||
hash: hashSignedTx(multisigned),
|
||||
},
|
||||
}
|
||||
|
||||
assert.deepEqual(submitResponse, expectedResponse)
|
||||
},
|
||||
TIMEOUT,
|
||||
)
|
||||
|
||||
it(
|
||||
'submit_multisigned transaction using api_version 1',
|
||||
async () => {
|
||||
const client: Client = testContext.client
|
||||
const signerWallet1 = await generateFundedWallet(testContext.client)
|
||||
const signerWallet2 = await generateFundedWallet(testContext.client)
|
||||
|
||||
// set up the multisigners for the account
|
||||
const signerListSet: SignerListSet = {
|
||||
TransactionType: 'SignerListSet',
|
||||
Account: testContext.wallet.classicAddress,
|
||||
SignerEntries: [
|
||||
{
|
||||
SignerEntry: {
|
||||
Account: signerWallet1.classicAddress,
|
||||
SignerWeight: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
SignerEntry: {
|
||||
Account: signerWallet2.classicAddress,
|
||||
SignerWeight: 1,
|
||||
},
|
||||
},
|
||||
],
|
||||
SignerQuorum: 2,
|
||||
}
|
||||
await testTransaction(
|
||||
testContext.client,
|
||||
signerListSet,
|
||||
testContext.wallet,
|
||||
)
|
||||
|
||||
// try to multisign
|
||||
const accountSet: AccountSet = {
|
||||
TransactionType: 'AccountSet',
|
||||
Account: testContext.wallet.classicAddress,
|
||||
Domain: convertStringToHex('example.com'),
|
||||
}
|
||||
const accountSetTx = await client.autofill(accountSet, 2)
|
||||
const signed1 = signerWallet1.sign(accountSetTx, true)
|
||||
const signed2 = signerWallet2.sign(accountSetTx, true)
|
||||
const multisigned = multisign([signed1.tx_blob, signed2.tx_blob])
|
||||
const submitResponse = await client.request<SubmitMultisignedRequest, 1>({
|
||||
command: 'submit_multisigned',
|
||||
tx_json: decode(multisigned) as unknown as Transaction,
|
||||
api_version: 1,
|
||||
})
|
||||
await ledgerAccept(client)
|
||||
assert.strictEqual(submitResponse.result.engine_result, 'tesSUCCESS')
|
||||
await verifySubmittedTransaction(testContext.client, multisigned)
|
||||
|
||||
const expectedResponse: SubmitMultisignedV1Response = {
|
||||
api_version: 1,
|
||||
id: submitResponse.id,
|
||||
type: 'response',
|
||||
result: {
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
import { assert } from 'chai'
|
||||
|
||||
import { AccountSet, hashes, SubmitResponse, TxResponse } from '../../../src'
|
||||
import {
|
||||
AccountSet,
|
||||
hashes,
|
||||
SubmitResponse,
|
||||
TxRequest,
|
||||
TxResponse,
|
||||
TxV1Response,
|
||||
} from '../../../src'
|
||||
import { convertStringToHex } from '../../../src/utils'
|
||||
import serverUrl from '../serverUrl'
|
||||
import {
|
||||
@@ -45,17 +52,20 @@ describe('tx', function () {
|
||||
})
|
||||
|
||||
const expectedResponse: TxResponse = {
|
||||
api_version: 2,
|
||||
id: txResponse.id,
|
||||
type: 'response',
|
||||
result: {
|
||||
...accountSet,
|
||||
Fee: txResponse.result.Fee,
|
||||
Flags: 0,
|
||||
LastLedgerSequence: txResponse.result.LastLedgerSequence,
|
||||
Sequence: txResponse.result.Sequence,
|
||||
SigningPubKey: testContext.wallet.publicKey,
|
||||
TxnSignature: txResponse.result.TxnSignature,
|
||||
hash: hashSignedTx(response.result.tx_blob),
|
||||
tx_json: {
|
||||
...accountSet,
|
||||
Fee: txResponse.result.tx_json.Fee,
|
||||
Flags: 0,
|
||||
LastLedgerSequence: txResponse.result.tx_json.LastLedgerSequence,
|
||||
Sequence: txResponse.result.tx_json.Sequence,
|
||||
SigningPubKey: testContext.wallet.publicKey,
|
||||
TxnSignature: txResponse.result.tx_json.TxnSignature,
|
||||
},
|
||||
validated: false,
|
||||
},
|
||||
}
|
||||
@@ -64,4 +74,50 @@ describe('tx', function () {
|
||||
},
|
||||
TIMEOUT,
|
||||
)
|
||||
|
||||
it(
|
||||
'uses api_version 1',
|
||||
async () => {
|
||||
const account = testContext.wallet.classicAddress
|
||||
const accountSet: AccountSet = {
|
||||
TransactionType: 'AccountSet',
|
||||
Account: account,
|
||||
Domain: convertStringToHex('example.com'),
|
||||
}
|
||||
|
||||
const response: SubmitResponse = await testContext.client.submit(
|
||||
accountSet,
|
||||
{
|
||||
wallet: testContext.wallet,
|
||||
},
|
||||
)
|
||||
|
||||
const hash = hashSignedTx(response.result.tx_blob)
|
||||
const txV1Response = await testContext.client.request<TxRequest, 1>({
|
||||
command: 'tx',
|
||||
transaction: hash,
|
||||
api_version: 1,
|
||||
})
|
||||
|
||||
const expectedResponse: TxV1Response = {
|
||||
api_version: 1,
|
||||
id: txV1Response.id,
|
||||
type: 'response',
|
||||
result: {
|
||||
...accountSet,
|
||||
Fee: txV1Response.result.Fee,
|
||||
Flags: 0,
|
||||
LastLedgerSequence: txV1Response.result.LastLedgerSequence,
|
||||
Sequence: txV1Response.result.Sequence,
|
||||
SigningPubKey: testContext.wallet.publicKey,
|
||||
TxnSignature: txV1Response.result.TxnSignature,
|
||||
hash: hashSignedTx(response.result.tx_blob),
|
||||
validated: false,
|
||||
},
|
||||
}
|
||||
|
||||
assert.deepEqual(txV1Response, expectedResponse)
|
||||
},
|
||||
TIMEOUT,
|
||||
)
|
||||
})
|
||||
|
||||
@@ -26,6 +26,7 @@ describe('Utility method integration tests', function () {
|
||||
command: 'ping',
|
||||
})
|
||||
const expected: unknown = {
|
||||
api_version: 2,
|
||||
result: { role: 'admin', unlimited: true },
|
||||
type: 'response',
|
||||
}
|
||||
@@ -41,6 +42,7 @@ describe('Utility method integration tests', function () {
|
||||
command: 'random',
|
||||
})
|
||||
const expected = {
|
||||
api_version: 2,
|
||||
id: 0,
|
||||
result: {
|
||||
random: '[random string of 64 bytes]',
|
||||
|
||||
@@ -158,8 +158,7 @@ export async function setupBridge(client: Client): Promise<TestBridge> {
|
||||
account: doorAccount.classicAddress,
|
||||
signer_lists: true,
|
||||
})
|
||||
const signerListInfo =
|
||||
signerAccountInfoResponse.result.account_data.signer_lists?.[0]
|
||||
const signerListInfo = signerAccountInfoResponse.result.signer_lists?.[0]
|
||||
assert.deepEqual(
|
||||
signerListInfo?.SignerEntries,
|
||||
signerTx.SignerEntries,
|
||||
|
||||
@@ -71,7 +71,7 @@ describe('EscrowCancel', function () {
|
||||
command: 'tx',
|
||||
transaction: accountObjects[0].PreviousTxnID,
|
||||
})
|
||||
).result.Sequence
|
||||
).result.tx_json.Sequence
|
||||
|
||||
if (!sequence) {
|
||||
throw new Error('sequence did not exist')
|
||||
|
||||
@@ -64,7 +64,7 @@ describe('EscrowFinish', function () {
|
||||
command: 'tx',
|
||||
transaction: accountObjects[0].PreviousTxnID,
|
||||
})
|
||||
).result.Sequence
|
||||
).result.tx_json.Sequence
|
||||
|
||||
const finishTx: EscrowFinish = {
|
||||
TransactionType: 'EscrowFinish',
|
||||
|
||||
@@ -85,7 +85,7 @@ describe('NFTokenMint', function () {
|
||||
|
||||
assert.equal(
|
||||
nftokenID,
|
||||
getNFTokenID(binaryTxResponse.result.meta) ?? 'undefined',
|
||||
getNFTokenID(binaryTxResponse.result.meta_blob) ?? 'undefined',
|
||||
`getNFTokenID produced a different outcome when decoding the metadata in binary format.`,
|
||||
)
|
||||
},
|
||||
|
||||
@@ -50,8 +50,7 @@ describe('SignerListSet', function () {
|
||||
account: testContext.wallet.classicAddress,
|
||||
signer_lists: true,
|
||||
})
|
||||
const signerListInfo =
|
||||
accountInfoResponse.result.account_data.signer_lists?.[0]
|
||||
const signerListInfo = accountInfoResponse.result.signer_lists?.[0]
|
||||
assert.deepEqual(
|
||||
signerListInfo?.SignerEntries,
|
||||
tx.SignerEntries,
|
||||
|
||||
@@ -191,8 +191,7 @@ describe('XChainCreateBridge', function () {
|
||||
account: testContext.wallet.classicAddress,
|
||||
signer_lists: true,
|
||||
})
|
||||
const signerListInfo =
|
||||
signerAccountInfoResponse.result.account_data.signer_lists?.[0]
|
||||
const signerListInfo = signerAccountInfoResponse.result.signer_lists?.[0]
|
||||
assert.deepEqual(
|
||||
signerListInfo?.SignerEntries,
|
||||
signerTx.SignerEntries,
|
||||
|
||||
@@ -198,11 +198,12 @@ export async function verifySubmittedTransaction(
|
||||
const decodedTx: any = typeof tx === 'string' ? decode(tx) : tx
|
||||
if (decodedTx.TransactionType === 'Payment') {
|
||||
decodedTx.DeliverMax = decodedTx.Amount
|
||||
delete decodedTx.Amount
|
||||
}
|
||||
|
||||
assert(data.result)
|
||||
assert.deepEqual(
|
||||
omit(data.result, [
|
||||
omit(data.result.tx_json, [
|
||||
'ctid',
|
||||
'date',
|
||||
'hash',
|
||||
|
||||
Reference in New Issue
Block a user