diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 7faedc46bb..c796e43883 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -10,7 +10,7 @@ on: workflow_dispatch: env: - RIPPLED_DOCKER_IMAGE: rippleci/rippled:2.0.0-b3 + RIPPLED_DOCKER_IMAGE: rippleci/rippled:2.0.0-b4 jobs: build-and-lint: diff --git a/packages/xrpl/HISTORY.md b/packages/xrpl/HISTORY.md index 06b3dd618a..56f485090f 100644 --- a/packages/xrpl/HISTORY.md +++ b/packages/xrpl/HISTORY.md @@ -4,6 +4,9 @@ Subscribe to [the **xrpl-announce** mailing list](https://groups.google.com/g/xr ## Unreleased +### Added +* Support for `server_definitions` RPC + ## 2.13.0 (2023-10-18) ### Fixed diff --git a/packages/xrpl/src/client/index.ts b/packages/xrpl/src/client/index.ts index 2d7e4e9c79..09b0332496 100644 --- a/packages/xrpl/src/client/index.ts +++ b/packages/xrpl/src/client/index.ts @@ -98,6 +98,8 @@ import { // AMM methods AMMInfoRequest, AMMInfoResponse, + ServerDefinitionsRequest, + ServerDefinitionsResponse, } from '../models/methods' import { BaseRequest, BaseResponse } from '../models/methods/baseMethod' import { @@ -346,6 +348,9 @@ class Client extends EventEmitter { public async request( r: RipplePathFindRequest, ): Promise + public async request( + r: ServerDefinitionsRequest, + ): Promise public async request(r: ServerInfoRequest): Promise public async request(r: ServerStateRequest): Promise public async request(r: SubmitRequest): Promise diff --git a/packages/xrpl/src/models/methods/index.ts b/packages/xrpl/src/models/methods/index.ts index 530e7e75cf..98c687c636 100644 --- a/packages/xrpl/src/models/methods/index.ts +++ b/packages/xrpl/src/models/methods/index.ts @@ -108,6 +108,10 @@ import { RipplePathFindResponse, SourceCurrencyAmount, } from './ripplePathFind' +import { + ServerDefinitionsRequest, + ServerDefinitionsResponse, +} from './serverDefinitions' import { JobType, ServerInfoRequest, @@ -186,6 +190,7 @@ type Request = // server info methods | FeeRequest | ManifestRequest + | ServerDefinitionsRequest | ServerInfoRequest | ServerStateRequest // utility methods @@ -239,6 +244,7 @@ type Response = // server info methods | FeeResponse | ManifestResponse + | ServerDefinitionsResponse | ServerInfoResponse | ServerStateResponse // utility methods @@ -360,6 +366,8 @@ export { FeeResponse, ManifestRequest, ManifestResponse, + ServerDefinitionsRequest, + ServerDefinitionsResponse, ServerInfoRequest, ServerInfoResponse, ServerStateRequest, diff --git a/packages/xrpl/src/models/methods/nftInfo.ts b/packages/xrpl/src/models/methods/nftInfo.ts index be45be5451..150f068c27 100644 --- a/packages/xrpl/src/models/methods/nftInfo.ts +++ b/packages/xrpl/src/models/methods/nftInfo.ts @@ -16,7 +16,7 @@ export interface NFTInfoRequest extends BaseRequest, LookupByLedgerRequest { } /** - * Response expected from an {@link NFTInfoResponse}. + * Response expected from an {@link NFTInfoRequest}. * * @category Responses */ diff --git a/packages/xrpl/src/models/methods/serverDefinitions.ts b/packages/xrpl/src/models/methods/serverDefinitions.ts new file mode 100644 index 0000000000..9f786bef93 --- /dev/null +++ b/packages/xrpl/src/models/methods/serverDefinitions.ts @@ -0,0 +1,61 @@ +import { BaseRequest, BaseResponse } from './baseMethod' + +/** + * The `server_definitions` method retrieves information about the definition + * enums available in this rippled node. Expects a response in the form of a + * {@link ServerDefinitionsResponse}. + * + * @category Requests + */ +export interface ServerDefinitionsRequest extends BaseRequest { + command: 'server_definitions' + /** + * The hash of a `server_definitions` response. + */ + hash?: string +} + +/** + * Response expected from an {@link ServerDefinitionsRequest}. + * + * @category Responses + */ +export interface ServerDefinitionsResponse extends BaseResponse { + result: { + hash: string + } & ( + | { + FIELDS: Array< + [ + string, + { + nth: number + isVLEncoded: boolean + isSerialized: boolean + isSigningField: boolean + type: string + }, + ] + > + + LEDGER_ENTRY_TYPES: Record + + TRANSACTION_RESULTS: Record + + TRANSACTION_TYPES: Record + + TYPES: Record + } + | { + FIELDS?: never + + LEDGER_ENTRY_TYPES?: never + + TRANSACTION_RESULTS?: never + + TRANSACTION_TYPES?: never + + TYPES?: never + } + ) +} diff --git a/packages/xrpl/src/models/methods/subscribe.ts b/packages/xrpl/src/models/methods/subscribe.ts index 2fcc66557f..6a203fd61b 100644 --- a/packages/xrpl/src/models/methods/subscribe.ts +++ b/packages/xrpl/src/models/methods/subscribe.ts @@ -38,7 +38,7 @@ export interface SubscribeBook { /** * The subscribe method requests periodic notifications from the server when - * certain events happen. Expects a response in the form of a. + * certain events happen. Expects a response in the form of a * {@link SubscribeResponse}. * * @category Requests diff --git a/packages/xrpl/test/integration/requests/serverDefinitions.test.ts b/packages/xrpl/test/integration/requests/serverDefinitions.test.ts new file mode 100644 index 0000000000..fb5afc1826 --- /dev/null +++ b/packages/xrpl/test/integration/requests/serverDefinitions.test.ts @@ -0,0 +1,118 @@ +import { assert } from 'chai' + +import { type ServerDefinitionsRequest } from '../../../src' +import serverUrl from '../serverUrl' +import { + setupClient, + teardownClient, + type XrplIntegrationTestContext, +} from '../setup' + +// how long before each test case times out +const TIMEOUT = 20000 + +describe('server_definitions', function () { + let testContext: XrplIntegrationTestContext + + beforeEach(async () => { + testContext = await setupClient(serverUrl) + }) + afterEach(async () => teardownClient(testContext)) + + it( + 'base', + async () => { + const request: ServerDefinitionsRequest = { + command: 'server_definitions', + } + const response = await testContext.client.request(request) + assert.equal(response.type, 'response') + assert.exists(response.result) + + const result = response.result + assert.hasAllKeys(result, [ + 'hash', + 'FIELDS', + 'LEDGER_ENTRY_TYPES', + 'TRANSACTION_RESULTS', + 'TRANSACTION_TYPES', + 'TYPES', + ]) + + assert.typeOf(result.hash, 'string') + + assert.typeOf(result.FIELDS, 'array') + for (const field of result.FIELDS!) { + assert.typeOf(field[0], 'string') + assert.hasAllKeys(field[1], [ + 'nth', + 'isVLEncoded', + 'isSerialized', + 'isSigningField', + 'type', + ]) + assert.typeOf(field[1].nth, 'number') + assert.typeOf(field[1].isVLEncoded, 'boolean') + assert.typeOf(field[1].isSerialized, 'boolean') + assert.typeOf(field[1].isSigningField, 'boolean') + assert.typeOf(field[1].type, 'string') + } + + assert.typeOf(result.LEDGER_ENTRY_TYPES, 'object') + Object.entries(result.LEDGER_ENTRY_TYPES!).forEach(([key, value]) => { + assert.typeOf(key, 'string') + assert.typeOf(value, 'number') + }) + + assert.typeOf(result.TRANSACTION_RESULTS, 'object') + Object.entries(result.TRANSACTION_RESULTS!).forEach(([key, value]) => { + assert.typeOf(key, 'string') + assert.typeOf(value, 'number') + }) + + assert.typeOf(result.TRANSACTION_TYPES, 'object') + Object.entries(result.TRANSACTION_TYPES!).forEach(([key, value]) => { + assert.typeOf(key, 'string') + assert.typeOf(value, 'number') + }) + + assert.typeOf(result.TYPES, 'object') + Object.entries(result.TYPES!).forEach(([key, value]) => { + assert.typeOf(key, 'string') + assert.typeOf(value, 'number') + }) + }, + TIMEOUT, + ) + + it( + 'with same hash', + async () => { + const initialRequest: ServerDefinitionsRequest = { + command: 'server_definitions', + } + const hash = (await testContext.client.request(initialRequest)).result + .hash + + const request: ServerDefinitionsRequest = { + command: 'server_definitions', + hash, + } + const response = await testContext.client.request(request) + assert.equal(response.type, 'response') + assert.exists(response.result) + + const result = response.result + assert.doesNotHaveAnyKeys(result, [ + 'FIELDS', + 'LEDGER_ENTRY_TYPES', + 'TRANSACTION_RESULTS', + 'TRANSACTION_TYPES', + 'TYPES', + ]) + + assert.equal(result.hash, hash) + }, + TIMEOUT, + ) +}) diff --git a/packages/xrpl/test/integration/utils.ts b/packages/xrpl/test/integration/utils.ts index 9183eb1333..4e3849ba5b 100644 --- a/packages/xrpl/test/integration/utils.ts +++ b/packages/xrpl/test/integration/utils.ts @@ -183,6 +183,11 @@ export async function verifySubmittedTransaction( command: 'tx', transaction: hash, }) + // eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO: handle this API change for 2.0.0 + const decodedTx: any = typeof tx === 'string' ? decode(tx) : tx + if (decodedTx.TransactionType === 'Payment') { + decodedTx.DeliverMax = decodedTx.Amount + } assert(data.result) assert.deepEqual( @@ -195,7 +200,7 @@ export async function verifySubmittedTransaction( 'validated', 'ctid', ]), - typeof tx === 'string' ? decode(tx) : tx, + decodedTx, ) if (typeof data.result.meta === 'object') { assert.strictEqual(data.result.meta.TransactionResult, 'tesSUCCESS')