For these instructions:
- There's a decent amount of boilerplate code, so each step will include a template you should copy along with a list of which fields need updating.
...
in the template indicates you should edit something (Ex. Replacing...Request
withAccountChannelsRequest
)- If this is for a request documented on xrpl.org, please copy and paste the documentation from there.
- Read through
shared/base.yaml
after doing a draft of your spec to see if there are any re-usable components that make sense for your requests/responses
Run the following command to generate boilerplate code for a new request where you can edit based on the steps in the latter sections:
npm run template <request_name>
For the above command, <request_name>
should be the name of the new request in snake_case convention (e.g. account_channels). This would create 3 different files:
shared/requests/<request_name.yaml>
(instructions to edit here).open_api/requests/<request_name.yaml>
(instructions to edit here).async_api/requests/<request_name.yaml>
(instructions to edit here).
-
If you've already created a spec in the shared folder for this request, skip to the OpenAPI specific steps!
-
Some of the steps mentioned here could be automatically generated by this instruction. If you've already done so, only fill in the details that are missing.
-
Create a new file for the rippled request / response information in
shared/requests/<request_name.yaml>
- For example:
shared/requests/account_channels.yaml
- For example:
-
In that shared file, add the
Request
type....
indicates you should edit something (Ex. Replacing...Request
withAccountChannelsRequest
)- If this is for a request documented on xrpl.org, please copy and paste the documentation from there.
- Read through
shared/base.yaml
to see if there are any re-usable components that make sense for your request
- Fields to update:
...Request
with the name of the request (ex.AccountChannelsRequest
)description:
with a description of this request- If there are any common fields in
shared/base.yaml
that can be re-used, do so withallOf
- otherwise delete that TODO comment. properties
with the parameters for this request (in alphabetical order)required
with a list of any required parameters (in alphabetical order)
...Request: description: > ... type: object # TODO: Add any common fields from `shared/base.yaml` that are applicable using `allOf`. Otherwise delete these comments! For example: # allOf: # - $ref: '../base.yaml#/components/schemas/LookupByLedgerRequest' # - ... properties: # Example property # account: # type: string # description: The unique identifier of an account, typically the account's address. ... required: - ...
-
Create the
...SuccessResponse
schema for whenrippled
responds withsuccess
.- Fields to update:
...SuccessResponse
with the name of the request (ex.AccountChannelsSuccessResponse
)- If there are any common fields in
shared/base.yaml
that can be re-used, do so withallOf
- otherwise delete that TODO comment. properties
with the parameters for this request (in alphabetical order)required
with a list of any required parameters (in alphabetical order)
...SuccessResponse: # TODO: Add any common fields from `shared/base.yaml` that are applicable using `allOf`. Otherwise delete these comments! For example: # allOf: # - $ref: '../base.yaml#/components/schemas/LookupByLedgerRequest' # - ... type: object properties: # Example property # account: # type: string # description: The unique identifier of an account, typically the account's address. ... required: - ...
- Fields to update:
-
Create the
...ErrorResponse
schema for whenrippled
responds with an error code.- Fields to update:
...ErrorResponse
with the name of the request (ex.AccountChannelsErrorResponse
)enum:
with a yaml list of the specific error codes that are associated with this specific response (ex. invalidParams). Do not include errors which are already in theUniversalErrorResponseCodes
listed inshared/base.yaml
.request
should have a reference to the shared...Request
. (NOT the...Request
object that is in this file!)
...ErrorResponse: type: object properties: error: type: string oneOf: - $ref: '../base.yaml#/components/schemas/UniversalErrorResponseCodes' # Add the error codes specific to this response here (ex. invalidParams) - enum: - ... # Include a bullet descrip for every description: > ... status: type: string enum: - error request: # This should link to the ...Request type you defined above $ref: ... required: - status - error - request
- Fields to update:
-
If you want to add a request to the OpenAPI spec, follow these steps here (otherwise skip this step)
-
If you want to add a request to the AsyncAPI spec, follow these steps here (otherwise skip this step)
This section assumes you've already completed the shared work steps for this request in How to add a new request
At a high level, we're going to wrap the core types we defined in shared/
in boilerplate so it matches the JSON RPC formatting rippled
expects / produces, then we're going to reference our wrapped types in the core json_api.yaml
file.
Some of the steps mentioned here could be automatically generated by this instruction. If you've already done so, only fill in the details that are missing.
-
Create a new file in
open_api/requests
named..._open_api.yaml
for your new request. Ex.account_channels_open_api.yaml
- The reason to include
_open_api
in the name is to make it easier to tell which file we're referencing throughout the codebase, and to make filename searches less confusing when debugging. Including it at the end also makes it easier to at a glance find the right file in the explorer. - Example file: open_api/requests/account_channels_open_api.yaml
- The reason to include
-
Add a
...Request
schema with the following boilerplate and an example which references the...Request
we defined inshared/requests
. See template below:- Fields to update:
...Request
with the name of the request (Ex.AccountChannelRequest
)description
with a long explanation of what the request is (use xrpl.org text if available)method
with the request name (ex.account_channels
)items
's$ref:
to reference the...Request
we defined inshared/requests
example
with a valid request of this type that includes most if as many optional fields as possible while still being valid
...Request: type: object description: > ... properties: method: type: string enum: # This is the most supported way to define a specific string as the only valid input. `const` is a new keyword which is supported in OpenAPI, but not in all corresponding codegen tools. https://github.com/OAI/OpenAPI-Specification/issues/1313 - ... params: type: array items: $ref: # Reference the shared `...Request` schema required: - method example: # Provide a valid example here, such as: # method: 'account_channels' # params: # - account: 'rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn' # destination_account: 'ra5nK24KXen9AHvsdFTKHSANinZseWnPcX' # ledger_index": 'validated'
- Fields to update:
-
Add the
...Response
object which is mostly boilerplate, but still has a couple fields to update:- Fields to update:
...Response
with the name of the request (Ex.AccountChannelResponse
)- In the
mapping
: 3. Mapsuccess
to a reference to the...SuccessResponse
in this file (NOT the shared file!) 4. Maperror
to the the...ErrorResponse
in the SHARED file - In the oneOf, add BOTH of the above references in a list.
example
with a valid successful response of this type, ideally the exact response to sending the example in...Request
in this file.
...Response: type: object properties: result: type: object discriminator: propertyName: status mapping: success: # Include a reference to ...SuccessResponse from this file error: # Include a reference to the **shared** ...ErrorResponse oneOf: - $ref: # Include a reference to ...SuccessResponse from this file - $ref: # Include a reference to the **shared** ...ErrorResponse required: - result example: # result: # account: rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn # channels: # - account: rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn # amount: '1000' # balance: '0' # channel_id: C7F634794B79DB40E87179A9D1BF05D05797AE7E92DF8E93FD6656E8C4BE3AE7 # destination_account: ra5nK24KXen9AHvsdFTKHSANinZseWnPcX # public_key: aBR7mdD75Ycs8DRhMgQ4EMUEmBArF8SEh1hfjrT2V9DQTLNbJVqw # public_key_hex: 03CFD18E689434F032A4E84C63E2A3A6472D684EAF4FD52CA67742F3E24BAE81B2 # settle_delay: 60 # ledger_hash: 27F530E5C93ED5C13994812787C1ED073C822BAEC7597964608F2C049C2ACD2D # ledger_index: 71766343 # status: success # validated: true ...
- Fields to update:
-
Create the
...SuccessResponse
schema to combine theBaseSuccessResponse
and the shared success schema. (This is done to match the JSON RPC response format while re-using our shared schema)- Fields to update:
...SuccessResponse
- Update the 2nd reference in
allOf
to the SHARED...SuccessResponse
(NOT the one in this file!)
...SuccessResponse: type: object allOf: - $ref: '../../shared/base.yaml#/components/schemas/BaseSuccessResponse' - $ref: # Reference the `...SuccessResponse` in the **SHARED** folder
- Fields to update:
-
Lastly, we need to update the
open_api/json_api.yaml
file:- Fields to update:
-
Update
#paths///post/requestBody/content/application/json/schema/discriminator/mapping
with a mapping between the request name and your...Request
object from the..._open_api.yaml
file (NOT the shared file!)- Ex.
account_channels: 'requests/account_channels_open_api.yaml#/components/schemas/AccountChannelsRequest'
- Ex.
-
Update the
oneOf
just below themapping
you modified with another reference to the...Request
object from the..._open_api.yaml
file- Ex.
- $ref: 'requests/account_channels_open_api.yaml#/components/schemas/AccountChannelsRequest'
- Ex.
-
Update
#paths///post/responses/200/content/application/json/schema/oneOf
with a reference to the...Response
(NOT...Request
) object from the..._open_api.yaml
file.- Ex.
- $ref: 'requests/account_channels_open_api.yaml#/components/schemas/AccountChannelsResponse'
- Ex.
Note: If you want to also add this request to the AsyncAPI, continue by following these steps here
This section assumes you've already completed the shared work steps for this request in How to add a new request
At a high level, we're going to wrap the core types we defined in shared/
in boilerplate so it matches the Websocket formatting rippled
expects / produces, then we're going to reference our wrapped types in the core websocket_api.yaml
file.
Some of the steps mentioned here could be automatically generated by this instruction. If you've already done so, only fill in the details that are missing.
-
Create a new file in
async_api/requests
named..._async_api.yaml
for your new request. Ex.account_channels_async_api.yaml
- The reason to include
_async_api
in the name is to make it easier to tell which file we're referencing throughout the codebase, and to make filename searches less confusing when debugging. Including it at the end also makes it easier to at a glance find the right file in the explorer. - Example file: async_api/requests/account_channels_async_api.yaml
- The reason to include
-
Add a
...Request
schema with the following boilerplate and an example which references the...Request
we defined inshared/requests
. See template below:- Fields to update:
...Request
with the name of the request (Ex.AccountChannelRequest
)description
with a long explanation of what the request is (use xrpl.org text if available)allOf
's-$ref:
to reference the...Request
we defined inshared/requests
command
with the request name (ex.account_channels
)example
with a valid request of this type that includes most if as many optional fields as possible while still being valid
...Request: description: > ... type: object allOf: - $ref: ... # Reference the Request in `shared/requests` here properties: command: type: string enum: # This is the most supported way to define a specific string as the only valid input. `const` is a new keyword which is supported in OpenAPI, but not in all corresponding codegen tools. https://github.com/OAI/OpenAPI-Specification/issues/1313 - ... id: # Not specifying a type is how we express "any" value is acceptable description: 'A unique identifier for the request.' required: - command - id example: # Show a valid request that follows the schema here, for example for account_channels: # id: 1 # command: account_channels # account: rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn # destination_account: ra5nK24KXen9AHvsdFTKHSANinZseWnPcX # ledger_index: validated ...
- Fields to update:
-
Add the
...Response
object which is mostly boilerplate, but still has a couple fields to update:- Fields to update:
...Response
with the name of the request (Ex.AccountChannelResponse
)- In the oneOf, the first entry should reference the
...SuccessResponse
in this file (NOT the shared file!) - In the oneOf, the second entry should reference the
...ErrorResponse
in this file (NOT the shared file!) example
with a valid successful response of this type, ideally the exact response to sending the example in...Request
in this file.
...Response: discriminator: status oneOf: - $ref: # Reference the ...SuccessResponse in this file - $ref: # Reference the ...ErrorResponse in this file type: object properties: id: # Not specifying a type is how we express "any" value is acceptable description: 'A unique identifier for the request.' type: type: string description: The value response indicates a direct response to an API request. Asynchronous notifications use a different value such as `ledgerClosed` or `transaction`. enum: # This is the most supported way to define a specific string as the only valid input. `const` is a new keyword which is supported in OpenAPI, but not in all corresponding codegen tools. https://github.com/OAI/OpenAPI-Specification/issues/1313 - response required: - id - type example: # Example formatting for `account_channels` response # id: 1 # result: # account: rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn # channels: # - account: rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn # amount: '1000' # balance: '0' # channel_id: C7F634794B79DB40E87179A9D1BF05D05797AE7E92DF8E93FD6656E8C4BE3AE7 # destination_account: ra5nK24KXen9AHvsdFTKHSANinZseWnPcX # public_key: aBR7mdD75Ycs8DRhMgQ4EMUEmBArF8SEh1hfjrT2V9DQTLNbJVqw # public_key_hex: 03CFD18E689434F032A4E84C63E2A3A6472D684EAF4FD52CA67742F3E24BAE81B2 # settle_delay: 60 # ledger_hash: 27F530E5C93ED5C13994812787C1ED073C822BAEC7597964608F2C049C2ACD2D # ledger_index: 71766343 # validated: true # status: success # type: response ...
- Fields to update:
-
Create the
...SuccessResponse
schema to combine theBaseSuccessResponse
and the shared success schema. (This is done to match the JSON RPC response format while re-using our shared schema)- Fields to update:
...SuccessResponse
- Update the 2nd reference in
allOf
to the SHARED...SuccessResponse
(NOT the one in this file!)
AccountChannelsSuccessResponse: type: object allOf: - $ref: '../../shared/base.yaml#/components/schemas/BaseSuccessResponse' - $ref: # Reference the `...SuccessResponse` in the **SHARED** folder
- Fields to update:
-
Lastly, we're going to update the
websocket_api.yaml
file to reference our newly createdWebsocket
wrapper of ourrippled
request / response types.-
In
subscribe
add a newmessage
object for your new request which references the...Request
we made in the..._async_api.yaml
(NOT the shared version!)- Fields to update:
name
with the name of your request +Request
(Ex.AccountChannelsRequest
)$ref
with a reference to the...Request
object in the..._async_api.yaml
file (NOT the shared version!)- Ex.
'./requests/account_channels_async_api.yaml#/components/schemas/AccountChannelsRequest'
- Ex.
message: name: '...Request' payload: $ref: ...
- Fields to update:
-
Do the same in the
publish
section except forResponse
instead ofRequest
- Fields to update:
name
->...Response
$ref
should point to the...Response
(not...Request
) schema from the..._async_api.yaml
file (NOT the shared version!)
- Fields to update:
-
Note: If you want to also add this request to the OpenAPI spec and haven't already, continue by following these steps here