mirror of
https://github.com/Xahau/xahau.js.git
synced 2025-12-06 17:27:59 +00:00
Compare commits
57 Commits
@xrplf/sec
...
xrpl@4.0.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
275c95752b | ||
|
|
3bc3c2029b | ||
|
|
c9ef96e0a2 | ||
|
|
00f1a6bcdd | ||
|
|
3858a09e1f | ||
|
|
3aaf526107 | ||
|
|
1460cf5026 | ||
|
|
7e733c4446 | ||
|
|
735ac2eb07 | ||
|
|
c79a5db8f2 | ||
|
|
8e2aba3b78 | ||
|
|
39fed49654 | ||
|
|
a0678857a1 | ||
|
|
38e2091fd2 | ||
|
|
a528d6632a | ||
|
|
ab081e7db9 | ||
|
|
493c56c0fa | ||
|
|
c73b2c5a86 | ||
|
|
02e2b0e48e | ||
|
|
d3b03a536d | ||
|
|
036f1f9850 | ||
|
|
92849e57ce | ||
|
|
32f0d7b121 | ||
|
|
b27bbb49b3 | ||
|
|
23adb4924b | ||
|
|
9b3bb9c14b | ||
|
|
d441361999 | ||
|
|
fb94f2a020 | ||
|
|
7b56a49dae | ||
|
|
212686baae | ||
|
|
4d6fef597c | ||
|
|
8b596a6687 | ||
|
|
8afc9ad506 | ||
|
|
3b08d7d379 | ||
|
|
616ad4af60 | ||
|
|
dbdb35abb5 | ||
|
|
445a05e6ef | ||
|
|
ccad092fc2 | ||
|
|
faa23b430e | ||
|
|
923e5d16ac | ||
|
|
602ac481d7 | ||
|
|
b322396a99 | ||
|
|
b9af7bdb6c | ||
|
|
bdb3ad7f3e | ||
|
|
1fdbf85d47 | ||
|
|
3e3911464f | ||
|
|
be732a4a6b | ||
|
|
e505843dc6 | ||
|
|
ff9489ba10 | ||
|
|
365763d6f7 | ||
|
|
9349a6ba1a | ||
|
|
34f35a5912 | ||
|
|
05f16068ff | ||
|
|
ddda7f4552 | ||
|
|
38406212c3 | ||
|
|
62a0d39ac3 | ||
|
|
0e6ab4e4ee |
@@ -170,3 +170,11 @@ fixNFTokenRemint
|
||||
# 2.0.0 Amendments
|
||||
XChainBridge
|
||||
DID
|
||||
# 2.2.0-b3 Amendments
|
||||
fixNFTokenReserve
|
||||
fixInnerObjTemplate
|
||||
fixAMMOverflowOffer
|
||||
PriceOracle
|
||||
fixEmptyDID
|
||||
fixXChainRewardRounding
|
||||
fixPreviousTxnID
|
||||
|
||||
12
.github/workflows/nodejs.yml
vendored
12
.github/workflows/nodejs.yml
vendored
@@ -4,7 +4,7 @@
|
||||
name: Node.js CI
|
||||
|
||||
env:
|
||||
RIPPLED_DOCKER_IMAGE: rippleci/rippled:2.0.0-b4
|
||||
RIPPLED_DOCKER_IMAGE: rippleci/rippled:2.2.0-b3
|
||||
|
||||
on:
|
||||
push:
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [16.x]
|
||||
node-version: [18.x]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
@@ -60,7 +60,7 @@ jobs:
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [16.x, 18.x, 20.x]
|
||||
node-version: [18.x, 20.x]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
@@ -101,7 +101,7 @@ jobs:
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [16.x, 18.x, 20.x]
|
||||
node-version: [18.x, 20.x]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
@@ -153,7 +153,7 @@ jobs:
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [16.x]
|
||||
node-version: [18.x]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
@@ -205,7 +205,7 @@ jobs:
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [16.x, 18.x, 20.x]
|
||||
node-version: [18.x, 20.x]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
@@ -39,7 +39,7 @@
|
||||
"enable": true
|
||||
},
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": true
|
||||
"source.fixAll.eslint": "explicit"
|
||||
},
|
||||
"files.insertFinalNewline": true,
|
||||
"files.trimFinalNewlines": true,
|
||||
|
||||
@@ -58,6 +58,10 @@ Warning: Use at your own risk.
|
||||
|
||||
XRP Ledger explorer, API, metrics, and analytics using a graph database that is synchronized live with the XRPL.
|
||||
|
||||
- **[XRPLWin](https://xrplwin.com)**
|
||||
|
||||
XRP Ledger and Xahau explorer, Hooks explorer, metrics, and analytics using a XWA backend that is synchronized live with the XRPL and Xahau.
|
||||
|
||||
## Data monitoring
|
||||
|
||||
- **[zerptracker](https://zerptracker.com)**
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
### Requirements
|
||||
|
||||
We use Node v16 for development - that is the version that our linters require.
|
||||
We use Node v18 for development - that is the version that our linters require.
|
||||
You must also use `npm` v7. You can check your `npm` version with:
|
||||
|
||||
```bash
|
||||
@@ -90,7 +90,7 @@ This should be run from the `xrpl.js` top level folder (one above the `packages`
|
||||
```bash
|
||||
npm run build
|
||||
# sets up the rippled standalone Docker container - you can skip this step if you already have it set up
|
||||
docker run -p 6006:6006 --interactive -t --volume $PWD/.ci-config:/opt/ripple/etc/ --platform linux/amd64 rippleci/rippled:2.0.0-b3 /opt/ripple/bin/rippled -a --conf /opt/ripple/etc/rippled.cfg
|
||||
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
|
||||
npm run test:browser
|
||||
```
|
||||
|
||||
@@ -104,6 +104,8 @@ The 4 packages currently here are:
|
||||
2. ripple-binary-codec - A library for serializing and deserializing transactions for the ledger.
|
||||
3. ripple-keypairs - A library for generating and using cryptographic keypairs.
|
||||
4. ripple-address-codec - A library for encoding and decoding XRP Ledger addresses and seeds.
|
||||
5. isomorphic - A collection of isomorphic implementations of crypto and utility functions.
|
||||
6. secret-numbers - Generate XRPL Accounts with a number-based secret: 8 chunks of 6 digits.
|
||||
|
||||
Each package has it's own README which dives deeper into what it's main purpose is, and the core functionality it offers.
|
||||
They also run tests independently as they were originally in separate repositories.
|
||||
|
||||
33
MIGRATION.md
33
MIGRATION.md
@@ -2,12 +2,15 @@
|
||||
|
||||
In xrpl.js 3.0, we've made significant improvements that result in a 60% reduction in bundle size for browser applications. We've also eliminated the need for polyfills with minimal disruption to existing code. This was achieved by replacing node-specific dependencies with ones that are compatible with browsers.
|
||||
|
||||
The main change you'll notice is the update replacing `Buffer` with `Uint8Array` across the board. This was done since browsers don't support `Buffer`. Fortunately, this transition is relatively straightforward, as `Buffer` is a subclass of `Uint8Array`, meaning in many circumstances `Buffer` can be directly replaced by `Uint8Array`. The primary difference is that `Buffer` has additional helper functions. We've listed the affected client library functions below in the `Uint8Array` section for your reference.
|
||||
The two main changes you'll notice are:
|
||||
* A breaking change to `Wallet` object creation, to use a more performant algorithm by default. See [here](#8-wallet-functions-default-to-ed25519-instead-of-secp256k1-signing-algorithm) for details.
|
||||
* Replacing `Buffer` with `Uint8Array` across the board. This was done since browsers don't support `Buffer`. Fortunately, this transition is relatively straightforward, as `Buffer` is a subclass of `Uint8Array`, meaning in many circumstances `Buffer` can be directly replaced by `Uint8Array`. The primary difference is that `Buffer` has additional helper functions. We've listed the affected client library functions below in the `Uint8Array` section for your reference.
|
||||
|
||||
This migration guide also applies to:
|
||||
`ripple-address-codec` 4.3.1 -> 5.0.0
|
||||
`ripple-binary-codec` 1.11.0 -> 2.0.0
|
||||
`ripple-keypairs` 1.3.1 -> 2.0.0
|
||||
- `ripple-address-codec` 4.3.1 -> 5.0.0
|
||||
- `ripple-binary-codec` 1.11.0 -> 2.0.0
|
||||
- `ripple-keypairs` 1.3.1 -> 2.0.0
|
||||
- `xrpl-secret-numbers` 0.3.4 -> `@xrplf/secret-numbers` 1.0.0
|
||||
|
||||
# Why update to 3.0?
|
||||
|
||||
@@ -229,9 +232,27 @@ This was done to remove a hard dependency on `https-proxy-agent` when running
|
||||
authorization: 'authorization'
|
||||
}`
|
||||
|
||||
### 8. Bug fix: Setting an explicit `algorithm` when generating a wallet works now
|
||||
### 8. `Wallet` functions default to `ed25519` instead of `secp256k1` signing algorithm
|
||||
|
||||
`Wallet.generate()` and `Wallet.fromSeed` were ignoring the `algorithm` parameter. This means that if you were manually specifying `algorithm` in any `Wallet` constructors, you may generate a different `Wallet` keypair when upgrading to 3.0. In that case to get the same generated wallets as before, don’t specify the `algorithm` parameter.
|
||||
In previous releases of this library, `Wallet.generate()` and `Wallet.fromSeed` were ignoring the `algorithm` parameter. Instead, the algorithm was assumed from the seed provided; if it started with `sEd`, it would use `ed25519`, and otherwise it would use `secp256k1`. However, seeds do not actually have algorithms; a seed starting with `s...` can still use the `ed25519` algorithm.
|
||||
|
||||
With 3.0, we updated the default signing algorithm used by the `Wallet` object to always be `ed25519` in order to default to the higher-performance algorithm. This is a breaking change to all functions used to generate a Wallet, so if you have a pre-existing XRPL account that you're using to generate a specific Wallet using older versions of xrpl.js, you may need to specify that you are using `secp256k1` as the algorithm to decode your private key / seed / etc to get the same behavior as before. See below for specifically how to update your code.
|
||||
|
||||
If you are creating new accounts each time (ex. via `Client.fundWallet` or `Wallet.generate`), you do not need to specify the signing algorithm.
|
||||
|
||||
**Before**
|
||||
```
|
||||
Wallet.fromSeed('s...')
|
||||
Wallet.fromEntropy(entropy)
|
||||
deriveKeyPair(seed="s...")
|
||||
```
|
||||
|
||||
**After**
|
||||
```
|
||||
Wallet.fromSeed(seed='s...',algorithm: 'ecdsa-secp256k1')
|
||||
Wallet.fromEntropy(entropy, opts={algorithm: 'ecdsa-secp256k1'})
|
||||
deriveKeypair(seed='s...', opts={ algorithm: 'ecdsa-secp256k1' }) (ripple-keypairs)
|
||||
```
|
||||
|
||||
### 9. `AssertionError` → `Error`
|
||||
|
||||
|
||||
@@ -19,13 +19,13 @@ See the full reference documentation for all classes, methods, and utilities.
|
||||
4. Subscribing to changes in the ledger ([Ex. ledger, transactions, & more...](https://xrpl.org/subscribe.html))
|
||||
5. Parsing ledger data into more convenient formats ([`xrpToDrops`](https://js.xrpl.org/functions/xrpToDrops.html) and [`rippleTimeToISOTime`](https://js.xrpl.org/functions/rippleTimeToISOTime.html))
|
||||
|
||||
All of which works in Node.js (tested for v16+) & web browsers (tested for Chrome).
|
||||
All of which works in Node.js (tested for v18+) & web browsers (tested for Chrome).
|
||||
|
||||
# Quickstart
|
||||
|
||||
### Requirements
|
||||
|
||||
+ **[Node.js v16](https://nodejs.org/)** is recommended. We also support v18 and v20. Other versions may work but are not frequently tested.
|
||||
+ **[Node.js v18](https://nodejs.org/)** is recommended. We also support v20. Other versions may work but are not frequently tested.
|
||||
|
||||
### Installing xrpl.js
|
||||
|
||||
@@ -56,7 +56,7 @@ async function main() {
|
||||
});
|
||||
console.log(response);
|
||||
|
||||
client.disconnect();
|
||||
await client.disconnect();
|
||||
}
|
||||
main();
|
||||
```
|
||||
|
||||
16606
package-lock.json
generated
16606
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -25,7 +25,7 @@
|
||||
"@types/chai": "^4.2.21",
|
||||
"@types/jest": "^29.2.2",
|
||||
"@types/lodash": "^4.14.136",
|
||||
"@types/node": "^16.18.38",
|
||||
"@types/node": "^18.19.29",
|
||||
"@types/ws": "^8.2.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.28.0",
|
||||
"@typescript-eslint/parser": "^5.28.0",
|
||||
@@ -64,7 +64,7 @@
|
||||
"./packages/*"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=16.0.0",
|
||||
"node": ">=18.0.0",
|
||||
"npm": ">=7.10.0 < 10.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# @xrplf/isomorphic Release History
|
||||
|
||||
## Unreleased
|
||||
|
||||
## 1.0.1 (2024-06-03)
|
||||
|
||||
### Fixed
|
||||
|
||||
* Throw error if `hexToBytes` or `hexToString` is provided a string that is not in hex
|
||||
|
||||
## 1.0.0 (2024-02-01)
|
||||
|
||||
Initial release providing isomorphic and tree-shakable implementations of:
|
||||
@@ -14,21 +22,3 @@ Initial release providing isomorphic and tree-shakable implementations of:
|
||||
* randomBytes
|
||||
* stringToHex
|
||||
* ws
|
||||
|
||||
## 1.0.0 Beta 1 (2023-11-30)
|
||||
|
||||
## Added
|
||||
* hexToString
|
||||
* stringToHex
|
||||
|
||||
## 1.0.0 Beta 0 (2023-10-19)
|
||||
|
||||
Initial release providing isomorphic and tree-shakable implementations of:
|
||||
|
||||
* ripemd160
|
||||
* sha256
|
||||
* sha512
|
||||
* bytesToHash
|
||||
* hashToBytes
|
||||
* randomBytes
|
||||
* ws_
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@xrplf/isomorphic",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.1",
|
||||
"description": "A collection of isomorphic and tree-shakeable crypto hashes and utils for xrpl.js",
|
||||
"keywords": [
|
||||
"crypto",
|
||||
@@ -33,7 +33,7 @@
|
||||
"ws": "^8.13.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^16.18.38",
|
||||
"@types/node": "^18.18.38",
|
||||
"@types/ws": "^8.5.6"
|
||||
},
|
||||
"repository": {
|
||||
@@ -43,6 +43,6 @@
|
||||
"license": "ISC",
|
||||
"prettier": "@xrplf/prettier-config",
|
||||
"engines": {
|
||||
"node": ">=16.0.0"
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import type {
|
||||
RandomBytesFn,
|
||||
StringToHexFn,
|
||||
} from './types'
|
||||
import { HEX_REGEX } from './shared'
|
||||
|
||||
/* eslint-disable func-style -- Typed to ensure uniformity between node and browser implementations and docs */
|
||||
export const bytesToHex: typeof BytesToHexFn = (bytes) => {
|
||||
@@ -22,6 +23,9 @@ export const bytesToHex: typeof BytesToHexFn = (bytes) => {
|
||||
export const hexToBytes: typeof HexToBytesFn = (hex): Uint8Array => {
|
||||
const len = hex.length
|
||||
const array = new Uint8Array(len / 2)
|
||||
if (!HEX_REGEX.test(hex)) {
|
||||
throw new Error('Invalid hex string')
|
||||
}
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
const j = i * 2
|
||||
const hexByte = hex.slice(j, j + 2)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { randomBytes as cryptoRandomBytes } from 'crypto'
|
||||
import type { BytesToHexFn, HexToBytesFn, RandomBytesFn } from './types'
|
||||
import { HexToStringFn, StringToHexFn } from './types'
|
||||
import { HEX_REGEX } from './shared'
|
||||
|
||||
const OriginalBuffer = Symbol('OriginalBuffer')
|
||||
|
||||
@@ -64,6 +65,9 @@ export const bytesToHex: typeof BytesToHexFn = (bytes) => {
|
||||
}
|
||||
|
||||
export const hexToBytes: typeof HexToBytesFn = (hex) => {
|
||||
if (!HEX_REGEX.test(hex)) {
|
||||
throw new Error('Invalid hex string')
|
||||
}
|
||||
return toUint8Array(Buffer.from(hex, 'hex'))
|
||||
}
|
||||
|
||||
@@ -75,6 +79,9 @@ export const hexToString: typeof HexToStringFn = (
|
||||
hex: string,
|
||||
encoding = 'utf8',
|
||||
): string => {
|
||||
if (!HEX_REGEX.test(hex)) {
|
||||
throw new Error('Invalid hex string')
|
||||
}
|
||||
return new TextDecoder(encoding).decode(hexToBytes(hex))
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { concatBytes } from '@noble/hashes/utils'
|
||||
|
||||
export const HEX_REGEX = /^[A-F0-9]*$/iu
|
||||
|
||||
export function concat(views: Uint8Array[]): Uint8Array {
|
||||
return concatBytes(...views)
|
||||
}
|
||||
|
||||
@@ -23,10 +23,18 @@ describe('utils', function () {
|
||||
expect(hexToBytes('DEADBEEF')).toEqual(new Uint8Array([222, 173, 190, 239]))
|
||||
})
|
||||
|
||||
it('hexToBytes - DEADBEEF', () => {
|
||||
expect(hexToBytes('DEADBEEF')).toEqual(new Uint8Array([222, 173, 190, 239]))
|
||||
})
|
||||
|
||||
it('bytesToHex - DEADBEEF', () => {
|
||||
expect(bytesToHex([222, 173, 190, 239])).toEqual('DEADBEEF')
|
||||
})
|
||||
|
||||
it('bytesToHex - bad hex', () => {
|
||||
expect(() => hexToBytes('hello')).toThrow(new Error('Invalid hex string'))
|
||||
})
|
||||
|
||||
it('bytesToHex - 010203', () => {
|
||||
expect(bytesToHex([1, 2, 3])).toEqual('010203')
|
||||
})
|
||||
@@ -43,6 +51,10 @@ describe('utils', function () {
|
||||
expect(hexToString('6465616462656566D68D')).toEqual('deadbeef֍')
|
||||
})
|
||||
|
||||
it('hexToString - bad hex', () => {
|
||||
expect(() => hexToString('hello')).toThrow(new Error('Invalid hex string'))
|
||||
})
|
||||
|
||||
it('stringToHex - deadbeef+infinity symbol (utf8)', () => {
|
||||
expect(stringToHex('deadbeef֍')).toEqual('6465616462656566D68D')
|
||||
})
|
||||
|
||||
@@ -15,25 +15,6 @@
|
||||
* Eliminates 4 runtime dependencies: `base-x`, `base64-js`, `buffer`, and `ieee754`.
|
||||
* Execute test in a browser in addition to node
|
||||
|
||||
## 5.0.0 Beta 1 (2023-11-30)
|
||||
|
||||
### Breaking Changes
|
||||
* `Buffer` has been replaced with `UInt8Array` for both params and return values. `Buffer` may continue to work with params since they extend `UInt8Arrays`.
|
||||
|
||||
### Changes
|
||||
* Eliminates 4 runtime dependencies: `base-x`, `base64-js`, `buffer`, and `ieee754`.
|
||||
|
||||
## 5.0.0 Beta 0 (2023-10-19)
|
||||
|
||||
### Breaking Changes
|
||||
* Bump typescript to 5.x
|
||||
* Remove Node 14 support
|
||||
* Remove `assert` dependency. If you were catching `AssertionError` you need to change to `Error`.
|
||||
* Remove `create-hash` in favor of `@noble/hashes`
|
||||
|
||||
### Changes
|
||||
* Execute test in a browser in addition to node
|
||||
|
||||
## 4.3.1 (2023-09-27)
|
||||
### Fixed
|
||||
* Fix source-maps not finding their designated source
|
||||
|
||||
@@ -34,6 +34,6 @@
|
||||
},
|
||||
"prettier": "@xrplf/prettier-config",
|
||||
"engines": {
|
||||
"node": ">= 16"
|
||||
"node": ">= 18"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,14 @@
|
||||
|
||||
## Unreleased
|
||||
|
||||
## 2.1.0 (2024-06-03)
|
||||
|
||||
### Added
|
||||
* Support for the Price Oracles amendment (XLS-47).
|
||||
|
||||
### Fixed
|
||||
* Better error handling/error messages for serialization/deserialization errors.
|
||||
|
||||
## 2.0.0 (2024-02-01)
|
||||
|
||||
### BREAKING CHANGES
|
||||
@@ -19,23 +27,6 @@
|
||||
* `Comparable` is now a generic type so that it allows `compareTo` methods to take more that the type itself.
|
||||
* Eliminates 4 runtime dependencies: `base-x`, `base64-js`, `buffer`, and `ieee754`.
|
||||
|
||||
## 2.0.0 Beta 1 (2023-11-30)
|
||||
|
||||
### Breaking Changes
|
||||
* `Buffer` has been replaced with `UInt8Array` for both params and return values. `Buffer` may continue to work with params since they extend `UInt8Arrays`.
|
||||
|
||||
### Changes
|
||||
* Eliminates 4 runtime dependencies: `base-x`, `base64-js`, `buffer`, and `ieee754`.
|
||||
|
||||
## 2.0.0 Beta 0 (2023-10-19)
|
||||
|
||||
### Breaking Changes
|
||||
* Bump typescript to 5.x
|
||||
* Remove Node 14 support
|
||||
* Remove decimal.js and big-integer. Use `BigNumber` from `bignumber.js` instead of `Decimal` and the native `BigInt` instead of `bigInt`.
|
||||
* Remove `assert` dependency. If you were catching `AssertionError` you need to change to `Error`.
|
||||
* Remove `create-hash` in favor of `@noble/hashes`
|
||||
|
||||
### Changes
|
||||
* Update type definitions which causing errors in tests that the code already supported
|
||||
* `makeParser` to accept a `Buffer` in addition to `string`
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ripple-binary-codec",
|
||||
"version": "2.0.0",
|
||||
"version": "2.1.0",
|
||||
"description": "XRP Ledger binary codec",
|
||||
"files": [
|
||||
"dist/*",
|
||||
@@ -11,7 +11,7 @@
|
||||
"test": "test"
|
||||
},
|
||||
"dependencies": {
|
||||
"@xrplf/isomorphic": "^1.0.0",
|
||||
"@xrplf/isomorphic": "^1.0.1",
|
||||
"bignumber.js": "^9.0.0",
|
||||
"ripple-address-codec": "^5.0.0"
|
||||
},
|
||||
@@ -41,6 +41,6 @@
|
||||
"readmeFilename": "README.md",
|
||||
"prettier": "@xrplf/prettier-config",
|
||||
"engines": {
|
||||
"node": ">= 16"
|
||||
"node": ">= 18"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
"UInt512": 23,
|
||||
"Issue": 24,
|
||||
"XChainBridge": 25,
|
||||
"Currency": 26,
|
||||
"Transaction": 10001,
|
||||
"LedgerEntry": 10002,
|
||||
"Validation": 10003,
|
||||
@@ -51,6 +52,7 @@
|
||||
"NFTokenOffer": 55,
|
||||
"AMM": 121,
|
||||
"DID": 73,
|
||||
"Oracle": 128,
|
||||
"Any": -3,
|
||||
"Child": -2,
|
||||
"Nickname": 110,
|
||||
@@ -208,6 +210,16 @@
|
||||
"type": "UInt8"
|
||||
}
|
||||
],
|
||||
[
|
||||
"Scale",
|
||||
{
|
||||
"nth": 4,
|
||||
"isVLEncoded": false,
|
||||
"isSerialized": true,
|
||||
"isSigningField": true,
|
||||
"type": "UInt8"
|
||||
}
|
||||
],
|
||||
[
|
||||
"TickSize",
|
||||
{
|
||||
@@ -498,6 +510,16 @@
|
||||
"type": "UInt32"
|
||||
}
|
||||
],
|
||||
[
|
||||
"LastUpdateTime",
|
||||
{
|
||||
"nth": 15,
|
||||
"isVLEncoded": false,
|
||||
"isSerialized": true,
|
||||
"isSigningField": true,
|
||||
"type": "UInt32"
|
||||
}
|
||||
],
|
||||
[
|
||||
"HighQualityIn",
|
||||
{
|
||||
@@ -828,6 +850,16 @@
|
||||
"type": "UInt32"
|
||||
}
|
||||
],
|
||||
[
|
||||
"OracleDocumentID",
|
||||
{
|
||||
"nth": 51,
|
||||
"isVLEncoded": false,
|
||||
"isSerialized": true,
|
||||
"isSigningField": true,
|
||||
"type": "UInt32"
|
||||
}
|
||||
],
|
||||
[
|
||||
"IndexNext",
|
||||
{
|
||||
@@ -1028,6 +1060,16 @@
|
||||
"type": "UInt64"
|
||||
}
|
||||
],
|
||||
[
|
||||
"AssetPrice",
|
||||
{
|
||||
"nth": 23,
|
||||
"isVLEncoded": false,
|
||||
"isSerialized": true,
|
||||
"isSigningField": true,
|
||||
"type": "UInt64"
|
||||
}
|
||||
],
|
||||
[
|
||||
"EmailHash",
|
||||
{
|
||||
@@ -1918,6 +1960,26 @@
|
||||
"type": "Blob"
|
||||
}
|
||||
],
|
||||
[
|
||||
"AssetClass",
|
||||
{
|
||||
"nth": 28,
|
||||
"isVLEncoded": true,
|
||||
"isSerialized": true,
|
||||
"isSigningField": true,
|
||||
"type": "Blob"
|
||||
}
|
||||
],
|
||||
[
|
||||
"Provider",
|
||||
{
|
||||
"nth": 29,
|
||||
"isVLEncoded": true,
|
||||
"isSerialized": true,
|
||||
"isSigningField": true,
|
||||
"type": "Blob"
|
||||
}
|
||||
],
|
||||
[
|
||||
"Account",
|
||||
{
|
||||
@@ -2128,6 +2190,26 @@
|
||||
"type": "PathSet"
|
||||
}
|
||||
],
|
||||
[
|
||||
"BaseAsset",
|
||||
{
|
||||
"nth": 1,
|
||||
"isVLEncoded": false,
|
||||
"isSerialized": true,
|
||||
"isSigningField": true,
|
||||
"type": "Currency"
|
||||
}
|
||||
],
|
||||
[
|
||||
"QuoteAsset",
|
||||
{
|
||||
"nth": 2,
|
||||
"isVLEncoded": false,
|
||||
"isSerialized": true,
|
||||
"isSigningField": true,
|
||||
"type": "Currency"
|
||||
}
|
||||
],
|
||||
[
|
||||
"LockingChainIssue",
|
||||
{
|
||||
@@ -2458,6 +2540,16 @@
|
||||
"type": "STObject"
|
||||
}
|
||||
],
|
||||
[
|
||||
"PriceData",
|
||||
{
|
||||
"nth": 32,
|
||||
"isVLEncoded": false,
|
||||
"isSerialized": true,
|
||||
"isSigningField": true,
|
||||
"type": "STObject"
|
||||
}
|
||||
],
|
||||
[
|
||||
"Signers",
|
||||
{
|
||||
@@ -2628,6 +2720,16 @@
|
||||
"type": "STArray"
|
||||
}
|
||||
],
|
||||
[
|
||||
"PriceDataSeries",
|
||||
{
|
||||
"nth": 24,
|
||||
"isVLEncoded": false,
|
||||
"isSerialized": true,
|
||||
"isSigningField": true,
|
||||
"type": "STArray"
|
||||
}
|
||||
],
|
||||
[
|
||||
"AuthAccounts",
|
||||
{
|
||||
@@ -2656,6 +2758,7 @@
|
||||
"telWRONG_NETWORK": -386,
|
||||
"telREQUIRES_NETWORK_ID": -385,
|
||||
"telNETWORK_ID_MAKES_TX_NON_CANONICAL": -384,
|
||||
"telENV_RPC_FAILED": -383,
|
||||
|
||||
"temMALFORMED": -299,
|
||||
"temBAD_AMOUNT": -298,
|
||||
@@ -2703,6 +2806,8 @@
|
||||
"temXCHAIN_BRIDGE_BAD_MIN_ACCOUNT_CREATE_AMOUNT": -256,
|
||||
"temXCHAIN_BRIDGE_BAD_REWARD_AMOUNT": -255,
|
||||
"temEMPTY_DID": -254,
|
||||
"temARRAY_EMPTY": -253,
|
||||
"temARRAY_TOO_LARGE": -252,
|
||||
|
||||
"tefFAILURE": -199,
|
||||
"tefALREADY": -198,
|
||||
@@ -2739,7 +2844,6 @@
|
||||
"terQUEUED": -89,
|
||||
"terPRE_TICKET": -88,
|
||||
"terNO_AMM": -87,
|
||||
"terSUBMITTED": -86,
|
||||
|
||||
"tesSUCCESS": 0,
|
||||
|
||||
@@ -2815,7 +2919,11 @@
|
||||
"tecXCHAIN_SELF_COMMIT": 184,
|
||||
"tecXCHAIN_BAD_PUBLIC_KEY_ACCOUNT_PAIR": 185,
|
||||
"tecXCHAIN_CREATE_ACCOUNT_DISABLED": 186,
|
||||
"tecEMPTY_DID": 187
|
||||
"tecEMPTY_DID": 187,
|
||||
"tecINVALID_UPDATE_TIME": 188,
|
||||
"tecTOKEN_PAIR_NOT_FOUND": 189,
|
||||
"tecARRAY_EMPTY": 190,
|
||||
"tecARRAY_TOO_LARGE": 191
|
||||
},
|
||||
"TRANSACTION_TYPES": {
|
||||
"Invalid": -1,
|
||||
@@ -2864,6 +2972,8 @@
|
||||
"XChainCreateBridge": 48,
|
||||
"DIDSet": 49,
|
||||
"DIDDelete": 50,
|
||||
"OracleSet": 51,
|
||||
"OracleDelete": 52,
|
||||
"EnableAmendment": 100,
|
||||
"SetFee": 101,
|
||||
"UNLModify": 102
|
||||
|
||||
@@ -144,14 +144,18 @@ class BinaryParser {
|
||||
if (type === 0) {
|
||||
type = this.readUInt8()
|
||||
if (type === 0 || type < 16) {
|
||||
throw new Error('Cannot read FieldOrdinal, type_code out of range')
|
||||
throw new Error(
|
||||
`Cannot read FieldOrdinal, type_code ${type} out of range`,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (nth === 0) {
|
||||
nth = this.readUInt8()
|
||||
if (nth === 0 || nth < 16) {
|
||||
throw new Error('Cannot read FieldOrdinal, field_code out of range')
|
||||
throw new Error(
|
||||
`Cannot read FieldOrdinal, field_code ${nth} out of range`,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,9 @@ class Blob extends SerializedType {
|
||||
}
|
||||
|
||||
if (typeof value === 'string') {
|
||||
if (!/^[A-F0-9]*$/iu.test(value)) {
|
||||
throw new Error('Cannot construct Blob from a non-hex string')
|
||||
}
|
||||
return new Blob(hexToBytes(value))
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,13 @@ const OBJECT_END_MARKER = Uint8Array.from([0xe1])
|
||||
*/
|
||||
function isObjects(args): args is Array<JsonObject> {
|
||||
return (
|
||||
Array.isArray(args) && (args.length === 0 || typeof args[0] === 'object')
|
||||
Array.isArray(args) &&
|
||||
args.every(
|
||||
(arg) =>
|
||||
typeof arg === 'object' &&
|
||||
Object.keys(arg).length === 1 &&
|
||||
typeof Object.values(arg)[0] === 'object',
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -238,19 +238,19 @@ function fieldParsingTests() {
|
||||
it('Field throws when type code out of range', () => {
|
||||
const parser = makeParser('0101')
|
||||
expect(() => parser.readField()).toThrow(
|
||||
new Error('Cannot read FieldOrdinal, type_code out of range'),
|
||||
new Error('Cannot read FieldOrdinal, type_code 1 out of range'),
|
||||
)
|
||||
})
|
||||
it('Field throws when field code out of range', () => {
|
||||
const parser = makeParser('1001')
|
||||
expect(() => parser.readFieldOrdinal()).toThrow(
|
||||
new Error('Cannot read FieldOrdinal, field_code out of range'),
|
||||
new Error('Cannot read FieldOrdinal, field_code 1 out of range'),
|
||||
)
|
||||
})
|
||||
it('Field throws when both type and field code out of range', () => {
|
||||
const parser = makeParser('000101')
|
||||
expect(() => parser.readFieldOrdinal()).toThrow(
|
||||
new Error('Cannot read FieldOrdinal, type_code out of range'),
|
||||
new Error('Cannot read FieldOrdinal, type_code 1 out of range'),
|
||||
)
|
||||
})
|
||||
it('readUIntN', () => {
|
||||
|
||||
@@ -4868,6 +4868,36 @@
|
||||
"TxnSignature": "AACD31A04CAE14670FC483A1382F393AA96B49C84479B58067F049FBD772999325667A6AA2520A63756EE84F3657298815019DD56A1AECE796B08535C4009C08",
|
||||
"URI": "6469645F6578616D706C65"
|
||||
}
|
||||
},
|
||||
{
|
||||
"binary": "1200332FFFFFFFFF2033000004D2750B6469645F6578616D706C65701C0863757272656E6379701D0870726F7669646572811401476926B590BA3245F63C829116A0A3AF7F382DF018E020301700000000000001E2041003011A0000000000000000000000000000000000000000021A0000000000000000000000005553440000000000E1F1",
|
||||
"json": {
|
||||
"TransactionType": "OracleSet",
|
||||
"Account": "rfmDuhDyLGgx94qiwf3YF8BUV5j6KSvE8",
|
||||
"OracleDocumentID": 1234,
|
||||
"LastUpdateTime": 4294967295,
|
||||
"PriceDataSeries": [
|
||||
{
|
||||
"PriceData": {
|
||||
"BaseAsset": "XRP",
|
||||
"QuoteAsset": "USD",
|
||||
"AssetPrice": "00000000000001E2",
|
||||
"Scale": 3
|
||||
}
|
||||
}
|
||||
],
|
||||
"Provider": "70726F7669646572",
|
||||
"URI": "6469645F6578616D706C65",
|
||||
"AssetClass": "63757272656E6379"
|
||||
}
|
||||
},
|
||||
{
|
||||
"binary": "1200342033000004D2811401476926B590BA3245F63C829116A0A3AF7F382D",
|
||||
"json": {
|
||||
"TransactionType": "OracleDelete",
|
||||
"Account": "rfmDuhDyLGgx94qiwf3YF8BUV5j6KSvE8",
|
||||
"OracleDocumentID": 1234
|
||||
}
|
||||
}
|
||||
],
|
||||
"ledgerData": [{
|
||||
|
||||
@@ -19,29 +19,6 @@
|
||||
* Remove `brorand` as a dependency and use `@xrplf/isomorphic` instead.
|
||||
* Eliminates 4 runtime dependencies: `base-x`, `base64-js`, `buffer`, and `ieee754`.
|
||||
|
||||
## 2.0.0 Beta 1 (2023-11-30)
|
||||
|
||||
### Breaking Changes
|
||||
* `Buffer` has been replaced with `UInt8Array` for both params and return values. `Buffer` may continue to work with params since they extend `UInt8Arrays`.
|
||||
|
||||
### Changes
|
||||
* Eliminates 4 runtime dependencies: `base-x`, `base64-js`, `buffer`, and `ieee754`.
|
||||
|
||||
## 2.0.0 Beta 0 (2023-10-19)
|
||||
|
||||
### Breaking Changes
|
||||
* Bump typescript to 5.x
|
||||
* Remove Node 14 support
|
||||
* Remove `assert` dependency. If you were catching `AssertionError` you need to change to `Error`.
|
||||
* Fix `deriveKeypair` ignoring manual decoding algorithm. (Specifying algorithm=`ed25519` in `opts` now works on secrets like `sNa1...`)
|
||||
* Remove `crypto` polyfills, `create-hash`, `elliptic`, `hash.js`, and their many dependencies in favor of `@noble/hashes` and `@nobel/curves`
|
||||
* Remove `bytesToHex` and `hexToBytes`. They can now be found in `@xrplf/isomorphic/utils`
|
||||
* `verifyTransaction` will throw an error if there is no signature
|
||||
* Improved key algorithm detection. It will now throw Errors with helpful messages
|
||||
|
||||
### Changes
|
||||
* Remove `brorand` as a dependency and use `@xrplf/isomorphic` instead.
|
||||
|
||||
## 1.3.1 (2023-09-27)
|
||||
### Fixed
|
||||
* Fix source-maps not finding their designated source
|
||||
|
||||
@@ -36,6 +36,6 @@
|
||||
"license": "ISC",
|
||||
"prettier": "@xrplf/prettier-config",
|
||||
"engines": {
|
||||
"node": ">= 16"
|
||||
"node": ">= 18"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,24 +19,3 @@ Subscribe to [the **xrpl-announce** mailing list](https://groups.google.com/g/xr
|
||||
* Unit tests run in a browser and node.
|
||||
* Remove `brorand` as a dependency and use `@xrplf/isomorphic` instead.
|
||||
* Eliminates 4 runtime dependencies: `base-x`, `base64-js`, `buffer`, and `ieee754`.
|
||||
|
||||
## 1.0.0 Beta 1 (2023-11-30)
|
||||
|
||||
### BREAKING CHANGES:
|
||||
* Moved all methods that were on `Utils` are now individually exported.
|
||||
* `Buffer` has been replaced with `UInt8Array` for both params and return values. `Buffer` may continue to work with params since they extend `UInt8Arrays`.
|
||||
|
||||
### Changes
|
||||
* Eliminates 4 runtime dependencies: `base-x`, `base64-js`, `buffer`, and `ieee754`.
|
||||
|
||||
## 1.0.0 Beta 0 (2023-10-19)
|
||||
|
||||
* Add `xrpl-secret-numbers` by @WietseWind to the mono repo.
|
||||
* `unpkg` and `jsdelivr` support was simplified.
|
||||
* Unit tests run in a browser and node.
|
||||
* Remove `brorand` as a dependency and use `@xrplf/isomorphic` instead.
|
||||
|
||||
### BREAKING CHANGES:
|
||||
* `xrpl-secret-numbers` is now `@xrplf/secret-numbers`.
|
||||
* The bundled file produced changed from `dist/browerified.js` to `build/xrplf-secret-numbers-latest.js`.
|
||||
* Bundle variable is `xrplf_secret_numbers` instead of using browserify's loader.
|
||||
|
||||
@@ -2,7 +2,36 @@
|
||||
|
||||
Subscribe to [the **xrpl-announce** mailing list](https://groups.google.com/g/xrpl-announce) for release announcements. We recommend that xrpl.js (ripple-lib) users stay up-to-date with the latest stable release.
|
||||
|
||||
## Unreleased
|
||||
## 4.0.0 (2024-07-15)
|
||||
|
||||
### BREAKING CHANGES
|
||||
* Use rippled api_version v2 as default while maintaining support for v1.
|
||||
|
||||
### Added
|
||||
* Add `nfts_by_issuer` clio-only API definition
|
||||
* Support for the `fixPreviousTxnID` amendment.
|
||||
* Support for the user version of the `feature` RPC.
|
||||
* Add `hash` field to `ledger` command response
|
||||
|
||||
### Removed
|
||||
* Remove references to the Hooks testnet faucet in the xrpl.js code repository.
|
||||
|
||||
## 3.1.0 (2024-06-03)
|
||||
|
||||
### BREAKING CHANGES
|
||||
* Small fix in the API to use a new flag name `tfNoDirectRipple` instead of the existing flag name `tfNoRippleDirect`
|
||||
* Node.js has been upgraded to a minimum version of 18
|
||||
* `fetch` now relies on the native javascript environment in browsers and Node.js
|
||||
|
||||
### Added
|
||||
* Support for the Price Oracles amendment (XLS-47).
|
||||
|
||||
### Fixed
|
||||
* Typo in `Channel` type `source_tab` -> `source_tag`
|
||||
* Fix `client.requestAll` to handle filters better
|
||||
* Add the missing `AMMDeposit` flag `tfTwoAssetIfEmpty`
|
||||
* Add missing `lsfAMMNode` flag to `RippleState` ledger object
|
||||
* Add `PreviousFields` to `DeletedNode` metadata type
|
||||
|
||||
## 3.0.0 (2024-02-01)
|
||||
|
||||
@@ -52,80 +81,6 @@ Bundler configurations are much more simplified. See [../UNIQUE_STEPS](Unique St
|
||||
* Deprecated:
|
||||
* `convertHexToString` in favor of `@xrplf/isomorphic/utils`'s `hexToString`
|
||||
* `convertStringToHex` in favor of `@xrplf/isomorphic/utils`'s `stringToHex`
|
||||
|
||||
## 3.0.0 Beta 1 (2023-11-30)
|
||||
|
||||
### Breaking Changes
|
||||
* `Transaction` type has been redefined to include all transactions and `SubmittableTransaction` was created to define the old value. The following functions which only handle transactions to be submitted now use `SubmittableTransaction`:
|
||||
* `Client.autofill`
|
||||
* `Client.submit`
|
||||
* `Client.submitAndWait`
|
||||
* `Client.prepareTransaction`
|
||||
* `getSignedTx`
|
||||
* `isAccountDelete`
|
||||
* `dropsToXRP` and `Client.getXrpBalance` now return a `number` instead of a `string`
|
||||
* `Buffer` has been replaced with `UInt8Array` for both params and return values. `Buffer` may continue to work with params since they extend `UInt8Arrays`.
|
||||
|
||||
### Bundling Changes
|
||||
* `Buffer` and `process` polyfills are no longer required.
|
||||
|
||||
### Changes
|
||||
* Deprecated:
|
||||
* `convertHexToString` in favor of `@xrplf/isomorphic/utils`'s `hexToString`
|
||||
* `convertStringToHex` in favor of `@xrplf/isomorphic/utils`'s `stringToHex`
|
||||
* Remove `lodash` as a dependency
|
||||
* Remove many polyfills that were only used for testing in the browser
|
||||
* Remove `util` from bundle by switching `inspect` to `JSON.stringify`
|
||||
* Add type for metadata for specific transactions(`Payment`, `NFTokenMint`, `NFTokenCreateOffer`, `NFTokenAcceptOffer`, `NFTokenCancelOffer`)
|
||||
|
||||
### Fixed
|
||||
* Fixed Wallet.generate() ignoring the `algorithm` parameter (Only a problem once binary-codec fix for `derive_keypair` is added)
|
||||
* Fixed Wallet.fromSeed() ignoring the `algorithm` parameter
|
||||
* Added pseudo-transaction support to hash functions and response types
|
||||
|
||||
## 3.0.0 Beta 0 (2023-10-19)
|
||||
|
||||
### Breaking Changes
|
||||
* Bump typescript to 5.x
|
||||
* Remove Node 14 support
|
||||
* Remove `crypto` polyfills, `create-hash`, `elliptic`, `hash.js`, and their many dependencies in favor of `@noble/hashes` and `@nobel/curves`
|
||||
* Remove `bip32` and `bip39` in favor of `@scure/bip32` and `@scure/bip39`
|
||||
* Remove `assert` dependency. If you were catching `AssertionError` you need to change to `Error`
|
||||
* Configuring a proxy:
|
||||
* Instead of passing various parameters on the `ConnectionsOptions` you know specify the `agent` parameter. This object can use be created by libraries such as `https-proxy-agent` or any that implements the `http.Agent`.
|
||||
* This was changed to both support the latest `https-proxy-agent` and to remove the need to include the package in bundlers. Tests will still be done using `https-proxy-agent` and only tested in a node environment which was the only way it was previously supported anyway
|
||||
* Remove `BroadcastClient` which was deprecated
|
||||
* Uses `@xrplf/secret-numbers` instead of `xrpl-secret-numbers`
|
||||
* Improve key algorithm detection. It will now throw Errors with helpful messages
|
||||
* Move `authorizeChannel` from `wallet/signer` to `wallet/authorizeChannel` to solve a circular dependency issue.
|
||||
* When using a bundler you must remove the mapping of `ws` to `WSWrapper`. ex. `ws: 'xrpl/dist/npm/client/WSWrapper'`. See [../UNIQUE_STEPS](Unique Steps) for the new, much smaller, configs.
|
||||
|
||||
### Bundling Changes
|
||||
Bundler configurations are much more simplified. See [../UNIQUE_STEPS](Unique Steps) for the new, much smaller, configs.
|
||||
* removed the following polyfills:
|
||||
* `assert`
|
||||
* `crypto-browserify`
|
||||
* `https-browserify`
|
||||
* `os-browserify`
|
||||
* `stream-browserify`
|
||||
* `stream-http`
|
||||
* `url`
|
||||
* `util` - previously added automatically by `webpack`
|
||||
* `events` - previously added automatically by `webpack` but manual for `vite`
|
||||
* Removed mappings for:
|
||||
* `ws` to `WsWrapper`
|
||||
* Excluding `https-proxy-agent`
|
||||
|
||||
### Changed
|
||||
* Remove `lodash` as a dependency
|
||||
* Remove many polyfills that were only used for testing in the browser
|
||||
* Remove `util` from bundle by switching `inspect` to `JSON.stringify`
|
||||
* Add type for metadata for specific transactions(`Payment`, `NFTokenMint`, `NFTokenCreateOffer`, `NFTokenAcceptOffer`, `NFTokenCancelOffer`)
|
||||
|
||||
### Fixed
|
||||
* Fixed Wallet.generate() ignoring the `algorithm` parameter (Only a problem once binary-codec fix for `derive_keypair` is added)
|
||||
* Fixed Wallet.fromSeed() ignoring the `algorithm` parameter
|
||||
* Added pseudo-transaction support to hash functions and response types
|
||||
|
||||
## 2.14.1 (2024-02-01)
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "xrpl",
|
||||
"version": "3.0.0",
|
||||
"version": "4.0.0",
|
||||
"license": "ISC",
|
||||
"description": "A TypeScript/JavaScript API for interacting with the XRP Ledger in Node.js and the browser",
|
||||
"files": [
|
||||
@@ -24,17 +24,16 @@
|
||||
"dependencies": {
|
||||
"@scure/bip32": "^1.3.1",
|
||||
"@scure/bip39": "^1.2.1",
|
||||
"@xrplf/isomorphic": "^1.0.0",
|
||||
"@xrplf/isomorphic": "^1.0.1",
|
||||
"@xrplf/secret-numbers": "^1.0.0",
|
||||
"bignumber.js": "^9.0.0",
|
||||
"cross-fetch": "^4.0.0",
|
||||
"eventemitter3": "^5.0.1",
|
||||
"ripple-address-codec": "^5.0.0",
|
||||
"ripple-binary-codec": "^2.0.0",
|
||||
"ripple-binary-codec": "^2.1.0",
|
||||
"ripple-keypairs": "^2.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^16.18.38",
|
||||
"@types/node": "^18.18.38",
|
||||
"eventemitter3": "^5.0.1",
|
||||
"https-proxy-agent": "^7.0.1",
|
||||
"karma": "^6.4.1",
|
||||
@@ -44,7 +43,7 @@
|
||||
"lodash": "^4.17.4",
|
||||
"react": "^18.2.0",
|
||||
"run-s": "^0.0.0",
|
||||
"typedoc": "0.25.0",
|
||||
"typedoc": "0.26.3",
|
||||
"ws": "^8.14.2"
|
||||
},
|
||||
"resolutions": {
|
||||
@@ -87,6 +86,6 @@
|
||||
"xrpl"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=16.0.0"
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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, {
|
||||
|
||||
@@ -14,13 +14,11 @@ export interface FaucetWallet {
|
||||
export enum FaucetNetwork {
|
||||
Testnet = 'faucet.altnet.rippletest.net',
|
||||
Devnet = 'faucet.devnet.rippletest.net',
|
||||
HooksV3Testnet = 'hooks-testnet-v3.xrpl-labs.com',
|
||||
}
|
||||
|
||||
export const FaucetNetworkPaths: Record<string, string> = {
|
||||
[FaucetNetwork.Testnet]: '/accounts',
|
||||
[FaucetNetwork.Devnet]: '/accounts',
|
||||
[FaucetNetwork.HooksV3Testnet]: '/accounts',
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -33,10 +31,6 @@ export const FaucetNetworkPaths: Record<string, string> = {
|
||||
export function getFaucetHost(client: Client): FaucetNetwork | undefined {
|
||||
const connectionUrl = client.url
|
||||
|
||||
if (connectionUrl.includes('hooks-testnet-v3')) {
|
||||
return FaucetNetwork.HooksV3Testnet
|
||||
}
|
||||
|
||||
// 'altnet' for Ripple Testnet server and 'testnet' for XRPL Labs Testnet server
|
||||
if (connectionUrl.includes('altnet') || connectionUrl.includes('testnet')) {
|
||||
return FaucetNetwork.Testnet
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import fetch from 'cross-fetch'
|
||||
import { isValidClassicAddress } from 'ripple-address-codec'
|
||||
|
||||
import type { Client } from '../client'
|
||||
|
||||
@@ -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
|
||||
@@ -88,8 +93,23 @@ import {
|
||||
} from './partialPayment'
|
||||
|
||||
export interface ClientOptions extends ConnectionUserOptions {
|
||||
/**
|
||||
* Multiplication factor to multiply estimated fee by to provide a cushion in case the
|
||||
* required fee rises during submission of a transaction. Defaults to 1.2.
|
||||
*
|
||||
* @category Fee
|
||||
*/
|
||||
feeCushion?: number
|
||||
/**
|
||||
* Maximum transaction cost to allow, in decimal XRP. Must be a string-encoded
|
||||
* number. Defaults to '2'.
|
||||
*
|
||||
* @category Fee
|
||||
*/
|
||||
maxFeeXRP?: string
|
||||
/**
|
||||
* Duration to wait for a request to timeout.
|
||||
*/
|
||||
timeout?: number
|
||||
}
|
||||
|
||||
@@ -198,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.
|
||||
*
|
||||
@@ -211,7 +237,7 @@ class Client extends EventEmitter<EventTypes> {
|
||||
* const client = new Client('wss://s.altnet.rippletest.net:51233')
|
||||
* ```
|
||||
*/
|
||||
// eslint-disable-next-line max-lines-per-function -- okay because we have to set up all the connection handlers
|
||||
/* eslint-disable max-lines-per-function -- the constructor requires more lines to implement the logic */
|
||||
public constructor(server: string, options: ClientOptions = {}) {
|
||||
super()
|
||||
if (typeof server !== 'string' || !/wss?(?:\+unix)?:\/\//u.exec(server)) {
|
||||
@@ -275,6 +301,7 @@ class Client extends EventEmitter<EventTypes> {
|
||||
this.emit('path_find', path)
|
||||
})
|
||||
}
|
||||
/* eslint-enable max-lines-per-function */
|
||||
|
||||
/**
|
||||
* Get the url that the client is connected to.
|
||||
@@ -291,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.
|
||||
*
|
||||
@@ -304,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)
|
||||
: undefined,
|
||||
})
|
||||
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)
|
||||
@@ -422,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
|
||||
@@ -441,7 +472,6 @@ class Client extends EventEmitter<EventTypes> {
|
||||
const countTo: number = request.limit == null ? Infinity : request.limit
|
||||
let count = 0
|
||||
let marker: unknown = request.marker
|
||||
let lastBatchLength: number
|
||||
const results: U[] = []
|
||||
do {
|
||||
const countRemaining = clamp(countTo - count, MIN_LIMIT, MAX_LIMIT)
|
||||
@@ -453,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`)
|
||||
}
|
||||
@@ -465,11 +495,8 @@ class Client extends EventEmitter<EventTypes> {
|
||||
// Make sure we handle when no data (not even an empty array) is returned.
|
||||
if (Array.isArray(collectedData)) {
|
||||
count += collectedData.length
|
||||
lastBatchLength = collectedData.length
|
||||
} else {
|
||||
lastBatchLength = 0
|
||||
}
|
||||
} while (Boolean(marker) && count < countTo && lastBatchLength !== 0)
|
||||
} while (Boolean(marker) && count < countTo)
|
||||
return results
|
||||
}
|
||||
|
||||
@@ -627,7 +654,10 @@ class Client extends EventEmitter<EventTypes> {
|
||||
* @param signersCount - The expected number of signers for this transaction.
|
||||
* Only used for multisigned transactions.
|
||||
* @returns The autofilled transaction.
|
||||
* @throws ValidationError If Amount and DeliverMax fields are not identical in a Payment Transaction
|
||||
*/
|
||||
|
||||
// eslint-disable-next-line complexity -- handling Payment transaction API v2 requires more logic
|
||||
public async autofill<T extends SubmittableTransaction>(
|
||||
transaction: T,
|
||||
signersCount?: number,
|
||||
@@ -635,7 +665,6 @@ class Client extends EventEmitter<EventTypes> {
|
||||
const tx = { ...transaction }
|
||||
|
||||
setValidAddresses(tx)
|
||||
|
||||
setTransactionFlagsToNumber(tx)
|
||||
|
||||
const promises: Array<Promise<void>> = []
|
||||
@@ -655,6 +684,34 @@ class Client extends EventEmitter<EventTypes> {
|
||||
promises.push(checkAccountDeleteBlockers(this, tx))
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment -- ignore type-assertions on the DeliverMax property
|
||||
// @ts-expect-error -- DeliverMax property exists only at the RPC level, not at the protocol level
|
||||
if (tx.TransactionType === 'Payment' && tx.DeliverMax != null) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- This is a valid null check for Amount
|
||||
if (tx.Amount == null) {
|
||||
// If only DeliverMax is provided, use it to populate the Amount field
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment -- ignore type-assertions on the DeliverMax property
|
||||
// @ts-expect-error -- DeliverMax property exists only at the RPC level, not at the protocol level
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- DeliverMax is a known RPC-level property
|
||||
tx.Amount = tx.DeliverMax
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment -- ignore type-assertions on the DeliverMax property
|
||||
// @ts-expect-error -- DeliverMax property exists only at the RPC level, not at the protocol level
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- This is a valid null check for Amount
|
||||
if (tx.Amount != null && tx.Amount !== tx.DeliverMax) {
|
||||
return Promise.reject(
|
||||
new ValidationError(
|
||||
'PaymentTransaction: Amount and DeliverMax fields must be identical when both are provided',
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment -- ignore type-assertions on the DeliverMax property
|
||||
// @ts-expect-error -- DeliverMax property exists only at the RPC level, not at the protocol level
|
||||
delete tx.DeliverMax
|
||||
}
|
||||
|
||||
return Promise.all(promises).then(() => tx)
|
||||
}
|
||||
|
||||
@@ -898,7 +955,7 @@ class Client extends EventEmitter<EventTypes> {
|
||||
* @param options.limit - Limit number of balances to return.
|
||||
* @returns An array of XRP/non-XRP balances for the given account.
|
||||
*/
|
||||
// eslint-disable-next-line max-lines-per-function -- Longer definition is required for end users to see the definition.
|
||||
/* eslint-disable max-lines-per-function -- getBalances requires more lines to implement logic */
|
||||
public async getBalances(
|
||||
address: string,
|
||||
options: {
|
||||
@@ -946,6 +1003,7 @@ class Client extends EventEmitter<EventTypes> {
|
||||
)
|
||||
return balances.slice(0, options.limit)
|
||||
}
|
||||
/* eslint-enable max-lines-per-function */
|
||||
|
||||
/**
|
||||
* Fetch orderbook (buy/sell orders) between two currency pairs. This checks both sides of the orderbook
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
@@ -155,3 +163,36 @@ export interface XChainBridge {
|
||||
IssuingChainDoor: string
|
||||
IssuingChainIssue: Currency
|
||||
}
|
||||
|
||||
/**
|
||||
* A PriceData object represents the price information for a token pair.
|
||||
*
|
||||
*/
|
||||
export interface PriceData {
|
||||
PriceData: {
|
||||
/**
|
||||
* The primary asset in a trading pair. Any valid identifier, such as a stock symbol, bond CUSIP, or currency code is allowed.
|
||||
* For example, in the BTC/USD pair, BTC is the base asset; in 912810RR9/BTC, 912810RR9 is the base asset.
|
||||
*/
|
||||
BaseAsset: string
|
||||
|
||||
/**
|
||||
* The quote asset in a trading pair. The quote asset denotes the price of one unit of the base asset. For example, in the
|
||||
* BTC/USD pair,BTC is the base asset; in 912810RR9/BTC, 912810RR9 is the base asset.
|
||||
*/
|
||||
QuoteAsset: string
|
||||
|
||||
/**
|
||||
* The asset price after applying the Scale precision level. It's not included if the last update transaction didn't include
|
||||
* the BaseAsset/QuoteAsset pair.
|
||||
*/
|
||||
AssetPrice?: number | string
|
||||
|
||||
/**
|
||||
* The scaling factor to apply to an asset price. For example, if Scale is 6 and original price is 0.155, then the scaled
|
||||
* price is 155000. Valid scale ranges are 0-10. It's not included if the last update transaction didn't include the
|
||||
* BaseAsset/QuoteAsset pair.
|
||||
*/
|
||||
Scale?: number
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { AuthAccount, Currency, IssuedCurrencyAmount } from '../common'
|
||||
|
||||
import { BaseLedgerEntry, MissingPreviousTxnID } from './BaseLedgerEntry'
|
||||
import { BaseLedgerEntry, HasOptionalPreviousTxnID } from './BaseLedgerEntry'
|
||||
|
||||
export interface VoteSlot {
|
||||
VoteEntry: {
|
||||
@@ -15,7 +15,7 @@ export interface VoteSlot {
|
||||
*
|
||||
* @category Ledger Entries
|
||||
*/
|
||||
export default interface AMM extends BaseLedgerEntry, MissingPreviousTxnID {
|
||||
export default interface AMM extends BaseLedgerEntry, HasOptionalPreviousTxnID {
|
||||
LedgerEntryType: 'AMM'
|
||||
/**
|
||||
* The address of the special account that holds this AMM's assets.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { BaseLedgerEntry, MissingPreviousTxnID } from './BaseLedgerEntry'
|
||||
import { BaseLedgerEntry, HasOptionalPreviousTxnID } from './BaseLedgerEntry'
|
||||
|
||||
/**
|
||||
* The unique id for the Amendments object https://xrpl.org/amendments-object.html#amendments-id-format
|
||||
@@ -26,7 +26,7 @@ export interface Majority {
|
||||
*/
|
||||
export default interface Amendments
|
||||
extends BaseLedgerEntry,
|
||||
MissingPreviousTxnID {
|
||||
HasOptionalPreviousTxnID {
|
||||
LedgerEntryType: 'Amendments'
|
||||
/**
|
||||
* Array of 256-bit amendment IDs for all currently-enabled amendments. If
|
||||
|
||||
@@ -15,13 +15,17 @@ export interface HasPreviousTxnID {
|
||||
PreviousTxnLgrSeq: number
|
||||
}
|
||||
|
||||
export interface MissingPreviousTxnID {
|
||||
export interface HasOptionalPreviousTxnID {
|
||||
/**
|
||||
* This field is missing on this object but is present on most other returned objects.
|
||||
* The identifying hash of the transaction that most recently modified this
|
||||
* object. This field was added in the `fixPreviousTxnID` amendment, so it
|
||||
* may not be present in every object.
|
||||
*/
|
||||
PreviousTxnID: never
|
||||
PreviousTxnID?: string
|
||||
/**
|
||||
* This field is missing on this object but is present on most other returned objects.
|
||||
* The index of the ledger that contains the transaction that most recently
|
||||
* modified this object. This field was added in the `fixPreviousTxnID`
|
||||
* amendment, so it may not be present in every object.
|
||||
*/
|
||||
PreviousTxnLgrSeq: never
|
||||
PreviousTxnLgrSeq?: number
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { BaseLedgerEntry, MissingPreviousTxnID } from './BaseLedgerEntry'
|
||||
import { BaseLedgerEntry, HasOptionalPreviousTxnID } from './BaseLedgerEntry'
|
||||
|
||||
/**
|
||||
* The DirectoryNode object type provides a list of links to other objects in
|
||||
@@ -8,7 +8,7 @@ import { BaseLedgerEntry, MissingPreviousTxnID } from './BaseLedgerEntry'
|
||||
*/
|
||||
export default interface DirectoryNode
|
||||
extends BaseLedgerEntry,
|
||||
MissingPreviousTxnID {
|
||||
HasOptionalPreviousTxnID {
|
||||
LedgerEntryType: 'DirectoryNode'
|
||||
/**
|
||||
* A bit-map of boolean flags enabled for this directory. Currently, the
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { BaseLedgerEntry, MissingPreviousTxnID } from './BaseLedgerEntry'
|
||||
import { BaseLedgerEntry, HasOptionalPreviousTxnID } from './BaseLedgerEntry'
|
||||
|
||||
/**
|
||||
* The unique id for the FeeSettings object https://xrpl.org/feesettings.html#feesettings-id-format
|
||||
@@ -26,7 +26,9 @@ export interface FeeSettingsPostAmendmentFields {
|
||||
ReserveIncrementDrops: string
|
||||
}
|
||||
|
||||
export interface FeeSettingsBase extends BaseLedgerEntry, MissingPreviousTxnID {
|
||||
export interface FeeSettingsBase
|
||||
extends BaseLedgerEntry,
|
||||
HasOptionalPreviousTxnID {
|
||||
LedgerEntryType: 'FeeSettings'
|
||||
/**
|
||||
* A bit-map of boolean flags for this object. No flags are defined for this type.
|
||||
|
||||
@@ -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
|
||||
/**
|
||||
@@ -61,5 +56,47 @@ export default interface Ledger {
|
||||
* either JSON or binary depending on whether the request specified binary
|
||||
* as true.
|
||||
*/
|
||||
transactions?: Array<Transaction & { metaData?: TransactionMetadata }>
|
||||
transactions?: Array<
|
||||
Transaction & {
|
||||
hash: string
|
||||
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
|
||||
|
||||
@@ -10,6 +10,7 @@ import FeeSettings from './FeeSettings'
|
||||
import LedgerHashes from './LedgerHashes'
|
||||
import NegativeUNL from './NegativeUNL'
|
||||
import Offer from './Offer'
|
||||
import Oracle from './Oracle'
|
||||
import PayChannel from './PayChannel'
|
||||
import RippleState from './RippleState'
|
||||
import SignerList from './SignerList'
|
||||
@@ -30,6 +31,7 @@ type LedgerEntry =
|
||||
| LedgerHashes
|
||||
| NegativeUNL
|
||||
| Offer
|
||||
| Oracle
|
||||
| PayChannel
|
||||
| RippleState
|
||||
| SignerList
|
||||
@@ -52,6 +54,7 @@ type LedgerEntryFilter =
|
||||
| 'nft_offer'
|
||||
| 'nft_page'
|
||||
| 'offer'
|
||||
| 'oracle'
|
||||
| 'payment_channel'
|
||||
| 'signer_list'
|
||||
| 'state'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { BaseLedgerEntry, MissingPreviousTxnID } from './BaseLedgerEntry'
|
||||
import { BaseLedgerEntry } from './BaseLedgerEntry'
|
||||
|
||||
/**
|
||||
* The LedgerHashes objects exist to make it possible to look up a previous
|
||||
@@ -7,9 +7,7 @@ import { BaseLedgerEntry, MissingPreviousTxnID } from './BaseLedgerEntry'
|
||||
*
|
||||
* @category Ledger Entries
|
||||
*/
|
||||
export default interface LedgerHashes
|
||||
extends BaseLedgerEntry,
|
||||
MissingPreviousTxnID {
|
||||
export default interface LedgerHashes extends BaseLedgerEntry {
|
||||
LedgerEntryType: 'LedgerHashes'
|
||||
/** The Ledger Index of the last entry in this object's Hashes array. */
|
||||
LastLedgerSequence?: number
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { BaseLedgerEntry, MissingPreviousTxnID } from './BaseLedgerEntry'
|
||||
import { BaseLedgerEntry, HasOptionalPreviousTxnID } from './BaseLedgerEntry'
|
||||
|
||||
/**
|
||||
* The unique id for the nUNL object https://xrpl.org/negativeunl.html#negativeunl-id-format
|
||||
@@ -14,7 +14,7 @@ export const NEGATIVE_UNL_ID =
|
||||
*/
|
||||
export default interface NegativeUNL
|
||||
extends BaseLedgerEntry,
|
||||
MissingPreviousTxnID {
|
||||
HasOptionalPreviousTxnID {
|
||||
LedgerEntryType: 'NegativeUNL'
|
||||
/**
|
||||
* A list of trusted validators that are currently disabled.
|
||||
|
||||
43
packages/xrpl/src/models/ledger/Oracle.ts
Normal file
43
packages/xrpl/src/models/ledger/Oracle.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import { PriceData } from '../common'
|
||||
|
||||
import { BaseLedgerEntry, HasPreviousTxnID } from './BaseLedgerEntry'
|
||||
|
||||
/**
|
||||
* The Oracle object type describes a single Price Oracle instance.
|
||||
*
|
||||
* @category Ledger Entries
|
||||
*/
|
||||
export default interface Oracle extends BaseLedgerEntry, HasPreviousTxnID {
|
||||
LedgerEntryType: 'Oracle'
|
||||
|
||||
/**
|
||||
* The time the data was last updated, represented as a unix timestamp in seconds.
|
||||
*/
|
||||
LastUpdateTime: number
|
||||
|
||||
/**
|
||||
* The XRPL account with update and delete privileges for the oracle.
|
||||
*/
|
||||
Owner: string
|
||||
|
||||
/**
|
||||
* Describes the type of asset, such as "currency", "commodity", or "index".
|
||||
*/
|
||||
AssetClass: string
|
||||
|
||||
/**
|
||||
* The oracle provider, such as Chainlink, Band, or DIA.
|
||||
*/
|
||||
Provider: string
|
||||
|
||||
/**
|
||||
* An array of up to 10 PriceData objects.
|
||||
*/
|
||||
PriceDataSeries: PriceData[]
|
||||
|
||||
/**
|
||||
* A bit-map of boolean flags. No flags are defined for the Oracle object
|
||||
* type, so this value is always 0.
|
||||
*/
|
||||
Flags: 0
|
||||
}
|
||||
@@ -75,4 +75,6 @@ export enum RippleStateFlags {
|
||||
lsfLowFreeze = 0x00400000,
|
||||
// True, high side has set freeze flag
|
||||
lsfHighFreeze = 0x00800000,
|
||||
// True, trust line to AMM. Used by client apps to identify payments via AMM.
|
||||
lsfAMMNode = 0x01000000,
|
||||
}
|
||||
|
||||
@@ -15,13 +15,14 @@ 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'
|
||||
import { NFTokenOffer } from './NFTokenOffer'
|
||||
import { NFToken, NFTokenPage } from './NFTokenPage'
|
||||
import Offer, { OfferFlags } from './Offer'
|
||||
import Oracle from './Oracle'
|
||||
import PayChannel from './PayChannel'
|
||||
import RippleState, { RippleStateFlags } from './RippleState'
|
||||
import SignerList, { SignerListFlags } from './SignerList'
|
||||
@@ -47,6 +48,7 @@ export {
|
||||
FeeSettingsPreAmendmentFields,
|
||||
FeeSettingsPostAmendmentFields,
|
||||
Ledger,
|
||||
LedgerV1,
|
||||
LedgerEntryFilter,
|
||||
LedgerEntry,
|
||||
LedgerHashes,
|
||||
@@ -58,6 +60,7 @@ export {
|
||||
NFToken,
|
||||
Offer,
|
||||
OfferFlags,
|
||||
Oracle,
|
||||
PayChannel,
|
||||
RippleState,
|
||||
RippleStateFlags,
|
||||
|
||||
@@ -1,17 +1,80 @@
|
||||
import { BaseRequest, BaseResponse, LookupByLedgerRequest } from './baseMethod'
|
||||
|
||||
/**
|
||||
* Represents a payment channel in the XRP Ledger.
|
||||
*/
|
||||
export interface Channel {
|
||||
/** The owner of the channel, as an Address. */
|
||||
account: string
|
||||
|
||||
/** The total amount of XRP, in drops allocated to this channel. */
|
||||
amount: string
|
||||
|
||||
/**
|
||||
* The total amount of XRP, in drops, paid out from this channel,
|
||||
* as of the ledger version used. (You can calculate the amount of
|
||||
* XRP left in the channel by subtracting balance from amount.)
|
||||
*/
|
||||
balance: string
|
||||
|
||||
/**
|
||||
* A unique ID for this channel, as a 64-character hexadecimal string.
|
||||
* This is also the ID of the channel object in the ledger's state data.
|
||||
*/
|
||||
channel_id: string
|
||||
|
||||
/**
|
||||
* The destination account of the channel, as an Address.
|
||||
* Only this account can receive the XRP in the channel while it is open.
|
||||
*/
|
||||
destination_account: string
|
||||
|
||||
/**
|
||||
* The number of seconds the payment channel must stay open after the owner
|
||||
* of the channel requests to close it.
|
||||
*/
|
||||
settle_delay: number
|
||||
|
||||
/**
|
||||
* The public key for the payment channel in the XRP Ledger's base58 format.
|
||||
* Signed claims against this channel must be redeemed with the matching key pair.
|
||||
*/
|
||||
public_key?: string
|
||||
|
||||
/**
|
||||
* The public key for the payment channel in hexadecimal format, if one was
|
||||
* specified at channel creation. Signed claims against this channel must be
|
||||
* redeemed with the matching key pair.
|
||||
*/
|
||||
public_key_hex?: string
|
||||
|
||||
/**
|
||||
* Time, in seconds since the Ripple Epoch, when this channel is set to expire.
|
||||
* This expiration date is mutable. If this is before the close time of the most
|
||||
* recent validated ledger, the channel is expired.
|
||||
*/
|
||||
expiration?: number
|
||||
|
||||
/**
|
||||
* Time, in seconds since the Ripple Epoch, of this channel's immutable expiration,
|
||||
* if one was specified at channel creation. If this is before the close time of the
|
||||
* most recent validated ledger, the channel is expired.
|
||||
*/
|
||||
cancel_after?: number
|
||||
source_tab?: number
|
||||
|
||||
/**
|
||||
* A 32-bit unsigned integer to use as a source tag for payments through this payment channel,
|
||||
* if one was specified at channel creation. This indicates the payment channel's originator or
|
||||
* other purpose at the source account. Conventionally, if you bounce payments from this channel,
|
||||
* you should specify this value in the DestinationTag of the return payment.
|
||||
*/
|
||||
source_tag?: number
|
||||
|
||||
/**
|
||||
* A 32-bit unsigned integer to use as a destination tag for payments through this channel,
|
||||
* if one was specified at channel creation. This indicates the payment channel's beneficiary
|
||||
* or other purpose at the destination account.
|
||||
*/
|
||||
destination_tag?: number
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
68
packages/xrpl/src/models/methods/feature.ts
Normal file
68
packages/xrpl/src/models/methods/feature.ts
Normal 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
|
||||
119
packages/xrpl/src/models/methods/getAggregatePrice.ts
Normal file
119
packages/xrpl/src/models/methods/getAggregatePrice.ts
Normal file
@@ -0,0 +1,119 @@
|
||||
import { BaseRequest, BaseResponse } from './baseMethod'
|
||||
|
||||
/**
|
||||
* The `get_aggregate_price` method retrieves the aggregate price of specified Oracle objects,
|
||||
* returning three price statistics: mean, median, and trimmed mean.
|
||||
* Returns an {@link GetAggregatePriceResponse}.
|
||||
*
|
||||
* @category Requests
|
||||
*/
|
||||
export interface GetAggregatePriceRequest extends BaseRequest {
|
||||
command: 'get_aggregate_price'
|
||||
|
||||
/**
|
||||
* The currency code of the asset to be priced.
|
||||
*/
|
||||
base_asset: string
|
||||
|
||||
/**
|
||||
* The currency code of the asset to quote the price of the base asset.
|
||||
*/
|
||||
quote_asset: string
|
||||
|
||||
/**
|
||||
* The oracle identifier.
|
||||
*/
|
||||
oracles: Array<{
|
||||
/**
|
||||
* The XRPL account that controls the Oracle object.
|
||||
*/
|
||||
account: string
|
||||
|
||||
/**
|
||||
* A unique identifier of the price oracle for the Account
|
||||
*/
|
||||
oracle_document_id: string | number
|
||||
}>
|
||||
|
||||
/**
|
||||
* The percentage of outliers to trim. Valid trim range is 1-25. If included, the API returns statistics for the trimmed mean.
|
||||
*/
|
||||
trim?: number
|
||||
|
||||
/**
|
||||
* Defines a time range in seconds for filtering out older price data. Default value is 0, which doesn't filter any data.
|
||||
*/
|
||||
trim_threshold?: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Response expected from an {@link GetAggregatePriceRequest}.
|
||||
*
|
||||
* @category Responses
|
||||
*/
|
||||
export interface GetAggregatePriceResponse extends BaseResponse {
|
||||
result: {
|
||||
/**
|
||||
* The statistics from the collected oracle prices.
|
||||
*/
|
||||
entire_set: {
|
||||
/**
|
||||
* The simple mean.
|
||||
*/
|
||||
mean: string
|
||||
|
||||
/**
|
||||
* The size of the data set to calculate the mean.
|
||||
*/
|
||||
size: number
|
||||
|
||||
/**
|
||||
* The standard deviation.
|
||||
*/
|
||||
standard_deviation: string
|
||||
}
|
||||
|
||||
/**
|
||||
* The trimmed statistics from the collected oracle prices. Only appears if the trim field was specified in the request.
|
||||
*/
|
||||
trimmed_set?: {
|
||||
/**
|
||||
* The simple mean of the trimmed data.
|
||||
*/
|
||||
mean: string
|
||||
|
||||
/**
|
||||
* The size of the data to calculate the trimmed mean.
|
||||
*/
|
||||
size: number
|
||||
|
||||
/**
|
||||
* The standard deviation of the trimmed data.
|
||||
*/
|
||||
standard_deviation: string
|
||||
}
|
||||
|
||||
/**
|
||||
* The median of the collected oracle prices.
|
||||
*/
|
||||
median: string
|
||||
|
||||
/**
|
||||
* The most recent timestamp out of all LastUpdateTime values.
|
||||
*/
|
||||
time: number
|
||||
|
||||
/**
|
||||
* The ledger index of the ledger version that was used to generate this
|
||||
* response.
|
||||
*/
|
||||
ledger_current_index: number
|
||||
|
||||
/**
|
||||
* If included and set to true, the information in this response comes from
|
||||
* a validated ledger version. Otherwise, the information is subject to
|
||||
* change.
|
||||
*/
|
||||
validated: boolean
|
||||
}
|
||||
}
|
||||
@@ -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'
|
||||
@@ -60,23 +66,37 @@ import {
|
||||
DepositAuthorizedRequest,
|
||||
DepositAuthorizedResponse,
|
||||
} from './depositAuthorized'
|
||||
import {
|
||||
FeatureAllRequest,
|
||||
FeatureAllResponse,
|
||||
FeatureOneRequest,
|
||||
FeatureOneResponse,
|
||||
FeatureRequest,
|
||||
FeatureResponse,
|
||||
} from './feature'
|
||||
import { FeeRequest, FeeResponse } from './fee'
|
||||
import {
|
||||
GatewayBalance,
|
||||
GatewayBalancesRequest,
|
||||
GatewayBalancesResponse,
|
||||
} from './gatewayBalances'
|
||||
import {
|
||||
GetAggregatePriceRequest,
|
||||
GetAggregatePriceResponse,
|
||||
} from './getAggregatePrice'
|
||||
import {
|
||||
LedgerBinary,
|
||||
LedgerModifiedOfferCreateTransaction,
|
||||
LedgerQueueData,
|
||||
LedgerRequest,
|
||||
LedgerResponse,
|
||||
LedgerV1Response,
|
||||
LedgerRequestExpandedTransactionsOnly,
|
||||
LedgerResponseExpanded,
|
||||
LedgerRequestExpandedAccountsAndTransactions,
|
||||
LedgerRequestExpandedAccountsOnly,
|
||||
LedgerRequestExpandedTransactionsBinary,
|
||||
LedgerVersionResponseMap,
|
||||
} from './ledger'
|
||||
import { LedgerClosedRequest, LedgerClosedResponse } from './ledgerClosed'
|
||||
import { LedgerCurrentRequest, LedgerCurrentResponse } from './ledgerCurrent'
|
||||
@@ -96,6 +116,7 @@ import {
|
||||
NFTHistoryTransaction,
|
||||
} from './nftHistory'
|
||||
import { NFTInfoRequest, NFTInfoResponse } from './nftInfo'
|
||||
import { NFTsByIssuerRequest, NFTsByIssuerResponse } from './nftsByIssuer'
|
||||
import { NFTSellOffersRequest, NFTSellOffersResponse } from './nftSellOffers'
|
||||
import { NoRippleCheckRequest, NoRippleCheckResponse } from './norippleCheck'
|
||||
import {
|
||||
@@ -131,6 +152,8 @@ import { SubmitRequest, SubmitResponse } from './submit'
|
||||
import {
|
||||
SubmitMultisignedRequest,
|
||||
SubmitMultisignedResponse,
|
||||
SubmitMultisignedV1Response,
|
||||
SubmitMultisignedVersionResponseMap,
|
||||
} from './submitMultisigned'
|
||||
import {
|
||||
BooksSnapshot,
|
||||
@@ -151,7 +174,7 @@ import {
|
||||
TransactionEntryRequest,
|
||||
TransactionEntryResponse,
|
||||
} from './transactionEntry'
|
||||
import { TxRequest, TxResponse } from './tx'
|
||||
import { TxRequest, TxResponse, TxV1Response, TxVersionResponseMap } from './tx'
|
||||
import {
|
||||
UnsubscribeBook,
|
||||
UnsubscribeRequest,
|
||||
@@ -199,6 +222,7 @@ type Request =
|
||||
| ServerDefinitionsRequest
|
||||
| ServerInfoRequest
|
||||
| ServerStateRequest
|
||||
| FeatureRequest
|
||||
// utility methods
|
||||
| PingRequest
|
||||
| RandomRequest
|
||||
@@ -208,33 +232,36 @@ type Request =
|
||||
// clio only methods
|
||||
| NFTInfoRequest
|
||||
| NFTHistoryRequest
|
||||
| NFTsByIssuerRequest
|
||||
// AMM methods
|
||||
| AMMInfoRequest
|
||||
// Price Oracle methods
|
||||
| GetAggregatePriceRequest
|
||||
|
||||
/**
|
||||
* @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
|
||||
@@ -253,6 +280,7 @@ type Response =
|
||||
| ServerDefinitionsResponse
|
||||
| ServerInfoResponse
|
||||
| ServerStateResponse
|
||||
| FeatureResponse
|
||||
// utility methods
|
||||
| PingResponse
|
||||
| RandomResponse
|
||||
@@ -262,15 +290,21 @@ type Response =
|
||||
// clio only methods
|
||||
| NFTInfoResponse
|
||||
| NFTHistoryResponse
|
||||
| NFTsByIssuerResponse
|
||||
// AMM methods
|
||||
| AMMInfoResponse
|
||||
// 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
|
||||
@@ -280,11 +314,13 @@ export type RequestResponseMap<T> = T extends AccountChannelsRequest
|
||||
: T extends AccountOffersRequest
|
||||
? AccountOffersResponse
|
||||
: T extends AccountTxRequest
|
||||
? AccountTxResponse
|
||||
? AccountTxVersionResponseMap<Version>
|
||||
: T extends AMMInfoRequest
|
||||
? AMMInfoResponse
|
||||
: T extends GatewayBalancesRequest
|
||||
? GatewayBalancesResponse
|
||||
: T extends GetAggregatePriceRequest
|
||||
? GetAggregatePriceResponse
|
||||
: T extends NoRippleCheckRequest
|
||||
? NoRippleCheckResponse
|
||||
: // NOTE: The order of these LedgerRequest types is important
|
||||
@@ -344,15 +380,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
|
||||
@@ -364,11 +400,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
|
||||
@@ -393,6 +429,10 @@ export type RequestResponseMap<T> = T extends AccountChannelsRequest
|
||||
? ServerStateResponse
|
||||
: T extends ServerDefinitionsRequest
|
||||
? ServerDefinitionsResponse
|
||||
: T extends FeatureAllRequest
|
||||
? FeatureAllResponse
|
||||
: T extends FeatureOneRequest
|
||||
? FeatureOneResponse
|
||||
: T extends PingRequest
|
||||
? PingResponse
|
||||
: T extends RandomRequest
|
||||
@@ -403,22 +443,29 @@ export type RequestResponseMap<T> = T extends AccountChannelsRequest
|
||||
? NFTSellOffersResponse
|
||||
: T extends NFTInfoRequest
|
||||
? NFTInfoResponse
|
||||
: T extends NFTsByIssuerRequest
|
||||
? 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
|
||||
@@ -427,14 +474,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
|
||||
@@ -452,6 +497,7 @@ export {
|
||||
AccountInfoAccountFlags,
|
||||
AccountInfoRequest,
|
||||
AccountInfoResponse,
|
||||
AccountInfoV1Response,
|
||||
AccountQueueData,
|
||||
AccountQueueTransaction,
|
||||
AccountLinesRequest,
|
||||
@@ -469,15 +515,19 @@ export {
|
||||
AccountOffersResponse,
|
||||
AccountTxRequest,
|
||||
AccountTxResponse,
|
||||
AccountTxV1Response,
|
||||
AccountTxTransaction,
|
||||
GatewayBalance,
|
||||
GatewayBalancesRequest,
|
||||
GatewayBalancesResponse,
|
||||
GetAggregatePriceRequest,
|
||||
GetAggregatePriceResponse,
|
||||
NoRippleCheckRequest,
|
||||
NoRippleCheckResponse,
|
||||
// ledger methods
|
||||
LedgerRequest,
|
||||
LedgerResponse,
|
||||
LedgerV1Response,
|
||||
LedgerQueueData,
|
||||
LedgerBinary,
|
||||
LedgerModifiedOfferCreateTransaction,
|
||||
@@ -497,10 +547,12 @@ export {
|
||||
SubmitResponse,
|
||||
SubmitMultisignedRequest,
|
||||
SubmitMultisignedResponse,
|
||||
SubmitMultisignedV1Response,
|
||||
TransactionEntryRequest,
|
||||
TransactionEntryResponse,
|
||||
TxRequest,
|
||||
TxResponse,
|
||||
TxV1Response,
|
||||
// path and order book methods with types
|
||||
BookOffersRequest,
|
||||
BookOffer,
|
||||
@@ -553,6 +605,8 @@ export {
|
||||
ServerState,
|
||||
StateAccountingFinal,
|
||||
StateAccounting,
|
||||
FeatureRequest,
|
||||
FeatureResponse,
|
||||
// utility methods
|
||||
PingRequest,
|
||||
PingResponse,
|
||||
@@ -570,6 +624,8 @@ export {
|
||||
NFTHistoryRequest,
|
||||
NFTHistoryResponse,
|
||||
NFTHistoryTransaction,
|
||||
NFTsByIssuerRequest,
|
||||
NFTsByIssuerResponse,
|
||||
// AMM methods
|
||||
AMMInfoRequest,
|
||||
AMMInfoResponse,
|
||||
|
||||
@@ -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>
|
||||
}
|
||||
|
||||
68
packages/xrpl/src/models/methods/nftsByIssuer.ts
Normal file
68
packages/xrpl/src/models/methods/nftsByIssuer.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
import { NFToken } from '../common'
|
||||
|
||||
import { BaseRequest, BaseResponse, LookupByLedgerRequest } from './baseMethod'
|
||||
|
||||
/**
|
||||
* The nfts_by_issuer method returns a list of NFTokens issued by the account.
|
||||
* The order of the NFTs is not associated with the date the NFTs were minted.
|
||||
* Expects a response in the form of a {@link
|
||||
* NFTsByIssuerResponse}.
|
||||
*
|
||||
* @category Requests
|
||||
*/
|
||||
export interface NFTsByIssuerRequest
|
||||
extends BaseRequest,
|
||||
LookupByLedgerRequest {
|
||||
command: 'nfts_by_issuer'
|
||||
/**
|
||||
* A unique identifier for the account, most commonly the account's address
|
||||
*/
|
||||
issuer: string
|
||||
/**
|
||||
* Value from a previous paginated response. Resume retrieving data where
|
||||
* that response left off. This value is stable even if there is a change in
|
||||
* the server's range of available ledgers.
|
||||
*/
|
||||
marker?: unknown
|
||||
/**
|
||||
* Filter NFTs issued by this issuer that have this taxon.
|
||||
*/
|
||||
nft_taxon?: number
|
||||
/**
|
||||
* Default varies. Limit the number of transactions to retrieve. The server
|
||||
* is not required to honor this value.
|
||||
*/
|
||||
limit?: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Expected response from an {@link NFTsByIssuerRequest}.
|
||||
*
|
||||
* @category Responses
|
||||
*/
|
||||
export interface NFTsByIssuerResponse extends BaseResponse {
|
||||
result: {
|
||||
/**
|
||||
* The unique identifier for the account, most commonly the account's address
|
||||
*/
|
||||
issuer: string
|
||||
/**
|
||||
* A list of NFTs issued by the account.
|
||||
* The order of the NFTs is not associated with the date the NFTs were minted.
|
||||
*/
|
||||
nfts: NFToken[]
|
||||
/**
|
||||
* Server-defined value indicating the response is paginated. Pass this
|
||||
* to the next call to resume where this call left off.
|
||||
*/
|
||||
marker?: unknown
|
||||
/**
|
||||
* The limit value used in the request.
|
||||
*/
|
||||
limit?: number
|
||||
/**
|
||||
* Use to filter NFTs issued by this issuer that have this taxon.
|
||||
*/
|
||||
nft_taxon?: number
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
import { APIVersion, DEFAULT_API_VERSION, RIPPLED_API_V1 } from '../common'
|
||||
import { Transaction } from '../transactions'
|
||||
|
||||
import { BaseRequest, BaseResponse } from './baseMethod'
|
||||
@@ -24,28 +25,59 @@ export interface SubmitMultisignedRequest extends BaseRequest {
|
||||
fail_hard?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Common properties for multisigned transaction responses.
|
||||
*
|
||||
* @category Responses
|
||||
*/
|
||||
interface BaseSubmitMultisignedResult {
|
||||
/**
|
||||
* Code indicating the preliminary result of the transaction, for example.
|
||||
* `tesSUCCESS`.
|
||||
*/
|
||||
engine_result: string
|
||||
/**
|
||||
* Numeric code indicating the preliminary result of the transaction,
|
||||
* directly correlated to `engine_result`.
|
||||
*/
|
||||
engine_result_code: number
|
||||
/** Human-readable explanation of the preliminary transaction result. */
|
||||
engine_result_message: string
|
||||
/** 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: {
|
||||
/**
|
||||
* Code indicating the preliminary result of the transaction, for example.
|
||||
* `tesSUCCESS` .
|
||||
*/
|
||||
engine_result: string
|
||||
/**
|
||||
* Numeric code indicating the preliminary result of the transaction,
|
||||
* directly correlated to `engine_result`.
|
||||
*/
|
||||
engine_result_code: number
|
||||
/** Human-readable explanation of the preliminary transaction result. */
|
||||
engine_result_message: string
|
||||
/** The complete transaction in hex string format. */
|
||||
tx_blob: string
|
||||
/** The complete transaction in JSON format. */
|
||||
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'
|
||||
|
||||
@@ -41,6 +47,47 @@ export interface TxRequest extends BaseRequest {
|
||||
max_ledger?: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Common properties of transaction responses.
|
||||
*
|
||||
* @category Responses
|
||||
*/
|
||||
interface BaseTxResult<
|
||||
Version extends APIVersion = typeof DEFAULT_API_VERSION,
|
||||
T extends BaseTransaction = Transaction,
|
||||
> {
|
||||
/** The SHA-512 hash of the transaction. */
|
||||
hash: string
|
||||
/**
|
||||
* The Concise Transaction Identifier of the transaction (16-byte hex string)
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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
|
||||
}
|
||||
|
||||
/**
|
||||
* Response expected from a {@link TxRequest}.
|
||||
*
|
||||
@@ -48,28 +95,7 @@ export interface TxRequest extends BaseRequest {
|
||||
*/
|
||||
export interface TxResponse<T extends BaseTransaction = Transaction>
|
||||
extends BaseResponse {
|
||||
result: {
|
||||
/** The SHA-512 hash of the transaction. */
|
||||
hash: string
|
||||
/**
|
||||
* The Concise Transaction Identifier of the transaction (16-byte hex string)
|
||||
*/
|
||||
ctid?: string
|
||||
/** The ledger index of the ledger that includes this transaction. */
|
||||
ledger_index?: number
|
||||
/** 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.
|
||||
*/
|
||||
validated?: boolean
|
||||
/**
|
||||
* This number measures the number of seconds since the "Ripple Epoch" of January 1, 2000 (00:00 UTC)
|
||||
*/
|
||||
date?: number
|
||||
} & T
|
||||
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
|
||||
|
||||
@@ -21,6 +21,7 @@ export enum AMMDepositFlags {
|
||||
tfTwoAsset = 0x00100000,
|
||||
tfOneAssetLPToken = 0x00200000,
|
||||
tfLimitLPToken = 0x00400000,
|
||||
tfTwoAssetIfEmpty = 0x00800000,
|
||||
}
|
||||
|
||||
export interface AMMDepositFlagsInterface extends GlobalFlags {
|
||||
@@ -29,6 +30,7 @@ export interface AMMDepositFlagsInterface extends GlobalFlags {
|
||||
tfTwoAsset?: boolean
|
||||
tfOneAssetLPToken?: boolean
|
||||
tfLimitLPToken?: boolean
|
||||
tfTwoAssetIfEmpty?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -58,6 +58,8 @@ export {
|
||||
OfferCreateFlagsInterface,
|
||||
OfferCreate,
|
||||
} from './offerCreate'
|
||||
export { OracleDelete } from './oracleDelete'
|
||||
export { OracleSet } from './oracleSet'
|
||||
export { PaymentFlags, PaymentFlagsInterface, Payment } from './payment'
|
||||
export {
|
||||
PaymentChannelClaimFlags,
|
||||
|
||||
@@ -40,6 +40,7 @@ export interface DeletedNode {
|
||||
DeletedNode: {
|
||||
LedgerEntryType: string
|
||||
LedgerIndex: string
|
||||
PreviousFields?: { [field: string]: unknown }
|
||||
FinalFields: { [field: string]: unknown }
|
||||
}
|
||||
}
|
||||
|
||||
32
packages/xrpl/src/models/transactions/oracleDelete.ts
Normal file
32
packages/xrpl/src/models/transactions/oracleDelete.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import {
|
||||
BaseTransaction,
|
||||
isNumber,
|
||||
validateBaseTransaction,
|
||||
validateRequiredField,
|
||||
} from './common'
|
||||
|
||||
/**
|
||||
* Delete an Oracle ledger entry.
|
||||
*
|
||||
* @category Transaction Models
|
||||
*/
|
||||
export interface OracleDelete extends BaseTransaction {
|
||||
TransactionType: 'OracleDelete'
|
||||
|
||||
/**
|
||||
* A unique identifier of the price oracle for the Account.
|
||||
*/
|
||||
OracleDocumentID: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the form and type of a OracleDelete at runtime.
|
||||
*
|
||||
* @param tx - A OracleDelete Transaction.
|
||||
* @throws When the OracleDelete is malformed.
|
||||
*/
|
||||
export function validateOracleDelete(tx: Record<string, unknown>): void {
|
||||
validateBaseTransaction(tx)
|
||||
|
||||
validateRequiredField(tx, 'OracleDocumentID', isNumber)
|
||||
}
|
||||
176
packages/xrpl/src/models/transactions/oracleSet.ts
Normal file
176
packages/xrpl/src/models/transactions/oracleSet.ts
Normal file
@@ -0,0 +1,176 @@
|
||||
import { ValidationError } from '../../errors'
|
||||
import { PriceData } from '../common'
|
||||
|
||||
import {
|
||||
BaseTransaction,
|
||||
isNumber,
|
||||
isString,
|
||||
validateBaseTransaction,
|
||||
validateOptionalField,
|
||||
validateRequiredField,
|
||||
} from './common'
|
||||
|
||||
const PRICE_DATA_SERIES_MAX_LENGTH = 10
|
||||
const SCALE_MAX = 10
|
||||
|
||||
/**
|
||||
* Creates a new Oracle ledger entry or updates the fields of an existing one, using the Oracle ID.
|
||||
*
|
||||
* The oracle provider must complete these steps before submitting this transaction:
|
||||
* 1. Create or own the XRPL account in the Owner field and have enough XRP to meet the reserve and transaction fee requirements.
|
||||
* 2. Publish the XRPL account public key, so it can be used for verification by dApps.
|
||||
* 3. Publish a registry of available price oracles with their unique OracleDocumentID.
|
||||
*
|
||||
* @category Transaction Models
|
||||
*/
|
||||
export interface OracleSet extends BaseTransaction {
|
||||
TransactionType: 'OracleSet'
|
||||
|
||||
/**
|
||||
* A unique identifier of the price oracle for the Account.
|
||||
*/
|
||||
OracleDocumentID: number
|
||||
|
||||
/**
|
||||
* The time the data was last updated, represented as a unix timestamp in seconds.
|
||||
*/
|
||||
LastUpdateTime: number
|
||||
|
||||
/**
|
||||
* An array of up to 10 PriceData objects, each representing the price information
|
||||
* for a token pair. More than five PriceData objects require two owner reserves.
|
||||
*/
|
||||
PriceDataSeries: PriceData[]
|
||||
|
||||
/**
|
||||
* An arbitrary value that identifies an oracle provider, such as Chainlink, Band,
|
||||
* or DIA. This field is a string, up to 256 ASCII hex encoded characters (0x20-0x7E).
|
||||
* This field is required when creating a new Oracle ledger entry, but is optional for updates.
|
||||
*/
|
||||
Provider?: string
|
||||
|
||||
/**
|
||||
* An optional Universal Resource Identifier to reference price data off-chain. This field is limited to 256 bytes.
|
||||
*/
|
||||
URI?: string
|
||||
|
||||
/**
|
||||
* Describes the type of asset, such as "currency", "commodity", or "index". This field is a string, up to 16 ASCII
|
||||
* hex encoded characters (0x20-0x7E). This field is required when creating a new Oracle ledger entry, but is optional
|
||||
* for updates.
|
||||
*/
|
||||
AssetClass?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the form and type of a OracleSet at runtime.
|
||||
*
|
||||
* @param tx - A OracleSet Transaction.
|
||||
* @throws When the OracleSet is malformed.
|
||||
*/
|
||||
// eslint-disable-next-line max-lines-per-function -- necessary to validate many fields
|
||||
export function validateOracleSet(tx: Record<string, unknown>): void {
|
||||
validateBaseTransaction(tx)
|
||||
|
||||
validateRequiredField(tx, 'OracleDocumentID', isNumber)
|
||||
|
||||
validateRequiredField(tx, 'LastUpdateTime', isNumber)
|
||||
|
||||
validateOptionalField(tx, 'Provider', isString)
|
||||
|
||||
validateOptionalField(tx, 'URI', isString)
|
||||
|
||||
validateOptionalField(tx, 'AssetClass', isString)
|
||||
|
||||
// eslint-disable-next-line max-lines-per-function -- necessary to validate many fields
|
||||
validateRequiredField(tx, 'PriceDataSeries', (value) => {
|
||||
if (!Array.isArray(value)) {
|
||||
throw new ValidationError('OracleSet: PriceDataSeries must be an array')
|
||||
}
|
||||
|
||||
if (value.length > PRICE_DATA_SERIES_MAX_LENGTH) {
|
||||
throw new ValidationError(
|
||||
`OracleSet: PriceDataSeries must have at most ${PRICE_DATA_SERIES_MAX_LENGTH} PriceData objects`,
|
||||
)
|
||||
}
|
||||
|
||||
// TODO: add support for handling inner objects easier (similar to validateRequiredField/validateOptionalField)
|
||||
for (const priceData of value) {
|
||||
if (typeof priceData !== 'object') {
|
||||
throw new ValidationError(
|
||||
'OracleSet: PriceDataSeries must be an array of objects',
|
||||
)
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access -- we are validating the type
|
||||
if (priceData.PriceData == null) {
|
||||
throw new ValidationError(
|
||||
'OracleSet: PriceDataSeries must have a `PriceData` object',
|
||||
)
|
||||
}
|
||||
|
||||
// check if priceData only has PriceData
|
||||
if (Object.keys(priceData).length !== 1) {
|
||||
throw new ValidationError(
|
||||
'OracleSet: PriceDataSeries must only have a single PriceData object',
|
||||
)
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access -- we are validating the type
|
||||
if (typeof priceData.PriceData.BaseAsset !== 'string') {
|
||||
throw new ValidationError(
|
||||
'OracleSet: PriceDataSeries must have a `BaseAsset` string',
|
||||
)
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access -- we are validating the type
|
||||
if (typeof priceData.PriceData.QuoteAsset !== 'string') {
|
||||
throw new ValidationError(
|
||||
'OracleSet: PriceDataSeries must have a `QuoteAsset` string',
|
||||
)
|
||||
}
|
||||
|
||||
// Either AssetPrice and Scale are both present or both excluded
|
||||
if (
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access -- we are validating the type
|
||||
(priceData.PriceData.AssetPrice == null) !==
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access -- we are validating the type
|
||||
(priceData.PriceData.Scale == null)
|
||||
) {
|
||||
throw new ValidationError(
|
||||
'OracleSet: PriceDataSeries must have both `AssetPrice` and `Scale` if any are present',
|
||||
)
|
||||
}
|
||||
|
||||
if (
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access -- we are validating the type
|
||||
'AssetPrice' in priceData.PriceData &&
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access -- we are validating the type
|
||||
!isNumber(priceData.PriceData.AssetPrice)
|
||||
) {
|
||||
throw new ValidationError('OracleSet: invalid field AssetPrice')
|
||||
}
|
||||
|
||||
if (
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access -- we are validating the type
|
||||
'Scale' in priceData.PriceData &&
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access -- we are validating the type
|
||||
!isNumber(priceData.PriceData.Scale)
|
||||
) {
|
||||
throw new ValidationError('OracleSet: invalid field Scale')
|
||||
}
|
||||
|
||||
if (
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access -- we are validating the type
|
||||
priceData.PriceData.Scale < 0 ||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access -- we are validating the type
|
||||
priceData.PriceData.Scale > SCALE_MAX
|
||||
) {
|
||||
throw new ValidationError(
|
||||
`OracleSet: Scale must be in range 0-${SCALE_MAX}`,
|
||||
)
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
@@ -26,7 +26,7 @@ export enum PaymentFlags {
|
||||
* This is intended to force the transaction to take arbitrage opportunities.
|
||||
* Most clients do not need this.
|
||||
*/
|
||||
tfNoDirectRipple = 0x00010000,
|
||||
tfNoRippleDirect = 0x00010000,
|
||||
/**
|
||||
* If the specified Amount cannot be sent without spending more than SendMax,
|
||||
* reduce the received amount instead of failing outright. See Partial.
|
||||
@@ -88,7 +88,7 @@ export interface PaymentFlagsInterface extends GlobalFlags {
|
||||
* This is intended to force the transaction to take arbitrage opportunities.
|
||||
* Most clients do not need this.
|
||||
*/
|
||||
tfNoDirectRipple?: boolean
|
||||
tfNoRippleDirect?: boolean
|
||||
/**
|
||||
* If the specified Amount cannot be sent without spending more than SendMax,
|
||||
* reduce the received amount instead of failing outright. See Partial.
|
||||
|
||||
@@ -43,6 +43,8 @@ import {
|
||||
import { NFTokenMint, validateNFTokenMint } from './NFTokenMint'
|
||||
import { OfferCancel, validateOfferCancel } from './offerCancel'
|
||||
import { OfferCreate, validateOfferCreate } from './offerCreate'
|
||||
import { OracleDelete, validateOracleDelete } from './oracleDelete'
|
||||
import { OracleSet, validateOracleSet } from './oracleSet'
|
||||
import { Payment, validatePayment } from './payment'
|
||||
import {
|
||||
PaymentChannelClaim,
|
||||
@@ -120,6 +122,8 @@ export type SubmittableTransaction =
|
||||
| NFTokenMint
|
||||
| OfferCancel
|
||||
| OfferCreate
|
||||
| OracleDelete
|
||||
| OracleSet
|
||||
| Payment
|
||||
| PaymentChannelClaim
|
||||
| PaymentChannelCreate
|
||||
@@ -330,6 +334,14 @@ export function validate(transaction: Record<string, unknown>): void {
|
||||
validateOfferCreate(tx)
|
||||
break
|
||||
|
||||
case 'OracleDelete':
|
||||
validateOracleDelete(tx)
|
||||
break
|
||||
|
||||
case 'OracleSet':
|
||||
validateOracleSet(tx)
|
||||
break
|
||||
|
||||
case 'Payment':
|
||||
validatePayment(tx)
|
||||
break
|
||||
|
||||
@@ -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'
|
||||
@@ -17,7 +17,6 @@ const LEDGER_OFFSET = 20
|
||||
// Mainnet and testnet are exceptions. More context: https://github.com/XRPLF/rippled/pull/4370
|
||||
const RESTRICTED_NETWORKS = 1024
|
||||
const REQUIRED_NETWORKID_VERSION = '1.11.0'
|
||||
const HOOKS_TESTNET_ID = 21338
|
||||
|
||||
/**
|
||||
* Determines whether the source rippled version is not later than the target rippled version.
|
||||
@@ -87,8 +86,7 @@ function isNotLaterRippledVersion(source: string, target: string): boolean {
|
||||
|
||||
/**
|
||||
* Determine if the transaction required a networkID to be valid.
|
||||
* Transaction needs networkID if later than restricted ID and either the network is hooks testnet
|
||||
* or build version is >= 1.11.0
|
||||
* Transaction needs networkID if later than restricted ID and build version is >= 1.11.0
|
||||
*
|
||||
* @param client -- The connected client.
|
||||
* @returns True if required networkID, false otherwise.
|
||||
@@ -99,12 +97,8 @@ export function txNeedsNetworkID(client: Client): boolean {
|
||||
client.networkID > RESTRICTED_NETWORKS
|
||||
) {
|
||||
if (
|
||||
(client.buildVersion &&
|
||||
isNotLaterRippledVersion(
|
||||
REQUIRED_NETWORKID_VERSION,
|
||||
client.buildVersion,
|
||||
)) ||
|
||||
client.networkID === HOOKS_TESTNET_ID
|
||||
client.buildVersion &&
|
||||
isNotLaterRippledVersion(REQUIRED_NETWORKID_VERSION, client.buildVersion)
|
||||
) {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -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'])
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
Payment,
|
||||
Transaction,
|
||||
} from '../../src'
|
||||
import { ValidationError } from '../../src/errors'
|
||||
import rippled from '../fixtures/rippled'
|
||||
import {
|
||||
setupClient,
|
||||
@@ -19,10 +20,11 @@ const NetworkID = 1025
|
||||
const Fee = '10'
|
||||
const Sequence = 1432
|
||||
const LastLedgerSequence = 2908734
|
||||
const HOOKS_TESTNET_ID = 21338
|
||||
|
||||
describe('client.autofill', function () {
|
||||
let testContext: XrplTestContext
|
||||
const AMOUNT = '1234'
|
||||
let paymentTx: Payment
|
||||
|
||||
async function setupMockRippledVersionAndID(
|
||||
buildVersion: string,
|
||||
@@ -41,10 +43,68 @@ describe('client.autofill', function () {
|
||||
await testContext.client.connect()
|
||||
}
|
||||
|
||||
beforeEach(async () => {
|
||||
beforeAll(async () => {
|
||||
testContext = await setupClient()
|
||||
})
|
||||
afterEach(async () => teardownClient(testContext))
|
||||
afterAll(async () => teardownClient(testContext))
|
||||
|
||||
beforeEach(async () => {
|
||||
paymentTx = {
|
||||
TransactionType: 'Payment',
|
||||
Account: 'rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo',
|
||||
Amount: AMOUNT,
|
||||
Destination: 'rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy',
|
||||
DestinationTag: 1,
|
||||
Fee: '12',
|
||||
Flags: 2147483648,
|
||||
LastLedgerSequence: 65953073,
|
||||
Sequence: 65923914,
|
||||
SigningPubKey:
|
||||
'02F9E33F16DF9507705EC954E3F94EB5F10D1FC4A354606DBE6297DBB1096FE654',
|
||||
TxnSignature:
|
||||
'3045022100E3FAE0EDEC3D6A8FF6D81BC9CF8288A61B7EEDE8071E90FF9314CB4621058D10022043545CF631706D700CEE65A1DB83EFDD185413808292D9D90F14D87D3DC2D8CB',
|
||||
InvoiceID:
|
||||
'6F1DFD1D0FE8A32E40E1F2C05CF1C15545BAB56B617F9C6C2D63A6B704BEF59B',
|
||||
Paths: [
|
||||
[{ currency: 'BTC', issuer: 'r9vbV3EHvXWjSkeQ6CAcYVPGeq7TuiXY2X' }],
|
||||
],
|
||||
SendMax: '100000000',
|
||||
}
|
||||
})
|
||||
|
||||
it('Validate Payment transaction API v2: Payment Transaction: Specify Only Amount field', async function () {
|
||||
const txResult = await testContext.client.autofill(paymentTx)
|
||||
|
||||
assert.strictEqual(txResult.Amount, AMOUNT)
|
||||
})
|
||||
|
||||
it('Validate Payment transaction API v2: Payment Transaction: Specify Only DeliverMax field', async function () {
|
||||
// @ts-expect-error -- DeliverMax is a non-protocol, RPC level field in Payment transactions
|
||||
paymentTx.DeliverMax = paymentTx.Amount
|
||||
// @ts-expect-error -- DeliverMax is a non-protocol, RPC level field in Payment transactions
|
||||
delete paymentTx.Amount
|
||||
const txResult = await testContext.client.autofill(paymentTx)
|
||||
|
||||
assert.strictEqual(txResult.Amount, AMOUNT)
|
||||
})
|
||||
|
||||
it('Validate Payment transaction API v2: Payment Transaction: identical DeliverMax and Amount fields', async function () {
|
||||
// @ts-expect-error -- DeliverMax is a non-protocol, RPC level field in Payment transactions
|
||||
paymentTx.DeliverMax = paymentTx.Amount
|
||||
|
||||
const txResult = await testContext.client.autofill(paymentTx)
|
||||
|
||||
assert.strictEqual(txResult.Amount, AMOUNT)
|
||||
assert.strictEqual('DeliverMax' in txResult, false)
|
||||
})
|
||||
|
||||
it('Validate Payment transaction API v2: Payment Transaction: differing DeliverMax and Amount fields', async function () {
|
||||
// @ts-expect-error -- DeliverMax is a non-protocol, RPC level field in Payment transactions
|
||||
paymentTx.DeliverMax = '6789'
|
||||
paymentTx.Amount = '1234'
|
||||
|
||||
await assertRejects(testContext.client.autofill(paymentTx), ValidationError)
|
||||
})
|
||||
|
||||
it('should not autofill if fields are present', async function () {
|
||||
const tx: Transaction = {
|
||||
@@ -141,26 +201,6 @@ describe('client.autofill', function () {
|
||||
assert.strictEqual(txResult.NetworkID, undefined)
|
||||
})
|
||||
|
||||
// Hooks Testnet requires networkID in transaction regardless of version.
|
||||
// More context: https://github.com/XRPLF/rippled/pull/4370
|
||||
it('overrides network ID for hooks testnet', async function () {
|
||||
await setupMockRippledVersionAndID('1.10.1', HOOKS_TESTNET_ID)
|
||||
const tx: Payment = {
|
||||
TransactionType: 'Payment',
|
||||
Account: 'XVLhHMPHU98es4dbozjVtdWzVrDjtV18pX8yuPT7y4xaEHi',
|
||||
Amount: '1234',
|
||||
Destination: 'X7AcgcsBL6XDcUb289X4mJ8djcdyKaB5hJDWMArnXr61cqZ',
|
||||
Fee,
|
||||
Sequence,
|
||||
LastLedgerSequence,
|
||||
}
|
||||
testContext.mockRippled!.addResponse('ledger', rippled.ledger.normal)
|
||||
|
||||
const txResult = await testContext.client.autofill(tx)
|
||||
|
||||
assert.strictEqual(txResult.NetworkID, HOOKS_TESTNET_ID)
|
||||
})
|
||||
|
||||
it('converts Account & Destination X-address to their classic address', async function () {
|
||||
const tx: Payment = {
|
||||
TransactionType: 'Payment',
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -10,9 +10,18 @@ import {
|
||||
|
||||
const rippledResponse = function (request: Request): Record<string, unknown> {
|
||||
if ('marker' in request) {
|
||||
return rippled.ledger_data.last_page
|
||||
return rippled.ledger_data.lastPage
|
||||
}
|
||||
return rippled.ledger_data.first_page
|
||||
return rippled.ledger_data.firstPage
|
||||
}
|
||||
|
||||
const rippledResponseFirstEmpty = function (
|
||||
request: Request,
|
||||
): Record<string, unknown> {
|
||||
if ('marker' in request) {
|
||||
return rippled.ledger_data.lastPage
|
||||
}
|
||||
return rippled.ledger_data.firstPageEmpty
|
||||
}
|
||||
|
||||
describe('client.requestAll', function () {
|
||||
@@ -34,14 +43,25 @@ describe('client.requestAll', function () {
|
||||
)
|
||||
})
|
||||
|
||||
it('rejects when there are no more pages', async function () {
|
||||
it('stops when there are no more pages', async function () {
|
||||
testContext.mockRippled!.addResponse(
|
||||
'ledger_data',
|
||||
rippled.ledger_data.last_page,
|
||||
rippled.ledger_data.lastPage,
|
||||
)
|
||||
const allResponses = await testContext.client.requestAll({
|
||||
command: 'ledger_data',
|
||||
})
|
||||
assert.equal(allResponses.length, 1)
|
||||
})
|
||||
|
||||
it('handles when the first page has no results', async function () {
|
||||
testContext.mockRippled!.addResponse(
|
||||
'ledger_data',
|
||||
rippledResponseFirstEmpty,
|
||||
)
|
||||
const allResponses = await testContext.client.requestAll({
|
||||
command: 'ledger_data',
|
||||
})
|
||||
assert.equal(allResponses.length, 2)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -11,9 +11,9 @@ import { assertRejects } from '../testUtils'
|
||||
|
||||
const rippledResponse = function (request: Request): Record<string, unknown> {
|
||||
if ('marker' in request) {
|
||||
return rippled.ledger_data.last_page
|
||||
return rippled.ledger_data.lastPage
|
||||
}
|
||||
return rippled.ledger_data.first_page
|
||||
return rippled.ledger_data.firstPage
|
||||
}
|
||||
|
||||
describe('client.requestNextPage', function () {
|
||||
|
||||
@@ -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",
|
||||
|
||||
10
packages/xrpl/test/fixtures/rippled/index.ts
vendored
10
packages/xrpl/test/fixtures/rippled/index.ts
vendored
@@ -6,8 +6,9 @@ import fabric from './bookOffers'
|
||||
import usd_xrp from './bookOffersUsdXrp.json'
|
||||
import xrp_usd from './bookOffersXrpUsd.json'
|
||||
import normalLedger from './ledger.json'
|
||||
import first_page from './ledgerDataFirstPage.json'
|
||||
import last_page from './ledgerDataLastPage.json'
|
||||
import firstPage from './ledgerDataFirstPage.json'
|
||||
import firstPageEmpty from './ledgerDataFirstPageEmpty.json'
|
||||
import lastPage from './ledgerDataLastPage.json'
|
||||
import iouPartialPayment from './partialPaymentIOU.json'
|
||||
import xrpPartialPayment from './partialPaymentXRP.json'
|
||||
import normalServerInfo from './serverInfo.json'
|
||||
@@ -82,8 +83,9 @@ const book_offers = {
|
||||
}
|
||||
|
||||
const ledger_data = {
|
||||
first_page,
|
||||
last_page,
|
||||
firstPage,
|
||||
firstPageEmpty,
|
||||
lastPage,
|
||||
}
|
||||
|
||||
const server_info = {
|
||||
|
||||
14
packages/xrpl/test/fixtures/rippled/ledgerDataFirstPageEmpty.json
vendored
Normal file
14
packages/xrpl/test/fixtures/rippled/ledgerDataFirstPageEmpty.json
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"id": 0,
|
||||
"status": "success",
|
||||
"type": "response",
|
||||
"result": {
|
||||
"ledger_hash":
|
||||
"102A6E70FFB18C18E97BB56E3047B0E45EA1BCC90BFCCB8CBB0D07BF0E2AB449",
|
||||
"ledger_index": 38202000,
|
||||
"marker":
|
||||
"000B714B790C3C79FEE00D17C4DEB436B375466F29679447BA64F265FD63D730",
|
||||
"state": [],
|
||||
"validated": true
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,20 @@
|
||||
{
|
||||
"Account": "rGFuMiw48HdbnrUbkRYuitXTmfrDBNTCnX",
|
||||
"Amount": {
|
||||
"currency": "USD",
|
||||
"issuer": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B",
|
||||
"value": "10"
|
||||
"tx_json": {
|
||||
"Account": "rGFuMiw48HdbnrUbkRYuitXTmfrDBNTCnX",
|
||||
"DeliverMax": {
|
||||
"currency": "USD",
|
||||
"issuer": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B",
|
||||
"value": "10"
|
||||
},
|
||||
"Destination": "rNNuQMuExCiEjeZ4h9JJnj5PSWypdMXDj4",
|
||||
"Fee": "10000",
|
||||
"Flags": 131072,
|
||||
"Sequence": 23295,
|
||||
"SigningPubKey": "02B205F4B92351AC0EEB04254B636F4C49EF922CFA3CAAD03C6477DA1E04E94B53",
|
||||
"TransactionType": "Payment",
|
||||
"TxnSignature": "3045022100FAF247A836D601DE74A515B2AADE31186D8B0DA9C23DE489E09753F5CF4BB81F0220477C5B5BC3AC89F2347744F9E00CCA62267E198489D747578162C4C7D156211D",
|
||||
"hash": "A0A074D10355223CBE2520A42F93A52E3CC8B4D692570EB4841084F9BBB39F7A"
|
||||
},
|
||||
"Destination": "rNNuQMuExCiEjeZ4h9JJnj5PSWypdMXDj4",
|
||||
"Fee": "10000",
|
||||
"Flags": 131072,
|
||||
"Sequence": 23295,
|
||||
"SigningPubKey": "02B205F4B92351AC0EEB04254B636F4C49EF922CFA3CAAD03C6477DA1E04E94B53",
|
||||
"TransactionType": "Payment",
|
||||
"TxnSignature": "3045022100FAF247A836D601DE74A515B2AADE31186D8B0DA9C23DE489E09753F5CF4BB81F0220477C5B5BC3AC89F2347744F9E00CCA62267E198489D747578162C4C7D156211D",
|
||||
"hash": "A0A074D10355223CBE2520A42F93A52E3CC8B4D692570EB4841084F9BBB39F7A",
|
||||
"meta": {
|
||||
"AffectedNodes": [
|
||||
{
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
{
|
||||
"Account": "rGFuMiw48HdbnrUbkRYuitXTmfrDBNTCnX",
|
||||
"Amount": "2000000",
|
||||
"Destination": "rNNuQMuExCiEjeZ4h9JJnj5PSWypdMXDj4",
|
||||
"Fee": "10000",
|
||||
"Flags": 131072,
|
||||
"Sequence": 23295,
|
||||
"SigningPubKey": "02B205F4B92351AC0EEB04254B636F4C49EF922CFA3CAAD03C6477DA1E04E94B53",
|
||||
"TransactionType": "Payment",
|
||||
"TxnSignature": "3045022100FAF247A836D601DE74A515B2AADE31186D8B0DA9C23DE489E09753F5CF4BB81F0220477C5B5BC3AC89F2347744F9E00CCA62267E198489D747578162C4C7D156211D",
|
||||
"hash": "A0A074D10355223CBE2520A42F93A52E3CC8B4D692570EB4841084F9BBB39F7A",
|
||||
"tx_json": {
|
||||
"Account": "rGFuMiw48HdbnrUbkRYuitXTmfrDBNTCnX",
|
||||
"DeliverMax": "2000000",
|
||||
"Destination": "rNNuQMuExCiEjeZ4h9JJnj5PSWypdMXDj4",
|
||||
"Fee": "10000",
|
||||
"Flags": 131072,
|
||||
"Sequence": 23295,
|
||||
"SigningPubKey": "02B205F4B92351AC0EEB04254B636F4C49EF922CFA3CAAD03C6477DA1E04E94B53",
|
||||
"TransactionType": "Payment",
|
||||
"TxnSignature": "3045022100FAF247A836D601DE74A515B2AADE31186D8B0DA9C23DE489E09753F5CF4BB81F0220477C5B5BC3AC89F2347744F9E00CCA62267E198489D747578162C4C7D156211D",
|
||||
"hash": "A0A074D10355223CBE2520A42F93A52E3CC8B4D692570EB4841084F9BBB39F7A"
|
||||
},
|
||||
"meta": {
|
||||
"AffectedNodes": [
|
||||
{
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
},
|
||||
"tx_json": {
|
||||
"Account": "rLSn6Z3T8uCxbcd1oxwfGQN1Fdn5CyGujK",
|
||||
"Amount": "104169972",
|
||||
"DeliverMax": "104169972",
|
||||
"Destination": "rEb8TK3gBgk5auZkwc6sHnwrGVJH8DuaLh",
|
||||
"DestinationTag": 109735445,
|
||||
"Fee": "6000",
|
||||
|
||||
@@ -3,41 +3,43 @@
|
||||
"status": "success",
|
||||
"type": "response",
|
||||
"result": {
|
||||
"Account": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59",
|
||||
"Amount": {
|
||||
"currency": "USD",
|
||||
"issuer": "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM",
|
||||
"value": "0.001"
|
||||
"tx_json": {
|
||||
"Account": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59",
|
||||
"DeliverMax": {
|
||||
"currency": "USD",
|
||||
"issuer": "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM",
|
||||
"value": "0.001"
|
||||
},
|
||||
"Destination": "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM",
|
||||
"Fee": "10",
|
||||
"Flags": 0,
|
||||
"Paths": [
|
||||
[
|
||||
{
|
||||
"currency": "USD",
|
||||
"issuer": "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo",
|
||||
"type": 48,
|
||||
"type_hex": "0000000000000030"
|
||||
},
|
||||
{
|
||||
"account": "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo",
|
||||
"currency": "USD",
|
||||
"issuer": "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo",
|
||||
"type": 49,
|
||||
"type_hex": "0000000000000031"
|
||||
}
|
||||
]
|
||||
],
|
||||
"SendMax": "1112209",
|
||||
"Sequence": 4,
|
||||
"SigningPubKey": "02BC8C02199949B15C005B997E7C8594574E9B02BA2D0628902E0532989976CF9D",
|
||||
"TransactionType": "Payment",
|
||||
"TxnSignature": "304502204EE3E9D1B01D8959B08450FCA9E22025AF503DEF310E34A93863A85CAB3C0BC5022100B61F5B567F77026E8DEED89EED0B7CAF0E6C96C228A2A65216F0DC2D04D52083",
|
||||
"date": 416447810,
|
||||
"inLedger": 348860,
|
||||
"ledger_index": 348860,
|
||||
"hash": "F4AB442A6D4CBB935D66E1DA7309A5FC71C7143ED4049053EC14E3875B0CF9BF"
|
||||
},
|
||||
"Destination": "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM",
|
||||
"Fee": "10",
|
||||
"Flags": 0,
|
||||
"Paths": [
|
||||
[
|
||||
{
|
||||
"currency": "USD",
|
||||
"issuer": "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo",
|
||||
"type": 48,
|
||||
"type_hex": "0000000000000030"
|
||||
},
|
||||
{
|
||||
"account": "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo",
|
||||
"currency": "USD",
|
||||
"issuer": "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo",
|
||||
"type": 49,
|
||||
"type_hex": "0000000000000031"
|
||||
}
|
||||
]
|
||||
],
|
||||
"SendMax": "1112209",
|
||||
"Sequence": 4,
|
||||
"SigningPubKey": "02BC8C02199949B15C005B997E7C8594574E9B02BA2D0628902E0532989976CF9D",
|
||||
"TransactionType": "Payment",
|
||||
"TxnSignature": "304502204EE3E9D1B01D8959B08450FCA9E22025AF503DEF310E34A93863A85CAB3C0BC5022100B61F5B567F77026E8DEED89EED0B7CAF0E6C96C228A2A65216F0DC2D04D52083",
|
||||
"date": 416447810,
|
||||
"hash": "F4AB442A6D4CBB935D66E1DA7309A5FC71C7143ED4049053EC14E3875B0CF9BF",
|
||||
"inLedger": 348860,
|
||||
"ledger_index": 348860,
|
||||
"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`
|
||||
|
||||
@@ -83,40 +83,6 @@ describe('fundWallet', function () {
|
||||
// )
|
||||
// })
|
||||
|
||||
it(
|
||||
'can generate wallet on hooks v3 testnet',
|
||||
async function () {
|
||||
const api = new Client('wss://hooks-testnet-v3.xrpl-labs.com')
|
||||
|
||||
await api.connect()
|
||||
|
||||
const { wallet, balance } = await api.fundWallet(null, {
|
||||
usageContext: 'integration-test',
|
||||
})
|
||||
|
||||
assert.notStrictEqual(wallet, undefined)
|
||||
assert(isValidClassicAddress(wallet.classicAddress))
|
||||
assert(isValidXAddress(wallet.getXAddress()))
|
||||
|
||||
const info = await api.request({
|
||||
command: 'account_info',
|
||||
account: wallet.classicAddress,
|
||||
})
|
||||
|
||||
assert.equal(dropsToXrp(info.result.account_data.Balance), balance)
|
||||
assert.equal(balance, 10000)
|
||||
|
||||
/*
|
||||
* No test for fund given wallet because the hooks v3 testnet faucet
|
||||
* requires 10 seconds between requests. Would significantly slow down
|
||||
* the test suite.
|
||||
*/
|
||||
|
||||
await api.disconnect()
|
||||
},
|
||||
TIMEOUT,
|
||||
)
|
||||
|
||||
it(
|
||||
'submit funds wallet with custom amount',
|
||||
async function () {
|
||||
@@ -124,10 +90,10 @@ describe('fundWallet', function () {
|
||||
|
||||
await api.connect()
|
||||
const { wallet, balance } = await api.fundWallet(null, {
|
||||
amount: '2000',
|
||||
amount: '1000',
|
||||
usageContext: 'integration-test',
|
||||
})
|
||||
assert.equal(balance, 2000)
|
||||
assert.equal(balance, 1000)
|
||||
assert.notStrictEqual(wallet, undefined)
|
||||
assert(isValidClassicAddress(wallet.classicAddress))
|
||||
assert(isValidXAddress(wallet.getXAddress()))
|
||||
|
||||
@@ -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: {
|
||||
|
||||
68
packages/xrpl/test/integration/requests/feature.test.ts
Normal file
68
packages/xrpl/test/integration/requests/feature.test.ts
Normal 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,
|
||||
)
|
||||
})
|
||||
@@ -0,0 +1,78 @@
|
||||
import { stringToHex } from '@xrplf/isomorphic/utils'
|
||||
import { assert } from 'chai'
|
||||
|
||||
import { OracleSet } from '../../../src'
|
||||
import serverUrl from '../serverUrl'
|
||||
import {
|
||||
setupClient,
|
||||
teardownClient,
|
||||
type XrplIntegrationTestContext,
|
||||
} from '../setup'
|
||||
import { testTransaction } from '../utils'
|
||||
|
||||
// how long before each test case times out
|
||||
const TIMEOUT = 20000
|
||||
|
||||
describe('get_aggregate_price', function () {
|
||||
let testContext: XrplIntegrationTestContext
|
||||
|
||||
beforeEach(async () => {
|
||||
testContext = await setupClient(serverUrl)
|
||||
})
|
||||
afterEach(async () => teardownClient(testContext))
|
||||
|
||||
it(
|
||||
'base',
|
||||
async () => {
|
||||
const tx: OracleSet = {
|
||||
TransactionType: 'OracleSet',
|
||||
Account: testContext.wallet.classicAddress,
|
||||
OracleDocumentID: 1234,
|
||||
LastUpdateTime: Math.floor(Date.now() / 1000),
|
||||
PriceDataSeries: [
|
||||
{
|
||||
PriceData: {
|
||||
BaseAsset: 'XRP',
|
||||
QuoteAsset: 'USD',
|
||||
AssetPrice: 740,
|
||||
Scale: 3,
|
||||
},
|
||||
},
|
||||
],
|
||||
Provider: stringToHex('chainlink'),
|
||||
URI: '6469645F6578616D706C65',
|
||||
AssetClass: stringToHex('currency'),
|
||||
}
|
||||
|
||||
await testTransaction(testContext.client, tx, testContext.wallet)
|
||||
|
||||
// confirm that the Oracle was actually created
|
||||
const getAggregatePriceResponse = await testContext.client.request({
|
||||
command: 'get_aggregate_price',
|
||||
account: testContext.wallet.classicAddress,
|
||||
base_asset: 'XRP',
|
||||
quote_asset: 'USD',
|
||||
trim: 20,
|
||||
oracles: [
|
||||
{
|
||||
account: testContext.wallet.classicAddress,
|
||||
oracle_document_id: 1234,
|
||||
},
|
||||
],
|
||||
})
|
||||
assert.deepEqual(getAggregatePriceResponse.result.entire_set, {
|
||||
mean: '0.74',
|
||||
size: 1,
|
||||
standard_deviation: '0',
|
||||
})
|
||||
assert.deepEqual(getAggregatePriceResponse.result.trimmed_set, {
|
||||
mean: '0.74',
|
||||
size: 1,
|
||||
standard_deviation: '0',
|
||||
})
|
||||
assert.equal(getAggregatePriceResponse.result.median, '0.74')
|
||||
assert.equal(getAggregatePriceResponse.result.time, tx.LastUpdateTime)
|
||||
},
|
||||
TIMEOUT,
|
||||
)
|
||||
})
|
||||
@@ -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,
|
||||
)
|
||||
})
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user