Skip to content
Open
Show file tree
Hide file tree
Changes from 3 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
4 changes: 3 additions & 1 deletion packages/xrpl/src/client/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,9 @@ class Client extends EventEmitter<EventTypes> {
*/
public async request<
R extends Request,
V extends APIVersion = typeof DEFAULT_API_VERSION,
V extends APIVersion = R['api_version'] extends APIVersion
? R['api_version']
: typeof DEFAULT_API_VERSION,
T = RequestResponseMap<R, V>,
>(req: R): Promise<T> {
const request = {
Expand Down
4 changes: 2 additions & 2 deletions packages/xrpl/src/models/methods/baseMethod.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { LedgerIndex } from '../common'
import { APIVersion, LedgerIndex } from '../common'

import type { Request } from '.'

Expand All @@ -13,7 +13,7 @@ export interface BaseRequest {
/** The name of the API method. */
command: string
/** The API version to use. If omitted, use version 1. */
api_version?: number
api_version?: APIVersion
}

export interface LookupByLedgerRequest {
Expand Down
6 changes: 4 additions & 2 deletions packages/xrpl/src/models/methods/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ import {
TransactionEntryRequest,
TransactionEntryResponse,
} from './transactionEntry'
import { TxRequest, TxResponse, TxV1Response, TxVersionResponseMap } from './tx'
import { TxBinaryRequest, TxJsonRequest, TxRequest, TxResponse, TxV1Response, TxVersionResponseMap } from './tx'
import {
UnsubscribeBook,
UnsubscribeRequest,
Expand Down Expand Up @@ -437,7 +437,9 @@ export type RequestResponseMap<
? SubmitMultisignedVersionResponseMap<Version>
: T extends TransactionEntryRequest
? TransactionEntryResponse
: T extends TxRequest
: T extends TxBinaryRequest
? TxVersionResponseMap<Version, true>
: T extends TxJsonRequest
? TxVersionResponseMap<Version>
: T extends BookOffersRequest
? BookOffersResponse
Expand Down
98 changes: 75 additions & 23 deletions packages/xrpl/src/models/methods/tx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { BaseRequest, BaseResponse } from './baseMethod'
*
* @category Requests
*/
export interface TxRequest extends BaseRequest {
interface TxRequestBase extends BaseRequest {
command: 'tx'
/**
* The transaction hash to look up. Exactly one of `transaction` or `ctid` must be specified for a TxRequest.
Expand All @@ -25,12 +25,6 @@ export interface TxRequest extends BaseRequest {
* The Concise Transaction ID to look up. Exactly one of `transaction` or `ctid` must be specified for a TxRequest.
*/
ctid?: string
/**
* If true, return transaction data and metadata as binary serialized to
* hexadecimal strings. If false, return transaction data and metadata as.
* JSON. The default is false.
*/
binary?: boolean
/**
* Use this with max_ledger to specify a range of up to 1000 ledger indexes,
* starting with this ledger (inclusive). If the server cannot find the
Expand All @@ -47,15 +41,39 @@ export interface TxRequest extends BaseRequest {
max_ledger?: number
}

export interface TxRequest extends TxRequestBase {
/**
* If true, return transaction data and metadata as binary serialized to
* hexadecimal strings. If false, return transaction data and metadata as.
* JSON. The default is false.
*/
binary?: boolean
}

export interface TxBinaryRequest extends TxRequestBase {
/**
* If true, return transaction data and metadata as binary serialized to
* hexadecimal strings. If false, return transaction data and metadata as.
* JSON. The default is false.
*/
binary: true
}

export interface TxJsonRequest extends TxRequestBase {
/**
* If true, return transaction data and metadata as binary serialized to
* hexadecimal strings. If false, return transaction data and metadata as.
* JSON. The default is false.
*/
binary?: false
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
Comment thread
coderabbitai[bot] marked this conversation as resolved.

/**
* Common properties of transaction responses.
*
* @category Responses
*/
interface BaseTxResult<
Version extends APIVersion = typeof DEFAULT_API_VERSION,
T extends BaseTransaction = Transaction,
> {
interface BaseTxResult {
/** The SHA-512 hash of the transaction. */
hash: string
/**
Expand All @@ -64,15 +82,6 @@ interface BaseTxResult<
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
/**
* If true, this data comes from a validated ledger version; if omitted or.
* Set to false, this data is not final.
Expand All @@ -88,15 +97,52 @@ interface BaseTxResult<
date?: number
}

interface TxJsonResult<
T extends BaseTransaction = Transaction,
> extends BaseTxResult {
/** Transaction metadata, which describes the results of the transaction.
* Can be undefined if a transaction has not been validated yet. */
meta?: TransactionMetadata<T>
}

type RemoveIndexSignature<T> = T extends unknown
? {
// Drop BaseTransaction's Record<string, unknown> index signature so
// unknown transaction fields are not treated as valid response fields.
[K in keyof T as string extends K
? never
: number extends K
? never
: symbol extends K
? never
: K]: T[K]
}
: never

interface TxBinaryResult extends BaseTxResult {
tx_blob: string
/** Unique hashed string Transaction metadata blob, which describes the results of the transaction.
* Can be undefined if a transaction has not been validated yet. */
meta_blob?: string
}

interface TxBinaryResultV1 extends BaseTxResult {
tx_blob: string
/** Unique hashed string Transaction metadata blob, which describes the results of the transaction.
* Can be undefined if a transaction has not been validated yet. */
meta?: string
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

/**
* Response expected from a {@link TxRequest}.
*
* @category Responses
*/
export interface TxResponse<
T extends BaseTransaction = Transaction,
B extends boolean = false,
> extends BaseResponse {
result: BaseTxResult<typeof RIPPLED_API_V2, T> & { tx_json: T }
result: B extends true ? TxBinaryResult : TxJsonResult<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
Expand All @@ -113,8 +159,11 @@ export interface TxResponse<
*/
export interface TxV1Response<
T extends BaseTransaction = Transaction,
B extends boolean = false,
> extends BaseResponse {
result: BaseTxResult<typeof RIPPLED_API_V1, T> & T
result: B extends true
? TxBinaryResultV1
: TxJsonResult<T> & RemoveIndexSignature<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
Expand All @@ -131,4 +180,7 @@ export interface TxV1Response<
*/
export type TxVersionResponseMap<
Version extends APIVersion = typeof DEFAULT_API_VERSION,
> = Version extends typeof RIPPLED_API_V1 ? TxV1Response : TxResponse
B extends boolean = false,
> = Version extends typeof RIPPLED_API_V1
? TxV1Response<Transaction, B>
: TxResponse<Transaction, B>
43 changes: 40 additions & 3 deletions packages/xrpl/test/integration/requests/tx.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import {
AccountSet,
hashes,
SubmitResponse,
TxRequest,
TxResponse,
TxV1Response,
} from '../../../src'
Expand All @@ -29,7 +28,7 @@ describe('tx', function () {
afterEach(async () => teardownClient(testContext))

it(
'base',
'uses api_version 2 (default)',
async () => {
const account = testContext.wallet.classicAddress
const accountSet: AccountSet = {
Expand All @@ -51,6 +50,11 @@ describe('tx', function () {
transaction: hash,
})

assert.isDefined(txResponse.result.tx_json)
assert.isDefined(txResponse.result.meta)
// @ts-expect-error: meta_blob is only defined for binary responses
assert.isUndefined(txResponse.result.meta_blob)
Comment thread
coderabbitai[bot] marked this conversation as resolved.

const expectedResponse: TxResponse = {
api_version: 2,
id: txResponse.id,
Expand All @@ -71,6 +75,19 @@ describe('tx', function () {
}

assert.deepEqual(txResponse, expectedResponse)

// test with binary response
const txBinaryResponse = await testContext.client.request({
command: 'tx',
transaction: hash,
binary: true,
})
assert.isDefined(txBinaryResponse.result.tx_blob)
assert.isDefined(txBinaryResponse.result.meta_blob)
// @ts-expect-error: tx_json is not defined for binary responses
assert.isUndefined(txBinaryResponse.result.tx_json)
// @ts-expect-error: meta is not defined for binary responses
assert.isUndefined(txBinaryResponse.result.meta)
Comment thread
coderabbitai[bot] marked this conversation as resolved.
},
TIMEOUT,
)
Expand All @@ -93,12 +110,18 @@ describe('tx', function () {
)

const hash = hashSignedTx(response.result.tx_blob)
const txV1Response = await testContext.client.request<TxRequest, 1>({
const txV1Response = await testContext.client.request({
command: 'tx',
transaction: hash,
api_version: 1,
})

assert.isDefined(txV1Response.result.meta)
// @ts-expect-error: tx_json is not defined for api_version 1 responses
assert.isUndefined(txV1Response.result.tx_json)
// @ts-expect-error: meta_blob is only defined for binary responses
assert.isUndefined(txV1Response.result.meta_blob)

const expectedResponse: TxV1Response = {
api_version: 1,
id: txV1Response.id,
Expand All @@ -117,6 +140,20 @@ describe('tx', function () {
}

assert.deepEqual(txV1Response, expectedResponse)

// test with binary response
const txBinaryResponse = await testContext.client.request({
command: 'tx',
transaction: hash,
api_version: 1,
binary: true,
})
assert.isDefined(txBinaryResponse.result.tx_blob)
assert.isDefined(txBinaryResponse.result.meta)
// @ts-expect-error: tx_json is not defined for binary responses
assert.isUndefined(txBinaryResponse.result.tx_json)
// @ts-expect-error: meta_blob is not defined for binary responses V1
assert.isUndefined(txBinaryResponse.result.meta_blob)
},
TIMEOUT,
)
Expand Down
17 changes: 17 additions & 0 deletions packages/xrpl/test/integration/submitAndWait.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,4 +145,21 @@ describe('client.submitAndWait', function () {
},
TIMEOUT,
)

it('returns a TxResponse with the transaction data and metadata', async () => {
const accountSet: AccountSet = {
TransactionType: 'AccountSet',
Account: testContext.wallet.classicAddress,
Domain: convertStringToHex('example.com'),
}
const { tx_blob: signedAccountSet } = testContext.wallet.sign(
await testContext.client.autofill(accountSet),
)
const response = await testContext.client.submitAndWait(signedAccountSet)

assert.isDefined(response.result.tx_json)
assert.isDefined(response.result.meta)
// @ts-expect-error: meta_blob is only defined for binary responses
assert.isUndefined(response.result.meta_blob)
})
Comment thread
coderabbitai[bot] marked this conversation as resolved.
})
Loading