feat: add feature RPC (#2719)

* add feature RPC

* export, add tests

* update history

* fix test

* update models

* update feature models to correctly handle both cases

* fix models/tests

* fix test, improve type

* undo type change

* fix test
This commit is contained in:
Mayukha Vadari
2024-07-10 13:18:16 -04:00
committed by GitHub
parent 3858a09e1f
commit 00f1a6bcdd
4 changed files with 153 additions and 0 deletions

View File

@@ -11,6 +11,7 @@ Subscribe to [the **xrpl-announce** mailing list](https://groups.google.com/g/xr
### Added ### Added
* Add `nfts_by_issuer` clio-only API definition * Add `nfts_by_issuer` clio-only API definition
* Support for the `fixPreviousTxnID` amendment. * Support for the `fixPreviousTxnID` amendment.
* Support for the user version of the `feature` RPC.
## 3.1.0 (2024-06-03) ## 3.1.0 (2024-06-03)

View File

@@ -0,0 +1,68 @@
import { BaseRequest, BaseResponse } from './baseMethod'
export interface FeatureAllRequest extends BaseRequest {
command: 'feature'
feature?: never
}
export interface FeatureOneRequest extends BaseRequest {
command: 'feature'
feature: string
}
/**
* The `feature` command returns information about amendments this server knows about, including whether they are enabled.
* Returns an {@link FeatureResponse}.
*
* @category Requests
*/
export type FeatureRequest = FeatureAllRequest | FeatureOneRequest
export interface FeatureAllResponse extends BaseResponse {
result: {
features: Record<
string,
{
/*
* Whether this amendment is currently enabled in the latest ledger.
*/
enabled: boolean
/*
* The human-readable name for this amendment, if known.
*/
name: string
supported: boolean
}
>
}
}
export interface FeatureOneResponse extends BaseResponse {
result: Record<
string,
{
/*
* Whether this amendment is currently enabled in the latest ledger.
*/
enabled: boolean
/*
* The human-readable name for this amendment, if known.
*/
name: string
supported: boolean
}
>
}
/**
* Response expected from an {@link FeatureRequest}.
*
* @category Responses
*/
export type FeatureResponse = FeatureAllResponse | FeatureOneResponse

View File

@@ -66,6 +66,14 @@ import {
DepositAuthorizedRequest, DepositAuthorizedRequest,
DepositAuthorizedResponse, DepositAuthorizedResponse,
} from './depositAuthorized' } from './depositAuthorized'
import {
FeatureAllRequest,
FeatureAllResponse,
FeatureOneRequest,
FeatureOneResponse,
FeatureRequest,
FeatureResponse,
} from './feature'
import { FeeRequest, FeeResponse } from './fee' import { FeeRequest, FeeResponse } from './fee'
import { import {
GatewayBalance, GatewayBalance,
@@ -214,6 +222,7 @@ type Request =
| ServerDefinitionsRequest | ServerDefinitionsRequest
| ServerInfoRequest | ServerInfoRequest
| ServerStateRequest | ServerStateRequest
| FeatureRequest
// utility methods // utility methods
| PingRequest | PingRequest
| RandomRequest | RandomRequest
@@ -271,6 +280,7 @@ type Response<Version extends APIVersion = typeof DEFAULT_API_VERSION> =
| ServerDefinitionsResponse | ServerDefinitionsResponse
| ServerInfoResponse | ServerInfoResponse
| ServerStateResponse | ServerStateResponse
| FeatureResponse
// utility methods // utility methods
| PingResponse | PingResponse
| RandomResponse | RandomResponse
@@ -419,6 +429,10 @@ export type RequestResponseMap<
? ServerStateResponse ? ServerStateResponse
: T extends ServerDefinitionsRequest : T extends ServerDefinitionsRequest
? ServerDefinitionsResponse ? ServerDefinitionsResponse
: T extends FeatureAllRequest
? FeatureAllResponse
: T extends FeatureOneRequest
? FeatureOneResponse
: T extends PingRequest : T extends PingRequest
? PingResponse ? PingResponse
: T extends RandomRequest : T extends RandomRequest
@@ -591,6 +605,8 @@ export {
ServerState, ServerState,
StateAccountingFinal, StateAccountingFinal,
StateAccounting, StateAccounting,
FeatureRequest,
FeatureResponse,
// utility methods // utility methods
PingRequest, PingRequest,
PingResponse, PingResponse,

View File

@@ -0,0 +1,68 @@
import { assert } from 'chai'
import { FeatureRequest } from '../../../src'
import serverUrl from '../serverUrl'
import {
setupClient,
teardownClient,
type XrplIntegrationTestContext,
} from '../setup'
// how long before each test case times out
const TIMEOUT = 20000
const AMENDMENT =
'8CC0774A3BF66D1D22E76BBDA8E8A232E6B6313834301B3B23E8601196AE6455'
describe('feature', function () {
let testContext: XrplIntegrationTestContext
beforeEach(async () => {
testContext = await setupClient(serverUrl)
})
afterEach(async () => teardownClient(testContext))
it(
'all',
async () => {
const featureRequest: FeatureRequest = {
command: 'feature',
}
const featureResponse = await testContext.client.request(featureRequest)
assert.equal(featureResponse.type, 'response')
assert.typeOf(featureResponse.result.features, 'object')
assert.isTrue(AMENDMENT in featureResponse.result.features)
const amendmentData = featureResponse.result.features[AMENDMENT]
assert.equal(amendmentData.name, 'AMM')
// TODO: rippled says "false" for standalone nodes for some reason
assert.typeOf(amendmentData.enabled, 'boolean')
assert.equal(amendmentData.supported, true)
},
TIMEOUT,
)
it(
'one',
async () => {
const featureRequest: FeatureRequest = {
command: 'feature',
feature: AMENDMENT,
}
const featureResponse = await testContext.client.request(featureRequest)
assert.equal(featureResponse.type, 'response')
assert.typeOf(featureResponse.result, 'object')
assert.isTrue(AMENDMENT in featureResponse.result)
assert.lengthOf(Object.keys(featureResponse.result), 1)
const amendmentData = featureResponse.result[AMENDMENT]
assert.equal(amendmentData.name, 'AMM')
// TODO: rippled says "false" for standalone nodes for some reason
assert.typeOf(amendmentData.enabled, 'boolean')
assert.equal(amendmentData.supported, true)
},
TIMEOUT,
)
})