mirror of
https://github.com/Xahau/xahau.js.git
synced 2025-12-06 17:27:59 +00:00
xahau-patch
This commit is contained in:
6
packages/xahau/.eslintignore
Normal file
6
packages/xahau/.eslintignore
Normal file
@@ -0,0 +1,6 @@
|
||||
dist
|
||||
node_modules
|
||||
.github
|
||||
.vscode
|
||||
karma.config.js
|
||||
karma-setup.js
|
||||
151
packages/xahau/.eslintrc.js
Normal file
151
packages/xahau/.eslintrc.js
Normal file
@@ -0,0 +1,151 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
|
||||
// Make ESLint compatible with TypeScript
|
||||
parser: '@typescript-eslint/parser',
|
||||
parserOptions: {
|
||||
// Enable linting rules with type information from our tsconfig
|
||||
tsconfigRootDir: __dirname,
|
||||
project: [
|
||||
'./tsconfig.eslint.json',
|
||||
'../xahau-binary-codec/tsconfig.eslint.json',
|
||||
'../xahau-address-codec/tsconfig.eslint.json',
|
||||
'../xahau-keypairs/tsconfig.eslint.json',
|
||||
],
|
||||
|
||||
// Allow the use of imports / ES modules
|
||||
sourceType: 'module',
|
||||
|
||||
ecmaFeatures: {
|
||||
// Enable global strict mode
|
||||
impliedStrict: true,
|
||||
},
|
||||
},
|
||||
|
||||
// Specify global variables that are predefined
|
||||
env: {
|
||||
// Enable node global variables & Node.js scoping
|
||||
node: true,
|
||||
// Add all ECMAScript 2020 globals and automatically set the ecmaVersion parser option to ES2020
|
||||
es2020: true,
|
||||
jest: true,
|
||||
},
|
||||
|
||||
plugins: [],
|
||||
extends: ['@xrplf/eslint-config/base'],
|
||||
rules: {
|
||||
'multiline-comment-style': 'off',
|
||||
// Disabled until https://github.com/import-js/eslint-plugin-import/pull/2305 is resolved to
|
||||
// accomodate this change https://github.com/XRPLF/xrpl.js/pull/2133
|
||||
'import/no-unused-modules': 'off',
|
||||
'eslint-comments/no-unused-disable': 'off',
|
||||
// Certain xahaud APIs require snake_case naming
|
||||
'@typescript-eslint/naming-convention': [
|
||||
'error',
|
||||
{
|
||||
selector: 'interface',
|
||||
format: ['PascalCase', 'snake_case'],
|
||||
},
|
||||
],
|
||||
'max-lines-per-function': [
|
||||
'warn',
|
||||
{ max: 40, skipBlankLines: true, skipComments: true },
|
||||
],
|
||||
'max-statements': ['warn', 25],
|
||||
// exception for lodash
|
||||
'id-length': ['error', { exceptions: ['_'] }],
|
||||
|
||||
// no-shadow has false-positives for enum, @typescript-eslint version fixes that
|
||||
'no-shadow': 'off',
|
||||
'@typescript-eslint/no-shadow': ['error'],
|
||||
'jsdoc/check-examples': 'off',
|
||||
// We want to use certain fields like "@interface" to make join types treated as interfaces.
|
||||
'jsdoc/check-tag-names': 'off',
|
||||
'jsdoc/require-hyphen-before-param-description': 'off',
|
||||
|
||||
'tsdoc/syntax': 'off',
|
||||
'jsdoc/require-description-complete-sentence': 'off',
|
||||
'import/prefer-default-export': 'off',
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: ['.eslintrc.js'],
|
||||
rules: {
|
||||
'import/no-unused-modules': 'off',
|
||||
'@typescript-eslint/no-magic-numbers': 'off',
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['test/**/*.ts'],
|
||||
rules: {
|
||||
/*
|
||||
* Because this project is managed by lerna, dev dependencies are
|
||||
* hoisted and do not appear in the package.json.
|
||||
*/
|
||||
'import/no-extraneous-dependencies': 'off',
|
||||
'node/no-extraneous-import': 'off',
|
||||
|
||||
// We have lots of magic numbers in tests
|
||||
'@typescript-eslint/no-magic-numbers': 'off',
|
||||
|
||||
// We have files with a lot of tests
|
||||
'max-lines-per-function': 'off',
|
||||
'max-lines': 'off',
|
||||
|
||||
// We need to test things without type guards sometimes
|
||||
'@typescript-eslint/no-unsafe-assignment': 'off',
|
||||
'@typescript-eslint/no-unsafe-call': 'off',
|
||||
'@typescript-eslint/consistent-type-assertions': 'off',
|
||||
|
||||
// We need to mess with internal things to generate certain testing situations
|
||||
'@typescript-eslint/no-unsafe-member-access': 'off',
|
||||
|
||||
// Tests are already in 2 callbacks, so max 3 is pretty restrictive
|
||||
'max-nested-callbacks': 'off',
|
||||
|
||||
// messes with fixtures
|
||||
'consistent-default-export-name/default-import-match-filename': 'off',
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['test/client/*.ts'],
|
||||
},
|
||||
{
|
||||
files: ['test/models/*.ts'],
|
||||
rules: {
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['src/models/**/*.ts'],
|
||||
rules: {
|
||||
complexity: ['off'],
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['.eslintrc.js', 'jest.config.js'],
|
||||
rules: {
|
||||
// Removed no-commonjs requirement as eslint must be in common js format
|
||||
'import/no-commonjs': 'off',
|
||||
|
||||
// Removed this as eslint prevents us from doing this differently
|
||||
'import/unambiguous': 'off',
|
||||
|
||||
// Javascript files have CommonJS exports
|
||||
'import/no-unused-modules': 'off',
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['tools/*.ts', 'tools/*.js'],
|
||||
rules: {
|
||||
'no-console': ['off'],
|
||||
'node/no-process-exit': ['off'],
|
||||
'@typescript-eslint/no-magic-numbers': ['off'],
|
||||
'max-lines-per-function': ['off'],
|
||||
'max-statements': ['off'],
|
||||
complexity: ['off'],
|
||||
'max-depth': ['warn', 3],
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
3
packages/xahau/.gitignore
vendored
Normal file
3
packages/xahau/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
# Replaced by root README during the prepare lifecycle phase because npm does not allow symlinking README files
|
||||
# https://docs.npmjs.com/cli/v7/using-npm/scripts#npm-publish
|
||||
README.md
|
||||
1947
packages/xahau/HISTORY.md
Normal file
1947
packages/xahau/HISTORY.md
Normal file
File diff suppressed because it is too large
Load Diff
15
packages/xahau/LICENSE
Normal file
15
packages/xahau/LICENSE
Normal file
@@ -0,0 +1,15 @@
|
||||
ISC License
|
||||
|
||||
Copyright (c) 2012-2021 Contributers to xrpl.js
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
13
packages/xahau/jest.config.integration.js
Normal file
13
packages/xahau/jest.config.integration.js
Normal file
@@ -0,0 +1,13 @@
|
||||
// Jest configuration for api
|
||||
const base = require('../../jest.config.base.js')
|
||||
|
||||
module.exports = {
|
||||
...base,
|
||||
roots: [...base.roots, '<rootDir>/test'],
|
||||
testTimeout: 20000,
|
||||
testMatch: [
|
||||
'<rootDir>/test/integration/**/*.test.ts',
|
||||
'<rootDir>/test/integration/*.test.ts',
|
||||
],
|
||||
displayName: 'xahau.js',
|
||||
}
|
||||
13
packages/xahau/jest.config.unit.js
Normal file
13
packages/xahau/jest.config.unit.js
Normal file
@@ -0,0 +1,13 @@
|
||||
// Jest configuration for api
|
||||
const base = require('../../jest.config.base.js')
|
||||
|
||||
module.exports = {
|
||||
...base,
|
||||
roots: [...base.roots, '<rootDir>/test'],
|
||||
testMatch: ['<rootDir>/test/**/*.test.ts'],
|
||||
testPathIgnorePatterns: [
|
||||
'<rootDir>/test/integration',
|
||||
'<rootDir>/test/fixtures',
|
||||
],
|
||||
displayName: 'xahau.js',
|
||||
}
|
||||
14
packages/xahau/karma.config.js
Normal file
14
packages/xahau/karma.config.js
Normal file
@@ -0,0 +1,14 @@
|
||||
const baseKarmaConfig = require('../../karma.config')
|
||||
const webpackConfig = require('./test/webpack.config')
|
||||
delete webpackConfig.entry
|
||||
|
||||
module.exports = function (config) {
|
||||
config.set({
|
||||
webpack: webpackConfig,
|
||||
|
||||
// list of files / patterns to load in the browser
|
||||
files: ['build/xrpl-latest.js', 'test/integration/**/*.test.ts'],
|
||||
})
|
||||
|
||||
baseKarmaConfig(config)
|
||||
}
|
||||
87
packages/xahau/package.json
Normal file
87
packages/xahau/package.json
Normal file
@@ -0,0 +1,87 @@
|
||||
{
|
||||
"name": "xahau",
|
||||
"version": "4.0.0",
|
||||
"license": "ISC",
|
||||
"description": "A TypeScript/JavaScript API for interacting with the XAH Ledger in Node.js and the browser",
|
||||
"files": [
|
||||
"build/xrpl-latest-min.js",
|
||||
"build/xrpl-latest-min.js.map",
|
||||
"build/xrpl-latest.js",
|
||||
"build/xrpl-latest.js.map",
|
||||
"dist/npm/*",
|
||||
"src/*"
|
||||
],
|
||||
"main": "dist/npm/",
|
||||
"unpkg": "build/xrpl-latest-min.js",
|
||||
"jsdelivr": "build/xrpl-latest-min.js",
|
||||
"types": "dist/npm/index.d.ts",
|
||||
"directories": {
|
||||
"test": "test"
|
||||
},
|
||||
"browser": {
|
||||
"ws": "./dist/npm/client/WSWrapper.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@scure/bip32": "^1.3.1",
|
||||
"@scure/bip39": "^1.2.1",
|
||||
"@xrplf/isomorphic": "^1.0.1",
|
||||
"@xrplf/secret-numbers": "^1.0.0",
|
||||
"bignumber.js": "^9.0.0",
|
||||
"eventemitter3": "^5.0.1",
|
||||
"xahau-address-codec": "^5.0.0",
|
||||
"xahau-binary-codec": "^2.1.0",
|
||||
"xahau-keypairs": "^2.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^18.18.38",
|
||||
"eventemitter3": "^5.0.1",
|
||||
"https-proxy-agent": "^7.0.1",
|
||||
"karma": "^6.4.1",
|
||||
"karma-chrome-launcher": "^3.1.1",
|
||||
"karma-jasmine": "^5.1.0",
|
||||
"karma-webpack": "^5.0.0",
|
||||
"lodash": "^4.17.4",
|
||||
"react": "^18.2.0",
|
||||
"run-s": "^0.0.0",
|
||||
"typedoc": "0.26.10",
|
||||
"ws": "^8.14.2"
|
||||
},
|
||||
"resolutions": {
|
||||
"elliptic": "^6.5.4"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "run-s build:lib build:web",
|
||||
"build:lib": "tsc --build tsconfig.build.json",
|
||||
"build:web": "webpack",
|
||||
"build:browserTests": "webpack --config ./test/webpack.config.js",
|
||||
"analyze": "webpack --analyze",
|
||||
"watch": "run-s build:lib --watch",
|
||||
"clean": "rm -rf ./dist ./coverage ./test/testCompiledForWeb tsconfig.build.tsbuildinfo",
|
||||
"docgen": "tsc --build tsconfig.docs.json && typedoc && echo js.xrpl.org >> ../../docs/CNAME",
|
||||
"prepare": "copyfiles ../../README.md xrpl/README.md",
|
||||
"prepublish": "run-s clean build",
|
||||
"test": "jest --config=jest.config.unit.js --verbose false --silent=false",
|
||||
"test:integration": "TS_NODE_PROJECT=tsconfig.build.json jest --config=jest.config.integration.js --verbose false --silent=false --runInBand",
|
||||
"test:browser": "npm run build && npm run build:browserTests && karma start ./karma.config.js",
|
||||
"test:watch": "jest --watch --verbose false --silent=false --runInBand ./test/**/*.test.ts --testPathIgnorePatterns=./test/integration --testPathIgnorePatterns=./test/fixtures",
|
||||
"format": "prettier --write '{src,test}/**/*.ts'",
|
||||
"lint": "eslint . --ext .ts --max-warnings 0",
|
||||
"perf": "./scripts/perf_test.sh"
|
||||
},
|
||||
"prettier": "@xrplf/prettier-config",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git@github.com:XRPLF/xrpl.js.git"
|
||||
},
|
||||
"readmeFilename": "README.md",
|
||||
"keywords": [
|
||||
"xahau-lib",
|
||||
"xahau",
|
||||
"xah",
|
||||
"xahau ledger",
|
||||
"xahau"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
}
|
||||
6
packages/xahau/src/ECDSA.ts
Normal file
6
packages/xahau/src/ECDSA.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
enum ECDSA {
|
||||
ed25519 = 'ed25519',
|
||||
secp256k1 = 'ecdsa-secp256k1',
|
||||
}
|
||||
|
||||
export default ECDSA
|
||||
26
packages/xahau/src/Wallet/authorizeChannel.ts
Normal file
26
packages/xahau/src/Wallet/authorizeChannel.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { encodeForSigningClaim } from 'xahau-binary-codec'
|
||||
import { sign } from 'xahau-keypairs'
|
||||
|
||||
import { Wallet } from './index'
|
||||
|
||||
/**
|
||||
* Creates a signature that can be used to redeem a specific amount of XAH from a payment channel.
|
||||
*
|
||||
* @param wallet - The account that will sign for this payment channel.
|
||||
* @param channelId - An id for the payment channel to redeem XAH from.
|
||||
* @param amount - The amount in drops to redeem.
|
||||
* @returns A signature that can be used to redeem a specific amount of XAH from a payment channel.
|
||||
* @category Utilities
|
||||
*/
|
||||
export function authorizeChannel(
|
||||
wallet: Wallet,
|
||||
channelId: string,
|
||||
amount: string,
|
||||
): string {
|
||||
const signingData = encodeForSigningClaim({
|
||||
channel: channelId,
|
||||
amount,
|
||||
})
|
||||
|
||||
return sign(signingData, wallet.privateKey)
|
||||
}
|
||||
58
packages/xahau/src/Wallet/defaultFaucets.ts
Normal file
58
packages/xahau/src/Wallet/defaultFaucets.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import type { Client } from '../client'
|
||||
import { XRPLFaucetError } from '../errors'
|
||||
|
||||
export interface FaucetWallet {
|
||||
account: {
|
||||
xAddress: string
|
||||
classicAddress?: string
|
||||
secret: string
|
||||
}
|
||||
amount: number
|
||||
balance: number
|
||||
}
|
||||
|
||||
export enum FaucetNetwork {
|
||||
Testnet = 'xahau-test.net',
|
||||
Devnet = 'jshooks.xahau-test.net',
|
||||
}
|
||||
|
||||
export const FaucetNetworkPaths: Record<string, string> = {
|
||||
[FaucetNetwork.Testnet]: '/accounts',
|
||||
[FaucetNetwork.Devnet]: '/accounts',
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the faucet host based on the Client connection.
|
||||
*
|
||||
* @param client - Client.
|
||||
* @returns A {@link FaucetNetwork}.
|
||||
* @throws When the client url is not on devnet.
|
||||
*/
|
||||
export function getFaucetHost(client: Client): FaucetNetwork | undefined {
|
||||
const connectionUrl = client.url
|
||||
|
||||
if (connectionUrl.includes('jshooks')) {
|
||||
return FaucetNetwork.Devnet
|
||||
}
|
||||
|
||||
// 'altnet' for Ripple Testnet server and 'test' for XAHL Labs Testnet server
|
||||
if (connectionUrl.includes('test')) {
|
||||
return FaucetNetwork.Testnet
|
||||
}
|
||||
|
||||
throw new XRPLFaucetError('Faucet URL is not defined or inferrable.')
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the faucet pathname based on the faucet hostname.
|
||||
*
|
||||
* @param hostname - hostname.
|
||||
* @returns A String with the correct path for the input hostname.
|
||||
* If hostname undefined or cannot find (key, value) pair in {@link FaucetNetworkPaths}, defaults to '/accounts'
|
||||
*/
|
||||
export function getDefaultFaucetPath(hostname: string | undefined): string {
|
||||
if (hostname === undefined) {
|
||||
return '/accounts'
|
||||
}
|
||||
return FaucetNetworkPaths[hostname] || '/accounts'
|
||||
}
|
||||
282
packages/xahau/src/Wallet/fundWallet.ts
Normal file
282
packages/xahau/src/Wallet/fundWallet.ts
Normal file
@@ -0,0 +1,282 @@
|
||||
import { isValidClassicAddress } from 'xahau-address-codec'
|
||||
|
||||
import type { Client } from '../client'
|
||||
import { XRPLFaucetError } from '../errors'
|
||||
|
||||
import {
|
||||
FaucetWallet,
|
||||
getFaucetHost,
|
||||
getDefaultFaucetPath,
|
||||
} from './defaultFaucets'
|
||||
|
||||
import { Wallet } from '.'
|
||||
|
||||
// Interval to check an account balance
|
||||
const INTERVAL_SECONDS = 1
|
||||
// Maximum attempts to retrieve a balance
|
||||
const MAX_ATTEMPTS = 20
|
||||
|
||||
export interface FundingOptions {
|
||||
/**
|
||||
* A custom amount to fund, if undefined or null, the default amount will be 1000.
|
||||
*/
|
||||
amount?: string
|
||||
/**
|
||||
* A custom host for a faucet server. On devnet, testnet, AMM devnet, and HooksV3 testnet, `fundWallet` will
|
||||
* attempt to determine the correct server automatically. In other environments, or if you would like to customize
|
||||
* the faucet host in devnet or testnet, you should provide the host using this option.
|
||||
*/
|
||||
faucetHost?: string
|
||||
/**
|
||||
* A custom path for a faucet server. On devnet,
|
||||
* testnet, AMM devnet, and HooksV3 testnet, `fundWallet` will
|
||||
* attempt to determine the correct path automatically. In other environments,
|
||||
* or if you would like to customize the faucet path in devnet or testnet,
|
||||
* you should provide the path using this option.
|
||||
* Ex: client.fundWallet(null,{'xahau-test.net/accounts', '/accounts'})
|
||||
* specifies a request to 'xahau-test.net/accounts/accounts' to fund a new wallet.
|
||||
*/
|
||||
faucetPath?: string
|
||||
/**
|
||||
* An optional field to indicate the use case context of the faucet transaction
|
||||
* Ex: integration test, code snippets.
|
||||
*/
|
||||
usageContext?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Parameters to pass into a faucet request to fund an XAH account.
|
||||
*/
|
||||
export interface FaucetRequestBody {
|
||||
/**
|
||||
* The address to fund. If no address is provided the faucet will fund a random account.
|
||||
*/
|
||||
destination?: string
|
||||
/**
|
||||
* The total amount of XAH to fund the account with.
|
||||
*/
|
||||
xrpAmount?: string
|
||||
/**
|
||||
* An optional field to indicate the use case context of the faucet transaction
|
||||
* Ex: integration test, code snippets.
|
||||
*/
|
||||
usageContext?: string
|
||||
/**
|
||||
* Information about the context of where the faucet is being called from.
|
||||
* Ex: xrpl.js or xrpl-py
|
||||
*/
|
||||
userAgent: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a new wallet to fund if no existing wallet is provided or its address is invalid.
|
||||
*
|
||||
* @param wallet - Optional existing wallet.
|
||||
* @returns The wallet to fund.
|
||||
*/
|
||||
export function generateWalletToFund(wallet?: Wallet | null): Wallet {
|
||||
if (wallet && isValidClassicAddress(wallet.classicAddress)) {
|
||||
return wallet
|
||||
}
|
||||
return Wallet.generate()
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the starting balance of the wallet.
|
||||
*
|
||||
* @param client - The client object.
|
||||
* @param classicAddress - The classic address of the wallet.
|
||||
* @returns The starting balance.
|
||||
*/
|
||||
export async function getStartingBalance(
|
||||
client: Client,
|
||||
classicAddress: string,
|
||||
): Promise<number> {
|
||||
let startingBalance = 0
|
||||
try {
|
||||
startingBalance = Number(await client.getXrpBalance(classicAddress))
|
||||
} catch {
|
||||
// startingBalance remains '0'
|
||||
}
|
||||
return startingBalance
|
||||
}
|
||||
|
||||
export interface FundWalletOptions {
|
||||
faucetHost?: string
|
||||
faucetPath?: string
|
||||
amount?: string
|
||||
usageContext?: string
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Helper function to request funding from a faucet. Should not be called directly from outside the xrpl.js library.
|
||||
*
|
||||
* @param options - See below
|
||||
* @param options.faucetHost - A custom host for a faucet server. On devnet,
|
||||
* testnet, AMM devnet, and HooksV3 testnet, `fundWallet` will
|
||||
* attempt to determine the correct server automatically. In other environments,
|
||||
* or if you would like to customize the faucet host in devnet or testnet,
|
||||
* you should provide the host using this option.
|
||||
* @param options.faucetPath - A custom path for a faucet server. On devnet,
|
||||
* testnet, AMM devnet, and HooksV3 testnet, `fundWallet` will
|
||||
* attempt to determine the correct path automatically. In other environments,
|
||||
* or if you would like to customize the faucet path in devnet or testnet,
|
||||
* you should provide the path using this option.
|
||||
* Ex: client.fundWallet(null,{'xahau-test.net/accounts', '/accounts'})
|
||||
* specifies a request to 'xahau-test.net/accounts/accounts' to fund a new wallet.
|
||||
* @param options.amount - A custom amount to fund, if undefined or null, the default amount will be 1000.
|
||||
* @param client - A connection to the XAHL to send requests and transactions.
|
||||
* @param startingBalance - The amount of XAH in the given walletToFund on ledger already.
|
||||
* @param walletToFund - An existing XAHL Wallet to fund.
|
||||
* @param postBody - The content to send the faucet to indicate which address to fund, how much to fund it, and
|
||||
* where the request is coming from.
|
||||
* @returns A promise that resolves to a funded wallet and the balance within it.
|
||||
*/
|
||||
// eslint-disable-next-line max-params -- Helper function created for organizational purposes
|
||||
export async function requestFunding(
|
||||
options: FundingOptions,
|
||||
client: Client,
|
||||
startingBalance: number,
|
||||
walletToFund: Wallet,
|
||||
postBody: FaucetRequestBody,
|
||||
): Promise<{
|
||||
wallet: Wallet
|
||||
balance: number
|
||||
}> {
|
||||
const hostname = options.faucetHost ?? getFaucetHost(client)
|
||||
if (!hostname) {
|
||||
throw new XRPLFaucetError('No faucet hostname could be derived')
|
||||
}
|
||||
const pathname = options.faucetPath ?? getDefaultFaucetPath(hostname)
|
||||
const response = await fetch(`https://${hostname}${pathname}`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(postBody),
|
||||
})
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- it can be anything
|
||||
const body = await response.json()
|
||||
if (
|
||||
response.ok &&
|
||||
response.headers.get('Content-Type')?.startsWith('application/json')
|
||||
) {
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- It's a FaucetWallet
|
||||
const classicAddress = (body as FaucetWallet).account.classicAddress
|
||||
return processSuccessfulResponse(
|
||||
client,
|
||||
classicAddress,
|
||||
walletToFund,
|
||||
startingBalance,
|
||||
)
|
||||
}
|
||||
return processError(response, body)
|
||||
}
|
||||
|
||||
// eslint-disable-next-line max-params -- Only used as a helper function, lines inc due to added balance.
|
||||
async function processSuccessfulResponse(
|
||||
client: Client,
|
||||
classicAddress: string | undefined,
|
||||
walletToFund: Wallet,
|
||||
startingBalance: number,
|
||||
): Promise<{
|
||||
wallet: Wallet
|
||||
balance: number
|
||||
}> {
|
||||
if (!classicAddress) {
|
||||
return Promise.reject(
|
||||
new XRPLFaucetError(`The faucet account is undefined`),
|
||||
)
|
||||
}
|
||||
try {
|
||||
// Check at regular interval if the address is enabled on the XAHL and funded
|
||||
const updatedBalance = await getUpdatedBalance(
|
||||
client,
|
||||
classicAddress,
|
||||
startingBalance,
|
||||
)
|
||||
|
||||
if (updatedBalance > startingBalance) {
|
||||
return {
|
||||
wallet: walletToFund,
|
||||
balance: updatedBalance,
|
||||
}
|
||||
}
|
||||
throw new XRPLFaucetError(
|
||||
`Unable to fund address with faucet after waiting ${
|
||||
INTERVAL_SECONDS * MAX_ATTEMPTS
|
||||
} seconds`,
|
||||
)
|
||||
} catch (err) {
|
||||
if (err instanceof Error) {
|
||||
throw new XRPLFaucetError(err.message)
|
||||
}
|
||||
throw err
|
||||
}
|
||||
}
|
||||
|
||||
async function processError(response: Response, body): Promise<never> {
|
||||
return Promise.reject(
|
||||
new XRPLFaucetError(
|
||||
`Request failed: ${JSON.stringify({
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- json response could be anything
|
||||
body: body || {},
|
||||
contentType: response.headers.get('Content-Type'),
|
||||
statusCode: response.status,
|
||||
})}`,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Check at regular interval if the address is enabled on the XAHL and funded.
|
||||
*
|
||||
* @param client - Client.
|
||||
* @param address - The account address to check.
|
||||
* @param originalBalance - The initial balance before the funding.
|
||||
* @returns A Promise boolean.
|
||||
*/
|
||||
async function getUpdatedBalance(
|
||||
client: Client,
|
||||
address: string,
|
||||
originalBalance: number,
|
||||
): Promise<number> {
|
||||
return new Promise((resolve, reject) => {
|
||||
let attempts = MAX_ATTEMPTS
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises -- Not actually misused here, different resolve
|
||||
const interval = setInterval(async () => {
|
||||
if (attempts < 0) {
|
||||
clearInterval(interval)
|
||||
resolve(originalBalance)
|
||||
} else {
|
||||
attempts -= 1
|
||||
}
|
||||
|
||||
try {
|
||||
let newBalance
|
||||
try {
|
||||
newBalance = Number(await client.getXrpBalance(address))
|
||||
} catch {
|
||||
/* newBalance remains undefined */
|
||||
}
|
||||
|
||||
if (newBalance > originalBalance) {
|
||||
clearInterval(interval)
|
||||
resolve(newBalance)
|
||||
}
|
||||
} catch (err) {
|
||||
clearInterval(interval)
|
||||
if (err instanceof Error) {
|
||||
reject(
|
||||
new XRPLFaucetError(
|
||||
`Unable to check if the address ${address} balance has increased. Error: ${err.message}`,
|
||||
),
|
||||
)
|
||||
}
|
||||
reject(err)
|
||||
}
|
||||
}, INTERVAL_SECONDS * 1000)
|
||||
})
|
||||
}
|
||||
507
packages/xahau/src/Wallet/index.ts
Normal file
507
packages/xahau/src/Wallet/index.ts
Normal file
@@ -0,0 +1,507 @@
|
||||
import { HDKey } from '@scure/bip32'
|
||||
import { mnemonicToSeedSync, validateMnemonic } from '@scure/bip39'
|
||||
import { wordlist } from '@scure/bip39/wordlists/english'
|
||||
import { bytesToHex } from '@xrplf/isomorphic/utils'
|
||||
import BigNumber from 'bignumber.js'
|
||||
import {
|
||||
classicAddressToXAddress,
|
||||
isValidXAddress,
|
||||
xAddressToClassicAddress,
|
||||
encodeSeed,
|
||||
} from 'xahau-address-codec'
|
||||
import {
|
||||
encodeForSigning,
|
||||
encodeForMultisigning,
|
||||
encode,
|
||||
} from 'xahau-binary-codec'
|
||||
import {
|
||||
deriveAddress,
|
||||
deriveKeypair,
|
||||
generateSeed,
|
||||
sign,
|
||||
} from 'xahau-keypairs'
|
||||
|
||||
import ECDSA from '../ECDSA'
|
||||
import { ValidationError } from '../errors'
|
||||
import { Transaction, validate } from '../models/transactions'
|
||||
import { ensureClassicAddress } from '../sugar/utils'
|
||||
import { omitBy } from '../utils/collections'
|
||||
import { hashSignedTx } from '../utils/hashes/hashLedger'
|
||||
|
||||
import { rfc1751MnemonicToKey } from './rfc1751'
|
||||
import { verifySignature } from './signer'
|
||||
|
||||
const DEFAULT_ALGORITHM: ECDSA = ECDSA.ed25519
|
||||
const DEFAULT_DERIVATION_PATH = "m/44'/144'/0'/0/0"
|
||||
|
||||
type ValidHDKey = HDKey & {
|
||||
privateKey: Uint8Array
|
||||
publicKey: Uint8Array
|
||||
}
|
||||
|
||||
function validateKey(node: HDKey): asserts node is ValidHDKey {
|
||||
if (!(node.privateKey instanceof Uint8Array)) {
|
||||
throw new ValidationError('Unable to derive privateKey from mnemonic input')
|
||||
}
|
||||
|
||||
if (!(node.publicKey instanceof Uint8Array)) {
|
||||
throw new ValidationError('Unable to derive publicKey from mnemonic input')
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A utility for deriving a wallet composed of a keypair (publicKey/privateKey).
|
||||
* A wallet can be derived from either a seed, mnemonic, or entropy (array of random numbers).
|
||||
* It provides functionality to sign/verify transactions offline.
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
*
|
||||
* // Derive a wallet from a base58 encoded seed.
|
||||
* const seedWallet = Wallet.fromSeed('ssZkdwURFMBXenJPbrpE14b6noJSu')
|
||||
* console.log(seedWallet)
|
||||
* // Wallet {
|
||||
* // publicKey: '02FE9932A9C4AA2AC9F0ED0F2B89302DE7C2C95F91D782DA3CF06E64E1C1216449',
|
||||
* // privateKey: '00445D0A16DD05EFAF6D5AF45E6B8A6DE4170D93C0627021A0B8E705786CBCCFF7',
|
||||
* // classicAddress: 'rG88FVLjvYiQaGftSa1cKuE2qNx7aK5ivo',
|
||||
* // seed: 'ssZkdwURFMBXenJPbrpE14b6noJSu'
|
||||
* // }.
|
||||
*
|
||||
* // Sign a JSON Transaction
|
||||
* const signed = seedWallet.signTransaction({
|
||||
* TransactionType: 'Payment',
|
||||
* Account: 'rG88FVLjvYiQaGftSa1cKuE2qNx7aK5ivo'
|
||||
* ...........
|
||||
* }).
|
||||
*
|
||||
* console.log(signed)
|
||||
* // '1200007321......B01BE1DFF3'.
|
||||
* console.log(decode(signed))
|
||||
* // {
|
||||
* // TransactionType: 'Payment',
|
||||
* // SigningPubKey: '02FE9932A9C4AA2AC9F0ED0F2B89302DE7C2C95F91D782DA3CF06E64E1C1216449',
|
||||
* // TxnSignature: '3045022100AAD......5B631ABD21171B61B07D304',
|
||||
* // Account: 'rG88FVLjvYiQaGftSa1cKuE2qNx7aK5ivo'
|
||||
* // ...........
|
||||
* // }
|
||||
* ```
|
||||
*
|
||||
* @category Signing
|
||||
*/
|
||||
export class Wallet {
|
||||
public readonly publicKey: string
|
||||
public readonly privateKey: string
|
||||
public readonly classicAddress: string
|
||||
public readonly seed?: string
|
||||
|
||||
/**
|
||||
* Creates a new Wallet.
|
||||
*
|
||||
* @param publicKey - The public key for the account.
|
||||
* @param privateKey - The private key used for signing transactions for the account.
|
||||
* @param opts - (Optional) Options to initialize a Wallet.
|
||||
* @param opts.masterAddress - Include if a Wallet uses a Regular Key Pair. It must be the master address of the account.
|
||||
* @param opts.seed - The seed used to derive the account keys.
|
||||
*/
|
||||
public constructor(
|
||||
publicKey: string,
|
||||
privateKey: string,
|
||||
opts: {
|
||||
masterAddress?: string
|
||||
seed?: string
|
||||
} = {},
|
||||
) {
|
||||
this.publicKey = publicKey
|
||||
this.privateKey = privateKey
|
||||
this.classicAddress = opts.masterAddress
|
||||
? ensureClassicAddress(opts.masterAddress)
|
||||
: deriveAddress(publicKey)
|
||||
this.seed = opts.seed
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias for wallet.classicAddress.
|
||||
*
|
||||
* @returns The wallet's classic address.
|
||||
*/
|
||||
public get address(): string {
|
||||
return this.classicAddress
|
||||
}
|
||||
|
||||
/**
|
||||
* `generate()` creates a new random Wallet. In order to make this a valid account on ledger, you must
|
||||
* Send XAH to it. On test networks that can be done with "faucets" which send XAH to any account which asks
|
||||
* For it. You can call `client.fundWallet()` in order to generate credentials and fund the account on test networks.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const { Wallet } = require('xah')
|
||||
* const wallet = Wallet.generate()
|
||||
* ```
|
||||
*
|
||||
* @param algorithm - The digital signature algorithm to generate an address for.
|
||||
* @returns A new Wallet derived from a generated seed.
|
||||
*
|
||||
* @throws ValidationError when signing algorithm isn't valid
|
||||
*/
|
||||
public static generate(algorithm: ECDSA = DEFAULT_ALGORITHM): Wallet {
|
||||
if (!Object.values(ECDSA).includes(algorithm)) {
|
||||
throw new ValidationError('Invalid cryptographic signing algorithm')
|
||||
}
|
||||
const seed = generateSeed({ algorithm })
|
||||
return Wallet.fromSeed(seed, { algorithm })
|
||||
}
|
||||
|
||||
/**
|
||||
* Derives a wallet from a seed.
|
||||
*
|
||||
* @param seed - A string used to generate a keypair (publicKey/privateKey) to derive a wallet.
|
||||
* @param opts - (Optional) Options to derive a Wallet.
|
||||
* @param opts.algorithm - The digital signature algorithm to generate an address for.
|
||||
* @param opts.masterAddress - Include if a Wallet uses a Regular Key Pair. It must be the master address of the account.
|
||||
* @returns A Wallet derived from a seed.
|
||||
*/
|
||||
public static fromSeed(
|
||||
seed: string,
|
||||
opts: { masterAddress?: string; algorithm?: ECDSA } = {},
|
||||
): Wallet {
|
||||
return Wallet.deriveWallet(seed, {
|
||||
algorithm: opts.algorithm,
|
||||
masterAddress: opts.masterAddress,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Derives a wallet from a secret (AKA a seed).
|
||||
*
|
||||
* @param secret - A string used to generate a keypair (publicKey/privateKey) to derive a wallet.
|
||||
* @param opts - (Optional) Options to derive a Wallet.
|
||||
* @param opts.algorithm - The digital signature algorithm to generate an address for.
|
||||
* @param opts.masterAddress - Include if a Wallet uses a Regular Key Pair. It must be the master address of the account.
|
||||
* @returns A Wallet derived from a secret (AKA a seed).
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/member-ordering -- Member is used as a function here
|
||||
public static fromSecret = Wallet.fromSeed
|
||||
|
||||
/**
|
||||
* Derives a wallet from an entropy (array of random numbers).
|
||||
*
|
||||
* @param entropy - An array of random numbers to generate a seed used to derive a wallet.
|
||||
* @param opts - (Optional) Options to derive a Wallet.
|
||||
* @param opts.algorithm - The digital signature algorithm to generate an address for.
|
||||
* @param opts.masterAddress - Include if a Wallet uses a Regular Key Pair. It must be the master address of the account.
|
||||
* @returns A Wallet derived from an entropy.
|
||||
*/
|
||||
public static fromEntropy(
|
||||
entropy: Uint8Array | number[],
|
||||
opts: { masterAddress?: string; algorithm?: ECDSA } = {},
|
||||
): Wallet {
|
||||
const algorithm = opts.algorithm ?? DEFAULT_ALGORITHM
|
||||
const options = {
|
||||
entropy: Uint8Array.from(entropy),
|
||||
algorithm,
|
||||
}
|
||||
const seed = generateSeed(options)
|
||||
return Wallet.deriveWallet(seed, {
|
||||
algorithm,
|
||||
masterAddress: opts.masterAddress,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Derives a wallet from a bip39 or RFC1751 mnemonic (Defaults to bip39).
|
||||
*
|
||||
* @deprecated since version 2.6.1.
|
||||
* Will be deleted in version 3.0.0.
|
||||
* This representation is currently deprecated in xahaud.
|
||||
* You should use another method to represent your keys such as a seed or public/private keypair.
|
||||
*
|
||||
* @param mnemonic - A string consisting of words (whitespace delimited) used to derive a wallet.
|
||||
* @param opts - (Optional) Options to derive a Wallet.
|
||||
* @param opts.masterAddress - Include if a Wallet uses a Regular Key Pair. It must be the master address of the account.
|
||||
* @param opts.derivationPath - The path to derive a keypair (publicKey/privateKey). Only used for bip39 conversions.
|
||||
* @param opts.mnemonicEncoding - If set to 'rfc1751', this interprets the mnemonic as a xahaud RFC1751 mnemonic like
|
||||
* `wallet_propose` generates in xahaud. Otherwise the function defaults to bip39 decoding.
|
||||
* @param opts.algorithm - Only used if opts.mnemonicEncoding is 'rfc1751'. Allows the mnemonic to generate its
|
||||
* secp256k1 seed, or its ed25519 seed. By default, it will generate the secp256k1 seed
|
||||
* to match the xahaud `wallet_propose` default algorithm.
|
||||
* @returns A Wallet derived from a mnemonic.
|
||||
* @throws ValidationError if unable to derive private key from mnemonic input.
|
||||
*/
|
||||
public static fromMnemonic(
|
||||
mnemonic: string,
|
||||
opts: {
|
||||
masterAddress?: string
|
||||
derivationPath?: string
|
||||
mnemonicEncoding?: 'bip39' | 'rfc1751'
|
||||
algorithm?: ECDSA
|
||||
} = {},
|
||||
): Wallet {
|
||||
if (opts.mnemonicEncoding === 'rfc1751') {
|
||||
return Wallet.fromRFC1751Mnemonic(mnemonic, {
|
||||
masterAddress: opts.masterAddress,
|
||||
algorithm: opts.algorithm,
|
||||
})
|
||||
}
|
||||
// Otherwise decode using bip39's mnemonic standard
|
||||
if (!validateMnemonic(mnemonic, wordlist)) {
|
||||
throw new ValidationError(
|
||||
'Unable to parse the given mnemonic using bip39 encoding',
|
||||
)
|
||||
}
|
||||
|
||||
const seed = mnemonicToSeedSync(mnemonic)
|
||||
const masterNode = HDKey.fromMasterSeed(seed)
|
||||
const node = masterNode.derive(
|
||||
opts.derivationPath ?? DEFAULT_DERIVATION_PATH,
|
||||
)
|
||||
validateKey(node)
|
||||
|
||||
const publicKey = bytesToHex(node.publicKey)
|
||||
const privateKey = bytesToHex(node.privateKey)
|
||||
return new Wallet(publicKey, `00${privateKey}`, {
|
||||
masterAddress: opts.masterAddress,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Derives a wallet from a RFC1751 mnemonic, which is how `wallet_propose` encodes mnemonics.
|
||||
*
|
||||
* @param mnemonic - A string consisting of words (whitespace delimited) used to derive a wallet.
|
||||
* @param opts - (Optional) Options to derive a Wallet.
|
||||
* @param opts.masterAddress - Include if a Wallet uses a Regular Key Pair. It must be the master address of the account.
|
||||
* @param opts.algorithm - The digital signature algorithm to generate an address for.
|
||||
* @returns A Wallet derived from a mnemonic.
|
||||
*/
|
||||
private static fromRFC1751Mnemonic(
|
||||
mnemonic: string,
|
||||
opts: { masterAddress?: string; algorithm?: ECDSA },
|
||||
): Wallet {
|
||||
const seed = rfc1751MnemonicToKey(mnemonic)
|
||||
let encodeAlgorithm: 'ed25519' | 'secp256k1'
|
||||
if (opts.algorithm === ECDSA.ed25519) {
|
||||
encodeAlgorithm = 'ed25519'
|
||||
} else {
|
||||
// Defaults to secp256k1 since that's the default for `wallet_propose`
|
||||
encodeAlgorithm = 'secp256k1'
|
||||
}
|
||||
const encodedSeed = encodeSeed(seed, encodeAlgorithm)
|
||||
return Wallet.fromSeed(encodedSeed, {
|
||||
masterAddress: opts.masterAddress,
|
||||
algorithm: opts.algorithm,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Derive a Wallet from a seed.
|
||||
*
|
||||
* @param seed - The seed used to derive the wallet.
|
||||
* @param opts - (Optional) Options to derive a Wallet.
|
||||
* @param opts.algorithm - The digital signature algorithm to generate an address for.
|
||||
* @param opts.masterAddress - Include if a Wallet uses a Regular Key Pair. It must be the master address of the account.
|
||||
* @returns A Wallet derived from the seed.
|
||||
*/
|
||||
private static deriveWallet(
|
||||
seed: string,
|
||||
opts: { masterAddress?: string; algorithm?: ECDSA } = {},
|
||||
): Wallet {
|
||||
const { publicKey, privateKey } = deriveKeypair(seed, {
|
||||
algorithm: opts.algorithm ?? DEFAULT_ALGORITHM,
|
||||
})
|
||||
return new Wallet(publicKey, privateKey, {
|
||||
seed,
|
||||
masterAddress: opts.masterAddress,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Signs a transaction offline.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* ```ts
|
||||
* const { Client, Wallet } = require('xah')
|
||||
* const client = new Client('wss://xahau-test.net')
|
||||
*
|
||||
* async function signTransaction() {
|
||||
* await client.connect()
|
||||
* const { balance: balance1, wallet: wallet1 } = client.fundWallet()
|
||||
* const { balance: balance2, wallet: wallet2 } = client.fundWallet()
|
||||
*
|
||||
* const transaction = {
|
||||
* TransactionType: 'Payment',
|
||||
* Account: wallet1.address,
|
||||
* Destination: wallet2.address,
|
||||
* Amount: '10'
|
||||
* }
|
||||
*
|
||||
* try {
|
||||
* await client.autofill(transaction)
|
||||
* const { tx_blob: signed_tx_blob, hash} = await wallet1.sign(transaction)
|
||||
* console.log(signed_tx_blob)
|
||||
* } catch (error) {
|
||||
* console.error(`Failed to sign transaction: ${error}`)
|
||||
* }
|
||||
* const result = await client.submit(signed_tx_blob)
|
||||
* await client.disconnect()
|
||||
* }
|
||||
*
|
||||
* signTransaction()
|
||||
* ```
|
||||
* In order for a transaction to be validated, it must be signed by the account sending the transaction to prove
|
||||
* That the owner is actually the one deciding to take that action.
|
||||
*
|
||||
* In this example, we created, signed, and then submitted a transaction to testnet. You may notice that the
|
||||
* Output of `sign` includes a `tx_blob` and a `hash`, both of which are needed to submit & verify the results.
|
||||
* Note: If you pass a `Wallet` to `client.submit` or `client.submitAndWait` it will do signing like this under the hood.
|
||||
*
|
||||
* `tx_blob` is a binary representation of a transaction on the XAH Ledger. It's essentially a byte array
|
||||
* that encodes all of the data necessary to execute the transaction, including the source address, the destination
|
||||
* address, the amount, and any additional fields required for the specific transaction type.
|
||||
*
|
||||
* `hash` is a unique identifier that's generated from the signed transaction data on the XAH Ledger. It's essentially
|
||||
* A cryptographic digest of the signed transaction blob, created using a hash function. The signed transaction hash is
|
||||
* Useful for identifying and tracking specific transactions on the XAH Ledger. It can be used to query transaction
|
||||
* Information, verify the authenticity of a transaction, and detect any tampering with the transaction data.
|
||||
*
|
||||
* @param this - Wallet instance.
|
||||
* @param transaction - A transaction to be signed offline.
|
||||
* @param multisign - Specify true/false to use multisign or actual address (classic/x-address) to make multisign tx request.
|
||||
* @returns A signed transaction.
|
||||
* @throws ValidationError if the transaction is already signed or does not encode/decode to same result.
|
||||
* @throws XahlError if the issued currency being signed is XAH ignoring case.
|
||||
*/
|
||||
// eslint-disable-next-line max-lines-per-function -- introduced more checks to support both string and boolean inputs.
|
||||
public sign(
|
||||
this: Wallet,
|
||||
transaction: Transaction,
|
||||
multisign?: boolean | string,
|
||||
): {
|
||||
tx_blob: string
|
||||
hash: string
|
||||
} {
|
||||
let multisignAddress: boolean | string = false
|
||||
if (typeof multisign === 'string' && multisign.startsWith('X')) {
|
||||
multisignAddress = multisign
|
||||
} else if (multisign) {
|
||||
multisignAddress = this.classicAddress
|
||||
}
|
||||
|
||||
// clean null & undefined valued tx properties
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- ensure Transaction flows through
|
||||
const tx = omitBy(
|
||||
{ ...transaction },
|
||||
(value) => value == null,
|
||||
) as unknown as Transaction
|
||||
|
||||
if (tx.TxnSignature || tx.Signers) {
|
||||
throw new ValidationError(
|
||||
'txJSON must not contain "TxnSignature" or "Signers" properties',
|
||||
)
|
||||
}
|
||||
|
||||
removeTrailingZeros(tx)
|
||||
|
||||
/*
|
||||
* This will throw a more clear error for JS users if the supplied transaction has incorrect formatting
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- validate does not accept Transaction type
|
||||
validate(tx as unknown as Record<string, unknown>)
|
||||
|
||||
const txToSignAndEncode = { ...tx }
|
||||
|
||||
txToSignAndEncode.SigningPubKey = multisignAddress ? '' : this.publicKey
|
||||
|
||||
if (multisignAddress) {
|
||||
const signer = {
|
||||
Account: multisignAddress,
|
||||
SigningPubKey: this.publicKey,
|
||||
TxnSignature: computeSignature(
|
||||
txToSignAndEncode,
|
||||
this.privateKey,
|
||||
multisignAddress,
|
||||
),
|
||||
}
|
||||
txToSignAndEncode.Signers = [{ Signer: signer }]
|
||||
} else {
|
||||
txToSignAndEncode.TxnSignature = computeSignature(
|
||||
txToSignAndEncode,
|
||||
this.privateKey,
|
||||
)
|
||||
}
|
||||
|
||||
const serialized = encode(txToSignAndEncode)
|
||||
return {
|
||||
tx_blob: serialized,
|
||||
hash: hashSignedTx(serialized),
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies a signed transaction offline.
|
||||
*
|
||||
* @param signedTransaction - A signed transaction (hex string of signTransaction result) to be verified offline.
|
||||
* @returns Returns true if a signedTransaction is valid.
|
||||
* @throws {Error} Transaction is missing a signature, TxnSignature
|
||||
*/
|
||||
public verifyTransaction(signedTransaction: Transaction | string): boolean {
|
||||
return verifySignature(signedTransaction, this.publicKey)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an X-address in Testnet/Mainnet format.
|
||||
*
|
||||
* @param tag - A tag to be included within the X-address.
|
||||
* @param isTestnet - A boolean to indicate if X-address should be in Testnet (true) or Mainnet (false) format.
|
||||
* @returns An X-address.
|
||||
*/
|
||||
public getXAddress(tag: number | false = false, isTestnet = false): string {
|
||||
return classicAddressToXAddress(this.classicAddress, tag, isTestnet)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Signs a transaction with the proper signing encoding.
|
||||
*
|
||||
* @param tx - A transaction to sign.
|
||||
* @param privateKey - A key to sign the transaction with.
|
||||
* @param signAs - Multisign only. An account address to include in the Signer field.
|
||||
* Can be either a classic address or an XAddress.
|
||||
* @returns A signed transaction in the proper format.
|
||||
*/
|
||||
function computeSignature(
|
||||
tx: Transaction,
|
||||
privateKey: string,
|
||||
signAs?: string,
|
||||
): string {
|
||||
if (signAs) {
|
||||
const classicAddress = isValidXAddress(signAs)
|
||||
? xAddressToClassicAddress(signAs).classicAddress
|
||||
: signAs
|
||||
|
||||
return sign(encodeForMultisigning(tx, classicAddress), privateKey)
|
||||
}
|
||||
return sign(encodeForSigning(tx), privateKey)
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove trailing insignificant zeros for non-XAH Payment amount.
|
||||
* This resolves the serialization mismatch bug when encoding/decoding a non-XAH Payment transaction
|
||||
* with an amount that contains trailing insignificant zeros; for example, '123.4000' would serialize
|
||||
* to '123.4' and cause a mismatch.
|
||||
*
|
||||
* @param tx - The transaction prior to signing.
|
||||
*/
|
||||
function removeTrailingZeros(tx: Transaction): void {
|
||||
if (
|
||||
tx.TransactionType === 'Payment' &&
|
||||
typeof tx.Amount !== 'string' &&
|
||||
tx.Amount.value.includes('.') &&
|
||||
tx.Amount.value.endsWith('0')
|
||||
) {
|
||||
// eslint-disable-next-line no-param-reassign -- Required to update Transaction.Amount.value
|
||||
tx.Amount = { ...tx.Amount }
|
||||
// eslint-disable-next-line no-param-reassign -- Required to update Transaction.Amount.value
|
||||
tx.Amount.value = new BigNumber(tx.Amount.value).toString()
|
||||
}
|
||||
}
|
||||
219
packages/xahau/src/Wallet/rfc1751.ts
Normal file
219
packages/xahau/src/Wallet/rfc1751.ts
Normal file
@@ -0,0 +1,219 @@
|
||||
/* eslint-disable @typescript-eslint/no-magic-numbers -- Doing many bitwise operations which need specific numbers */
|
||||
/* eslint-disable no-bitwise -- Bitwise operators are required for this encoding/decoding */
|
||||
/* eslint-disable id-length -- Bitwise math uses shorthand terms */
|
||||
/*
|
||||
*rfc1751.ts : Converts between 128-bit strings and a human-readable
|
||||
*sequence of words, as defined in RFC1751: "A Convention for
|
||||
*Human-Readable 128-bit Keys", by Daniel L. McDonald.
|
||||
*Ported from rfc1751.py / Python Cryptography Toolkit (public domain).
|
||||
*Copied from https://github.com/bip32/bip32.github.io/blob/master/js/rfc1751.js which
|
||||
*is part of the public domain.
|
||||
*/
|
||||
|
||||
import { hexToBytes, concat } from '@xrplf/isomorphic/utils'
|
||||
|
||||
import rfc1751Words from './rfc1751Words.json'
|
||||
|
||||
const rfc1751WordList: string[] = rfc1751Words
|
||||
|
||||
// Added prettier-ignore to allow _BINARY to be on two lines, instead of one entry per line.
|
||||
|
||||
// prettier-ignore
|
||||
const BINARY = ['0000', '0001', '0010', '0011', '0100', '0101', '0110', '0111',
|
||||
'1000', '1001', '1010', '1011', '1100', '1101', '1110', '1111'];
|
||||
|
||||
/**
|
||||
* Convert a number array into a binary string.
|
||||
*
|
||||
* @param key - An array of numbers in base 10.
|
||||
* @returns A binary string.
|
||||
*/
|
||||
function keyToBinary(key: number[]): string {
|
||||
let res = ''
|
||||
for (const num of key) {
|
||||
res += BINARY[num >> 4] + BINARY[num & 0x0f]
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a substring of an encoded secret to its numeric value.
|
||||
*
|
||||
* @param key - The encoded secret.
|
||||
* @param start - The start index to parse from.
|
||||
* @param length - The number of digits to parse after the start index.
|
||||
* @returns The binary value of the substring.
|
||||
*/
|
||||
function extract(key: string, start: number, length: number): number {
|
||||
const subKey = key.substring(start, start + length)
|
||||
let acc = 0
|
||||
for (let index = 0; index < subKey.length; index++) {
|
||||
acc = acc * 2 + subKey.charCodeAt(index) - 48
|
||||
}
|
||||
return acc
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a modified RFC1751 mnemonic in the same way xahaud's wallet_propose does.
|
||||
*
|
||||
* @param hex_key - An encoded secret in hex format.
|
||||
* @returns A mnemonic following xahaud's modified RFC1751 mnemonic standard.
|
||||
*/
|
||||
function keyToRFC1751Mnemonic(hex_key: string): string {
|
||||
// Remove whitespace and interpret hex
|
||||
const buf = hexToBytes(hex_key.replace(/\s+/gu, ''))
|
||||
// Swap byte order and use rfc1751
|
||||
let key: number[] = bufferToArray(swap128(buf))
|
||||
|
||||
// pad to 8 bytes
|
||||
const padding: number[] = []
|
||||
for (let index = 0; index < (8 - (key.length % 8)) % 8; index++) {
|
||||
padding.push(0)
|
||||
}
|
||||
key = padding.concat(key)
|
||||
|
||||
const english: string[] = []
|
||||
for (let index = 0; index < key.length; index += 8) {
|
||||
const subKey = key.slice(index, index + 8)
|
||||
|
||||
// add parity
|
||||
let skbin = keyToBinary(subKey)
|
||||
let parity = 0
|
||||
for (let j = 0; j < 64; j += 2) {
|
||||
parity += extract(skbin, j, 2)
|
||||
}
|
||||
subKey.push((parity << 6) & 0xff)
|
||||
|
||||
skbin = keyToBinary(subKey)
|
||||
for (let j = 0; j < 64; j += 11) {
|
||||
english.push(rfc1751WordList[extract(skbin, j, 11)])
|
||||
}
|
||||
}
|
||||
return english.join(' ')
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an english mnemonic following xahaud's modified RFC1751 standard to an encoded hex secret.
|
||||
*
|
||||
* @param english - A mnemonic generated using xahau's modified RFC1751 standard.
|
||||
* @throws Error if the parity after decoding does not match.
|
||||
* @returns A Buffer containing an encoded secret.
|
||||
*/
|
||||
function rfc1751MnemonicToKey(english: string): Uint8Array {
|
||||
const words = english.split(' ')
|
||||
let key: number[] = []
|
||||
|
||||
for (let index = 0; index < words.length; index += 6) {
|
||||
const { subKey, word }: { subKey: number[]; word: string } = getSubKey(
|
||||
words,
|
||||
index,
|
||||
)
|
||||
|
||||
// check parity
|
||||
const skbin = keyToBinary(subKey)
|
||||
let parity = 0
|
||||
for (let j = 0; j < 64; j += 2) {
|
||||
parity += extract(skbin, j, 2)
|
||||
}
|
||||
const cs0 = extract(skbin, 64, 2)
|
||||
const cs1 = parity & 3
|
||||
if (cs0 !== cs1) {
|
||||
throw new Error(`Parity error at ${word}`)
|
||||
}
|
||||
|
||||
key = key.concat(subKey.slice(0, 8))
|
||||
}
|
||||
|
||||
// This is a step specific to the XAHL's implementation
|
||||
const bufferKey = swap128(Uint8Array.from(key))
|
||||
return bufferKey
|
||||
}
|
||||
|
||||
function getSubKey(
|
||||
words: string[],
|
||||
index: number,
|
||||
): { subKey: number[]; word: string } {
|
||||
const sublist = words.slice(index, index + 6)
|
||||
let bits = 0
|
||||
const ch = [0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
let word = ''
|
||||
for (word of sublist) {
|
||||
const idx = rfc1751WordList.indexOf(word.toUpperCase())
|
||||
if (idx === -1) {
|
||||
throw new TypeError(
|
||||
`Expected an RFC1751 word, but received '${word}'. ` +
|
||||
`For the full list of words in the RFC1751 encoding see https://datatracker.ietf.org/doc/html/rfc1751`,
|
||||
)
|
||||
}
|
||||
const shift = (8 - ((bits + 11) % 8)) % 8
|
||||
const y = idx << shift
|
||||
const cl = y >> 16
|
||||
const cc = (y >> 8) & 0xff
|
||||
const cr = y & 0xff
|
||||
const t = Math.floor(bits / 8)
|
||||
if (shift > 5) {
|
||||
ch[t] |= cl
|
||||
ch[t + 1] |= cc
|
||||
ch[t + 2] |= cr
|
||||
} else if (shift > -3) {
|
||||
ch[t] |= cc
|
||||
ch[t + 1] |= cr
|
||||
} else {
|
||||
ch[t] |= cr
|
||||
}
|
||||
bits += 11
|
||||
}
|
||||
const subKey: number[] = ch.slice()
|
||||
return { subKey, word }
|
||||
}
|
||||
|
||||
function bufferToArray(buf: Uint8Array): number[] {
|
||||
/* eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- We know the end type */
|
||||
return Array.prototype.slice.call(buf) as number[]
|
||||
}
|
||||
|
||||
function swap(arr: Uint8Array, n: number, m: number): void {
|
||||
const i = arr[n]
|
||||
// eslint-disable-next-line no-param-reassign -- we have to swap
|
||||
arr[n] = arr[m]
|
||||
// eslint-disable-next-line no-param-reassign -- see above
|
||||
arr[m] = i
|
||||
}
|
||||
|
||||
/**
|
||||
* Interprets arr as an array of 64-bit numbers and swaps byte order in 64 bit chunks.
|
||||
* Example of two 64 bit numbers 0000000100000002 => 1000000020000000
|
||||
*
|
||||
* @param arr A Uint8Array representation of one or more 64 bit numbers
|
||||
* @returns Uint8Array An array containing the bytes of 64 bit numbers each with reversed endianness
|
||||
*/
|
||||
function swap64(arr: Uint8Array): Uint8Array {
|
||||
const len = arr.length
|
||||
|
||||
for (let i = 0; i < len; i += 8) {
|
||||
swap(arr, i, i + 7)
|
||||
swap(arr, i + 1, i + 6)
|
||||
swap(arr, i + 2, i + 5)
|
||||
swap(arr, i + 3, i + 4)
|
||||
}
|
||||
|
||||
return arr
|
||||
}
|
||||
|
||||
/**
|
||||
* Swap the byte order of a 128-bit array.
|
||||
* Ex. 0000000100000002 => 2000000010000000
|
||||
*
|
||||
* @param arr - A 128-bit (16 byte) array
|
||||
* @returns An array containing the same data with reversed endianness
|
||||
*/
|
||||
function swap128(arr: Uint8Array): Uint8Array {
|
||||
// Interprets arr as an array of (two, in this case) 64-bit numbers and swaps byte order in 64 bit chunks.
|
||||
// Ex. 0000000100000002 => 1000000020000000
|
||||
const reversedBytes = swap64(arr)
|
||||
// Further swap the two 64-bit numbers since our buffer is 128 bits.
|
||||
// Ex. 1000000020000000 => 2000000010000000
|
||||
return concat([reversedBytes.slice(8, 16), reversedBytes.slice(0, 8)])
|
||||
}
|
||||
|
||||
export { rfc1751MnemonicToKey, keyToRFC1751Mnemonic }
|
||||
243
packages/xahau/src/Wallet/rfc1751Words.json
Normal file
243
packages/xahau/src/Wallet/rfc1751Words.json
Normal file
@@ -0,0 +1,243 @@
|
||||
[ "A", "ABE", "ACE", "ACT", "AD", "ADA", "ADD",
|
||||
"AGO", "AID", "AIM", "AIR", "ALL", "ALP", "AM", "AMY", "AN", "ANA",
|
||||
"AND", "ANN", "ANT", "ANY", "APE", "APS", "APT", "ARC", "ARE", "ARK",
|
||||
"ARM", "ART", "AS", "ASH", "ASK", "AT", "ATE", "AUG", "AUK", "AVE",
|
||||
"AWE", "AWK", "AWL", "AWN", "AX", "AYE", "BAD", "BAG", "BAH", "BAM",
|
||||
"BAN", "BAR", "BAT", "BAY", "BE", "BED", "BEE", "BEG", "BEN", "BET",
|
||||
"BEY", "BIB", "BID", "BIG", "BIN", "BIT", "BOB", "BOG", "BON", "BOO",
|
||||
"BOP", "BOW", "BOY", "BUB", "BUD", "BUG", "BUM", "BUN", "BUS", "BUT",
|
||||
"BUY", "BY", "BYE", "CAB", "CAL", "CAM", "CAN", "CAP", "CAR", "CAT",
|
||||
"CAW", "COD", "COG", "COL", "CON", "COO", "COP", "COT", "COW", "COY",
|
||||
"CRY", "CUB", "CUE", "CUP", "CUR", "CUT", "DAB", "DAD", "DAM", "DAN",
|
||||
"DAR", "DAY", "DEE", "DEL", "DEN", "DES", "DEW", "DID", "DIE", "DIG",
|
||||
"DIN", "DIP", "DO", "DOE", "DOG", "DON", "DOT", "DOW", "DRY", "DUB",
|
||||
"DUD", "DUE", "DUG", "DUN", "EAR", "EAT", "ED", "EEL", "EGG", "EGO",
|
||||
"ELI", "ELK", "ELM", "ELY", "EM", "END", "EST", "ETC", "EVA", "EVE",
|
||||
"EWE", "EYE", "FAD", "FAN", "FAR", "FAT", "FAY", "FED", "FEE", "FEW",
|
||||
"FIB", "FIG", "FIN", "FIR", "FIT", "FLO", "FLY", "FOE", "FOG", "FOR",
|
||||
"FRY", "FUM", "FUN", "FUR", "GAB", "GAD", "GAG", "GAL", "GAM", "GAP",
|
||||
"GAS", "GAY", "GEE", "GEL", "GEM", "GET", "GIG", "GIL", "GIN", "GO",
|
||||
"GOT", "GUM", "GUN", "GUS", "GUT", "GUY", "GYM", "GYP", "HA", "HAD",
|
||||
"HAL", "HAM", "HAN", "HAP", "HAS", "HAT", "HAW", "HAY", "HE", "HEM",
|
||||
"HEN", "HER", "HEW", "HEY", "HI", "HID", "HIM", "HIP", "HIS", "HIT",
|
||||
"HO", "HOB", "HOC", "HOE", "HOG", "HOP", "HOT", "HOW", "HUB", "HUE",
|
||||
"HUG", "HUH", "HUM", "HUT", "I", "ICY", "IDA", "IF", "IKE", "ILL",
|
||||
"INK", "INN", "IO", "ION", "IQ", "IRA", "IRE", "IRK", "IS", "IT",
|
||||
"ITS", "IVY", "JAB", "JAG", "JAM", "JAN", "JAR", "JAW", "JAY", "JET",
|
||||
"JIG", "JIM", "JO", "JOB", "JOE", "JOG", "JOT", "JOY", "JUG", "JUT",
|
||||
"KAY", "KEG", "KEN", "KEY", "KID", "KIM", "KIN", "KIT", "LA", "LAB",
|
||||
"LAC", "LAD", "LAG", "LAM", "LAP", "LAW", "LAY", "LEA", "LED", "LEE",
|
||||
"LEG", "LEN", "LEO", "LET", "LEW", "LID", "LIE", "LIN", "LIP", "LIT",
|
||||
"LO", "LOB", "LOG", "LOP", "LOS", "LOT", "LOU", "LOW", "LOY", "LUG",
|
||||
"LYE", "MA", "MAC", "MAD", "MAE", "MAN", "MAO", "MAP", "MAT", "MAW",
|
||||
"MAY", "ME", "MEG", "MEL", "MEN", "MET", "MEW", "MID", "MIN", "MIT",
|
||||
"MOB", "MOD", "MOE", "MOO", "MOP", "MOS", "MOT", "MOW", "MUD", "MUG",
|
||||
"MUM", "MY", "NAB", "NAG", "NAN", "NAP", "NAT", "NAY", "NE", "NED",
|
||||
"NEE", "NET", "NEW", "NIB", "NIL", "NIP", "NIT", "NO", "NOB", "NOD",
|
||||
"NON", "NOR", "NOT", "NOV", "NOW", "NU", "NUN", "NUT", "O", "OAF",
|
||||
"OAK", "OAR", "OAT", "ODD", "ODE", "OF", "OFF", "OFT", "OH", "OIL",
|
||||
"OK", "OLD", "ON", "ONE", "OR", "ORB", "ORE", "ORR", "OS", "OTT",
|
||||
"OUR", "OUT", "OVA", "OW", "OWE", "OWL", "OWN", "OX", "PA", "PAD",
|
||||
"PAL", "PAM", "PAN", "PAP", "PAR", "PAT", "PAW", "PAY", "PEA", "PEG",
|
||||
"PEN", "PEP", "PER", "PET", "PEW", "PHI", "PI", "PIE", "PIN", "PIT",
|
||||
"PLY", "PO", "POD", "POE", "POP", "POT", "POW", "PRO", "PRY", "PUB",
|
||||
"PUG", "PUN", "PUP", "PUT", "QUO", "RAG", "RAM", "RAN", "RAP", "RAT",
|
||||
"RAW", "RAY", "REB", "RED", "REP", "RET", "RIB", "RID", "RIG", "RIM",
|
||||
"RIO", "RIP", "ROB", "ROD", "ROE", "RON", "ROT", "ROW", "ROY", "RUB",
|
||||
"RUE", "RUG", "RUM", "RUN", "RYE", "SAC", "SAD", "SAG", "SAL", "SAM",
|
||||
"SAN", "SAP", "SAT", "SAW", "SAY", "SEA", "SEC", "SEE", "SEN", "SET",
|
||||
"SEW", "SHE", "SHY", "SIN", "SIP", "SIR", "SIS", "SIT", "SKI", "SKY",
|
||||
"SLY", "SO", "SOB", "SOD", "SON", "SOP", "SOW", "SOY", "SPA", "SPY",
|
||||
"SUB", "SUD", "SUE", "SUM", "SUN", "SUP", "TAB", "TAD", "TAG", "TAN",
|
||||
"TAP", "TAR", "TEA", "TED", "TEE", "TEN", "THE", "THY", "TIC", "TIE",
|
||||
"TIM", "TIN", "TIP", "TO", "TOE", "TOG", "TOM", "TON", "TOO", "TOP",
|
||||
"TOW", "TOY", "TRY", "TUB", "TUG", "TUM", "TUN", "TWO", "UN", "UP",
|
||||
"US", "USE", "VAN", "VAT", "VET", "VIE", "WAD", "WAG", "WAR", "WAS",
|
||||
"WAY", "WE", "WEB", "WED", "WEE", "WET", "WHO", "WHY", "WIN", "WIT",
|
||||
"WOK", "WON", "WOO", "WOW", "WRY", "WU", "YAM", "YAP", "YAW", "YE",
|
||||
"YEA", "YES", "YET", "YOU", "ABED", "ABEL", "ABET", "ABLE", "ABUT",
|
||||
"ACHE", "ACID", "ACME", "ACRE", "ACTA", "ACTS", "ADAM", "ADDS",
|
||||
"ADEN", "AFAR", "AFRO", "AGEE", "AHEM", "AHOY", "AIDA", "AIDE",
|
||||
"AIDS", "AIRY", "AJAR", "AKIN", "ALAN", "ALEC", "ALGA", "ALIA",
|
||||
"ALLY", "ALMA", "ALOE", "ALSO", "ALTO", "ALUM", "ALVA", "AMEN",
|
||||
"AMES", "AMID", "AMMO", "AMOK", "AMOS", "AMRA", "ANDY", "ANEW",
|
||||
"ANNA", "ANNE", "ANTE", "ANTI", "AQUA", "ARAB", "ARCH", "AREA",
|
||||
"ARGO", "ARID", "ARMY", "ARTS", "ARTY", "ASIA", "ASKS", "ATOM",
|
||||
"AUNT", "AURA", "AUTO", "AVER", "AVID", "AVIS", "AVON", "AVOW",
|
||||
"AWAY", "AWRY", "BABE", "BABY", "BACH", "BACK", "BADE", "BAIL",
|
||||
"BAIT", "BAKE", "BALD", "BALE", "BALI", "BALK", "BALL", "BALM",
|
||||
"BAND", "BANE", "BANG", "BANK", "BARB", "BARD", "BARE", "BARK",
|
||||
"BARN", "BARR", "BASE", "BASH", "BASK", "BASS", "BATE", "BATH",
|
||||
"BAWD", "BAWL", "BEAD", "BEAK", "BEAM", "BEAN", "BEAR", "BEAT",
|
||||
"BEAU", "BECK", "BEEF", "BEEN", "BEER",
|
||||
"BEET", "BELA", "BELL", "BELT", "BEND", "BENT", "BERG", "BERN",
|
||||
"BERT", "BESS", "BEST", "BETA", "BETH", "BHOY", "BIAS", "BIDE",
|
||||
"BIEN", "BILE", "BILK", "BILL", "BIND", "BING", "BIRD", "BITE",
|
||||
"BITS", "BLAB", "BLAT", "BLED", "BLEW", "BLOB", "BLOC", "BLOT",
|
||||
"BLOW", "BLUE", "BLUM", "BLUR", "BOAR", "BOAT", "BOCA", "BOCK",
|
||||
"BODE", "BODY", "BOGY", "BOHR", "BOIL", "BOLD", "BOLO", "BOLT",
|
||||
"BOMB", "BONA", "BOND", "BONE", "BONG", "BONN", "BONY", "BOOK",
|
||||
"BOOM", "BOON", "BOOT", "BORE", "BORG", "BORN", "BOSE", "BOSS",
|
||||
"BOTH", "BOUT", "BOWL", "BOYD", "BRAD", "BRAE", "BRAG", "BRAN",
|
||||
"BRAY", "BRED", "BREW", "BRIG", "BRIM", "BROW", "BUCK", "BUDD",
|
||||
"BUFF", "BULB", "BULK", "BULL", "BUNK", "BUNT", "BUOY", "BURG",
|
||||
"BURL", "BURN", "BURR", "BURT", "BURY", "BUSH", "BUSS", "BUST",
|
||||
"BUSY", "BYTE", "CADY", "CAFE", "CAGE", "CAIN", "CAKE", "CALF",
|
||||
"CALL", "CALM", "CAME", "CANE", "CANT", "CARD", "CARE", "CARL",
|
||||
"CARR", "CART", "CASE", "CASH", "CASK", "CAST", "CAVE", "CEIL",
|
||||
"CELL", "CENT", "CERN", "CHAD", "CHAR", "CHAT", "CHAW", "CHEF",
|
||||
"CHEN", "CHEW", "CHIC", "CHIN", "CHOU", "CHOW", "CHUB", "CHUG",
|
||||
"CHUM", "CITE", "CITY", "CLAD", "CLAM", "CLAN", "CLAW", "CLAY",
|
||||
"CLOD", "CLOG", "CLOT", "CLUB", "CLUE", "COAL", "COAT", "COCA",
|
||||
"COCK", "COCO", "CODA", "CODE", "CODY", "COED", "COIL", "COIN",
|
||||
"COKE", "COLA", "COLD", "COLT", "COMA", "COMB", "COME", "COOK",
|
||||
"COOL", "COON", "COOT", "CORD", "CORE", "CORK", "CORN", "COST",
|
||||
"COVE", "COWL", "CRAB", "CRAG", "CRAM", "CRAY", "CREW", "CRIB",
|
||||
"CROW", "CRUD", "CUBA", "CUBE", "CUFF", "CULL", "CULT", "CUNY",
|
||||
"CURB", "CURD", "CURE", "CURL", "CURT", "CUTS", "DADE", "DALE",
|
||||
"DAME", "DANA", "DANE", "DANG", "DANK", "DARE", "DARK", "DARN",
|
||||
"DART", "DASH", "DATA", "DATE", "DAVE", "DAVY", "DAWN", "DAYS",
|
||||
"DEAD", "DEAF", "DEAL", "DEAN", "DEAR", "DEBT", "DECK", "DEED",
|
||||
"DEEM", "DEER", "DEFT", "DEFY", "DELL", "DENT", "DENY", "DESK",
|
||||
"DIAL", "DICE", "DIED", "DIET", "DIME", "DINE", "DING", "DINT",
|
||||
"DIRE", "DIRT", "DISC", "DISH", "DISK", "DIVE", "DOCK", "DOES",
|
||||
"DOLE", "DOLL", "DOLT", "DOME", "DONE", "DOOM", "DOOR", "DORA",
|
||||
"DOSE", "DOTE", "DOUG", "DOUR", "DOVE", "DOWN", "DRAB", "DRAG",
|
||||
"DRAM", "DRAW", "DREW", "DRUB", "DRUG", "DRUM", "DUAL", "DUCK",
|
||||
"DUCT", "DUEL", "DUET", "DUKE", "DULL", "DUMB", "DUNE", "DUNK",
|
||||
"DUSK", "DUST", "DUTY", "EACH", "EARL", "EARN", "EASE", "EAST",
|
||||
"EASY", "EBEN", "ECHO", "EDDY", "EDEN", "EDGE", "EDGY", "EDIT",
|
||||
"EDNA", "EGAN", "ELAN", "ELBA", "ELLA", "ELSE", "EMIL", "EMIT",
|
||||
"EMMA", "ENDS", "ERIC", "EROS", "EVEN", "EVER", "EVIL", "EYED",
|
||||
"FACE", "FACT", "FADE", "FAIL", "FAIN", "FAIR", "FAKE", "FALL",
|
||||
"FAME", "FANG", "FARM", "FAST", "FATE", "FAWN", "FEAR", "FEAT",
|
||||
"FEED", "FEEL", "FEET", "FELL", "FELT", "FEND", "FERN", "FEST",
|
||||
"FEUD", "FIEF", "FIGS", "FILE", "FILL", "FILM", "FIND", "FINE",
|
||||
"FINK", "FIRE", "FIRM", "FISH", "FISK", "FIST", "FITS", "FIVE",
|
||||
"FLAG", "FLAK", "FLAM", "FLAT", "FLAW", "FLEA", "FLED", "FLEW",
|
||||
"FLIT", "FLOC", "FLOG", "FLOW", "FLUB", "FLUE", "FOAL", "FOAM",
|
||||
"FOGY", "FOIL", "FOLD", "FOLK", "FOND", "FONT", "FOOD", "FOOL",
|
||||
"FOOT", "FORD", "FORE", "FORK", "FORM", "FORT", "FOSS", "FOUL",
|
||||
"FOUR", "FOWL", "FRAU", "FRAY", "FRED", "FREE", "FRET", "FREY",
|
||||
"FROG", "FROM", "FUEL", "FULL", "FUME", "FUND", "FUNK", "FURY",
|
||||
"FUSE", "FUSS", "GAFF", "GAGE", "GAIL", "GAIN", "GAIT", "GALA",
|
||||
"GALE", "GALL", "GALT", "GAME", "GANG", "GARB", "GARY", "GASH",
|
||||
"GATE", "GAUL", "GAUR", "GAVE", "GAWK", "GEAR", "GELD", "GENE",
|
||||
"GENT", "GERM", "GETS", "GIBE", "GIFT", "GILD", "GILL", "GILT",
|
||||
"GINA", "GIRD", "GIRL", "GIST", "GIVE", "GLAD", "GLEE", "GLEN",
|
||||
"GLIB", "GLOB", "GLOM", "GLOW", "GLUE", "GLUM", "GLUT", "GOAD",
|
||||
"GOAL", "GOAT", "GOER", "GOES", "GOLD", "GOLF", "GONE", "GONG",
|
||||
"GOOD", "GOOF", "GORE", "GORY", "GOSH", "GOUT", "GOWN", "GRAB",
|
||||
"GRAD", "GRAY", "GREG", "GREW", "GREY", "GRID", "GRIM", "GRIN",
|
||||
"GRIT", "GROW", "GRUB", "GULF", "GULL", "GUNK", "GURU", "GUSH",
|
||||
"GUST", "GWEN", "GWYN", "HAAG", "HAAS", "HACK", "HAIL", "HAIR",
|
||||
"HALE", "HALF", "HALL", "HALO", "HALT", "HAND", "HANG", "HANK",
|
||||
"HANS", "HARD", "HARK", "HARM", "HART", "HASH", "HAST", "HATE",
|
||||
"HATH", "HAUL", "HAVE", "HAWK", "HAYS", "HEAD", "HEAL", "HEAR",
|
||||
"HEAT", "HEBE", "HECK", "HEED", "HEEL", "HEFT", "HELD", "HELL",
|
||||
"HELM", "HERB", "HERD", "HERE", "HERO", "HERS", "HESS", "HEWN",
|
||||
"HICK", "HIDE", "HIGH", "HIKE", "HILL", "HILT", "HIND", "HINT",
|
||||
"HIRE", "HISS", "HIVE", "HOBO", "HOCK", "HOFF", "HOLD", "HOLE",
|
||||
"HOLM", "HOLT", "HOME", "HONE", "HONK", "HOOD", "HOOF", "HOOK",
|
||||
"HOOT", "HORN", "HOSE", "HOST", "HOUR", "HOVE", "HOWE", "HOWL",
|
||||
"HOYT", "HUCK", "HUED", "HUFF", "HUGE", "HUGH", "HUGO", "HULK",
|
||||
"HULL", "HUNK", "HUNT", "HURD", "HURL", "HURT", "HUSH", "HYDE",
|
||||
"HYMN", "IBIS", "ICON", "IDEA", "IDLE", "IFFY", "INCA", "INCH",
|
||||
"INTO", "IONS", "IOTA", "IOWA", "IRIS", "IRMA", "IRON", "ISLE",
|
||||
"ITCH", "ITEM", "IVAN", "JACK", "JADE", "JAIL", "JAKE", "JANE",
|
||||
"JAVA", "JEAN", "JEFF", "JERK", "JESS", "JEST", "JIBE", "JILL",
|
||||
"JILT", "JIVE", "JOAN", "JOBS", "JOCK", "JOEL", "JOEY", "JOHN",
|
||||
"JOIN", "JOKE", "JOLT", "JOVE", "JUDD", "JUDE", "JUDO", "JUDY",
|
||||
"JUJU", "JUKE", "JULY", "JUNE", "JUNK", "JUNO", "JURY", "JUST",
|
||||
"JUTE", "KAHN", "KALE", "KANE", "KANT", "KARL", "KATE", "KEEL",
|
||||
"KEEN", "KENO", "KENT", "KERN", "KERR", "KEYS", "KICK", "KILL",
|
||||
"KIND", "KING", "KIRK", "KISS", "KITE", "KLAN", "KNEE", "KNEW",
|
||||
"KNIT", "KNOB", "KNOT", "KNOW", "KOCH", "KONG", "KUDO", "KURD",
|
||||
"KURT", "KYLE", "LACE", "LACK", "LACY", "LADY", "LAID", "LAIN",
|
||||
"LAIR", "LAKE", "LAMB", "LAME", "LAND", "LANE", "LANG", "LARD",
|
||||
"LARK", "LASS", "LAST", "LATE", "LAUD", "LAVA", "LAWN", "LAWS",
|
||||
"LAYS", "LEAD", "LEAF", "LEAK", "LEAN", "LEAR", "LEEK", "LEER",
|
||||
"LEFT", "LEND", "LENS", "LENT", "LEON", "LESK", "LESS", "LEST",
|
||||
"LETS", "LIAR", "LICE", "LICK", "LIED", "LIEN", "LIES", "LIEU",
|
||||
"LIFE", "LIFT", "LIKE", "LILA", "LILT", "LILY", "LIMA", "LIMB",
|
||||
"LIME", "LIND", "LINE", "LINK", "LINT", "LION", "LISA", "LIST",
|
||||
"LIVE", "LOAD", "LOAF", "LOAM", "LOAN", "LOCK", "LOFT", "LOGE",
|
||||
"LOIS", "LOLA", "LONE", "LONG", "LOOK", "LOON", "LOOT", "LORD",
|
||||
"LORE", "LOSE", "LOSS", "LOST", "LOUD", "LOVE", "LOWE", "LUCK",
|
||||
"LUCY", "LUGE", "LUKE", "LULU", "LUND", "LUNG", "LURA", "LURE",
|
||||
"LURK", "LUSH", "LUST", "LYLE", "LYNN", "LYON", "LYRA", "MACE",
|
||||
"MADE", "MAGI", "MAID", "MAIL", "MAIN", "MAKE", "MALE", "MALI",
|
||||
"MALL", "MALT", "MANA", "MANN", "MANY", "MARC", "MARE", "MARK",
|
||||
"MARS", "MART", "MARY", "MASH", "MASK", "MASS", "MAST", "MATE",
|
||||
"MATH", "MAUL", "MAYO", "MEAD", "MEAL", "MEAN", "MEAT", "MEEK",
|
||||
"MEET", "MELD", "MELT", "MEMO", "MEND", "MENU", "MERT", "MESH",
|
||||
"MESS", "MICE", "MIKE", "MILD", "MILE", "MILK", "MILL", "MILT",
|
||||
"MIMI", "MIND", "MINE", "MINI", "MINK", "MINT", "MIRE", "MISS",
|
||||
"MIST", "MITE", "MITT", "MOAN", "MOAT", "MOCK", "MODE", "MOLD",
|
||||
"MOLE", "MOLL", "MOLT", "MONA", "MONK", "MONT", "MOOD", "MOON",
|
||||
"MOOR", "MOOT", "MORE", "MORN", "MORT", "MOSS", "MOST", "MOTH",
|
||||
"MOVE", "MUCH", "MUCK", "MUDD", "MUFF", "MULE", "MULL", "MURK",
|
||||
"MUSH", "MUST", "MUTE", "MUTT", "MYRA", "MYTH", "NAGY", "NAIL",
|
||||
"NAIR", "NAME", "NARY", "NASH", "NAVE", "NAVY", "NEAL", "NEAR",
|
||||
"NEAT", "NECK", "NEED", "NEIL", "NELL", "NEON", "NERO", "NESS",
|
||||
"NEST", "NEWS", "NEWT", "NIBS", "NICE", "NICK", "NILE", "NINA",
|
||||
"NINE", "NOAH", "NODE", "NOEL", "NOLL", "NONE", "NOOK", "NOON",
|
||||
"NORM", "NOSE", "NOTE", "NOUN", "NOVA", "NUDE", "NULL", "NUMB",
|
||||
"OATH", "OBEY", "OBOE", "ODIN", "OHIO", "OILY", "OINT", "OKAY",
|
||||
"OLAF", "OLDY", "OLGA", "OLIN", "OMAN", "OMEN", "OMIT", "ONCE",
|
||||
"ONES", "ONLY", "ONTO", "ONUS", "ORAL", "ORGY", "OSLO", "OTIS",
|
||||
"OTTO", "OUCH", "OUST", "OUTS", "OVAL", "OVEN", "OVER", "OWLY",
|
||||
"OWNS", "QUAD", "QUIT", "QUOD", "RACE", "RACK", "RACY", "RAFT",
|
||||
"RAGE", "RAID", "RAIL", "RAIN", "RAKE", "RANK", "RANT", "RARE",
|
||||
"RASH", "RATE", "RAVE", "RAYS", "READ", "REAL", "REAM", "REAR",
|
||||
"RECK", "REED", "REEF", "REEK", "REEL", "REID", "REIN", "RENA",
|
||||
"REND", "RENT", "REST", "RICE", "RICH", "RICK", "RIDE", "RIFT",
|
||||
"RILL", "RIME", "RING", "RINK", "RISE", "RISK", "RITE", "ROAD",
|
||||
"ROAM", "ROAR", "ROBE", "ROCK", "RODE", "ROIL", "ROLL", "ROME",
|
||||
"ROOD", "ROOF", "ROOK", "ROOM", "ROOT", "ROSA", "ROSE", "ROSS",
|
||||
"ROSY", "ROTH", "ROUT", "ROVE", "ROWE", "ROWS", "RUBE", "RUBY",
|
||||
"RUDE", "RUDY", "RUIN", "RULE", "RUNG", "RUNS", "RUNT", "RUSE",
|
||||
"RUSH", "RUSK", "RUSS", "RUST", "RUTH", "SACK", "SAFE", "SAGE",
|
||||
"SAID", "SAIL", "SALE", "SALK", "SALT", "SAME", "SAND", "SANE",
|
||||
"SANG", "SANK", "SARA", "SAUL", "SAVE", "SAYS", "SCAN", "SCAR",
|
||||
"SCAT", "SCOT", "SEAL", "SEAM", "SEAR", "SEAT", "SEED", "SEEK",
|
||||
"SEEM", "SEEN", "SEES", "SELF", "SELL", "SEND", "SENT", "SETS",
|
||||
"SEWN", "SHAG", "SHAM", "SHAW", "SHAY", "SHED", "SHIM", "SHIN",
|
||||
"SHOD", "SHOE", "SHOT", "SHOW", "SHUN", "SHUT", "SICK", "SIDE",
|
||||
"SIFT", "SIGH", "SIGN", "SILK", "SILL", "SILO", "SILT", "SINE",
|
||||
"SING", "SINK", "SIRE", "SITE", "SITS", "SITU", "SKAT", "SKEW",
|
||||
"SKID", "SKIM", "SKIN", "SKIT", "SLAB", "SLAM", "SLAT", "SLAY",
|
||||
"SLED", "SLEW", "SLID", "SLIM", "SLIT", "SLOB", "SLOG", "SLOT",
|
||||
"SLOW", "SLUG", "SLUM", "SLUR", "SMOG", "SMUG", "SNAG", "SNOB",
|
||||
"SNOW", "SNUB", "SNUG", "SOAK", "SOAR", "SOCK", "SODA", "SOFA",
|
||||
"SOFT", "SOIL", "SOLD", "SOME", "SONG", "SOON", "SOOT", "SORE",
|
||||
"SORT", "SOUL", "SOUR", "SOWN", "STAB", "STAG", "STAN", "STAR",
|
||||
"STAY", "STEM", "STEW", "STIR", "STOW", "STUB", "STUN", "SUCH",
|
||||
"SUDS", "SUIT", "SULK", "SUMS", "SUNG", "SUNK", "SURE", "SURF",
|
||||
"SWAB", "SWAG", "SWAM", "SWAN", "SWAT", "SWAY", "SWIM", "SWUM",
|
||||
"TACK", "TACT", "TAIL", "TAKE", "TALE", "TALK", "TALL", "TANK",
|
||||
"TASK", "TATE", "TAUT", "TEAL", "TEAM", "TEAR", "TECH", "TEEM",
|
||||
"TEEN", "TEET", "TELL", "TEND", "TENT", "TERM", "TERN", "TESS",
|
||||
"TEST", "THAN", "THAT", "THEE", "THEM", "THEN", "THEY", "THIN",
|
||||
"THIS", "THUD", "THUG", "TICK", "TIDE", "TIDY", "TIED", "TIER",
|
||||
"TILE", "TILL", "TILT", "TIME", "TINA", "TINE", "TINT", "TINY",
|
||||
"TIRE", "TOAD", "TOGO", "TOIL", "TOLD", "TOLL", "TONE", "TONG",
|
||||
"TONY", "TOOK", "TOOL", "TOOT", "TORE", "TORN", "TOTE", "TOUR",
|
||||
"TOUT", "TOWN", "TRAG", "TRAM", "TRAY", "TREE", "TREK", "TRIG",
|
||||
"TRIM", "TRIO", "TROD", "TROT", "TROY", "TRUE", "TUBA", "TUBE",
|
||||
"TUCK", "TUFT", "TUNA", "TUNE", "TUNG", "TURF", "TURN", "TUSK",
|
||||
"TWIG", "TWIN", "TWIT", "ULAN", "UNIT", "URGE", "USED", "USER",
|
||||
"USES", "UTAH", "VAIL", "VAIN", "VALE", "VARY", "VASE", "VAST",
|
||||
"VEAL", "VEDA", "VEIL", "VEIN", "VEND", "VENT", "VERB", "VERY",
|
||||
"VETO", "VICE", "VIEW", "VINE", "VISE", "VOID", "VOLT", "VOTE",
|
||||
"WACK", "WADE", "WAGE", "WAIL", "WAIT", "WAKE", "WALE", "WALK",
|
||||
"WALL", "WALT", "WAND", "WANE", "WANG", "WANT", "WARD", "WARM",
|
||||
"WARN", "WART", "WASH", "WAST", "WATS", "WATT", "WAVE", "WAVY",
|
||||
"WAYS", "WEAK", "WEAL", "WEAN", "WEAR", "WEED", "WEEK", "WEIR",
|
||||
"WELD", "WELL", "WELT", "WENT", "WERE", "WERT", "WEST", "WHAM",
|
||||
"WHAT", "WHEE", "WHEN", "WHET", "WHOA", "WHOM", "WICK", "WIFE",
|
||||
"WILD", "WILL", "WIND", "WINE", "WING", "WINK", "WINO", "WIRE",
|
||||
"WISE", "WISH", "WITH", "WOLF", "WONT", "WOOD", "WOOL", "WORD",
|
||||
"WORE", "WORK", "WORM", "WORN", "WOVE", "WRIT", "WYNN", "YALE",
|
||||
"YANG", "YANK", "YARD", "YARN", "YAWL", "YAWN", "YEAH", "YEAR",
|
||||
"YELL", "YOGA", "YOKE" ]
|
||||
163
packages/xahau/src/Wallet/signer.ts
Normal file
163
packages/xahau/src/Wallet/signer.ts
Normal file
@@ -0,0 +1,163 @@
|
||||
import { bytesToHex } from '@xrplf/isomorphic/utils'
|
||||
import { BigNumber } from 'bignumber.js'
|
||||
import { decodeAccountID } from 'xahau-address-codec'
|
||||
import { decode, encode, encodeForSigning } from 'xahau-binary-codec'
|
||||
import { verify } from 'xahau-keypairs'
|
||||
|
||||
import { ValidationError } from '../errors'
|
||||
import { Signer } from '../models/common'
|
||||
import { Transaction, validate } from '../models/transactions'
|
||||
|
||||
/**
|
||||
* Takes several transactions with Signer fields (in object or blob form) and creates a
|
||||
* single transaction with all Signers that then gets signed and returned.
|
||||
*
|
||||
* @param transactions - An array of signed Transactions (in object or blob form) to combine into a single signed Transaction.
|
||||
* @returns A single signed Transaction which has all Signers from transactions within it.
|
||||
* @throws ValidationError if:
|
||||
* - There were no transactions given to sign
|
||||
* - The SigningPubKey field is not the empty string in any given transaction
|
||||
* - Any transaction is missing a Signers field.
|
||||
* @category Signing
|
||||
*/
|
||||
function multisign(transactions: Array<Transaction | string>): string {
|
||||
if (transactions.length === 0) {
|
||||
throw new ValidationError('There were 0 transactions to multisign')
|
||||
}
|
||||
|
||||
const decodedTransactions: Transaction[] = transactions.map(
|
||||
(txOrBlob: string | Transaction) => {
|
||||
return getDecodedTransaction(txOrBlob)
|
||||
},
|
||||
)
|
||||
|
||||
decodedTransactions.forEach((tx) => {
|
||||
/*
|
||||
* This will throw a more clear error for JS users if any of the supplied transactions has incorrect formatting
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- validate does not accept Transaction type
|
||||
validate(tx as unknown as Record<string, unknown>)
|
||||
if (tx.Signers == null || tx.Signers.length === 0) {
|
||||
throw new ValidationError(
|
||||
"For multisigning all transactions must include a Signers field containing an array of signatures. You may have forgotten to pass the 'forMultisign' parameter when signing.",
|
||||
)
|
||||
}
|
||||
|
||||
if (tx.SigningPubKey !== '') {
|
||||
throw new ValidationError(
|
||||
'SigningPubKey must be an empty string for all transactions when multisigning.',
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
validateTransactionEquivalence(decodedTransactions)
|
||||
|
||||
return encode(getTransactionWithAllSigners(decodedTransactions))
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that the given transaction has a valid signature based on public-key encryption.
|
||||
*
|
||||
* @param tx - A transaction to verify the signature of. (Can be in object or encoded string format).
|
||||
* @param [publicKey] Specific public key to use to verify. If not specified the `SigningPublicKey` of tx will be used.
|
||||
* @returns Returns true if tx has a valid signature, and returns false otherwise.
|
||||
* @throws Error when transaction is missing TxnSignature
|
||||
* @throws Error when publicKey is not provided and transaction is missing SigningPubKey
|
||||
* @category Utilities
|
||||
*/
|
||||
function verifySignature(
|
||||
tx: Transaction | string,
|
||||
publicKey?: string,
|
||||
): boolean {
|
||||
const decodedTx: Transaction = getDecodedTransaction(tx)
|
||||
let key = publicKey
|
||||
|
||||
// Need a SignedTransaction class where TxnSignature is not optional.
|
||||
if (typeof decodedTx.TxnSignature !== 'string' || !decodedTx.TxnSignature) {
|
||||
throw new Error('Transaction is missing a signature, TxnSignature')
|
||||
}
|
||||
|
||||
if (!key) {
|
||||
// Need a SignedTransaction class where TxnSignature is not optional.
|
||||
if (
|
||||
typeof decodedTx.SigningPubKey !== 'string' ||
|
||||
!decodedTx.SigningPubKey
|
||||
) {
|
||||
throw new Error('Transaction is missing a public key, SigningPubKey')
|
||||
}
|
||||
key = decodedTx.SigningPubKey
|
||||
}
|
||||
|
||||
return verify(encodeForSigning(decodedTx), decodedTx.TxnSignature, key)
|
||||
}
|
||||
|
||||
/**
|
||||
* The transactions should all be equal except for the 'Signers' field.
|
||||
*
|
||||
* @param transactions - An array of Transactions which are expected to be equal other than 'Signers'.
|
||||
* @throws ValidationError if the transactions are not equal in any field other than 'Signers'.
|
||||
*/
|
||||
function validateTransactionEquivalence(transactions: Transaction[]): void {
|
||||
const exampleTransaction = JSON.stringify({
|
||||
...transactions[0],
|
||||
Signers: null,
|
||||
})
|
||||
if (
|
||||
transactions
|
||||
.slice(1)
|
||||
.some(
|
||||
(tx) => JSON.stringify({ ...tx, Signers: null }) !== exampleTransaction,
|
||||
)
|
||||
) {
|
||||
throw new ValidationError(
|
||||
'txJSON is not the same for all signedTransactions',
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
function getTransactionWithAllSigners(
|
||||
transactions: Transaction[],
|
||||
): Transaction {
|
||||
// Signers must be sorted in the combined transaction - See compareSigners' documentation for more details
|
||||
const sortedSigners: Signer[] = transactions
|
||||
.flatMap((tx) => tx.Signers ?? [])
|
||||
.sort(compareSigners)
|
||||
|
||||
return { ...transactions[0], Signers: sortedSigners }
|
||||
}
|
||||
|
||||
/**
|
||||
* If presented in binary form, the Signers array must be sorted based on
|
||||
* the numeric value of the signer addresses, with the lowest value first.
|
||||
* (If submitted as JSON, the submit_multisigned method handles this automatically.)
|
||||
* https://xrpl.org/multi-signing.html.
|
||||
*
|
||||
* @param left - A Signer to compare with.
|
||||
* @param right - A second Signer to compare with.
|
||||
* @returns 1 if left \> right, 0 if left = right, -1 if left \< right, and null if left or right are NaN.
|
||||
*/
|
||||
function compareSigners(left: Signer, right: Signer): number {
|
||||
return addressToBigNumber(left.Signer.Account).comparedTo(
|
||||
addressToBigNumber(right.Signer.Account),
|
||||
)
|
||||
}
|
||||
|
||||
const NUM_BITS_IN_HEX = 16
|
||||
|
||||
function addressToBigNumber(address: string): BigNumber {
|
||||
const hex = bytesToHex(decodeAccountID(address))
|
||||
return new BigNumber(hex, NUM_BITS_IN_HEX)
|
||||
}
|
||||
|
||||
function getDecodedTransaction(txOrBlob: Transaction | string): Transaction {
|
||||
if (typeof txOrBlob === 'object') {
|
||||
// We need this to handle X-addresses in multisigning
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- We are casting here to get strong typing
|
||||
return decode(encode(txOrBlob)) as unknown as Transaction
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- We are casting here to get strong typing
|
||||
return decode(txOrBlob) as unknown as Transaction
|
||||
}
|
||||
|
||||
export { verifySignature, multisign }
|
||||
37
packages/xahau/src/Wallet/walletFromSecretNumbers.ts
Normal file
37
packages/xahau/src/Wallet/walletFromSecretNumbers.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import { Account } from '@xrplf/secret-numbers'
|
||||
|
||||
import ECDSA from '../ECDSA'
|
||||
|
||||
import { Wallet } from '.'
|
||||
|
||||
/**
|
||||
* Derives a wallet from secret numbers.
|
||||
* NOTE: This uses a default encoding algorithm of secp256k1 to match the popular wallet
|
||||
* [Xumm (aka Xaman)](https://xumm.app/)'s behavior.
|
||||
* This may be different from the DEFAULT_ALGORITHM for other ways to generate a Wallet.
|
||||
*
|
||||
* @param secretNumbers - A string consisting of 8 times 6 numbers (whitespace delimited) used to derive a wallet.
|
||||
* @param opts - (Optional) Options to derive a Wallet.
|
||||
* @param opts.masterAddress - Include if a Wallet uses a Regular Key Pair. It must be the master address of the account.
|
||||
* @param opts.algorithm - The digital signature algorithm to generate an address for.
|
||||
* @returns A Wallet derived from secret numbers.
|
||||
* @throws ValidationError if unable to derive private key from secret number input.
|
||||
*/
|
||||
export function walletFromSecretNumbers(
|
||||
secretNumbers: string[] | string,
|
||||
opts?: { masterAddress?: string; algorithm?: ECDSA },
|
||||
): Wallet {
|
||||
const secret = new Account(secretNumbers).getFamilySeed()
|
||||
const updatedOpts: { masterAddress?: string; algorithm?: ECDSA } = {
|
||||
masterAddress: undefined,
|
||||
algorithm: undefined,
|
||||
}
|
||||
// Use secp256k1 since that's the algorithm used by popular wallets like Xumm when generating secret number accounts
|
||||
if (opts === undefined) {
|
||||
updatedOpts.algorithm = ECDSA.secp256k1
|
||||
} else {
|
||||
updatedOpts.masterAddress = opts.masterAddress
|
||||
updatedOpts.algorithm = opts.algorithm ?? ECDSA.secp256k1
|
||||
}
|
||||
return Wallet.fromSecret(secret, updatedOpts)
|
||||
}
|
||||
40
packages/xahau/src/client/ConnectionManager.ts
Normal file
40
packages/xahau/src/client/ConnectionManager.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Manage all the requests made to the websocket, and their async responses
|
||||
* that come in from the WebSocket. Because they come in over the WS connection
|
||||
* after-the-fact.
|
||||
*/
|
||||
export default class ConnectionManager {
|
||||
private promisesAwaitingConnection: Array<{
|
||||
resolve: (value?: void | PromiseLike<void>) => void
|
||||
reject: (value?: Error) => void
|
||||
}> = []
|
||||
|
||||
/**
|
||||
* Resolves all awaiting connections.
|
||||
*/
|
||||
public resolveAllAwaiting(): void {
|
||||
this.promisesAwaitingConnection.map(({ resolve }) => resolve())
|
||||
this.promisesAwaitingConnection = []
|
||||
}
|
||||
|
||||
/**
|
||||
* Rejects all awaiting connections.
|
||||
*
|
||||
* @param error - Error to throw in the rejection.
|
||||
*/
|
||||
public rejectAllAwaiting(error: Error): void {
|
||||
this.promisesAwaitingConnection.map(({ reject }) => reject(error))
|
||||
this.promisesAwaitingConnection = []
|
||||
}
|
||||
|
||||
/**
|
||||
* Await a new connection.
|
||||
*
|
||||
* @returns A promise for resolving the connection.
|
||||
*/
|
||||
public async awaitConnection(): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.promisesAwaitingConnection.push({ resolve, reject })
|
||||
})
|
||||
}
|
||||
}
|
||||
71
packages/xahau/src/client/ExponentialBackoff.ts
Normal file
71
packages/xahau/src/client/ExponentialBackoff.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Original code based on "backo" - https://github.com/segmentio/backo
|
||||
* MIT License - Copyright 2014 Segment.io
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following conditions:
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
||||
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
interface ExponentialBackoffOptions {
|
||||
// The min backoff duration.
|
||||
min?: number
|
||||
// The max backoff duration.
|
||||
max?: number
|
||||
}
|
||||
|
||||
const DEFAULT_MIN = 100
|
||||
const DEFAULT_MAX = 1000
|
||||
|
||||
/**
|
||||
* A Back off strategy that increases exponentially. Useful with repeated
|
||||
* setTimeout calls over a network (where the destination may be down).
|
||||
*/
|
||||
export default class ExponentialBackoff {
|
||||
private readonly ms: number
|
||||
private readonly max: number
|
||||
private readonly factor: number = 2
|
||||
private numAttempts = 0
|
||||
|
||||
/**
|
||||
* Constructs an ExponentialBackoff object.
|
||||
*
|
||||
* @param opts - The options for the object.
|
||||
*/
|
||||
public constructor(opts: ExponentialBackoffOptions = {}) {
|
||||
this.ms = opts.min ?? DEFAULT_MIN
|
||||
this.max = opts.max ?? DEFAULT_MAX
|
||||
}
|
||||
|
||||
/**
|
||||
* Number of attempts for backoff so far.
|
||||
*
|
||||
* @returns Number of attempts.
|
||||
*/
|
||||
public get attempts(): number {
|
||||
return this.numAttempts
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the backoff duration.
|
||||
*
|
||||
* @returns The backoff duration in milliseconds.
|
||||
*/
|
||||
public duration(): number {
|
||||
const ms = this.ms * this.factor ** this.numAttempts
|
||||
this.numAttempts += 1
|
||||
return Math.floor(Math.min(ms, this.max))
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the number of attempts.
|
||||
*/
|
||||
public reset(): void {
|
||||
this.numAttempts = 0
|
||||
}
|
||||
}
|
||||
225
packages/xahau/src/client/RequestManager.ts
Normal file
225
packages/xahau/src/client/RequestManager.ts
Normal file
@@ -0,0 +1,225 @@
|
||||
import {
|
||||
ResponseFormatError,
|
||||
XahaudError,
|
||||
TimeoutError,
|
||||
XahlError,
|
||||
} from '../errors'
|
||||
import type { APIVersion } from '../models'
|
||||
import { Response, RequestResponseMap } from '../models/methods'
|
||||
import { BaseRequest, ErrorResponse } from '../models/methods/baseMethod'
|
||||
|
||||
interface PromiseEntry<T> {
|
||||
resolve: (value: T | PromiseLike<T>) => void
|
||||
reject: (value: Error) => void
|
||||
timer: ReturnType<typeof setTimeout>
|
||||
}
|
||||
|
||||
/**
|
||||
* Manage all the requests made to the websocket, and their async responses
|
||||
* that come in from the WebSocket. Responses come in over the WS connection
|
||||
* after-the-fact, so this manager will tie that response to resolve the
|
||||
* original request.
|
||||
*/
|
||||
export default class RequestManager {
|
||||
private nextId = 0
|
||||
private readonly promisesAwaitingResponse = new Map<
|
||||
string | number,
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Necessary and typed wrapper in addPromise method
|
||||
PromiseEntry<any>
|
||||
>()
|
||||
|
||||
/**
|
||||
* Adds a promise to the collection of promises awaiting response. Handles typing with generics.
|
||||
*
|
||||
* @template T The generic type parameter representing the resolved value type.
|
||||
* @param newId - The identifier for the new promise.
|
||||
* @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, APIVersion>,
|
||||
>(newId: string | number, timer: ReturnType<typeof setTimeout>): Promise<T> {
|
||||
return new Promise<T>((resolve, reject) => {
|
||||
this.promisesAwaitingResponse.set(newId, {
|
||||
resolve,
|
||||
reject,
|
||||
timer,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Successfully resolves a request.
|
||||
*
|
||||
* @param id - ID of the request.
|
||||
* @param response - Response to return.
|
||||
* @throws Error if no existing promise with the given ID.
|
||||
*/
|
||||
public resolve(
|
||||
id: string | number,
|
||||
response: Partial<Response<APIVersion>>,
|
||||
): void {
|
||||
const promise = this.promisesAwaitingResponse.get(id)
|
||||
if (promise == null) {
|
||||
throw new XahlError(`No existing promise with id ${id}`, {
|
||||
type: 'resolve',
|
||||
response,
|
||||
})
|
||||
}
|
||||
clearTimeout(promise.timer)
|
||||
promise.resolve(response)
|
||||
this.deletePromise(id)
|
||||
}
|
||||
|
||||
/**
|
||||
* Rejects a request.
|
||||
*
|
||||
* @param id - ID of the request.
|
||||
* @param error - Error to throw with the reject.
|
||||
* @throws Error if no existing promise with the given ID.
|
||||
*/
|
||||
public reject(id: string | number, error: Error): void {
|
||||
const promise = this.promisesAwaitingResponse.get(id)
|
||||
if (promise == null) {
|
||||
throw new XahlError(`No existing promise with id ${id}`, {
|
||||
type: 'reject',
|
||||
error,
|
||||
})
|
||||
}
|
||||
clearTimeout(promise.timer)
|
||||
// TODO: figure out how to have a better stack trace for an error
|
||||
promise.reject(error)
|
||||
this.deletePromise(id)
|
||||
}
|
||||
|
||||
/**
|
||||
* Reject all pending requests.
|
||||
*
|
||||
* @param error - Error to throw with the reject.
|
||||
*/
|
||||
public rejectAll(error: Error): void {
|
||||
this.promisesAwaitingResponse.forEach((_promise, id, _map) => {
|
||||
this.reject(id, error)
|
||||
this.deletePromise(id)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new WebSocket request. This sets up a timeout timer to catch
|
||||
* hung responses, and a promise that will resolve with the response once
|
||||
* the response is seen & handled.
|
||||
*
|
||||
* @param request - Request to create.
|
||||
* @param timeout - Timeout length to catch hung responses.
|
||||
* @returns Request ID, new request form, and the promise for resolving the request.
|
||||
* @throws XahlError if request with the same ID is already pending.
|
||||
*/
|
||||
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
|
||||
this.nextId += 1
|
||||
} else {
|
||||
newId = request.id
|
||||
}
|
||||
const newRequest = JSON.stringify({ ...request, id: newId })
|
||||
// Typing required for Jest running in browser
|
||||
const timer: ReturnType<typeof setTimeout> = setTimeout(() => {
|
||||
this.reject(
|
||||
newId,
|
||||
new TimeoutError(
|
||||
`Timeout for request: ${JSON.stringify(request)} with id ${newId}`,
|
||||
request,
|
||||
),
|
||||
)
|
||||
}, timeout)
|
||||
/*
|
||||
* Node.js won't exit if a timer is still running, so we tell Node to ignore.
|
||||
* (Node will still wait for the request to complete).
|
||||
*/
|
||||
// The following type assertions are required to get this code to pass in browser environments
|
||||
// where setTimeout has a different type
|
||||
// eslint-disable-next-line max-len -- Necessary to disable both rules.
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions, @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access -- Reason above.
|
||||
if ((timer as unknown as any).unref) {
|
||||
// eslint-disable-next-line max-len -- Necessary to disable both rules.
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions, @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call -- Reason above.
|
||||
;(timer as unknown as any).unref()
|
||||
}
|
||||
if (this.promisesAwaitingResponse.has(newId)) {
|
||||
clearTimeout(timer)
|
||||
throw new XahlError(
|
||||
`Response with id '${newId}' is already pending`,
|
||||
request,
|
||||
)
|
||||
}
|
||||
const newPromise = new Promise<T>((resolve, reject) => {
|
||||
this.promisesAwaitingResponse.set(newId, {
|
||||
resolve,
|
||||
reject,
|
||||
timer,
|
||||
})
|
||||
})
|
||||
|
||||
return [newId, newRequest, newPromise]
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a "response". Responses match to the earlier request handlers,
|
||||
* and resolve/reject based on the data received.
|
||||
*
|
||||
* @param response - The response to handle.
|
||||
* @throws ResponseFormatError if the response format is invalid, XahaudError if xahaud returns an error.
|
||||
*/
|
||||
public handleResponse(
|
||||
response: Partial<Response<APIVersion> | ErrorResponse>,
|
||||
): void {
|
||||
if (
|
||||
response.id == null ||
|
||||
!(typeof response.id === 'string' || typeof response.id === 'number')
|
||||
) {
|
||||
throw new ResponseFormatError('valid id not found in response', response)
|
||||
}
|
||||
if (!this.promisesAwaitingResponse.has(response.id)) {
|
||||
return
|
||||
}
|
||||
if (response.status == null) {
|
||||
const error = new ResponseFormatError('Response has no status')
|
||||
this.reject(response.id, error)
|
||||
}
|
||||
if (response.status === 'error') {
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- We know this must be true
|
||||
const errorResponse = response as Partial<ErrorResponse>
|
||||
const error = new XahaudError(
|
||||
errorResponse.error_message ?? errorResponse.error,
|
||||
errorResponse,
|
||||
)
|
||||
this.reject(response.id, error)
|
||||
return
|
||||
}
|
||||
if (response.status !== 'success') {
|
||||
const error = new ResponseFormatError(
|
||||
`unrecognized response.status: ${response.status ?? ''}`,
|
||||
response,
|
||||
)
|
||||
this.reject(response.id, error)
|
||||
return
|
||||
}
|
||||
// status no longer needed because error is thrown if status is not "success"
|
||||
delete response.status
|
||||
this.resolve(response.id, response)
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a promise after it has been returned.
|
||||
*
|
||||
* @param id - ID of the request.
|
||||
*/
|
||||
private deletePromise(id: string | number): void {
|
||||
this.promisesAwaitingResponse.delete(id)
|
||||
}
|
||||
}
|
||||
528
packages/xahau/src/client/connection.ts
Normal file
528
packages/xahau/src/client/connection.ts
Normal file
@@ -0,0 +1,528 @@
|
||||
/* eslint-disable max-lines -- Connection is a large file w/ lots of imports/exports */
|
||||
import type { Agent } from 'http'
|
||||
|
||||
import { bytesToHex, hexToString } from '@xrplf/isomorphic/utils'
|
||||
import WebSocket, { ClientOptions } from '@xrplf/isomorphic/ws'
|
||||
import { EventEmitter } from 'eventemitter3'
|
||||
|
||||
import {
|
||||
DisconnectedError,
|
||||
NotConnectedError,
|
||||
ConnectionError,
|
||||
XahlError,
|
||||
} from '../errors'
|
||||
import type { APIVersion, RequestResponseMap } from '../models'
|
||||
import { BaseRequest } from '../models/methods/baseMethod'
|
||||
|
||||
import ConnectionManager from './ConnectionManager'
|
||||
import ExponentialBackoff from './ExponentialBackoff'
|
||||
import RequestManager from './RequestManager'
|
||||
|
||||
const SECONDS_PER_MINUTE = 60
|
||||
const TIMEOUT = 20
|
||||
const CONNECTION_TIMEOUT = 5
|
||||
|
||||
/**
|
||||
* ConnectionOptions is the configuration for the Connection class.
|
||||
*/
|
||||
interface ConnectionOptions {
|
||||
trace?: boolean | ((id: string, message: string) => void)
|
||||
headers?: { [key: string]: string }
|
||||
agent?: Agent
|
||||
authorization?: string
|
||||
connectionTimeout: number
|
||||
timeout: number
|
||||
}
|
||||
|
||||
/**
|
||||
* ConnectionUserOptions is the user-provided configuration object. All configuration
|
||||
* is optional, so any ConnectionOptions configuration that has a default value is
|
||||
* still optional at the point that the user provides it.
|
||||
*/
|
||||
export type ConnectionUserOptions = Partial<ConnectionOptions>
|
||||
|
||||
/**
|
||||
* Represents an intentionally triggered web-socket disconnect code.
|
||||
* WebSocket spec allows 4xxx codes for app/library specific codes.
|
||||
* See: https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent
|
||||
*/
|
||||
export const INTENTIONAL_DISCONNECT_CODE = 4000
|
||||
|
||||
type WebsocketState = 0 | 1 | 2 | 3
|
||||
|
||||
/**
|
||||
* Create a new websocket given your URL and optional proxy/certificate
|
||||
* configuration.
|
||||
*
|
||||
* @param url - The URL to connect to.
|
||||
* @param config - THe configuration options for the WebSocket.
|
||||
* @returns A Websocket that fits the given configuration parameters.
|
||||
*/
|
||||
function createWebSocket(
|
||||
url: string,
|
||||
config: ConnectionOptions,
|
||||
): WebSocket | null {
|
||||
const options: ClientOptions = {
|
||||
agent: config.agent,
|
||||
}
|
||||
if (config.headers) {
|
||||
options.headers = config.headers
|
||||
}
|
||||
if (config.authorization != null) {
|
||||
options.headers = {
|
||||
...options.headers,
|
||||
Authorization: `Basic ${btoa(config.authorization)}`,
|
||||
}
|
||||
}
|
||||
const websocketOptions = { ...options }
|
||||
return new WebSocket(url, websocketOptions)
|
||||
}
|
||||
|
||||
/**
|
||||
* Ws.send(), but promisified.
|
||||
*
|
||||
* @param ws - Websocket to send with.
|
||||
* @param message - Message to send.
|
||||
* @returns When the message has been sent.
|
||||
*/
|
||||
async function websocketSendAsync(
|
||||
ws: WebSocket,
|
||||
message: string,
|
||||
): Promise<void> {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
ws.send(message, (error) => {
|
||||
if (error) {
|
||||
reject(new DisconnectedError(error.message, error))
|
||||
} else {
|
||||
resolve()
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* The main Connection class. Responsible for connecting to & managing
|
||||
* an active WebSocket connection to a XAHL node.
|
||||
*/
|
||||
export class Connection extends EventEmitter {
|
||||
private readonly url: string | undefined
|
||||
private ws: WebSocket | null = null
|
||||
// Typing necessary for Jest tests running in browser
|
||||
private reconnectTimeoutID: null | ReturnType<typeof setTimeout> = null
|
||||
// Typing necessary for Jest tests running in browser
|
||||
private heartbeatIntervalID: null | ReturnType<typeof setTimeout> = null
|
||||
private readonly retryConnectionBackoff = new ExponentialBackoff({
|
||||
min: 100,
|
||||
max: SECONDS_PER_MINUTE * 1000,
|
||||
})
|
||||
|
||||
private readonly config: ConnectionOptions
|
||||
private readonly requestManager = new RequestManager()
|
||||
private readonly connectionManager = new ConnectionManager()
|
||||
|
||||
/**
|
||||
* Creates a new Connection object.
|
||||
*
|
||||
* @param url - URL to connect to.
|
||||
* @param options - Options for the Connection object.
|
||||
*/
|
||||
public constructor(url?: string, options: ConnectionUserOptions = {}) {
|
||||
super()
|
||||
this.url = url
|
||||
this.config = {
|
||||
timeout: TIMEOUT * 1000,
|
||||
connectionTimeout: CONNECTION_TIMEOUT * 1000,
|
||||
...options,
|
||||
}
|
||||
if (typeof options.trace === 'function') {
|
||||
this.trace = options.trace
|
||||
} else if (options.trace) {
|
||||
// eslint-disable-next-line no-console -- Used for tracing only
|
||||
this.trace = console.log
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the state of the websocket.
|
||||
*
|
||||
* @returns The Websocket's ready state.
|
||||
*/
|
||||
private get state(): WebsocketState {
|
||||
return this.ws ? this.ws.readyState : WebSocket.CLOSED
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the server should be connected.
|
||||
*
|
||||
* @returns Whether the server should be connected.
|
||||
*/
|
||||
private get shouldBeConnected(): boolean {
|
||||
return this.ws !== null
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the websocket is connected.
|
||||
*
|
||||
* @returns Whether the websocket connection is open.
|
||||
*/
|
||||
public isConnected(): boolean {
|
||||
return this.state === WebSocket.OPEN
|
||||
}
|
||||
|
||||
/**
|
||||
* Connects the websocket to the provided URL.
|
||||
*
|
||||
* @returns When the websocket is connected.
|
||||
* @throws ConnectionError if there is a connection error, RippleError if there is already a WebSocket in existence.
|
||||
*/
|
||||
// eslint-disable-next-line max-lines-per-function -- Necessary
|
||||
public async connect(): Promise<void> {
|
||||
if (this.isConnected()) {
|
||||
return Promise.resolve()
|
||||
}
|
||||
if (this.state === WebSocket.CONNECTING) {
|
||||
return this.connectionManager.awaitConnection()
|
||||
}
|
||||
if (!this.url) {
|
||||
return Promise.reject(
|
||||
new ConnectionError('Cannot connect because no server was specified'),
|
||||
)
|
||||
}
|
||||
if (this.ws != null) {
|
||||
return Promise.reject(
|
||||
new XahlError('Websocket connection never cleaned up.', {
|
||||
state: this.state,
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
// Create the connection timeout, in case the connection hangs longer than expected.
|
||||
const connectionTimeoutID: ReturnType<typeof setTimeout> = setTimeout(
|
||||
() => {
|
||||
this.onConnectionFailed(
|
||||
new ConnectionError(
|
||||
`Error: connect() timed out after ${this.config.connectionTimeout} ms. If your internet connection is working, the ` +
|
||||
`xahaud server may be blocked or inaccessible. You can also try setting the 'connectionTimeout' option in the Client constructor.`,
|
||||
),
|
||||
)
|
||||
},
|
||||
this.config.connectionTimeout,
|
||||
)
|
||||
// Connection listeners: these stay attached only until a connection is done/open.
|
||||
this.ws = createWebSocket(this.url, this.config)
|
||||
|
||||
if (this.ws == null) {
|
||||
throw new XahlError('Connect: created null websocket')
|
||||
}
|
||||
|
||||
this.ws.on('error', (error) => this.onConnectionFailed(error))
|
||||
this.ws.on('error', () => clearTimeout(connectionTimeoutID))
|
||||
this.ws.on('close', (reason) => this.onConnectionFailed(reason))
|
||||
this.ws.on('close', () => clearTimeout(connectionTimeoutID))
|
||||
this.ws.once('open', () => {
|
||||
void this.onceOpen(connectionTimeoutID)
|
||||
})
|
||||
return this.connectionManager.awaitConnection()
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect the websocket connection.
|
||||
* We never expect this method to reject. Even on "bad" disconnects, the websocket
|
||||
* should still successfully close with the relevant error code returned.
|
||||
* See https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent for the full list.
|
||||
* If no open websocket connection exists, resolve with no code (`undefined`).
|
||||
*
|
||||
* @returns A promise containing either `undefined` or a disconnected code, that resolves when the connection is destroyed.
|
||||
*/
|
||||
public async disconnect(): Promise<number | undefined> {
|
||||
this.clearHeartbeatInterval()
|
||||
if (this.reconnectTimeoutID !== null) {
|
||||
clearTimeout(this.reconnectTimeoutID)
|
||||
this.reconnectTimeoutID = null
|
||||
}
|
||||
if (this.state === WebSocket.CLOSED) {
|
||||
return Promise.resolve(undefined)
|
||||
}
|
||||
if (this.ws == null) {
|
||||
return Promise.resolve(undefined)
|
||||
}
|
||||
|
||||
return new Promise((resolve) => {
|
||||
if (this.ws == null) {
|
||||
resolve(undefined)
|
||||
}
|
||||
if (this.ws != null) {
|
||||
this.ws.once('close', (code) => resolve(code))
|
||||
}
|
||||
/*
|
||||
* Connection already has a disconnect handler for the disconnect logic.
|
||||
* Just close the websocket manually (with our "intentional" code) to
|
||||
* trigger that.
|
||||
*/
|
||||
if (this.ws != null && this.state !== WebSocket.CLOSING) {
|
||||
this.ws.close(INTENTIONAL_DISCONNECT_CODE)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect the websocket, then connect again.
|
||||
*
|
||||
*/
|
||||
public async reconnect(): Promise<void> {
|
||||
/*
|
||||
* NOTE: We currently have a "reconnecting" event, but that only triggers
|
||||
* through an unexpected connection retry logic.
|
||||
* See: https://github.com/XRPLF/xrpl.js/pull/1101#issuecomment-565360423
|
||||
*/
|
||||
this.emit('reconnect')
|
||||
await this.disconnect()
|
||||
await this.connect()
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a request to the xahaud server.
|
||||
*
|
||||
* @param request - The request to send to the server.
|
||||
* @param timeout - How long the Connection instance should wait before assuming that there will not be a response.
|
||||
* @returns The response from the xahaud server.
|
||||
* @throws NotConnectedError if the Connection isn't connected to a server.
|
||||
*/
|
||||
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)
|
||||
}
|
||||
const [id, message, responsePromise] = this.requestManager.createRequest<
|
||||
R,
|
||||
T
|
||||
>(request, timeout ?? this.config.timeout)
|
||||
this.trace('send', message)
|
||||
websocketSendAsync(this.ws, message).catch((error) => {
|
||||
this.requestManager.reject(id, error)
|
||||
})
|
||||
|
||||
return responsePromise
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Websocket connection URL.
|
||||
*
|
||||
* @returns The Websocket connection URL.
|
||||
*/
|
||||
public getUrl(): string {
|
||||
return this.url ?? ''
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function, class-methods-use-this -- Does nothing on default
|
||||
public readonly trace: (id: string, message: string) => void = () => {}
|
||||
|
||||
/**
|
||||
* Handler for when messages are received from the server.
|
||||
*
|
||||
* @param message - The message received from the server.
|
||||
*/
|
||||
private onMessage(message): void {
|
||||
this.trace('receive', message)
|
||||
let data: Record<string, unknown>
|
||||
try {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- Must be a JSON dictionary
|
||||
data = JSON.parse(message)
|
||||
} catch (error) {
|
||||
if (error instanceof Error) {
|
||||
this.emit('error', 'badMessage', error.message, message)
|
||||
}
|
||||
return
|
||||
}
|
||||
if (data.type == null && data.error) {
|
||||
// e.g. slowDown
|
||||
this.emit('error', data.error, data.error_message, data)
|
||||
return
|
||||
}
|
||||
if (data.type) {
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Should be true
|
||||
this.emit(data.type as string, data)
|
||||
}
|
||||
if (data.type === 'response') {
|
||||
try {
|
||||
this.requestManager.handleResponse(data)
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line max-depth -- okay here
|
||||
if (error instanceof Error) {
|
||||
this.emit('error', 'badMessage', error.message, message)
|
||||
} else {
|
||||
this.emit('error', 'badMessage', error, error)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler for what to do once the connection to the server is open.
|
||||
*
|
||||
* @param connectionTimeoutID - Timeout in case the connection hangs longer than expected.
|
||||
* @returns A promise that resolves to void when the connection is fully established.
|
||||
* @throws Error if the websocket initialized is somehow null.
|
||||
*/
|
||||
// eslint-disable-next-line max-lines-per-function -- Many error code conditionals to check.
|
||||
private async onceOpen(
|
||||
connectionTimeoutID: ReturnType<typeof setTimeout>,
|
||||
): Promise<void> {
|
||||
if (this.ws == null) {
|
||||
throw new XahlError('onceOpen: ws is null')
|
||||
}
|
||||
|
||||
// Once the connection completes successfully, remove all old listeners
|
||||
this.ws.removeAllListeners()
|
||||
clearTimeout(connectionTimeoutID)
|
||||
// Add new, long-term connected listeners for messages and errors
|
||||
this.ws.on('message', (message: string) => this.onMessage(message))
|
||||
this.ws.on('error', (error) =>
|
||||
this.emit('error', 'websocket', error.message, error),
|
||||
)
|
||||
// Handle a closed connection: reconnect if it was unexpected
|
||||
this.ws.once('close', (code?: number, reason?: Uint8Array) => {
|
||||
if (this.ws == null) {
|
||||
throw new XahlError('onceClose: ws is null')
|
||||
}
|
||||
|
||||
this.clearHeartbeatInterval()
|
||||
this.requestManager.rejectAll(
|
||||
new DisconnectedError(
|
||||
`websocket was closed, ${
|
||||
reason ? hexToString(bytesToHex(reason)) : ''
|
||||
}`,
|
||||
),
|
||||
)
|
||||
this.ws.removeAllListeners()
|
||||
this.ws = null
|
||||
|
||||
if (code === undefined) {
|
||||
// Useful to keep this code for debugging purposes.
|
||||
// const reasonText = reason ? reason.toString() : 'undefined'
|
||||
// // eslint-disable-next-line no-console -- The error is helpful for debugging.
|
||||
// console.error(
|
||||
// `Disconnected but the disconnect code was undefined (The given reason was ${reasonText}).` +
|
||||
// `This could be caused by an exception being thrown during a 'connect' callback. ` +
|
||||
// `Disconnecting with code 1011 to indicate an internal error has occurred.`,
|
||||
// )
|
||||
|
||||
/*
|
||||
* Error code 1011 represents an Internal Error according to
|
||||
* https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent/code
|
||||
*/
|
||||
const internalErrorCode = 1011
|
||||
this.emit('disconnected', internalErrorCode)
|
||||
} else {
|
||||
this.emit('disconnected', code)
|
||||
}
|
||||
|
||||
/*
|
||||
* If this wasn't a manual disconnect, then lets reconnect ASAP.
|
||||
* Code can be undefined if there's an exception while connecting.
|
||||
*/
|
||||
if (code !== INTENTIONAL_DISCONNECT_CODE && code !== undefined) {
|
||||
this.intentionalDisconnect()
|
||||
}
|
||||
})
|
||||
// Finalize the connection and resolve all awaiting connect() requests
|
||||
try {
|
||||
this.retryConnectionBackoff.reset()
|
||||
this.startHeartbeatInterval()
|
||||
this.connectionManager.resolveAllAwaiting()
|
||||
this.emit('connected')
|
||||
} catch (error) {
|
||||
if (error instanceof Error) {
|
||||
this.connectionManager.rejectAllAwaiting(error)
|
||||
// Ignore this error, propagate the root cause.
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function -- Need empty catch
|
||||
await this.disconnect().catch(() => {})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private intentionalDisconnect(): void {
|
||||
const retryTimeout = this.retryConnectionBackoff.duration()
|
||||
this.trace('reconnect', `Retrying connection in ${retryTimeout}ms.`)
|
||||
this.emit('reconnecting', this.retryConnectionBackoff.attempts)
|
||||
/*
|
||||
* Start the reconnect timeout, but set it to `this.reconnectTimeoutID`
|
||||
* so that we can cancel one in-progress on disconnect.
|
||||
*/
|
||||
this.reconnectTimeoutID = setTimeout(() => {
|
||||
this.reconnect().catch((error: Error) => {
|
||||
this.emit('error', 'reconnect', error.message, error)
|
||||
})
|
||||
}, retryTimeout)
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the heartbeat connection interval.
|
||||
*/
|
||||
private clearHeartbeatInterval(): void {
|
||||
if (this.heartbeatIntervalID) {
|
||||
clearInterval(this.heartbeatIntervalID)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a heartbeat to check the connection with the server.
|
||||
*
|
||||
*/
|
||||
private startHeartbeatInterval(): void {
|
||||
this.clearHeartbeatInterval()
|
||||
this.heartbeatIntervalID = setInterval(() => {
|
||||
void this.heartbeat()
|
||||
}, this.config.timeout)
|
||||
}
|
||||
|
||||
/**
|
||||
* A heartbeat is just a "ping" command, sent on an interval.
|
||||
* If this succeeds, we're good. If it fails, disconnect so that the consumer can reconnect, if desired.
|
||||
*
|
||||
* @returns A Promise that resolves to void when the heartbeat returns successfully.
|
||||
*/
|
||||
private async heartbeat(): Promise<void> {
|
||||
this.request({ command: 'ping' }).catch(async () => {
|
||||
return this.reconnect().catch((error: Error) => {
|
||||
this.emit('error', 'reconnect', error.message, error)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a failed connection.
|
||||
*
|
||||
* @param errorOrCode - (Optional) Error or code for connection failure.
|
||||
*/
|
||||
private onConnectionFailed(errorOrCode: Error | number | null): void {
|
||||
if (this.ws) {
|
||||
this.ws.removeAllListeners()
|
||||
this.ws.on('error', () => {
|
||||
/*
|
||||
* Correctly listen for -- but ignore -- any future errors: If you
|
||||
* don't have a listener on "error" node would log a warning on error.
|
||||
*/
|
||||
})
|
||||
this.ws.close()
|
||||
this.ws = null
|
||||
}
|
||||
if (typeof errorOrCode === 'number') {
|
||||
this.connectionManager.rejectAllAwaiting(
|
||||
new NotConnectedError(`Connection failed with code ${errorOrCode}.`, {
|
||||
code: errorOrCode,
|
||||
}),
|
||||
)
|
||||
} else if (errorOrCode?.message) {
|
||||
this.connectionManager.rejectAllAwaiting(
|
||||
new NotConnectedError(errorOrCode.message, errorOrCode),
|
||||
)
|
||||
} else {
|
||||
this.connectionManager.rejectAllAwaiting(
|
||||
new NotConnectedError('Connection failed.'),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
1203
packages/xahau/src/client/index.ts
Normal file
1203
packages/xahau/src/client/index.ts
Normal file
File diff suppressed because it is too large
Load Diff
176
packages/xahau/src/client/partialPayment.ts
Normal file
176
packages/xahau/src/client/partialPayment.ts
Normal file
@@ -0,0 +1,176 @@
|
||||
import BigNumber from 'bignumber.js'
|
||||
import { decode } from 'xahau-binary-codec'
|
||||
|
||||
import type {
|
||||
TransactionEntryResponse,
|
||||
TransactionStream,
|
||||
TransactionV1Stream,
|
||||
TxResponse,
|
||||
} from '..'
|
||||
import type { Amount, APIVersion, DEFAULT_API_VERSION } from '../models/common'
|
||||
import type { 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'
|
||||
import { isFlagEnabled } from '../models/utils'
|
||||
|
||||
const WARN_PARTIAL_PAYMENT_CODE = 2001
|
||||
|
||||
function amountsEqual(amt1: Amount, amt2: Amount): boolean {
|
||||
if (typeof amt1 === 'string' && typeof amt2 === 'string') {
|
||||
return amt1 === amt2
|
||||
}
|
||||
|
||||
if (typeof amt1 === 'string' || typeof amt2 === 'string') {
|
||||
return false
|
||||
}
|
||||
|
||||
const aValue = new BigNumber(amt1.value)
|
||||
const bValue = new BigNumber(amt2.value)
|
||||
|
||||
return (
|
||||
amt1.currency === amt2.currency &&
|
||||
amt1.issuer === amt2.issuer &&
|
||||
aValue.isEqualTo(bValue)
|
||||
)
|
||||
}
|
||||
|
||||
function isPartialPayment(
|
||||
tx?: Transaction,
|
||||
metadata?: TransactionMetadata | string,
|
||||
): boolean {
|
||||
if (tx == null || metadata == null || tx.TransactionType !== 'Payment') {
|
||||
return false
|
||||
}
|
||||
|
||||
let meta = metadata
|
||||
if (typeof meta === 'string') {
|
||||
if (meta === 'unavailable') {
|
||||
return false
|
||||
}
|
||||
|
||||
/* eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- binary-codec typing */
|
||||
meta = decode(meta) as unknown as TransactionMetadata
|
||||
}
|
||||
|
||||
const tfPartial =
|
||||
typeof tx.Flags === 'number'
|
||||
? isFlagEnabled(tx.Flags, PaymentFlags.tfPartialPayment)
|
||||
: tx.Flags?.tfPartialPayment
|
||||
|
||||
if (!tfPartial) {
|
||||
return false
|
||||
}
|
||||
|
||||
const delivered = meta.delivered_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
|
||||
}
|
||||
|
||||
return !amountsEqual(delivered, amount)
|
||||
}
|
||||
|
||||
function txHasPartialPayment(response: TxResponse): boolean {
|
||||
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<
|
||||
Version extends APIVersion = typeof DEFAULT_API_VERSION,
|
||||
>(response: AccountTxVersionResponseMap<Version>): boolean {
|
||||
const { transactions } = response.result
|
||||
const foo = transactions.some((tx) => {
|
||||
if (tx.tx_json != null) {
|
||||
const transaction = tx
|
||||
return isPartialPayment(transaction.tx_json, transaction.meta)
|
||||
}
|
||||
|
||||
const transaction = tx
|
||||
return isPartialPayment(transaction.tx, transaction.meta)
|
||||
})
|
||||
return foo
|
||||
}
|
||||
|
||||
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':
|
||||
return txHasPartialPayment(response as TxResponse)
|
||||
case 'transaction_entry':
|
||||
return txEntryHasPartialPayment(response as TransactionEntryResponse)
|
||||
case 'account_tx':
|
||||
return accountTxHasPartialPayment(
|
||||
response as AccountTxVersionResponseMap<V>,
|
||||
)
|
||||
default:
|
||||
return false
|
||||
}
|
||||
/* eslint-enable @typescript-eslint/consistent-type-assertions */
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks a response for a partial payment.
|
||||
*
|
||||
* @param command - Command from the request, tells us what response to expect.
|
||||
* @param response - Response to check for a partial payment.
|
||||
*/
|
||||
export function handlePartialPayment<
|
||||
R extends BaseRequest,
|
||||
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.
|
||||
const warnings = (response as BaseResponse).warnings ?? []
|
||||
|
||||
const warning = {
|
||||
id: WARN_PARTIAL_PAYMENT_CODE,
|
||||
message: 'This response contains a Partial Payment',
|
||||
}
|
||||
|
||||
warnings.push(warning)
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment -- We are checking dynamically and safely.
|
||||
// @ts-expect-error -- We are checking dynamically and safely.
|
||||
response.warnings = warnings
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check a transaction from a subscription stream for partial payment.
|
||||
*
|
||||
* @param stream - Stream Transaction to check for partial payment.
|
||||
* @param log - The method used for logging by the connection (to report the partial payment).
|
||||
*/
|
||||
export function handleStreamPartialPayment(
|
||||
stream: TransactionStream | TransactionV1Stream,
|
||||
log: (id: string, message: string) => void,
|
||||
): void {
|
||||
if (isPartialPayment(stream.tx_json ?? stream.transaction, stream.meta)) {
|
||||
const warnings = stream.warnings ?? []
|
||||
|
||||
const warning = {
|
||||
id: WARN_PARTIAL_PAYMENT_CODE,
|
||||
message: 'This response contains a Partial Payment',
|
||||
}
|
||||
|
||||
warnings.push(warning)
|
||||
|
||||
/* eslint-disable-next-line no-param-reassign -- Handles the case where there are no warnings */
|
||||
stream.warnings = warnings
|
||||
|
||||
log('Partial payment received', JSON.stringify(stream))
|
||||
}
|
||||
}
|
||||
159
packages/xahau/src/errors.ts
Normal file
159
packages/xahau/src/errors.ts
Normal file
@@ -0,0 +1,159 @@
|
||||
/* eslint-disable max-classes-per-file -- Errors can be defined in the same file */
|
||||
/**
|
||||
* Base Error class for xrpl.js. All Errors thrown by xrpl.js should throw
|
||||
* XahlErrors.
|
||||
*
|
||||
* @category Errors
|
||||
*/
|
||||
class XahlError extends Error {
|
||||
public readonly name: string
|
||||
public readonly message: string
|
||||
public readonly data?: unknown
|
||||
|
||||
/**
|
||||
* Construct an XahlError.
|
||||
*
|
||||
* @param message - The error message.
|
||||
* @param data - The data that caused the error.
|
||||
*/
|
||||
public constructor(message = '', data?: unknown) {
|
||||
super(message)
|
||||
|
||||
this.name = this.constructor.name
|
||||
this.message = message
|
||||
this.data = data
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- `captureStackTrace` can be null in browsers
|
||||
if (Error.captureStackTrace != null) {
|
||||
Error.captureStackTrace(this, this.constructor)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the Error to a human-readable String form.
|
||||
*
|
||||
* @returns The String output of the Error.
|
||||
*/
|
||||
public toString(): string {
|
||||
let result = `[${this.name}(${this.message}`
|
||||
if (this.data) {
|
||||
result += `, ${JSON.stringify(this.data)}`
|
||||
}
|
||||
result += ')]'
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* Console.log in node uses util.inspect on object, and util.inspect allows
|
||||
* us to customize its output:
|
||||
* https://nodejs.org/api/util.html#util_custom_inspect_function_on_objects.
|
||||
*
|
||||
* @returns The String output of the Error.
|
||||
*/
|
||||
public inspect(): string {
|
||||
return this.toString()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Error thrown when xahaud responds with an error.
|
||||
*
|
||||
* @category Errors
|
||||
*/
|
||||
class XahaudError extends XahlError {}
|
||||
|
||||
/**
|
||||
* Error thrown when xrpl.js cannot specify error type.
|
||||
*
|
||||
* @category Errors
|
||||
*/
|
||||
class UnexpectedError extends XahlError {}
|
||||
|
||||
/**
|
||||
* Error thrown when xrpl.js has an error with connection to xahaud.
|
||||
*
|
||||
* @category Errors
|
||||
*/
|
||||
class ConnectionError extends XahlError {}
|
||||
|
||||
/**
|
||||
* Error thrown when xrpl.js is not connected to xahaud server.
|
||||
*
|
||||
* @category Errors
|
||||
*/
|
||||
class NotConnectedError extends ConnectionError {}
|
||||
|
||||
/**
|
||||
* Error thrown when xrpl.js has disconnected from xahaud server.
|
||||
*
|
||||
* @category Errors
|
||||
*/
|
||||
class DisconnectedError extends ConnectionError {}
|
||||
|
||||
/**
|
||||
* Error thrown when xahaud is not initialized.
|
||||
*
|
||||
* @category Errors
|
||||
*/
|
||||
class XahaudNotInitializedError extends ConnectionError {}
|
||||
|
||||
/**
|
||||
* Error thrown when xrpl.js times out.
|
||||
*
|
||||
* @category Errors
|
||||
*/
|
||||
class TimeoutError extends ConnectionError {}
|
||||
|
||||
/**
|
||||
* Error thrown when xrpl.js sees a response in the wrong format.
|
||||
*
|
||||
* @category Errors
|
||||
*/
|
||||
class ResponseFormatError extends ConnectionError {}
|
||||
|
||||
/**
|
||||
* Error thrown when xrpl.js sees a malformed transaction.
|
||||
*
|
||||
* @category Errors
|
||||
*/
|
||||
class ValidationError extends XahlError {}
|
||||
|
||||
/**
|
||||
* Error thrown when a client cannot generate a wallet from the testnet/devnet
|
||||
* faucets, or when the client cannot infer the faucet URL (i.e. when the Client
|
||||
* is connected to mainnet).
|
||||
*
|
||||
* @category Errors
|
||||
*/
|
||||
class XRPLFaucetError extends XahlError {}
|
||||
|
||||
/**
|
||||
* Error thrown when xrpl.js cannot retrieve a transaction, ledger, account, etc.
|
||||
* From xahaud.
|
||||
*
|
||||
* @category Errors
|
||||
*/
|
||||
class NotFoundError extends XahlError {
|
||||
/**
|
||||
* Construct an XahlError.
|
||||
*
|
||||
* @param message - The error message. Defaults to "Not found".
|
||||
*/
|
||||
public constructor(message = 'Not found') {
|
||||
super(message)
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
XahlError,
|
||||
UnexpectedError,
|
||||
ConnectionError,
|
||||
XahaudError,
|
||||
NotConnectedError,
|
||||
DisconnectedError,
|
||||
XahaudNotInitializedError,
|
||||
TimeoutError,
|
||||
ResponseFormatError,
|
||||
ValidationError,
|
||||
NotFoundError,
|
||||
XRPLFaucetError,
|
||||
}
|
||||
18
packages/xahau/src/index.ts
Normal file
18
packages/xahau/src/index.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
export { Client, ClientOptions } from './client'
|
||||
|
||||
export * from './models'
|
||||
|
||||
export * from './utils'
|
||||
|
||||
export { default as ECDSA } from './ECDSA'
|
||||
|
||||
export * from './errors'
|
||||
|
||||
export { FundingOptions } from './Wallet/fundWallet'
|
||||
export { Wallet } from './Wallet'
|
||||
|
||||
export { walletFromSecretNumbers } from './Wallet/walletFromSecretNumbers'
|
||||
|
||||
export { keyToRFC1751Mnemonic, rfc1751MnemonicToKey } from './Wallet/rfc1751'
|
||||
|
||||
export * from './Wallet/signer'
|
||||
198
packages/xahau/src/models/common/index.ts
Normal file
198
packages/xahau/src/models/common/index.ts
Normal file
@@ -0,0 +1,198 @@
|
||||
export const XAHAUD_API_V1 = 1
|
||||
export const XAHAUD_API_V2 = 2
|
||||
export const DEFAULT_API_VERSION = XAHAUD_API_V1
|
||||
export type APIVersion = typeof XAHAUD_API_V1 | typeof XAHAUD_API_V2
|
||||
export type LedgerIndex = number | ('validated' | 'closed' | 'current')
|
||||
|
||||
export interface XAH {
|
||||
currency: 'XAH'
|
||||
issuer?: never
|
||||
}
|
||||
|
||||
export interface IssuedCurrency {
|
||||
currency: string
|
||||
issuer: string
|
||||
}
|
||||
|
||||
export type Currency = IssuedCurrency | XAH
|
||||
|
||||
export interface IssuedCurrencyAmount extends IssuedCurrency {
|
||||
value: string
|
||||
}
|
||||
|
||||
export type Amount = IssuedCurrencyAmount | string
|
||||
|
||||
export interface Balance {
|
||||
currency: string
|
||||
issuer?: string
|
||||
value: string
|
||||
}
|
||||
|
||||
export interface Signer {
|
||||
Signer: {
|
||||
Account: string
|
||||
TxnSignature: string
|
||||
SigningPubKey: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface Memo {
|
||||
Memo: {
|
||||
MemoData?: string
|
||||
MemoType?: string
|
||||
MemoFormat?: string
|
||||
}
|
||||
}
|
||||
|
||||
export type StreamType =
|
||||
| 'consensus'
|
||||
| 'ledger'
|
||||
| 'manifests'
|
||||
| 'peer_status'
|
||||
| 'transactions'
|
||||
| 'transactions_proposed'
|
||||
| 'server'
|
||||
| 'validations'
|
||||
|
||||
export interface PathStep {
|
||||
account?: string
|
||||
currency?: string
|
||||
issuer?: string
|
||||
}
|
||||
|
||||
export type Path = PathStep[]
|
||||
|
||||
/**
|
||||
* The object that describes the signer in SignerEntries.
|
||||
*/
|
||||
export interface SignerEntry {
|
||||
/**
|
||||
* The object that describes the signer in SignerEntries.
|
||||
*/
|
||||
SignerEntry: {
|
||||
/**
|
||||
* An XAH Ledger address whose signature contributes to the multi-signature.
|
||||
* It does not need to be a funded address in the ledger.
|
||||
*/
|
||||
Account: string
|
||||
/**
|
||||
* The weight of a signature from this signer.
|
||||
* A multi-signature is only valid if the sum weight of the signatures provided meets
|
||||
* or exceeds the signer list's SignerQuorum value.
|
||||
*/
|
||||
SignerWeight: number
|
||||
/**
|
||||
* An arbitrary 256-bit (32-byte) field that can be used to identify the signer, which
|
||||
* may be useful for smart contracts, or for identifying who controls a key in a large
|
||||
* organization.
|
||||
*/
|
||||
WalletLocator?: string
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This information is added to Transactions in request responses, but is not part
|
||||
* of the canonical Transaction information on ledger. These fields are denoted with
|
||||
* lowercase letters to indicate this in the xahaud responses.
|
||||
*/
|
||||
export interface ResponseOnlyTxInfo {
|
||||
/**
|
||||
* The date/time when this transaction was included in a validated ledger.
|
||||
*/
|
||||
date?: number
|
||||
/**
|
||||
* An identifying hash value unique to this transaction, as a hex string.
|
||||
*/
|
||||
hash?: string
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
inLedger?: number
|
||||
}
|
||||
|
||||
/**
|
||||
* One offer that might be returned from either an {@link NFTBuyOffersRequest}
|
||||
* or an {@link NFTSellOffersRequest}.
|
||||
*
|
||||
* @category Responses
|
||||
*/
|
||||
export interface NFTOffer {
|
||||
amount: Amount
|
||||
flags: number
|
||||
nft_offer_index: string
|
||||
owner: string
|
||||
destination?: string
|
||||
expiration?: number
|
||||
}
|
||||
|
||||
/**
|
||||
* One NFToken that might be returned from an {@link NFTInfoResponse}
|
||||
*
|
||||
* @category Responses
|
||||
*/
|
||||
export interface NFToken {
|
||||
nft_id: string
|
||||
ledger_index: number
|
||||
owner: string
|
||||
is_burned: boolean
|
||||
flags: number
|
||||
transfer_fee: number
|
||||
issuer: string
|
||||
nft_taxon: number
|
||||
nft_serial: number
|
||||
uri: string
|
||||
}
|
||||
|
||||
export interface AuthAccount {
|
||||
AuthAccount: {
|
||||
Account: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface XChainBridge {
|
||||
LockingChainDoor: string
|
||||
LockingChainIssue: Currency
|
||||
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
|
||||
}
|
||||
}
|
||||
17
packages/xahau/src/models/index.ts
Normal file
17
packages/xahau/src/models/index.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* LedgerEntry type definitions are exported in their own namespace to prevent
|
||||
* collisions of the DepositPreauth SLE and Transaction. LedgerEntries are used
|
||||
* by the client less often, and in most scenarios, like when parsing a
|
||||
* response, the client won't need to import the type. If it is required to use
|
||||
* a Ledger Entry, import `LedgerEntry`, and access individual ledger entry
|
||||
* types on the `LedgerEntry` namespace.
|
||||
*/
|
||||
export * as LedgerEntry from './ledger'
|
||||
export {
|
||||
setTransactionFlagsToNumber,
|
||||
parseAccountRootFlags,
|
||||
parseTransactionFlags,
|
||||
} from './utils/flags'
|
||||
export * from './methods'
|
||||
export * from './transactions'
|
||||
export * from './common'
|
||||
213
packages/xahau/src/models/ledger/AccountRoot.ts
Normal file
213
packages/xahau/src/models/ledger/AccountRoot.ts
Normal file
@@ -0,0 +1,213 @@
|
||||
import { BaseLedgerEntry, HasPreviousTxnID } from './BaseLedgerEntry'
|
||||
|
||||
/**
|
||||
* The AccountRoot object type describes a single account, its settings, and
|
||||
* XAH balance.
|
||||
*
|
||||
* @category Ledger Entries
|
||||
*/
|
||||
export default interface AccountRoot extends BaseLedgerEntry, HasPreviousTxnID {
|
||||
LedgerEntryType: 'AccountRoot'
|
||||
/** The identifying (classic) address of this account. */
|
||||
Account: string
|
||||
/** The account's current XAH balance in drops, represented as a string. */
|
||||
Balance: string
|
||||
/** A bit-map of boolean flags enabled for this account. */
|
||||
Flags: number
|
||||
/**
|
||||
* The number of objects this account owns in the ledger, which contributes
|
||||
* to its owner reserve.
|
||||
*/
|
||||
OwnerCount: number
|
||||
/** The sequence number of the next valid transaction for this account. */
|
||||
Sequence: number
|
||||
/**
|
||||
* The identifying hash of the transaction most recently sent by this
|
||||
* account. This field must be enabled to use the AccountTxnID transaction
|
||||
* field. To enable it, send an AccountSet transaction with the.
|
||||
* `asfAccountTxnID` flag enabled.
|
||||
*/
|
||||
AccountTxnID?: string
|
||||
/**
|
||||
* The ledger entry ID of the corresponding AMM ledger entry.
|
||||
* Set during account creation; cannot be modified.
|
||||
* If present, indicates that this is a special AMM AccountRoot; always omitted on non-AMM accounts.
|
||||
*/
|
||||
AMMID?: string
|
||||
/**
|
||||
* A domain associated with this account. In JSON, this is the hexadecimal
|
||||
* for the ASCII representation of the domain.
|
||||
*/
|
||||
Domain?: string
|
||||
/** The md5 hash of an email address. */
|
||||
EmailHash?: string
|
||||
/**
|
||||
* A public key that may be used to send encrypted messages to this account
|
||||
* in JSON, uses hexadecimal.
|
||||
*/
|
||||
MessageKey?: string
|
||||
/**
|
||||
* The address of a key pair that can be used to sign transactions for this
|
||||
* account instead of the master key. Use a SetRegularKey transaction to
|
||||
* change this value.
|
||||
*/
|
||||
RegularKey?: string
|
||||
/**
|
||||
* How many Tickets this account owns in the ledger. This is updated
|
||||
* automatically to ensure that the account stays within the hard limit of 250.
|
||||
* Tickets at a time.
|
||||
*/
|
||||
TicketCount?: number
|
||||
/**
|
||||
* How many significant digits to use for exchange rates of Offers involving
|
||||
* currencies issued by this address. Valid values are 3 to 15, inclusive.
|
||||
*/
|
||||
TickSize?: number
|
||||
/**
|
||||
* A transfer fee to charge other users for sending currency issued by this
|
||||
* account to each other.
|
||||
*/
|
||||
TransferRate?: number
|
||||
/** An arbitrary 256-bit value that users can set. */
|
||||
WalletLocator?: string
|
||||
/** Total NFTokens this account's issued that have been burned. This number is always equal or less than MintedNFTokens. */
|
||||
BurnedNFTokens?: number
|
||||
/** The sequence that the account first minted an NFToken */
|
||||
FirstNFTSequence: number
|
||||
/** Total NFTokens have been minted by and on behalf of this account. */
|
||||
MintedNFTokens?: number
|
||||
/** Another account that can mint NFTokens on behalf of this account. */
|
||||
NFTokenMinter?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* A boolean map of AccountRootFlags for simplified code checking AccountRoot settings.
|
||||
* For submitting settings flags to the ledger, use AccountRootFlags instead.
|
||||
*/
|
||||
export interface AccountRootFlagsInterface {
|
||||
/**
|
||||
* The account has used its free SetRegularKey transaction.
|
||||
*/
|
||||
lsfPasswordSpent?: boolean
|
||||
/**
|
||||
* Requires incoming payments to specify a Destination Tag.
|
||||
*/
|
||||
lsfRequireDestTag?: boolean
|
||||
/**
|
||||
* This account must individually approve other users for those users to hold this account's issued currencies.
|
||||
*/
|
||||
lsfRequireAuth?: boolean
|
||||
/**
|
||||
* Client applications should not send XAH to this account. Not enforced by xahaud.
|
||||
*/
|
||||
lsfDisallowXAH?: boolean
|
||||
/**
|
||||
* Disallows use of the master key to sign transactions for this account.
|
||||
*/
|
||||
lsfDisableMaster?: boolean
|
||||
/**
|
||||
* This address cannot freeze trust lines connected to it. Once enabled, cannot be disabled.
|
||||
*/
|
||||
lsfNoFreeze?: boolean
|
||||
/**
|
||||
* All assets issued by this address are frozen.
|
||||
*/
|
||||
lsfGlobalFreeze?: boolean
|
||||
/**
|
||||
* Enable rippling on this address's trust lines by default. Required for issuing addresses; discouraged for others.
|
||||
*/
|
||||
lsfDefaultRipple?: boolean
|
||||
/**
|
||||
* This account can only receive funds from transactions it sends, and from preauthorized accounts.
|
||||
* (It has DepositAuth enabled.)
|
||||
*/
|
||||
lsfDepositAuth?: boolean
|
||||
/**
|
||||
* This account is an Automated Market Maker (AMM) instance.
|
||||
*/
|
||||
lsfAMM?: boolean
|
||||
/**
|
||||
* Disallow incoming NFTOffers from other accounts.
|
||||
*/
|
||||
lsfDisallowIncomingNFTokenOffer?: boolean
|
||||
/**
|
||||
* Disallow incoming Checks from other accounts.
|
||||
*/
|
||||
lsfDisallowIncomingCheck?: boolean
|
||||
/**
|
||||
* Disallow incoming PayChannels from other accounts.
|
||||
*/
|
||||
lsfDisallowIncomingPayChan?: boolean
|
||||
/**
|
||||
* Disallow incoming Trustlines from other accounts.
|
||||
*/
|
||||
lsfDisallowIncomingTrustline?: boolean
|
||||
/**
|
||||
* This address can claw back issued IOUs. Once enabled, cannot be disabled.
|
||||
*/
|
||||
lsfAllowTrustLineClawback?: boolean
|
||||
}
|
||||
|
||||
export enum AccountRootFlags {
|
||||
/**
|
||||
* The account has used its free SetRegularKey transaction.
|
||||
*/
|
||||
lsfPasswordSpent = 0x00010000,
|
||||
/**
|
||||
* Requires incoming payments to specify a Destination Tag.
|
||||
*/
|
||||
lsfRequireDestTag = 0x00020000,
|
||||
/**
|
||||
* This account must individually approve other users for those users to hold this account's issued currencies.
|
||||
*/
|
||||
lsfRequireAuth = 0x00040000,
|
||||
/**
|
||||
* Client applications should not send XAH to this account. Not enforced by xahaud.
|
||||
*/
|
||||
lsfDisallowXAH = 0x00080000,
|
||||
/**
|
||||
* Disallows use of the master key to sign transactions for this account.
|
||||
*/
|
||||
lsfDisableMaster = 0x00100000,
|
||||
/**
|
||||
* This address cannot freeze trust lines connected to it. Once enabled, cannot be disabled.
|
||||
*/
|
||||
lsfNoFreeze = 0x00200000,
|
||||
/**
|
||||
* All assets issued by this address are frozen.
|
||||
*/
|
||||
lsfGlobalFreeze = 0x00400000,
|
||||
/**
|
||||
* Enable rippling on this address's trust lines by default. Required for issuing addresses; discouraged for others.
|
||||
*/
|
||||
lsfDefaultRipple = 0x00800000,
|
||||
/**
|
||||
* This account can only receive funds from transactions it sends, and from preauthorized accounts.
|
||||
* (It has DepositAuth enabled.)
|
||||
*/
|
||||
lsfDepositAuth = 0x01000000,
|
||||
/**
|
||||
* This account is an Automated Market Maker (AMM) instance.
|
||||
*/
|
||||
lsfAMM = 0x02000000,
|
||||
/**
|
||||
* Disallow incoming NFTOffers from other accounts.
|
||||
*/
|
||||
lsfDisallowIncomingNFTokenOffer = 0x04000000,
|
||||
/**
|
||||
* Disallow incoming Checks from other accounts.
|
||||
*/
|
||||
lsfDisallowIncomingCheck = 0x08000000,
|
||||
/**
|
||||
* Disallow incoming PayChannels from other accounts.
|
||||
*/
|
||||
lsfDisallowIncomingPayChan = 0x10000000,
|
||||
/**
|
||||
* Disallow incoming Trustlines from other accounts.
|
||||
*/
|
||||
lsfDisallowIncomingTrustline = 0x20000000,
|
||||
/**
|
||||
* This address can claw back issued IOUs. Once enabled, cannot be disabled.
|
||||
*/
|
||||
lsfAllowTrustLineClawback = 0x80000000,
|
||||
}
|
||||
47
packages/xahau/src/models/ledger/Amendments.ts
Normal file
47
packages/xahau/src/models/ledger/Amendments.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import { BaseLedgerEntry, HasOptionalPreviousTxnID } from './BaseLedgerEntry'
|
||||
|
||||
/**
|
||||
* The unique id for the Amendments object https://xrpl.org/amendments-object.html#amendments-id-format
|
||||
*/
|
||||
export const AMENDMENTS_ID =
|
||||
'7DB0788C020F02780A673DC74757F23823FA3014C1866E72CC4CD8B226CD6EF4'
|
||||
|
||||
export interface Majority {
|
||||
Majority: {
|
||||
/** The Amendment ID of the pending amendment. */
|
||||
Amendment: string
|
||||
/**
|
||||
* The `close_time` field of the ledger version where this amendment most
|
||||
* recently gained a majority.
|
||||
*/
|
||||
CloseTime: number
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The Amendments object type contains a list of Amendments that are currently
|
||||
* active.
|
||||
*
|
||||
* @category Ledger Entries
|
||||
*/
|
||||
export default interface Amendments
|
||||
extends BaseLedgerEntry,
|
||||
HasOptionalPreviousTxnID {
|
||||
LedgerEntryType: 'Amendments'
|
||||
/**
|
||||
* Array of 256-bit amendment IDs for all currently-enabled amendments. If
|
||||
* omitted, there are no enabled amendments.
|
||||
*/
|
||||
Amendments?: string[]
|
||||
/**
|
||||
* Array of objects describing the status of amendments that have majority
|
||||
* support but are not yet enabled. If omitted, there are no pending
|
||||
* amendments with majority support.
|
||||
*/
|
||||
Majorities?: Majority[]
|
||||
/**
|
||||
* A bit-map of boolean flags. No flags are defined for the Amendments object
|
||||
* type, so this value is always 0.
|
||||
*/
|
||||
Flags: 0
|
||||
}
|
||||
31
packages/xahau/src/models/ledger/BaseLedgerEntry.ts
Normal file
31
packages/xahau/src/models/ledger/BaseLedgerEntry.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
export interface BaseLedgerEntry {
|
||||
index: string
|
||||
}
|
||||
|
||||
export interface HasPreviousTxnID {
|
||||
/**
|
||||
* The identifying hash of the transaction that most recently modified this
|
||||
* object.
|
||||
*/
|
||||
PreviousTxnID: string
|
||||
/**
|
||||
* The index of the ledger that contains the transaction that most recently
|
||||
* modified this object.
|
||||
*/
|
||||
PreviousTxnLgrSeq: number
|
||||
}
|
||||
|
||||
export interface HasOptionalPreviousTxnID {
|
||||
/**
|
||||
* 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?: string
|
||||
/**
|
||||
* 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?: number
|
||||
}
|
||||
70
packages/xahau/src/models/ledger/Check.ts
Normal file
70
packages/xahau/src/models/ledger/Check.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
import { Amount } from '../common'
|
||||
|
||||
import { BaseLedgerEntry, HasPreviousTxnID } from './BaseLedgerEntry'
|
||||
|
||||
/**
|
||||
* A Check object describes a check, similar to a paper personal check, which
|
||||
* can be cashed by its destination to get money from its sender.
|
||||
*
|
||||
* @category Ledger Entries
|
||||
*/
|
||||
export default interface Check extends BaseLedgerEntry, HasPreviousTxnID {
|
||||
LedgerEntryType: 'Check'
|
||||
/** The sender of the Check. Cashing the Check debits this address's balance. */
|
||||
Account: string
|
||||
/**
|
||||
* The intended recipient of the Check. Only this address can cash the Check,
|
||||
* using a CheckCash transaction.
|
||||
*/
|
||||
Destination: string
|
||||
/**
|
||||
* A bit-map of boolean flags. No flags are defined for Checks, so this value
|
||||
* is always 0.
|
||||
*/
|
||||
Flags: 0
|
||||
/**
|
||||
* A hint indicating which page of the sender's owner directory links to this
|
||||
* object, in case the directory consists of multiple pages.
|
||||
*/
|
||||
OwnerNode: string
|
||||
/**
|
||||
* The identifying hash of the transaction that most recently modified this
|
||||
* object.
|
||||
*/
|
||||
PreviousTxnID: string
|
||||
/**
|
||||
* The index of the ledger that contains the transaction that most recently
|
||||
* modified this object.
|
||||
*/
|
||||
PreviousTxnLgrSeq: number
|
||||
/**
|
||||
* The maximum amount of currency this Check can debit the sender. If the
|
||||
* Check is successfully cashed, the destination is credited in the same
|
||||
* currency for up to this amount.
|
||||
*/
|
||||
SendMax: Amount
|
||||
/** The sequence number of the CheckCreate transaction that created this check. */
|
||||
Sequence: number
|
||||
/**
|
||||
* A hint indicating which page of the destination's owner directory links to
|
||||
* this object, in case the directory consists of multiple pages.
|
||||
*/
|
||||
DestinationNode?: string
|
||||
/**
|
||||
* An arbitrary tag to further specify the destination for this Check, such
|
||||
* as a hosted recipient at the destination address.
|
||||
*/
|
||||
DestinationTag?: number
|
||||
/** Indicates the time after which this Check is considered expired. */
|
||||
Expiration?: number
|
||||
/**
|
||||
* Arbitrary 256-bit hash provided by the sender as a specific reason or
|
||||
* identifier for this Check.
|
||||
*/
|
||||
InvoiceID?: string
|
||||
/**
|
||||
* An arbitrary tag to further specify the source for this Check, such as a
|
||||
* hosted recipient at the sender's address.
|
||||
*/
|
||||
SourceTag?: number
|
||||
}
|
||||
27
packages/xahau/src/models/ledger/DepositPreauth.ts
Normal file
27
packages/xahau/src/models/ledger/DepositPreauth.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { BaseLedgerEntry, HasPreviousTxnID } from './BaseLedgerEntry'
|
||||
|
||||
/**
|
||||
* A DepositPreauth object tracks a preauthorization from one account to
|
||||
* another. DepositPreauth transactions create these objects.
|
||||
*
|
||||
* @category Ledger Entries
|
||||
*/
|
||||
export default interface DepositPreauth
|
||||
extends BaseLedgerEntry,
|
||||
HasPreviousTxnID {
|
||||
LedgerEntryType: 'DepositPreauth'
|
||||
/** The account that granted the preauthorization. */
|
||||
Account: string
|
||||
/** The account that received the preauthorization. */
|
||||
Authorize: string
|
||||
/**
|
||||
* A bit-map of boolean flags. No flags are defined for DepositPreauth
|
||||
* objects, so this value is always 0.
|
||||
*/
|
||||
Flags: 0
|
||||
/**
|
||||
* A hint indicating which page of the sender's owner directory links to this
|
||||
* object, in case the directory consists of multiple pages.
|
||||
*/
|
||||
OwnerNode: string
|
||||
}
|
||||
48
packages/xahau/src/models/ledger/DirectoryNode.ts
Normal file
48
packages/xahau/src/models/ledger/DirectoryNode.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import { BaseLedgerEntry, HasOptionalPreviousTxnID } from './BaseLedgerEntry'
|
||||
|
||||
/**
|
||||
* The DirectoryNode object type provides a list of links to other objects in
|
||||
* the ledger's state tree.
|
||||
*
|
||||
* @category Ledger Entries
|
||||
*/
|
||||
export default interface DirectoryNode
|
||||
extends BaseLedgerEntry,
|
||||
HasOptionalPreviousTxnID {
|
||||
LedgerEntryType: 'DirectoryNode'
|
||||
/**
|
||||
* A bit-map of boolean flags enabled for this directory. Currently, the
|
||||
* protocol defines no flags for DirectoryNode objects.
|
||||
*/
|
||||
Flags: number
|
||||
/** The ID of root object for this directory. */
|
||||
RootIndex: string
|
||||
/** The contents of this Directory: an array of IDs of other objects. */
|
||||
Indexes: string[]
|
||||
/**
|
||||
* If this Directory consists of multiple pages, this ID links to the next
|
||||
* object in the chain, wrapping around at the end.
|
||||
*/
|
||||
IndexNext?: number
|
||||
/**
|
||||
* If this Directory consists of multiple pages, this ID links to the
|
||||
* previous object in the chain, wrapping around at the beginning.
|
||||
*/
|
||||
IndexPrevious?: number
|
||||
/** The address of the account that owns the objects in this directory. */
|
||||
Owner?: string
|
||||
/**
|
||||
* The currency code of the TakerPays amount from the offers in this
|
||||
* directory.
|
||||
*/
|
||||
TakerPaysCurrency?: string
|
||||
/** The issuer of the TakerPays amount from the offers in this directory. */
|
||||
TakerPaysIssuer?: string
|
||||
/**
|
||||
* The currency code of the TakerGets amount from the offers in this
|
||||
* directory.
|
||||
*/
|
||||
TakerGetsCurrency?: string
|
||||
/** The issuer of the TakerGets amount from the offers in this directory. */
|
||||
TakerGetsIssuer?: string
|
||||
}
|
||||
64
packages/xahau/src/models/ledger/Escrow.ts
Normal file
64
packages/xahau/src/models/ledger/Escrow.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
import { BaseLedgerEntry, HasPreviousTxnID } from './BaseLedgerEntry'
|
||||
|
||||
/**
|
||||
* The Escrow object type represents a held payment of XAH waiting to be
|
||||
* executed or canceled.
|
||||
*
|
||||
* @category Ledger Entries
|
||||
*/
|
||||
export default interface Escrow extends BaseLedgerEntry, HasPreviousTxnID {
|
||||
LedgerEntryType: 'Escrow'
|
||||
/**
|
||||
* The address of the owner (sender) of this held payment. This is the
|
||||
* account that provided the XAH, and gets it back if the held payment is
|
||||
* canceled.
|
||||
*/
|
||||
Account: string
|
||||
/**
|
||||
* The destination address where the XAH is paid if the held payment is
|
||||
* successful.
|
||||
*/
|
||||
Destination: string
|
||||
/** The amount of XAH, in drops, to be delivered by the held payment. */
|
||||
Amount: string
|
||||
/**
|
||||
* A PREIMAGE-SHA-256 crypto-condition, as hexadecimal. If present, the
|
||||
* EscrowFinish transaction must contain a fulfillment that satisfies this
|
||||
* condition.
|
||||
*/
|
||||
Condition?: string
|
||||
/**
|
||||
* The time after which this Escrow is considered expired.
|
||||
*/
|
||||
CancelAfter?: number
|
||||
/**
|
||||
* The time, in seconds, since the Ripple Epoch, after which this held payment
|
||||
* can be finished. Any EscrowFinish transaction before this time fails.
|
||||
*/
|
||||
FinishAfter?: number
|
||||
/**
|
||||
* A bit-map of boolean flags. No flags are defined for the Escrow type, so
|
||||
* this value is always 0.
|
||||
*/
|
||||
Flags: number
|
||||
/**
|
||||
* An arbitrary tag to further specify the source for this held payment, such
|
||||
* as a hosted recipient at the owner's address.
|
||||
*/
|
||||
SourceTag?: number
|
||||
/**
|
||||
* An arbitrary tag to further specify the destination for this held payment,
|
||||
* such as a hosted recipient at the destination address.
|
||||
*/
|
||||
DestinationTag?: number
|
||||
/**
|
||||
* A hint indicating which page of the owner directory links to this object,
|
||||
* in case the directory consists of multiple pages.
|
||||
*/
|
||||
OwnerNode: string
|
||||
/**
|
||||
* A hint indicating which page of the destination's owner directory links to
|
||||
* this object, in case the directory consists of multiple pages.
|
||||
*/
|
||||
DestinationNode?: string
|
||||
}
|
||||
54
packages/xahau/src/models/ledger/FeeSettings.ts
Normal file
54
packages/xahau/src/models/ledger/FeeSettings.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
import { BaseLedgerEntry, HasOptionalPreviousTxnID } from './BaseLedgerEntry'
|
||||
|
||||
/**
|
||||
* The unique id for the FeeSettings object https://xrpl.org/feesettings.html#feesettings-id-format
|
||||
*/
|
||||
export const FEE_SETTINGS_ID =
|
||||
'4BC50C9B0D8515D3EAAE1E74B29A95804346C491EE1A95BF25E4AAB854A6A651'
|
||||
|
||||
export interface FeeSettingsPreAmendmentFields {
|
||||
/** The transaction cost of the "reference transaction" in drops of XAH as hexadecimal. */
|
||||
BaseFee: string
|
||||
/** The BaseFee translated into "fee units". */
|
||||
ReferenceFeeUnits: number
|
||||
/** The base reserve for an account in the XAH Ledger, as drops of XAH. */
|
||||
ReserveBase: number
|
||||
/** The incremental owner reserve for owning objects, as drops of XAH. */
|
||||
ReserveIncrement: number
|
||||
}
|
||||
|
||||
export interface FeeSettingsPostAmendmentFields {
|
||||
/** The transaction cost of the "reference transaction" in drops of XAH as hexadecimal. */
|
||||
BaseFeeDrops: string
|
||||
/** The base reserve for an account in the XAH Ledger, as drops of XAH. */
|
||||
ReserveBaseDrops: string
|
||||
/** The incremental owner reserve for owning objects, as drops of XAH. */
|
||||
ReserveIncrementDrops: string
|
||||
}
|
||||
|
||||
export interface FeeSettingsBase
|
||||
extends BaseLedgerEntry,
|
||||
HasOptionalPreviousTxnID {
|
||||
LedgerEntryType: 'FeeSettings'
|
||||
/**
|
||||
* A bit-map of boolean flags for this object. No flags are defined for this type.
|
||||
*/
|
||||
Flags: 0
|
||||
}
|
||||
|
||||
/**
|
||||
* The FeeSettings object type contains the current base transaction cost and
|
||||
* reserve amounts as determined by fee voting.
|
||||
*
|
||||
* The fields will be based on the status of the `XAHFees` amendment.
|
||||
* - Before: {@link FeeSettingsPreAmendmentFields}
|
||||
* - After: {@link FeeSettingsPostAmendmentFields}
|
||||
*
|
||||
* @interface
|
||||
*
|
||||
* @category Ledger Entries
|
||||
*/
|
||||
type FeeSettings = FeeSettingsBase &
|
||||
(FeeSettingsPreAmendmentFields | FeeSettingsPostAmendmentFields)
|
||||
|
||||
export default FeeSettings
|
||||
107
packages/xahau/src/models/ledger/Ledger.ts
Normal file
107
packages/xahau/src/models/ledger/Ledger.ts
Normal file
@@ -0,0 +1,107 @@
|
||||
import { APIVersion, DEFAULT_API_VERSION, XAHAUD_API_V1 } from '../common'
|
||||
import { Transaction, TransactionMetadata } from '../transactions'
|
||||
|
||||
import { LedgerEntry } from './LedgerEntry'
|
||||
|
||||
/**
|
||||
* Common properties for ledger entries.
|
||||
*
|
||||
* @category Ledger Entries
|
||||
*/
|
||||
interface BaseLedger {
|
||||
/** The SHA-512Half of this ledger's state tree information. */
|
||||
account_hash: string
|
||||
/** All the state information in this ledger. Admin only. */
|
||||
accountState?: LedgerEntry[]
|
||||
/** A bit-map of flags relating to the closing of this ledger. */
|
||||
close_flags: number
|
||||
/**
|
||||
* The approximate time this ledger version closed, as the number of seconds
|
||||
* since the Ripple Epoch of 2000-01-01 00:00:00. This value is rounded based
|
||||
* on the close_time_resolution.
|
||||
*/
|
||||
close_time: number
|
||||
/**
|
||||
* The approximate time this ledger was closed, in human-readable format.
|
||||
* Always uses the UTC time zone.
|
||||
*/
|
||||
close_time_human: string
|
||||
/**
|
||||
* An integer in the range [2,120] indicating the maximum number of seconds
|
||||
* by which the close_time could be rounded.
|
||||
*/
|
||||
close_time_resolution: number
|
||||
/**
|
||||
* The approximate time this ledger was closed, in date time string format.
|
||||
* Always uses the UTC time zone.
|
||||
*/
|
||||
close_time_iso: string
|
||||
/** Whether or not this ledger has been closed. */
|
||||
closed: boolean
|
||||
/**
|
||||
* The SHA-512Half of this ledger version. This serves as a unique identifier
|
||||
* for this ledger and all its contents.
|
||||
*/
|
||||
ledger_hash: string
|
||||
/** The approximate time at which the previous ledger was closed. */
|
||||
parent_close_time: number
|
||||
/**
|
||||
* Unique identifying hash of the ledger that came immediately before this
|
||||
* one.
|
||||
*/
|
||||
parent_hash: string
|
||||
/** Total number of XAH drops in the network, as a quoted integer. */
|
||||
total_coins: string
|
||||
/** Hash of the transaction information included in this ledger, as hex. */
|
||||
transaction_hash: string
|
||||
/**
|
||||
* Transactions applied in this ledger version. By default, members are the
|
||||
* transactions' identifying Hash strings. If the request specified expand as
|
||||
* true, members are full representations of the transactions instead, in
|
||||
* either JSON or binary depending on whether the request specified binary
|
||||
* as true.
|
||||
*/
|
||||
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 XAHAUD_API_V1 ? LedgerV1 : Ledger
|
||||
47
packages/xahau/src/models/ledger/LedgerEntry.ts
Normal file
47
packages/xahau/src/models/ledger/LedgerEntry.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import AccountRoot from './AccountRoot'
|
||||
import Amendments from './Amendments'
|
||||
import Check from './Check'
|
||||
import DepositPreauth from './DepositPreauth'
|
||||
import DirectoryNode from './DirectoryNode'
|
||||
import Escrow from './Escrow'
|
||||
import FeeSettings from './FeeSettings'
|
||||
import LedgerHashes from './LedgerHashes'
|
||||
import NegativeUNL from './NegativeUNL'
|
||||
import Offer from './Offer'
|
||||
import PayChannel from './PayChannel'
|
||||
import RippleState from './RippleState'
|
||||
import SignerList from './SignerList'
|
||||
import Ticket from './Ticket'
|
||||
|
||||
type LedgerEntry =
|
||||
| AccountRoot
|
||||
| Amendments
|
||||
| Check
|
||||
| DepositPreauth
|
||||
| DirectoryNode
|
||||
| Escrow
|
||||
| FeeSettings
|
||||
| LedgerHashes
|
||||
| NegativeUNL
|
||||
| Offer
|
||||
| PayChannel
|
||||
| RippleState
|
||||
| SignerList
|
||||
| Ticket
|
||||
|
||||
type LedgerEntryFilter =
|
||||
| 'account'
|
||||
| 'amendments'
|
||||
| 'check'
|
||||
| 'deposit_preauth'
|
||||
| 'directory'
|
||||
| 'escrow'
|
||||
| 'fee'
|
||||
| 'hashes'
|
||||
| 'offer'
|
||||
| 'payment_channel'
|
||||
| 'signer_list'
|
||||
| 'state'
|
||||
| 'ticket'
|
||||
|
||||
export { LedgerEntry, LedgerEntryFilter }
|
||||
24
packages/xahau/src/models/ledger/LedgerHashes.ts
Normal file
24
packages/xahau/src/models/ledger/LedgerHashes.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { BaseLedgerEntry } from './BaseLedgerEntry'
|
||||
|
||||
/**
|
||||
* The LedgerHashes objects exist to make it possible to look up a previous
|
||||
* ledger's hash with only the current ledger version and at most one lookup of
|
||||
* a previous ledger version.
|
||||
*
|
||||
* @category Ledger Entries
|
||||
*/
|
||||
export default interface LedgerHashes extends BaseLedgerEntry {
|
||||
LedgerEntryType: 'LedgerHashes'
|
||||
/** The Ledger Index of the last entry in this object's Hashes array. */
|
||||
LastLedgerSequence?: number
|
||||
/**
|
||||
* An array of up to 256 ledger hashes. The contents depend on which sub-type
|
||||
* of LedgerHashes object this is.
|
||||
*/
|
||||
Hashes: string[]
|
||||
/**
|
||||
* A bit-map of boolean flags for this object. No flags are defined for this
|
||||
* type.
|
||||
*/
|
||||
Flags: number
|
||||
}
|
||||
14
packages/xahau/src/models/ledger/NFTokenOffer.ts
Normal file
14
packages/xahau/src/models/ledger/NFTokenOffer.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { Amount } from '../common'
|
||||
|
||||
import { BaseLedgerEntry, HasPreviousTxnID } from './BaseLedgerEntry'
|
||||
|
||||
export interface NFTokenOffer extends BaseLedgerEntry, HasPreviousTxnID {
|
||||
LedgerEntryType: 'NFTokenOffer'
|
||||
Amount: Amount
|
||||
Destination?: string
|
||||
Expiration: number
|
||||
Flags: number
|
||||
NFTokenOfferNode?: string
|
||||
Owner: string
|
||||
OwnerNode?: string
|
||||
}
|
||||
18
packages/xahau/src/models/ledger/NFTokenPage.ts
Normal file
18
packages/xahau/src/models/ledger/NFTokenPage.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { BaseLedgerEntry, HasPreviousTxnID } from './BaseLedgerEntry'
|
||||
|
||||
export interface NFToken {
|
||||
NFToken: {
|
||||
Flags: number
|
||||
Issuer: string
|
||||
NFTokenID: string
|
||||
NFTokenTaxon: number
|
||||
URI?: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface NFTokenPage extends BaseLedgerEntry, HasPreviousTxnID {
|
||||
LedgerEntryType: 'NFTokenPage'
|
||||
NextPageMin?: string
|
||||
NFTokens: NFToken[]
|
||||
PreviousPageMin?: string
|
||||
}
|
||||
36
packages/xahau/src/models/ledger/NegativeUNL.ts
Normal file
36
packages/xahau/src/models/ledger/NegativeUNL.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { BaseLedgerEntry, HasOptionalPreviousTxnID } from './BaseLedgerEntry'
|
||||
|
||||
/**
|
||||
* The unique id for the nUNL object https://xrpl.org/negativeunl.html#negativeunl-id-format
|
||||
*/
|
||||
export const NEGATIVE_UNL_ID =
|
||||
'2E8A59AA9D3B5B186B0B9E0F62E6C02587CA74A4D778938E957B6357D364B244'
|
||||
|
||||
/**
|
||||
* The NegativeUNL object type contains the current status of the Negative UNL,
|
||||
* a list of trusted validators currently believed to be offline.
|
||||
*
|
||||
* @category Ledger Entries
|
||||
*/
|
||||
export default interface NegativeUNL
|
||||
extends BaseLedgerEntry,
|
||||
HasOptionalPreviousTxnID {
|
||||
LedgerEntryType: 'NegativeUNL'
|
||||
/**
|
||||
* A list of trusted validators that are currently disabled.
|
||||
*/
|
||||
DisabledValidators?: Array<{
|
||||
FirstLedgerSequence: number
|
||||
PublicKey: string
|
||||
}>
|
||||
/**
|
||||
* The public key of a trusted validator that is scheduled to be disabled in
|
||||
* the next flag ledger.
|
||||
*/
|
||||
ValidatorToDisable?: string
|
||||
/**
|
||||
* The public key of a trusted validator in the Negative UNL that is
|
||||
* scheduled to be re-enabled in the next flag ledger.
|
||||
*/
|
||||
ValidatorToReEnable?: string
|
||||
}
|
||||
42
packages/xahau/src/models/ledger/Offer.ts
Normal file
42
packages/xahau/src/models/ledger/Offer.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { Amount } from '../common'
|
||||
|
||||
import { BaseLedgerEntry, HasPreviousTxnID } from './BaseLedgerEntry'
|
||||
|
||||
export default interface Offer extends BaseLedgerEntry, HasPreviousTxnID {
|
||||
LedgerEntryType: 'Offer'
|
||||
/** A bit-map of boolean flags enabled for this Offer. */
|
||||
Flags: number
|
||||
/** The address of the account that placed this Offer. */
|
||||
Account: string
|
||||
/**
|
||||
* The Sequence value of the OfferCreate transaction that created this Offer
|
||||
* object. Used in combination with the Account to identify this Offer.
|
||||
*/
|
||||
Sequence: number
|
||||
/** The remaining amount and type of currency requested by the Offer creator. */
|
||||
TakerPays: Amount
|
||||
/**
|
||||
* The remaining amount and type of currency being provided by the Offer
|
||||
* creator.
|
||||
*/
|
||||
TakerGets: Amount
|
||||
/** The ID of the Offer Directory that links to this Offer. */
|
||||
BookDirectory: string
|
||||
/**
|
||||
* A hint indicating which page of the Offer Directory links to this object,
|
||||
* in case the directory consists of multiple pages.
|
||||
*/
|
||||
BookNode: string
|
||||
/**
|
||||
* A hint indicating which page of the Owner Directory links to this object,
|
||||
* in case the directory consists of multiple pages.
|
||||
*/
|
||||
OwnerNode: string
|
||||
/** The time this Offer expires, in seconds since the Ripple Epoch. */
|
||||
Expiration?: number
|
||||
}
|
||||
|
||||
export enum OfferFlags {
|
||||
lsfPassive = 0x00010000,
|
||||
lsfSell = 0x00020000,
|
||||
}
|
||||
97
packages/xahau/src/models/ledger/PayChannel.ts
Normal file
97
packages/xahau/src/models/ledger/PayChannel.ts
Normal file
@@ -0,0 +1,97 @@
|
||||
import { BaseLedgerEntry, HasPreviousTxnID } from './BaseLedgerEntry'
|
||||
|
||||
/**
|
||||
* The PayChannel object type represents a payment channel. Payment channels
|
||||
* enable small, rapid off-ledger payments of XAH that can be later reconciled
|
||||
* with the consensus ledger. A payment channel holds a balance of XAH that can
|
||||
* only be paid out to a specific destination address until the channel is
|
||||
* closed.
|
||||
*
|
||||
* @category Ledger Entries
|
||||
*/
|
||||
export default interface PayChannel extends BaseLedgerEntry, HasPreviousTxnID {
|
||||
LedgerEntryType: 'PayChannel'
|
||||
/**
|
||||
* The source address that owns this payment channel. This comes from the
|
||||
* sending address of the transaction that created the channel.
|
||||
*/
|
||||
Account: string
|
||||
/**
|
||||
* The destination address for this payment channel. While the payment
|
||||
* channel is open, this address is the only one that can receive XAH from the
|
||||
* channel. This comes from the Destination field of the transaction that
|
||||
* created the channel.
|
||||
*/
|
||||
Destination: string
|
||||
/**
|
||||
* Total XAH, in drops, that has been allocated to this channel. This
|
||||
* includes XAH that has been paid to the destination address. This is
|
||||
* initially set by the transaction that created the channel and can be
|
||||
* increased if the source address sends a PaymentChannelFund transaction.
|
||||
*/
|
||||
Amount: string
|
||||
/**
|
||||
* Total XAH, in drops, already paid out by the channel. The difference
|
||||
* between this value and the Amount field is how much XAH can still be paid
|
||||
* to the destination address with PaymentChannelClaim transactions. If the
|
||||
* channel closes, the remaining difference is returned to the source address.
|
||||
*/
|
||||
Balance: string
|
||||
/**
|
||||
* Public key, in hexadecimal, of the key pair that can be used to sign
|
||||
* claims against this channel. This can be any valid secp256k1 or Ed25519
|
||||
* public key. This is set by the transaction that created the channel and
|
||||
* must match the public key used in claims against the channel. The channel
|
||||
* source address can also send XAH from this channel to the destination
|
||||
* without signed claims.
|
||||
*/
|
||||
PublicKey: string
|
||||
/**
|
||||
* Number of seconds the source address must wait to close the channel if
|
||||
* it still has any XAH in it. Smaller values mean that the destination
|
||||
* address has less time to redeem any outstanding claims after the source
|
||||
* address requests to close the channel. Can be any value that fits in a
|
||||
* 32-bit unsigned integer (0 to 2^32-1). This is set by the transaction that
|
||||
* creates the channel.
|
||||
*/
|
||||
SettleDelay: number
|
||||
/**
|
||||
* A hint indicating which page of the source address's owner directory links
|
||||
* to this object, in case the directory consists of multiple pages.
|
||||
*/
|
||||
OwnerNode: string
|
||||
/**
|
||||
* A bit-map of boolean flags enabled for this payment channel. Currently,
|
||||
* the protocol defines no flags for PayChannel objects.
|
||||
*/
|
||||
Flags: number
|
||||
/**
|
||||
* The mutable expiration time for this payment channel, in seconds since the
|
||||
* Ripple Epoch. The channel is expired if this value is present and smaller
|
||||
* than the previous ledger's close_time field. See Setting Channel Expiration
|
||||
* for more details.
|
||||
*/
|
||||
Expiration?: number
|
||||
/**
|
||||
* The immutable expiration time for this payment channel, in seconds since
|
||||
* the Ripple Epoch. This channel is expired if this value is present and
|
||||
* smaller than the previous ledger's close_time field. This is optionally
|
||||
* set by the transaction that created the channel, and cannot be changed.
|
||||
*/
|
||||
CancelAfter?: number
|
||||
/**
|
||||
* An arbitrary tag to further specify the source for this payment channel
|
||||
* useful for specifying a hosted recipient at the owner's address.
|
||||
*/
|
||||
SourceTag?: number
|
||||
/**
|
||||
* An arbitrary tag to further specify the destination for this payment
|
||||
* channel, such as a hosted recipient at the destination address.
|
||||
*/
|
||||
DestinationTag?: number
|
||||
/**
|
||||
* A hint indicating which page of the destination's owner directory links to
|
||||
* this object, in case the directory consists of multiple pages.
|
||||
*/
|
||||
DestinationNode?: string
|
||||
}
|
||||
80
packages/xahau/src/models/ledger/RippleState.ts
Normal file
80
packages/xahau/src/models/ledger/RippleState.ts
Normal file
@@ -0,0 +1,80 @@
|
||||
import { IssuedCurrencyAmount } from '../common'
|
||||
|
||||
import { BaseLedgerEntry, HasPreviousTxnID } from './BaseLedgerEntry'
|
||||
|
||||
/**
|
||||
* The RippleState object type connects two accounts in a single currency.
|
||||
*
|
||||
* @category Ledger Entries
|
||||
*/
|
||||
export default interface RippleState extends BaseLedgerEntry, HasPreviousTxnID {
|
||||
LedgerEntryType: 'RippleState'
|
||||
/** A bit-map of boolean options enabled for this object. */
|
||||
Flags: number
|
||||
/**
|
||||
* The balance of the trust line, from the perspective of the low account. A
|
||||
* negative balance indicates that the low account has issued currency to the
|
||||
* high account. The issuer is always the neutral value ACCOUNT_ONE.
|
||||
*/
|
||||
Balance: IssuedCurrencyAmount
|
||||
/**
|
||||
* The limit that the low account has set on the trust line. The issuer is
|
||||
* the address of the low account that set this limit.
|
||||
*/
|
||||
LowLimit: IssuedCurrencyAmount
|
||||
/**
|
||||
* The limit that the high account has set on the trust line. The issuer is
|
||||
* the address of the high account that set this limit.
|
||||
*/
|
||||
HighLimit: IssuedCurrencyAmount
|
||||
/**
|
||||
* A hint indicating which page of the low account's owner directory links to
|
||||
* this object, in case the directory consists of multiple pages.
|
||||
*/
|
||||
LowNode?: string
|
||||
/**
|
||||
* A hint indicating which page of the high account's owner directory links
|
||||
* to this object, in case the directory consists of multiple pages.
|
||||
*/
|
||||
HighNode?: string
|
||||
/**
|
||||
* The inbound quality set by the low account, as an integer in the implied
|
||||
* ratio LowQualityIn:1,000,000,000. As a special case, the value 0 is
|
||||
* equivalent to 1 billion, or face value.
|
||||
*/
|
||||
LowQualityIn?: number
|
||||
/**
|
||||
* The outbound quality set by the low account, as an integer in the implied
|
||||
* ratio LowQualityOut:1,000,000,000. As a special case, the value 0 is
|
||||
* equivalent to 1 billion, or face value.
|
||||
*/
|
||||
LowQualityOut?: number
|
||||
/**
|
||||
* The inbound quality set by the high account, as an integer in the implied
|
||||
* ratio HighQualityIn:1,000,000,000. As a special case, the value 0 is
|
||||
* equivalent to 1 billion, or face value.
|
||||
*/
|
||||
HighQualityIn?: number
|
||||
/**
|
||||
* The outbound quality set by the high account, as an integer in the implied
|
||||
* ratio HighQualityOut:1,000,000,000. As a special case, the value 0 is
|
||||
* equivalent to 1 billion, or face value.
|
||||
*/
|
||||
HighQualityOut?: number
|
||||
}
|
||||
|
||||
export enum RippleStateFlags {
|
||||
// True, if entry counts toward reserve.
|
||||
lsfLowReserve = 0x00010000,
|
||||
lsfHighReserve = 0x00020000,
|
||||
lsfLowAuth = 0x00040000,
|
||||
lsfHighAuth = 0x00080000,
|
||||
lsfLowNoRipple = 0x00100000,
|
||||
lsfHighNoRipple = 0x00200000,
|
||||
// True, low side has set freeze flag
|
||||
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,
|
||||
}
|
||||
46
packages/xahau/src/models/ledger/SignerList.ts
Normal file
46
packages/xahau/src/models/ledger/SignerList.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import { SignerEntry } from '../common'
|
||||
|
||||
import { BaseLedgerEntry, HasPreviousTxnID } from './BaseLedgerEntry'
|
||||
|
||||
/**
|
||||
* The SignerList object type represents a list of parties that, as a group,
|
||||
* are authorized to sign a transaction in place of an individual account. You
|
||||
* can create, replace, or remove a signer list using a SignerListSet
|
||||
* transaction.
|
||||
*
|
||||
* @category Ledger Entries
|
||||
*/
|
||||
export default interface SignerList extends BaseLedgerEntry, HasPreviousTxnID {
|
||||
LedgerEntryType: 'SignerList'
|
||||
/**
|
||||
* A bit-map of Boolean flags enabled for this signer list. For more
|
||||
* information, see SignerList Flags.
|
||||
*/
|
||||
Flags: number
|
||||
/**
|
||||
* A hint indicating which page of the owner directory links to this object,
|
||||
* in case the directory consists of multiple pages.
|
||||
*/
|
||||
OwnerNode: string
|
||||
/**
|
||||
* An array of Signer Entry objects representing the parties who are part of
|
||||
* this signer list.
|
||||
*/
|
||||
SignerEntries: SignerEntry[]
|
||||
/**
|
||||
* An ID for this signer list. Currently always set to 0. If a future
|
||||
* amendment allows multiple signer lists for an account, this may change.
|
||||
*/
|
||||
SignerListID: number
|
||||
/**
|
||||
* A target number for signer weights. To produce a valid signature for the
|
||||
* owner of this SignerList, the signers must provide valid signatures whose
|
||||
* weights sum to this value or more.
|
||||
*/
|
||||
SignerQuorum: number
|
||||
}
|
||||
|
||||
export enum SignerListFlags {
|
||||
// True, uses only one OwnerCount
|
||||
lsfOneOwnerCount = 0x00010000,
|
||||
}
|
||||
26
packages/xahau/src/models/ledger/Ticket.ts
Normal file
26
packages/xahau/src/models/ledger/Ticket.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { BaseLedgerEntry, HasPreviousTxnID } from './BaseLedgerEntry'
|
||||
|
||||
/**
|
||||
* The Ticket object type represents a Ticket, which tracks an account sequence
|
||||
* number that has been set aside for future use. You can create new tickets
|
||||
* with a TicketCreate transaction.
|
||||
*
|
||||
* @category Ledger Entries
|
||||
*/
|
||||
export default interface Ticket extends BaseLedgerEntry, HasPreviousTxnID {
|
||||
LedgerEntryType: 'Ticket'
|
||||
/** The account that owns this Ticket. */
|
||||
Account: string
|
||||
/**
|
||||
* A bit-map of Boolean flags enabled for this Ticket. Currently, there are
|
||||
* no flags defined for Tickets.
|
||||
*/
|
||||
Flags: number
|
||||
/**
|
||||
* A hint indicating which page of the owner directory links to this object,
|
||||
* in case the directory consists of multiple pages.
|
||||
*/
|
||||
OwnerNode: string
|
||||
/** The Sequence Number this Ticket sets aside. */
|
||||
TicketSequence: number
|
||||
}
|
||||
60
packages/xahau/src/models/ledger/index.ts
Normal file
60
packages/xahau/src/models/ledger/index.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import AccountRoot, {
|
||||
AccountRootFlags,
|
||||
AccountRootFlagsInterface,
|
||||
} from './AccountRoot'
|
||||
import Amendments, { Majority, AMENDMENTS_ID } from './Amendments'
|
||||
import Check from './Check'
|
||||
import DepositPreauth from './DepositPreauth'
|
||||
import DirectoryNode from './DirectoryNode'
|
||||
import Escrow from './Escrow'
|
||||
import FeeSettings, {
|
||||
FeeSettingsPreAmendmentFields,
|
||||
FeeSettingsPostAmendmentFields,
|
||||
FEE_SETTINGS_ID,
|
||||
} from './FeeSettings'
|
||||
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 PayChannel from './PayChannel'
|
||||
import RippleState, { RippleStateFlags } from './RippleState'
|
||||
import SignerList, { SignerListFlags } from './SignerList'
|
||||
import Ticket from './Ticket'
|
||||
|
||||
export {
|
||||
AccountRoot,
|
||||
AccountRootFlags,
|
||||
AccountRootFlagsInterface,
|
||||
AMENDMENTS_ID,
|
||||
Amendments,
|
||||
Check,
|
||||
DepositPreauth,
|
||||
DirectoryNode,
|
||||
Escrow,
|
||||
FEE_SETTINGS_ID,
|
||||
FeeSettings,
|
||||
FeeSettingsPreAmendmentFields,
|
||||
FeeSettingsPostAmendmentFields,
|
||||
Ledger,
|
||||
LedgerV1,
|
||||
LedgerEntryFilter,
|
||||
LedgerEntry,
|
||||
LedgerHashes,
|
||||
Majority,
|
||||
NEGATIVE_UNL_ID,
|
||||
NegativeUNL,
|
||||
NFTokenOffer,
|
||||
NFTokenPage,
|
||||
NFToken,
|
||||
Offer,
|
||||
OfferFlags,
|
||||
PayChannel,
|
||||
RippleState,
|
||||
RippleStateFlags,
|
||||
SignerList,
|
||||
SignerListFlags,
|
||||
Ticket,
|
||||
}
|
||||
156
packages/xahau/src/models/methods/accountChannels.ts
Normal file
156
packages/xahau/src/models/methods/accountChannels.ts
Normal file
@@ -0,0 +1,156 @@
|
||||
import { BaseRequest, BaseResponse, LookupByLedgerRequest } from './baseMethod'
|
||||
|
||||
/**
|
||||
* Represents a payment channel in the XAH Ledger.
|
||||
*/
|
||||
export interface Channel {
|
||||
/** The owner of the channel, as an Address. */
|
||||
account: string
|
||||
|
||||
/** The total amount of XAH, in drops allocated to this channel. */
|
||||
amount: string
|
||||
|
||||
/**
|
||||
* The total amount of XAH, in drops, paid out from this channel,
|
||||
* as of the ledger version used. (You can calculate the amount of
|
||||
* XAH 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 XAH 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 XAH 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
|
||||
|
||||
/**
|
||||
* 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
|
||||
}
|
||||
|
||||
/**
|
||||
* The account_channels method returns information about an account's Payment
|
||||
* Channels. This includes only channels where the specified account is the
|
||||
* channel's source, not the destination. (A channel's "source" and "owner" are
|
||||
* the same.) All information retrieved is relative to a particular version of
|
||||
* the ledger. Returns an {@link AccountChannelsResponse}.
|
||||
*
|
||||
* @category Requests
|
||||
*/
|
||||
export interface AccountChannelsRequest
|
||||
extends BaseRequest,
|
||||
LookupByLedgerRequest {
|
||||
command: 'account_channels'
|
||||
/**
|
||||
* The unique identifier of an account, typically the account's address. The
|
||||
* request returns channels where this account is the channel's owner/source.
|
||||
*
|
||||
*/
|
||||
account: string
|
||||
/**
|
||||
* The unique identifier of an account, typically the account's address. If
|
||||
* provided, filter results to payment channels whose destination is this
|
||||
* account.
|
||||
*/
|
||||
destination_account?: string
|
||||
/**
|
||||
* Limit the number of transactions to retrieve. Cannot be less than 10 or
|
||||
* more than 400. The default is 200.
|
||||
*/
|
||||
limit?: number
|
||||
/**
|
||||
* Value from a previous paginated response. Resume retrieving data where
|
||||
* that response left off.
|
||||
*/
|
||||
marker?: unknown
|
||||
}
|
||||
|
||||
/**
|
||||
* The expected response from an {@link AccountChannelsRequest}.
|
||||
*
|
||||
* @category Responses
|
||||
*/
|
||||
export interface AccountChannelsResponse extends BaseResponse {
|
||||
result: {
|
||||
/**
|
||||
* The address of the source/owner of the payment channels. This
|
||||
* corresponds to the account field of the request.
|
||||
*/
|
||||
account: string
|
||||
/** Payment channels owned by this account. */
|
||||
channels: Channel[]
|
||||
/**
|
||||
* The identifying hash of the ledger version used to generate this
|
||||
* response.
|
||||
*/
|
||||
ledger_hash: string
|
||||
/** The ledger index of the ledger version used to generate this response. */
|
||||
ledger_index: number
|
||||
/**
|
||||
* If true, the information in this response comes from a validated ledger
|
||||
* version. Otherwise, the information is subject to change.
|
||||
*/
|
||||
validated?: boolean
|
||||
/**
|
||||
* The limit to how many channel objects were actually returned by this
|
||||
* request.
|
||||
*/
|
||||
limit?: number
|
||||
/**
|
||||
* Server-defined value for pagination. Pass this to the next call to
|
||||
* resume getting results where this call left off. Omitted when there are
|
||||
* no additional pages after this one.
|
||||
*/
|
||||
marker?: unknown
|
||||
}
|
||||
}
|
||||
45
packages/xahau/src/models/methods/accountCurrencies.ts
Normal file
45
packages/xahau/src/models/methods/accountCurrencies.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import { BaseRequest, BaseResponse, LookupByLedgerRequest } from './baseMethod'
|
||||
|
||||
/**
|
||||
* The `account_currencies` command retrieves a list of currencies that an
|
||||
* account can send or receive, based on its trust lines. Expects an
|
||||
* {@link AccountCurrenciesResponse}.
|
||||
*
|
||||
* @category Requests
|
||||
*/
|
||||
export interface AccountCurrenciesRequest
|
||||
extends BaseRequest,
|
||||
LookupByLedgerRequest {
|
||||
command: 'account_currencies'
|
||||
/** A unique identifier for the account, most commonly the account's address. */
|
||||
account: string
|
||||
/**
|
||||
* If true, then the account field only accepts a public key or XAH Ledger
|
||||
* address. Otherwise, account can be a secret or passphrase (not
|
||||
* recommended). The default is false.
|
||||
*/
|
||||
strict?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* The expected response from an {@link AccountCurrenciesRequest}.
|
||||
*
|
||||
* @category Responses
|
||||
*/
|
||||
export interface AccountCurrenciesResponse extends BaseResponse {
|
||||
result: {
|
||||
/**
|
||||
* The identifying hash of the ledger version used to retrieve this data,
|
||||
* as hex.
|
||||
*/
|
||||
ledger_hash?: string
|
||||
/** The ledger index of the ledger version used to retrieve this data. */
|
||||
ledger_index: number
|
||||
/** Array of Currency Codes for currencies that this account can receive. */
|
||||
receive_currencies: string[]
|
||||
/** Array of Currency Codes for currencies that this account can send. */
|
||||
send_currencies: string[]
|
||||
/** If true, this data comes from a validated ledger. */
|
||||
validated: boolean
|
||||
}
|
||||
}
|
||||
228
packages/xahau/src/models/methods/accountInfo.ts
Normal file
228
packages/xahau/src/models/methods/accountInfo.ts
Normal file
@@ -0,0 +1,228 @@
|
||||
import { APIVersion, DEFAULT_API_VERSION, XAHAUD_API_V1 } from '../common'
|
||||
import { AccountRoot, SignerList } from '../ledger'
|
||||
|
||||
import { BaseRequest, BaseResponse, LookupByLedgerRequest } from './baseMethod'
|
||||
|
||||
/**
|
||||
* The `account_info` command retrieves information about an account, its
|
||||
* activity, and its XAH balance. All information retrieved is relative to a
|
||||
* particular version of the ledger. Returns an {@link AccountInfoResponse}.
|
||||
*
|
||||
* @category Requests
|
||||
*/
|
||||
export interface AccountInfoRequest extends BaseRequest, LookupByLedgerRequest {
|
||||
command: 'account_info'
|
||||
/** A unique identifier for the account, most commonly the account's address. */
|
||||
account: string
|
||||
/**
|
||||
* Whether to get info about this account's queued transactions. Can only be
|
||||
* used when querying for the data from the current open ledger. Not available
|
||||
* from servers in Reporting Mode.
|
||||
*/
|
||||
queue?: boolean
|
||||
/**
|
||||
* Request SignerList objects associated with this account.
|
||||
*/
|
||||
signer_lists?: boolean
|
||||
/**
|
||||
* If true, then the account field only accepts a public key or XAH Ledger
|
||||
* address. Otherwise, account can be a secret or passphrase (not
|
||||
* recommended). The default is false.
|
||||
*/
|
||||
strict?: boolean
|
||||
}
|
||||
|
||||
export interface AccountQueueTransaction {
|
||||
/**
|
||||
* Whether this transaction changes this address's ways of authorizing
|
||||
* transactions.
|
||||
*/
|
||||
auth_change: boolean
|
||||
/** The Transaction Cost of this transaction, in drops of XAH. */
|
||||
fee: string
|
||||
/**
|
||||
* The transaction cost of this transaction, relative to the minimum cost for
|
||||
* this type of transaction, in fee levels.
|
||||
*/
|
||||
fee_level: string
|
||||
/** The maximum amount of XAH, in drops, this transaction could send or destroy. */
|
||||
max_spend_drops: string
|
||||
/** The Sequence Number of this transaction. */
|
||||
seq: number
|
||||
}
|
||||
|
||||
export interface AccountQueueData {
|
||||
/** Number of queued transactions from this address. */
|
||||
txn_count: number
|
||||
/**
|
||||
* Whether a transaction in the queue changes this address's ways of
|
||||
* authorizing transactions. If true, this address can queue no further
|
||||
* transactions until that transaction has been executed or dropped from the
|
||||
* queue.
|
||||
*/
|
||||
auth_change_queued?: boolean
|
||||
/** The lowest Sequence Number among transactions queued by this address. */
|
||||
lowest_sequence?: number
|
||||
/** The highest Sequence Number among transactions queued by this address. */
|
||||
highest_sequence?: number
|
||||
/**
|
||||
* Integer amount of drops of XAH that could be debited from this address if
|
||||
* every transaction in the queue consumes the maximum amount of XAH possible.
|
||||
*/
|
||||
max_spend_drops_total?: string
|
||||
/** Information about each queued transaction from this address. */
|
||||
transactions?: AccountQueueTransaction[]
|
||||
}
|
||||
|
||||
export interface AccountInfoAccountFlags {
|
||||
/**
|
||||
* Enable rippling on this address's trust lines by default. Required for issuing addresses; discouraged for others.
|
||||
*/
|
||||
defaultRipple: boolean
|
||||
/**
|
||||
* This account can only receive funds from transactions it sends, and from preauthorized accounts.
|
||||
* (It has DepositAuth enabled.)
|
||||
*/
|
||||
depositAuth: boolean
|
||||
/**
|
||||
* Disallows use of the master key to sign transactions for this account.
|
||||
*/
|
||||
disableMasterKey: boolean
|
||||
/**
|
||||
* Disallow incoming Checks from other accounts.
|
||||
*/
|
||||
disallowIncomingCheck?: boolean
|
||||
/**
|
||||
* Disallow incoming NFTOffers from other accounts. Part of the DisallowIncoming amendment.
|
||||
*/
|
||||
disallowIncomingNFTokenOffer?: boolean
|
||||
/**
|
||||
* Disallow incoming PayChannels from other accounts. Part of the DisallowIncoming amendment.
|
||||
*/
|
||||
disallowIncomingPayChan?: boolean
|
||||
/**
|
||||
* Disallow incoming Trustlines from other accounts. Part of the DisallowIncoming amendment.
|
||||
*/
|
||||
disallowIncomingTrustline?: boolean
|
||||
/**
|
||||
* Client applications should not send XAH to this account. Not enforced by xahaud.
|
||||
*/
|
||||
disallowIncomingXAH: boolean
|
||||
/**
|
||||
* All assets issued by this address are frozen.
|
||||
*/
|
||||
globalFreeze: boolean
|
||||
/**
|
||||
* This address cannot freeze trust lines connected to it. Once enabled, cannot be disabled.
|
||||
*/
|
||||
noFreeze: boolean
|
||||
/**
|
||||
* The account has used its free SetRegularKey transaction.
|
||||
*/
|
||||
passwordSpent: boolean
|
||||
/**
|
||||
* This account must individually approve other users for those users to hold this account's issued currencies.
|
||||
*/
|
||||
requireAuthorization: boolean
|
||||
/**
|
||||
* Requires incoming payments to specify a Destination Tag.
|
||||
*/
|
||||
requireDestinationTag: boolean
|
||||
/**
|
||||
* This address can claw back issued IOUs. Once enabled, cannot be disabled.
|
||||
*/
|
||||
allowTrustLineClawback: boolean
|
||||
}
|
||||
|
||||
interface BaseAccountInfoResponse extends BaseResponse {
|
||||
result: {
|
||||
/**
|
||||
* The AccountRoot ledger object with this account's information, as stored
|
||||
* in the ledger.
|
||||
*/
|
||||
account_data: AccountRoot
|
||||
/**
|
||||
* A map of account flags parsed out. This will only be available for xahaud nodes 1.11.0 and higher.
|
||||
*/
|
||||
account_flags?: AccountInfoAccountFlags
|
||||
/**
|
||||
* The ledger index of the current in-progress ledger, which was used when
|
||||
* retrieving this information.
|
||||
*/
|
||||
ledger_current_index?: number
|
||||
/**
|
||||
* The ledger index of the ledger version used when retrieving this
|
||||
* information. The information does not contain any changes from ledger
|
||||
* versions newer than this one.
|
||||
*/
|
||||
ledger_index?: number
|
||||
/**
|
||||
* Information about queued transactions sent by this account. This
|
||||
* information describes the state of the local xahaud server, which may be
|
||||
* different from other servers in the peer-to-peer XAH Ledger network. Some
|
||||
* fields may be omitted because the values are calculated "lazily" by the
|
||||
* queuing mechanism.
|
||||
*/
|
||||
queue_data?: AccountQueueData
|
||||
/**
|
||||
* True if this data is from a validated ledger version; if omitted or set
|
||||
* to false, this data is not final.
|
||||
*/
|
||||
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 XAHAUD_API_V1
|
||||
? AccountInfoV1Response
|
||||
: AccountInfoResponse
|
||||
137
packages/xahau/src/models/methods/accountLines.ts
Normal file
137
packages/xahau/src/models/methods/accountLines.ts
Normal file
@@ -0,0 +1,137 @@
|
||||
import { BaseRequest, BaseResponse, LookupByLedgerRequest } from './baseMethod'
|
||||
|
||||
export interface AccountLinesTrustline {
|
||||
/** The unique Address of the counterparty to this trust line. */
|
||||
account: string
|
||||
/**
|
||||
* Representation of the numeric balance currently held against this line. A
|
||||
* positive balance means that the perspective account holds value; a negative
|
||||
* Balance means that the perspective account owes value.
|
||||
*/
|
||||
balance: string
|
||||
/** A Currency Code identifying what currency this trust line can hold. */
|
||||
currency: string
|
||||
/**
|
||||
* The maximum amount of the given currency that this account is willing to
|
||||
* owe the peer account.
|
||||
*/
|
||||
limit: string
|
||||
/**
|
||||
* The maximum amount of currency that the issuer account is willing to owe
|
||||
* the perspective account.
|
||||
*/
|
||||
limit_peer: string
|
||||
/**
|
||||
* Rate at which the account values incoming balances on this trust line, as
|
||||
* a ratio of this value per 1 billion units. (For example, a value of 500
|
||||
* million represents a 0.5:1 ratio.) As a special case, 0 is treated as a
|
||||
* 1:1 ratio.
|
||||
*/
|
||||
quality_in: number
|
||||
/**
|
||||
* Rate at which the account values outgoing balances on this trust line, as
|
||||
* a ratio of this value per 1 billion units. (For example, a value of 500
|
||||
* million represents a 0.5:1 ratio.) As a special case, 0 is treated as a 1:1
|
||||
* ratio.
|
||||
*/
|
||||
quality_out: number
|
||||
/**
|
||||
* If true, this account has enabled the No Ripple flag for this trust line.
|
||||
* If present and false, this account has disabled the No Ripple flag, but,
|
||||
* because the account also has the Default Ripple flag enabled, that is not
|
||||
* considered the default state. If omitted, the account has the No Ripple
|
||||
* flag disabled for this trust line and Default Ripple disabled.
|
||||
*/
|
||||
no_ripple?: boolean
|
||||
/**
|
||||
* If true, the peer account has enabled the No Ripple flag for this trust
|
||||
* line. If present and false, this account has disabled the No Ripple flag,
|
||||
* but, because the account also has the Default Ripple flag enabled, that is
|
||||
* not considered the default state. If omitted, the account has the No Ripple
|
||||
* flag disabled for this trust line and Default Ripple disabled.
|
||||
*/
|
||||
no_ripple_peer?: boolean
|
||||
/** If true, this account has authorized this trust line. The default is false. */
|
||||
authorized?: boolean
|
||||
/** If true, the peer account has authorized this trust line. The default is false. */
|
||||
peer_authorized?: boolean
|
||||
/** If true, this account has frozen this trust line. The default is false. */
|
||||
freeze?: boolean
|
||||
/**
|
||||
* If true, the peer account has frozen this trust line. The default is
|
||||
* false.
|
||||
*/
|
||||
freeze_peer?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* The account_lines method returns information about an account's trust lines,
|
||||
* including balances in all non-XAH currencies and assets. All information
|
||||
* retrieved is relative to a particular version of the ledger. Expects an
|
||||
* {@link AccountLinesResponse}.
|
||||
*
|
||||
* @category Requests
|
||||
*/
|
||||
export interface AccountLinesRequest
|
||||
extends BaseRequest,
|
||||
LookupByLedgerRequest {
|
||||
command: 'account_lines'
|
||||
/** A unique identifier for the account, most commonly the account's Address. */
|
||||
account: string
|
||||
/**
|
||||
* The Address of a second account. If provided, show only lines of trust
|
||||
* connecting the two accounts.
|
||||
*/
|
||||
peer?: string
|
||||
/**
|
||||
* Limit the number of trust lines to retrieve. The server is not required to
|
||||
* honor this value. Must be within the inclusive range 10 to 400.
|
||||
*/
|
||||
limit?: number
|
||||
/**
|
||||
* Value from a previous paginated response. Resume retrieving data where
|
||||
* that response left off.
|
||||
*/
|
||||
marker?: unknown
|
||||
}
|
||||
|
||||
/**
|
||||
* Response expected from an {@link AccountLinesRequest}.
|
||||
*
|
||||
* @category Responses
|
||||
*/
|
||||
export interface AccountLinesResponse extends BaseResponse {
|
||||
result: {
|
||||
/**
|
||||
* Unique Address of the account this request corresponds to. This is the
|
||||
* "perspective account" for purpose of the trust lines.
|
||||
*/
|
||||
account: string
|
||||
/**
|
||||
* Array of trust line objects. If the number of trust lines is large, only
|
||||
* returns up to the limit at a time.
|
||||
*/
|
||||
lines: AccountLinesTrustline[]
|
||||
/**
|
||||
* The ledger index of the current open ledger, which was used when
|
||||
* retrieving this information.
|
||||
*/
|
||||
ledger_current_index?: number
|
||||
/**
|
||||
* The ledger index of the ledger version that was used when retrieving
|
||||
* this data.
|
||||
*/
|
||||
ledger_index?: number
|
||||
/**
|
||||
* The identifying hash the ledger version that was used when retrieving
|
||||
* this data.
|
||||
*/
|
||||
ledger_hash?: string
|
||||
/**
|
||||
* Server-defined value indicating the response is paginated. Pass this to
|
||||
* the next call to resume where this call left off. Omitted when there are
|
||||
* No additional pages after this one.
|
||||
*/
|
||||
marker?: unknown
|
||||
}
|
||||
}
|
||||
98
packages/xahau/src/models/methods/accountObjects.ts
Normal file
98
packages/xahau/src/models/methods/accountObjects.ts
Normal file
@@ -0,0 +1,98 @@
|
||||
import { Amendments, FeeSettings, LedgerHashes } from '../ledger'
|
||||
import { LedgerEntry, LedgerEntryFilter } from '../ledger/LedgerEntry'
|
||||
|
||||
import { BaseRequest, BaseResponse, LookupByLedgerRequest } from './baseMethod'
|
||||
|
||||
export type AccountObjectType = Exclude<
|
||||
LedgerEntryFilter,
|
||||
'amendments' | 'fee' | 'hashes'
|
||||
>
|
||||
/**
|
||||
* The account_objects command returns the raw ledger format for all objects
|
||||
* owned by an account. For a higher-level view of an account's trust lines and
|
||||
* balances, see the account_lines method instead. Expects a response in the
|
||||
* form of an {@link AccountObjectsResponse}.
|
||||
*
|
||||
* @category Requests
|
||||
*/
|
||||
export interface AccountObjectsRequest
|
||||
extends BaseRequest,
|
||||
LookupByLedgerRequest {
|
||||
command: 'account_objects'
|
||||
/** A unique identifier for the account, most commonly the account's address. */
|
||||
account: string
|
||||
/**
|
||||
* If included, filter results to include only this type of ledger object.
|
||||
*/
|
||||
type?: AccountObjectType
|
||||
/**
|
||||
* If true, the response only includes objects that would block this account
|
||||
* from being deleted. The default is false.
|
||||
*/
|
||||
deletion_blockers_only?: boolean
|
||||
/**
|
||||
* The maximum number of objects to include in the results. Must be within
|
||||
* the inclusive range 10 to 400 on non-admin connections. The default is 200.
|
||||
*/
|
||||
limit?: number
|
||||
/**
|
||||
* Value from a previous paginated response. Resume retrieving data where
|
||||
* that response left off.
|
||||
*/
|
||||
marker?: unknown
|
||||
}
|
||||
|
||||
/**
|
||||
* Account Objects can be a Check, a DepositPreauth, an Escrow, an Offer, a
|
||||
* PayChannel, a SignerList, a Ticket, or a RippleState.
|
||||
*/
|
||||
export type AccountObject = Exclude<
|
||||
LedgerEntry,
|
||||
Amendments | FeeSettings | LedgerHashes
|
||||
>
|
||||
|
||||
/**
|
||||
* Response expected from an {@link AccountObjectsRequest}.
|
||||
*
|
||||
* @category Responses
|
||||
*/
|
||||
export interface AccountObjectsResponse extends BaseResponse {
|
||||
result: {
|
||||
/** Unique Address of the account this request corresponds to. */
|
||||
account: string
|
||||
/**
|
||||
* Array of objects owned by this account. Each object is in its raw
|
||||
* ledger format.
|
||||
*/
|
||||
account_objects: AccountObject[]
|
||||
/**
|
||||
* The identifying hash of the ledger that was used to generate this
|
||||
* response.
|
||||
*/
|
||||
ledger_hash?: string
|
||||
/**
|
||||
* The ledger index of the ledger version that was used to generate this
|
||||
* response.
|
||||
*/
|
||||
ledger_index?: number
|
||||
/**
|
||||
* The ledger index of the current in-progress ledger version, which was
|
||||
* used to generate this response.
|
||||
*/
|
||||
ledger_current_index?: number
|
||||
/** The limit that was used in this request, if any. */
|
||||
limit?: number
|
||||
/**
|
||||
* Server-defined value indicating the response is paginated. Pass this to
|
||||
* the next call to resume where this call left off. Omitted when there are
|
||||
* no additional pages after this one.
|
||||
*/
|
||||
marker?: string
|
||||
/**
|
||||
* 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
|
||||
}
|
||||
}
|
||||
100
packages/xahau/src/models/methods/accountOffers.ts
Normal file
100
packages/xahau/src/models/methods/accountOffers.ts
Normal file
@@ -0,0 +1,100 @@
|
||||
import { Amount } from '../common'
|
||||
|
||||
import { BaseRequest, BaseResponse, LookupByLedgerRequest } from './baseMethod'
|
||||
|
||||
/**
|
||||
* The account_offers method retrieves a list of offers made by a given account
|
||||
* that are outstanding as of a particular ledger version. Expects a response in
|
||||
* the form of a {@link AccountOffersResponse}.
|
||||
*
|
||||
* @category Requests
|
||||
*/
|
||||
export interface AccountOffersRequest
|
||||
extends BaseRequest,
|
||||
LookupByLedgerRequest {
|
||||
command: 'account_offers'
|
||||
/** A unique identifier for the account, most commonly the account's Address. */
|
||||
account: string
|
||||
/**
|
||||
* Limit the number of transactions to retrieve. The server is not required
|
||||
* to honor this value. Must be within the inclusive range 10 to 400.
|
||||
*/
|
||||
limit?: number
|
||||
/**
|
||||
* Value from a previous paginated response. Resume retrieving data where
|
||||
* that response left off.
|
||||
*/
|
||||
marker?: unknown
|
||||
/**
|
||||
* If true, then the account field only accepts a public key or XAH Ledger
|
||||
* address. Otherwise, account can be a secret or passphrase (not
|
||||
* recommended). The default is false.
|
||||
*/
|
||||
strict?: boolean
|
||||
}
|
||||
|
||||
export interface AccountOffer {
|
||||
/** Options set for this offer entry as bit-flags. */
|
||||
flags: number
|
||||
/** Sequence number of the transaction that created this entry. */
|
||||
seq: number
|
||||
/**
|
||||
* The amount the account placing this Offer receives.
|
||||
*/
|
||||
taker_gets: Amount
|
||||
/**
|
||||
* The amount the account placing this Offer pays.
|
||||
*/
|
||||
taker_pays: Amount
|
||||
/**
|
||||
* The exchange rate of the Offer, as the ratio of the original taker_pays
|
||||
* divided by the original taker_gets. When executing offers, the offer with
|
||||
* the most favorable (lowest) quality is consumed first; offers with the same
|
||||
* quality are executed from oldest to newest.
|
||||
*/
|
||||
quality: string
|
||||
/**
|
||||
* A time after which this offer is considered unfunded, as the number of
|
||||
* seconds since the Ripple Epoch. See also: Offer Expiration.
|
||||
*/
|
||||
expiration?: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Response expected from an {@link AccountOffersRequest}.
|
||||
*
|
||||
* @category Responses
|
||||
*/
|
||||
export interface AccountOffersResponse extends BaseResponse {
|
||||
result: {
|
||||
/** Unique Address identifying the account that made the offers. */
|
||||
account: string
|
||||
/**
|
||||
* Array of objects, where each object represents an offer made by this
|
||||
* account that is outstanding as of the requested ledger version. If the
|
||||
* number of offers is large, only returns up to limit at a time.
|
||||
*/
|
||||
offers?: AccountOffer[]
|
||||
/**
|
||||
* The ledger index of the current in-progress ledger version, which was
|
||||
* used when retrieving this data.
|
||||
*/
|
||||
ledger_current_index?: number
|
||||
/**
|
||||
* The ledger index of the ledger version that was used when retrieving
|
||||
* this data, as requested.
|
||||
*/
|
||||
ledger_index?: number
|
||||
/**
|
||||
* The identifying hash of the ledger version that was used when retrieving
|
||||
* this data.
|
||||
*/
|
||||
ledger_hash?: string
|
||||
/**
|
||||
* Server-defined value indicating the response is paginated. Pass this to
|
||||
* the next call to resume where this call left off. Omitted when there are
|
||||
* no pages of information after this one.
|
||||
*/
|
||||
marker?: unknown
|
||||
}
|
||||
}
|
||||
150
packages/xahau/src/models/methods/accountTx.ts
Normal file
150
packages/xahau/src/models/methods/accountTx.ts
Normal file
@@ -0,0 +1,150 @@
|
||||
import {
|
||||
APIVersion,
|
||||
DEFAULT_API_VERSION,
|
||||
XAHAUD_API_V1,
|
||||
XAHAUD_API_V2,
|
||||
ResponseOnlyTxInfo,
|
||||
} from '../common'
|
||||
import { Transaction, TransactionMetadata } from '../transactions'
|
||||
|
||||
import { BaseRequest, BaseResponse, LookupByLedgerRequest } from './baseMethod'
|
||||
|
||||
/**
|
||||
* The account_tx method retrieves a list of transactions that involved the
|
||||
* specified account. Expects a response in the form of a {@link
|
||||
* AccountTxResponse}.
|
||||
*
|
||||
* @category Requests
|
||||
*/
|
||||
export interface AccountTxRequest extends BaseRequest, LookupByLedgerRequest {
|
||||
command: 'account_tx'
|
||||
/** A unique identifier for the account, most commonly the account's address. */
|
||||
account: string
|
||||
/**
|
||||
* Use to specify the earliest ledger to include transactions from. A value
|
||||
* of -1 instructs the server to use the earliest validated ledger version
|
||||
* available.
|
||||
*/
|
||||
ledger_index_min?: number
|
||||
/**
|
||||
* Use to specify the most recent ledger to include transactions from. A
|
||||
* value of -1 instructs the server to use the most recent validated ledger
|
||||
* version available.
|
||||
*/
|
||||
ledger_index_max?: number
|
||||
/**
|
||||
* If true, return transactions as hex strings instead of JSON. The default is
|
||||
* false.
|
||||
*/
|
||||
binary?: boolean
|
||||
/**
|
||||
* If true, returns values indexed with the oldest ledger first. Otherwise,
|
||||
* the results are indexed with the newest ledger first.
|
||||
*/
|
||||
forward?: boolean
|
||||
/**
|
||||
* Default varies. Limit the number of transactions to retrieve. The server
|
||||
* is not required to honor this value.
|
||||
*/
|
||||
limit?: number
|
||||
/**
|
||||
* 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
|
||||
}
|
||||
|
||||
export interface AccountTxTransaction<
|
||||
Version extends APIVersion = typeof DEFAULT_API_VERSION,
|
||||
> {
|
||||
/** The ledger index of the ledger version that included this transaction. */
|
||||
ledger_index: number
|
||||
/**
|
||||
* If binary is True, then this is a hex string of the transaction metadata.
|
||||
* Otherwise, the transaction metadata is included in JSON format.
|
||||
*/
|
||||
meta: string | TransactionMetadata
|
||||
/** JSON object defining the transaction. */
|
||||
tx_json?: Version extends typeof XAHAUD_API_V2
|
||||
? Transaction & ResponseOnlyTxInfo
|
||||
: never
|
||||
/** JSON object defining the transaction in xahaud API v1. */
|
||||
tx?: Version extends typeof XAHAUD_API_V1
|
||||
? Transaction & ResponseOnlyTxInfo
|
||||
: never
|
||||
/** The hash of the transaction. */
|
||||
hash?: Version extends typeof XAHAUD_API_V2 ? string : never
|
||||
/** Unique hashed String representing the transaction. */
|
||||
tx_blob?: string
|
||||
/**
|
||||
* Whether or not the transaction is included in a validated ledger. Any
|
||||
* transaction not yet in a validated ledger is subject to change.
|
||||
*/
|
||||
validated: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Base interface for account transaction responses.
|
||||
*/
|
||||
interface AccountTxResponseBase<
|
||||
Version extends APIVersion = typeof DEFAULT_API_VERSION,
|
||||
> extends BaseResponse {
|
||||
result: {
|
||||
/** Unique Address identifying the related account. */
|
||||
account: string
|
||||
/**
|
||||
* The ledger index of the earliest ledger actually searched for
|
||||
* transactions.
|
||||
*/
|
||||
ledger_index_min: number
|
||||
/**
|
||||
* The ledger index of the most recent ledger actually searched for
|
||||
* transactions.
|
||||
*/
|
||||
ledger_index_max: number
|
||||
/** The limit value used in the request. */
|
||||
limit: number
|
||||
/**
|
||||
* Server-defined value indicating the response is paginated. Pass this
|
||||
* to the next call to resume where this call left off.
|
||||
*/
|
||||
marker?: unknown
|
||||
/**
|
||||
* Array of transactions matching the request's criteria, as explained
|
||||
* below.
|
||||
*/
|
||||
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
|
||||
* change.
|
||||
*/
|
||||
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
|
||||
|
||||
/**
|
||||
* 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 XAHAUD_API_V1
|
||||
? AccountTxV1Response
|
||||
: AccountTxResponse
|
||||
58
packages/xahau/src/models/methods/baseMethod.ts
Normal file
58
packages/xahau/src/models/methods/baseMethod.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import { LedgerIndex } from '../common'
|
||||
|
||||
import type { Request } from '.'
|
||||
|
||||
export interface BaseRequest {
|
||||
[x: string]: unknown
|
||||
/**
|
||||
* A unique value to identify this request. The response to this request uses
|
||||
* the same id field. This way, even if responses arrive out of order, you
|
||||
* know which request prompted which response.
|
||||
*/
|
||||
id?: number | string
|
||||
/** The name of the API method. */
|
||||
command: string
|
||||
/** The API version to use. If omitted, use version 1. */
|
||||
api_version?: number
|
||||
}
|
||||
|
||||
export interface LookupByLedgerRequest {
|
||||
/** A 20-byte hex string for the ledger version to use. */
|
||||
ledger_hash?: string
|
||||
/** The ledger index of the ledger to use, or a shortcut string. */
|
||||
ledger_index?: LedgerIndex
|
||||
}
|
||||
|
||||
export interface ResponseWarning {
|
||||
id: number
|
||||
message: string
|
||||
details?: { [key: string]: string }
|
||||
}
|
||||
|
||||
export interface BaseResponse {
|
||||
id: number | string
|
||||
status?: 'success' | string
|
||||
type: 'response' | string
|
||||
result: unknown
|
||||
warning?: 'load'
|
||||
warnings?: ResponseWarning[]
|
||||
forwarded?: boolean
|
||||
api_version?: number
|
||||
}
|
||||
|
||||
/**
|
||||
* The shape of an error response from xahaud. xrpl.js handles rejections by
|
||||
* throwing, and allowing the user to handle in the catch block of a promise.
|
||||
*
|
||||
* @category Responses
|
||||
*/
|
||||
export interface ErrorResponse {
|
||||
id: number | string
|
||||
status: 'error'
|
||||
type: 'response' | string
|
||||
error: string
|
||||
error_code?: string
|
||||
error_message?: string
|
||||
request: Request
|
||||
api_version?: number
|
||||
}
|
||||
96
packages/xahau/src/models/methods/bookOffers.ts
Normal file
96
packages/xahau/src/models/methods/bookOffers.ts
Normal file
@@ -0,0 +1,96 @@
|
||||
import { Amount } from '../common'
|
||||
import { Offer } from '../ledger'
|
||||
|
||||
import { BaseRequest, BaseResponse, LookupByLedgerRequest } from './baseMethod'
|
||||
|
||||
export interface BookOfferCurrency {
|
||||
currency: string
|
||||
issuer?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* The book_offers method retrieves a list of offers, also known as the order.
|
||||
* Book, between two currencies. Returns an {@link BookOffersResponse}.
|
||||
*
|
||||
* @category Requests
|
||||
*/
|
||||
export interface BookOffersRequest extends BaseRequest, LookupByLedgerRequest {
|
||||
command: 'book_offers'
|
||||
/**
|
||||
* If provided, the server does not provide more than this many offers in the
|
||||
* results. The total number of results returned may be fewer than the limit,
|
||||
* because the server omits unfunded offers.
|
||||
*/
|
||||
limit?: number
|
||||
/**
|
||||
* The Address of an account to use as a perspective. Unfunded offers placed
|
||||
* by this account are always included in the response.
|
||||
*/
|
||||
taker?: string
|
||||
/**
|
||||
* Specification of which currency the account taking the offer would
|
||||
* receive, as an object with currency and issuer fields (omit issuer for
|
||||
* XAH), like currency amounts.
|
||||
*/
|
||||
taker_gets: BookOfferCurrency
|
||||
/**
|
||||
* Specification of which currency the account taking the offer would pay, as
|
||||
* an object with currency and issuer fields (omit issuer for XAH), like
|
||||
* currency amounts.
|
||||
*/
|
||||
taker_pays: BookOfferCurrency
|
||||
}
|
||||
|
||||
export interface BookOffer extends Offer {
|
||||
/**
|
||||
* Amount of the TakerGets currency the side placing the offer has available
|
||||
* to be traded. (XAH is represented as drops; any other currency is
|
||||
* represented as a decimal value.) If a trader has multiple offers in the
|
||||
* same book, only the highest-ranked offer includes this field.
|
||||
*/
|
||||
owner_funds?: string
|
||||
/**
|
||||
* The maximum amount of currency that the taker can get, given the funding
|
||||
* status of the offer.
|
||||
*/
|
||||
taker_gets_funded?: Amount
|
||||
/**
|
||||
* The maximum amount of currency that the taker would pay, given the funding
|
||||
* status of the offer.
|
||||
*/
|
||||
taker_pays_funded?: Amount
|
||||
/**
|
||||
* The exchange rate, as the ratio taker_pays divided by taker_gets. For
|
||||
* fairness, offers that have the same quality are automatically taken
|
||||
* first-in, first-out.
|
||||
*/
|
||||
quality?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Expected response from a {@link BookOffersRequest}.
|
||||
*
|
||||
* @category Responses
|
||||
*/
|
||||
export interface BookOffersResponse extends BaseResponse {
|
||||
result: {
|
||||
/**
|
||||
* The ledger index of the current in-progress ledger version, which was
|
||||
* used to retrieve this information.
|
||||
*/
|
||||
ledger_current_index?: number
|
||||
/**
|
||||
* The ledger index of the ledger version that was used when retrieving
|
||||
* this data, as requested.
|
||||
*/
|
||||
ledger_index?: number
|
||||
/**
|
||||
* The identifying hash of the ledger version that was used when retrieving
|
||||
* this data, as requested.
|
||||
*/
|
||||
ledger_hash?: string
|
||||
/** Array of offer objects, each of which has the fields of an Offer object. */
|
||||
offers: BookOffer[]
|
||||
validated?: boolean
|
||||
}
|
||||
}
|
||||
41
packages/xahau/src/models/methods/channelVerify.ts
Normal file
41
packages/xahau/src/models/methods/channelVerify.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import { BaseRequest, BaseResponse } from './baseMethod'
|
||||
|
||||
/**
|
||||
* The `channel_verify` method checks the validity of a signature that can be
|
||||
* used to redeem a specific amount of XAH from a payment channel. Expects a
|
||||
* response in the form of a {@link ChannelVerifyResponse}.
|
||||
*
|
||||
* @category Requests
|
||||
*/
|
||||
export interface ChannelVerifyRequest extends BaseRequest {
|
||||
command: 'channel_verify'
|
||||
/** The amount of XAH, in drops, the provided signature authorizes. */
|
||||
amount: string
|
||||
/**
|
||||
* The Channel ID of the channel that provides the XAH. This is a
|
||||
* 64-character hexadecimal string.
|
||||
*/
|
||||
channel_id: string
|
||||
/**
|
||||
* The public key of the channel and the key pair that was used to create the
|
||||
* signature, in hexadecimal or the XAH Ledger's base58 format.
|
||||
*/
|
||||
public_key: string
|
||||
/** The signature to verify, in hexadecimal. */
|
||||
signature: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Response expected from an {@link ChannelVerifyRequest}.
|
||||
*
|
||||
* @category Responses
|
||||
*/
|
||||
export interface ChannelVerifyResponse extends BaseResponse {
|
||||
result: {
|
||||
/**
|
||||
* If true, the signature is valid for the stated amount, channel, and
|
||||
* public key.
|
||||
*/
|
||||
signature_verified: boolean
|
||||
}
|
||||
}
|
||||
56
packages/xahau/src/models/methods/depositAuthorized.ts
Normal file
56
packages/xahau/src/models/methods/depositAuthorized.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import { BaseRequest, BaseResponse, LookupByLedgerRequest } from './baseMethod'
|
||||
|
||||
/**
|
||||
* The deposit_authorized command indicates whether one account is authorized to
|
||||
* send payments directly to another. Expects a response in the form of a {@link
|
||||
* DepositAuthorizedResponse}.
|
||||
*
|
||||
* @category Requests
|
||||
*/
|
||||
export interface DepositAuthorizedRequest
|
||||
extends BaseRequest,
|
||||
LookupByLedgerRequest {
|
||||
command: 'deposit_authorized'
|
||||
/** The sender of a possible payment. */
|
||||
source_account: string
|
||||
/** The recipient of a possible payment. */
|
||||
destination_account: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Expected response from a {@link DepositAuthorizedRequest}.
|
||||
*
|
||||
* @category Responses
|
||||
*/
|
||||
export interface DepositAuthorizedResponse extends BaseResponse {
|
||||
result: {
|
||||
/**
|
||||
* Whether the specified source account is authorized to send payments
|
||||
* directly to the destination account. If true, either the destination
|
||||
* account does not require Deposit Authorization or the source account is
|
||||
* preauthorized.
|
||||
*/
|
||||
deposit_authorized: boolean
|
||||
/** The destination account specified in the request. */
|
||||
destination_account: string
|
||||
/**
|
||||
* The identifying hash of the ledger that was used to generate this
|
||||
* Response.
|
||||
*/
|
||||
ledger_hash?: string
|
||||
/**
|
||||
* The ledger index of the ledger version that was used to generate this
|
||||
* Response.
|
||||
*/
|
||||
ledger_index?: number
|
||||
/**
|
||||
* The ledger index of the current in-progress ledger version, which was
|
||||
* used to generate this response.
|
||||
*/
|
||||
ledger_current_index?: number
|
||||
/** The source account specified in the request. */
|
||||
source_account: string
|
||||
/** If true, the information comes from a validated ledger version. */
|
||||
validated?: boolean
|
||||
}
|
||||
}
|
||||
68
packages/xahau/src/models/methods/feature.ts
Normal file
68
packages/xahau/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
|
||||
91
packages/xahau/src/models/methods/fee.ts
Normal file
91
packages/xahau/src/models/methods/fee.ts
Normal file
@@ -0,0 +1,91 @@
|
||||
import { BaseRequest, BaseResponse } from './baseMethod'
|
||||
|
||||
/**
|
||||
* The `fee` command reports the current state of the open-ledger requirements
|
||||
* for the transaction cost. This requires the FeeEscalation amendment to be
|
||||
* enabled. Expects a response in the form of a {@link FeeResponse}.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const feeRequest: FeeRequest = {
|
||||
* command: 'fee'
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @category Requests
|
||||
*/
|
||||
export interface FeeRequest extends BaseRequest {
|
||||
command: 'fee'
|
||||
}
|
||||
|
||||
/**
|
||||
* Response expected from a {@link FeeRequest}.
|
||||
*
|
||||
* @category Responses
|
||||
*/
|
||||
export interface FeeResponse extends BaseResponse {
|
||||
result: {
|
||||
/** Number of transactions provisionally included in the in-progress ledger. */
|
||||
current_ledger_size: string
|
||||
/** Number of transactions currently queued for the next ledger. */
|
||||
current_queue_size: string
|
||||
drops: {
|
||||
/**
|
||||
* The transaction cost required for a reference transaction to be
|
||||
* included in a ledger under minimum load, represented in drops of XAH.
|
||||
*/
|
||||
base_fee: string
|
||||
/**
|
||||
* An approximation of the median transaction cost among transactions.
|
||||
* Included in the previous validated ledger, represented in drops of XAH.
|
||||
*/
|
||||
median_fee: string
|
||||
/**
|
||||
* The minimum transaction cost for a reference transaction to be queued
|
||||
* for a later ledger, represented in drops of XAH. If greater than
|
||||
* base_fee, the transaction queue is full.
|
||||
*/
|
||||
minimum_fee: string
|
||||
/**
|
||||
* The minimum transaction cost that a reference transaction must pay to
|
||||
* be included in the current open ledger, represented in drops of XAH.
|
||||
*/
|
||||
open_ledger_fee: string
|
||||
}
|
||||
/**
|
||||
* The approximate number of transactions expected to be included in the
|
||||
* current ledger. This is based on the number of transactions in the
|
||||
* previous ledger.
|
||||
*/
|
||||
expected_ledger_size: string
|
||||
/** The Ledger Index of the current open ledger these stats describe. */
|
||||
ledger_current_index: number
|
||||
levels: {
|
||||
/**
|
||||
* The median transaction cost among transactions in the previous
|
||||
* validated ledger, represented in fee levels.
|
||||
*/
|
||||
median_level: string
|
||||
/**
|
||||
* The minimum transaction cost required to be queued for a future
|
||||
* ledger, represented in fee levels.
|
||||
*/
|
||||
minimum_level: string
|
||||
/**
|
||||
* The minimum transaction cost required to be included in the current
|
||||
* open ledger, represented in fee levels.
|
||||
*/
|
||||
open_ledger_level: string
|
||||
/**
|
||||
* The equivalent of the minimum transaction cost, represented in fee
|
||||
* levels.
|
||||
*/
|
||||
reference_level: string
|
||||
}
|
||||
/**
|
||||
* The maximum number of transactions that the transaction queue can
|
||||
* currently hold.
|
||||
*/
|
||||
max_queue_size: string
|
||||
}
|
||||
}
|
||||
85
packages/xahau/src/models/methods/gatewayBalances.ts
Normal file
85
packages/xahau/src/models/methods/gatewayBalances.ts
Normal file
@@ -0,0 +1,85 @@
|
||||
import { BaseRequest, BaseResponse, LookupByLedgerRequest } from './baseMethod'
|
||||
|
||||
/**
|
||||
* The gateway_balances command calculates the total balances issued by a given
|
||||
* account, optionally excluding amounts held by operational addresses. Expects
|
||||
* a response in the form of a {@link GatewayBalancesResponse}.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const gatewayBalances: GatewayBalanceRequest = {
|
||||
* "id": "example_gateway_balances_1",
|
||||
* "command": "gateway_balances",
|
||||
* "account": "rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q",
|
||||
* "strict": true,
|
||||
* "hotwallet": ["rKm4uWpg9tfwbVSeATv4KxDe6mpE9yPkgJ","ra7JkEzrgeKHdzKgo4EUUVBnxggY4z37kt"],
|
||||
* "ledger_index": "validated"
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @category Requests
|
||||
*/
|
||||
export interface GatewayBalancesRequest
|
||||
extends BaseRequest,
|
||||
LookupByLedgerRequest {
|
||||
command: 'gateway_balances'
|
||||
/** The Address to check. This should be the issuing address. */
|
||||
account: string
|
||||
/**
|
||||
* If true, only accept an address or public key for the account parameter.
|
||||
* Defaults to false.
|
||||
*/
|
||||
strict?: boolean
|
||||
/**
|
||||
* An operational address to exclude from the balances issued, or an array of
|
||||
* Such addresses.
|
||||
*/
|
||||
hotwallet?: string | string[]
|
||||
}
|
||||
|
||||
export interface GatewayBalance {
|
||||
currency: string
|
||||
value: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Expected response from a {@link GatewayBalancesRequest}.
|
||||
*
|
||||
* @category Responses
|
||||
*/
|
||||
export interface GatewayBalancesResponse extends BaseResponse {
|
||||
result: {
|
||||
/** The address of the account that issued the balances. */
|
||||
account: string
|
||||
/**
|
||||
* Total amounts issued to addresses not excluded, as a map of currencies
|
||||
* to the total value issued.
|
||||
*/
|
||||
obligations?: { [currency: string]: string }
|
||||
/**
|
||||
* Amounts issued to the hotwallet addresses from the request. The keys are
|
||||
* addresses and the values are arrays of currency amounts they hold.
|
||||
*/
|
||||
balances?: { [address: string]: GatewayBalance[] }
|
||||
/**
|
||||
* Total amounts held that are issued by others. In the recommended
|
||||
* configuration, the issuing address should have none.
|
||||
*/
|
||||
assets?: { [address: string]: GatewayBalance[] }
|
||||
/**
|
||||
* The identifying hash of the ledger version that was used to generate
|
||||
* this response.
|
||||
*/
|
||||
ledger_hash?: string
|
||||
/**
|
||||
* The ledger index of the ledger version that was used to generate this
|
||||
* response.
|
||||
*/
|
||||
ledger_current_index?: number
|
||||
/**
|
||||
* The ledger index of the current in-progress ledger version, which was
|
||||
* used to retrieve this information.
|
||||
*/
|
||||
ledger_index?: number
|
||||
}
|
||||
}
|
||||
554
packages/xahau/src/models/methods/index.ts
Normal file
554
packages/xahau/src/models/methods/index.ts
Normal file
@@ -0,0 +1,554 @@
|
||||
/* 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,
|
||||
Channel,
|
||||
} from './accountChannels'
|
||||
import {
|
||||
AccountCurrenciesRequest,
|
||||
AccountCurrenciesResponse,
|
||||
} from './accountCurrencies'
|
||||
import {
|
||||
AccountInfoAccountFlags,
|
||||
AccountInfoRequest,
|
||||
AccountInfoResponse,
|
||||
AccountInfoV1Response,
|
||||
AccountInfoVersionResponseMap,
|
||||
AccountQueueData,
|
||||
AccountQueueTransaction,
|
||||
} from './accountInfo'
|
||||
import {
|
||||
AccountLinesRequest,
|
||||
AccountLinesResponse,
|
||||
AccountLinesTrustline,
|
||||
} from './accountLines'
|
||||
import {
|
||||
AccountObject,
|
||||
AccountObjectsRequest,
|
||||
AccountObjectsResponse,
|
||||
AccountObjectType,
|
||||
} from './accountObjects'
|
||||
import {
|
||||
AccountOffer,
|
||||
AccountOffersRequest,
|
||||
AccountOffersResponse,
|
||||
} from './accountOffers'
|
||||
import {
|
||||
AccountTxRequest,
|
||||
AccountTxResponse,
|
||||
AccountTxV1Response,
|
||||
AccountTxVersionResponseMap,
|
||||
AccountTxTransaction,
|
||||
} from './accountTx'
|
||||
import {
|
||||
BaseRequest,
|
||||
BaseResponse,
|
||||
ErrorResponse,
|
||||
ResponseWarning,
|
||||
} from './baseMethod'
|
||||
import {
|
||||
BookOffersRequest,
|
||||
BookOffer,
|
||||
BookOffersResponse,
|
||||
BookOfferCurrency,
|
||||
} from './bookOffers'
|
||||
import { ChannelVerifyRequest, ChannelVerifyResponse } from './channelVerify'
|
||||
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 {
|
||||
LedgerBinary,
|
||||
LedgerModifiedOfferCreateTransaction,
|
||||
LedgerQueueData,
|
||||
LedgerRequest,
|
||||
LedgerResponse,
|
||||
LedgerV1Response,
|
||||
LedgerRequestExpandedTransactionsOnly,
|
||||
LedgerResponseExpanded,
|
||||
LedgerRequestExpandedAccountsAndTransactions,
|
||||
LedgerRequestExpandedAccountsOnly,
|
||||
LedgerRequestExpandedTransactionsBinary,
|
||||
LedgerVersionResponseMap,
|
||||
} from './ledger'
|
||||
import { LedgerClosedRequest, LedgerClosedResponse } from './ledgerClosed'
|
||||
import { LedgerCurrentRequest, LedgerCurrentResponse } from './ledgerCurrent'
|
||||
import {
|
||||
LedgerDataBinaryLedgerEntry,
|
||||
LedgerDataLabeledLedgerEntry,
|
||||
LedgerDataLedgerState,
|
||||
LedgerDataRequest,
|
||||
LedgerDataResponse,
|
||||
} from './ledgerData'
|
||||
import { LedgerEntryRequest, LedgerEntryResponse } from './ledgerEntry'
|
||||
import { ManifestRequest, ManifestResponse } from './manifest'
|
||||
import { NoRippleCheckRequest, NoRippleCheckResponse } from './norippleCheck'
|
||||
import {
|
||||
PathFindRequest,
|
||||
PathFindCloseRequest,
|
||||
PathFindCreateRequest,
|
||||
PathFindStatusRequest,
|
||||
PathFindResponse,
|
||||
PathFindPathOption,
|
||||
} from './pathFind'
|
||||
import { PingRequest, PingResponse } from './ping'
|
||||
import { RandomRequest, RandomResponse } from './random'
|
||||
import {
|
||||
RipplePathFindPathOption,
|
||||
RipplePathFindRequest,
|
||||
RipplePathFindResponse,
|
||||
SourceCurrencyAmount,
|
||||
} from './ripplePathFind'
|
||||
import {
|
||||
ServerDefinitionsRequest,
|
||||
ServerDefinitionsResponse,
|
||||
} from './serverDefinitions'
|
||||
import {
|
||||
JobType,
|
||||
ServerInfoRequest,
|
||||
ServerInfoResponse,
|
||||
ServerState,
|
||||
StateAccounting,
|
||||
StateAccountingFinal,
|
||||
} from './serverInfo'
|
||||
import { ServerStateRequest, ServerStateResponse } from './serverState'
|
||||
import { SubmitRequest, SubmitResponse } from './submit'
|
||||
import {
|
||||
SubmitMultisignedRequest,
|
||||
SubmitMultisignedResponse,
|
||||
SubmitMultisignedV1Response,
|
||||
SubmitMultisignedVersionResponseMap,
|
||||
} from './submitMultisigned'
|
||||
import {
|
||||
BooksSnapshot,
|
||||
ConsensusStream,
|
||||
LedgerStream,
|
||||
LedgerStreamResponse,
|
||||
OrderBookStream,
|
||||
PathFindStream,
|
||||
PeerStatusStream,
|
||||
Stream,
|
||||
SubscribeBook,
|
||||
SubscribeRequest,
|
||||
SubscribeResponse,
|
||||
TransactionStream,
|
||||
TransactionV1Stream,
|
||||
ValidationStream,
|
||||
} from './subscribe'
|
||||
import {
|
||||
TransactionEntryRequest,
|
||||
TransactionEntryResponse,
|
||||
} from './transactionEntry'
|
||||
import { TxRequest, TxResponse, TxV1Response, TxVersionResponseMap } from './tx'
|
||||
import {
|
||||
UnsubscribeBook,
|
||||
UnsubscribeRequest,
|
||||
UnsubscribeResponse,
|
||||
} from './unsubscribe'
|
||||
/**
|
||||
* @category Requests
|
||||
*/
|
||||
type Request =
|
||||
// account methods
|
||||
| AccountChannelsRequest
|
||||
| AccountCurrenciesRequest
|
||||
| AccountInfoRequest
|
||||
| AccountLinesRequest
|
||||
| AccountObjectsRequest
|
||||
| AccountOffersRequest
|
||||
| AccountTxRequest
|
||||
| GatewayBalancesRequest
|
||||
| NoRippleCheckRequest
|
||||
// ledger methods
|
||||
| LedgerRequest
|
||||
| LedgerClosedRequest
|
||||
| LedgerCurrentRequest
|
||||
| LedgerDataRequest
|
||||
| LedgerEntryRequest
|
||||
// transaction methods
|
||||
| SubmitRequest
|
||||
| SubmitMultisignedRequest
|
||||
| TransactionEntryRequest
|
||||
| TxRequest
|
||||
// path and order book methods
|
||||
| BookOffersRequest
|
||||
| DepositAuthorizedRequest
|
||||
| PathFindRequest
|
||||
| RipplePathFindRequest
|
||||
// payment channel methods
|
||||
| ChannelVerifyRequest
|
||||
// subscription methods
|
||||
| SubscribeRequest
|
||||
| UnsubscribeRequest
|
||||
// server info methods
|
||||
| FeeRequest
|
||||
| ManifestRequest
|
||||
| ServerDefinitionsRequest
|
||||
| ServerInfoRequest
|
||||
| ServerStateRequest
|
||||
| FeatureRequest
|
||||
// utility methods
|
||||
| PingRequest
|
||||
| RandomRequest
|
||||
|
||||
/**
|
||||
* @category Responses
|
||||
*/
|
||||
type Response<Version extends APIVersion = typeof DEFAULT_API_VERSION> =
|
||||
// account methods
|
||||
| AccountChannelsResponse
|
||||
| AccountCurrenciesResponse
|
||||
| AccountInfoVersionResponseMap<Version>
|
||||
| AccountLinesResponse
|
||||
| AccountObjectsResponse
|
||||
| AccountOffersResponse
|
||||
| AccountTxVersionResponseMap<Version>
|
||||
| GatewayBalancesResponse
|
||||
| NoRippleCheckResponse
|
||||
// ledger methods
|
||||
| LedgerVersionResponseMap<Version>
|
||||
| LedgerClosedResponse
|
||||
| LedgerCurrentResponse
|
||||
| LedgerDataResponse
|
||||
| LedgerEntryResponse
|
||||
// transaction methods
|
||||
| SubmitResponse
|
||||
| SubmitMultisignedVersionResponseMap<Version>
|
||||
| TransactionEntryResponse
|
||||
| TxResponse
|
||||
// path and order book methods
|
||||
| BookOffersResponse
|
||||
| DepositAuthorizedResponse
|
||||
| PathFindResponse
|
||||
| RipplePathFindResponse
|
||||
// payment channel methods
|
||||
| ChannelVerifyResponse
|
||||
// subscription methods
|
||||
| SubscribeResponse
|
||||
| UnsubscribeResponse
|
||||
// server info methods
|
||||
| FeeResponse
|
||||
| ManifestResponse
|
||||
| ServerDefinitionsResponse
|
||||
| ServerInfoResponse
|
||||
| ServerStateResponse
|
||||
| FeatureResponse
|
||||
// utility methods
|
||||
| PingResponse
|
||||
| RandomResponse
|
||||
|
||||
export type RequestResponseMap<
|
||||
T,
|
||||
Version extends APIVersion = typeof DEFAULT_API_VERSION,
|
||||
> = T extends AccountChannelsRequest
|
||||
? AccountChannelsResponse
|
||||
: T extends AccountCurrenciesRequest
|
||||
? AccountCurrenciesResponse
|
||||
: T extends AccountInfoRequest
|
||||
? AccountInfoVersionResponseMap<Version>
|
||||
: T extends AccountLinesRequest
|
||||
? AccountLinesResponse
|
||||
: T extends AccountObjectsRequest
|
||||
? AccountObjectsResponse
|
||||
: T extends AccountOffersRequest
|
||||
? AccountOffersResponse
|
||||
: T extends AccountTxRequest
|
||||
? AccountTxVersionResponseMap<Version>
|
||||
: T extends GatewayBalancesRequest
|
||||
? GatewayBalancesResponse
|
||||
: T extends NoRippleCheckRequest
|
||||
? NoRippleCheckResponse
|
||||
: // NOTE: The order of these LedgerRequest types is important
|
||||
// to get the proper type matching overrides based on parameters set
|
||||
// in the request. For example LedgerRequestExpandedTransactionsBinary
|
||||
// should match LedgerRequestExpandedTransactionsOnly, but not
|
||||
// LedgerRequestExpandedAccountsOnly. This is because the
|
||||
// LedgerRequestExpandedTransactionsBinary type is a superset of
|
||||
// LedgerRequestExpandedTransactionsOnly, but not of the other.
|
||||
// This is why LedgerRequestExpandedTransactionsBinary is listed
|
||||
// first in the type list.
|
||||
//
|
||||
// Here is an example using real data:
|
||||
// LedgerRequestExpandedTransactionsBinary = {
|
||||
// command: 'ledger',
|
||||
// ledger_index: 'validated',
|
||||
// expand: true,
|
||||
// transactions: true,
|
||||
// binary: true,
|
||||
// }
|
||||
// LedgerRequestExpandedTransactionsOnly = {
|
||||
// command: 'ledger',
|
||||
// ledger_index: 'validated',
|
||||
// expand: true,
|
||||
// transactions: true,
|
||||
// }
|
||||
// LedgerRequestExpandedAccountsOnly = {
|
||||
// command: 'ledger',
|
||||
// ledger_index: 'validated',
|
||||
// accounts: true,
|
||||
// expand: true,
|
||||
// }
|
||||
// LedgerRequest = {
|
||||
// command: 'ledger',
|
||||
// ledger_index: 'validated',
|
||||
// }
|
||||
//
|
||||
// The type with the most parameters set should be listed first. In this
|
||||
// case LedgerRequestExpandedTransactionsBinary has the most parameters (`expand`, `transactions`, and `binary`)
|
||||
// set, so it is listed first. When TypeScript tries to match the type of
|
||||
// a request to a response, it will try to match the request type to the
|
||||
// response type in the order they are listed. So, if we have a request
|
||||
// with the following parameters:
|
||||
// {
|
||||
// command: 'ledger',
|
||||
// ledger_index: 'validated',
|
||||
// expand: true,
|
||||
// transactions: true,
|
||||
// binary: true,
|
||||
// }
|
||||
// TypeScript will first try to match the request type to
|
||||
// LedgerRequestExpandedTransactionsBinary, which will succeed. It will
|
||||
// then try to match the response type to LedgerResponseExpanded, which
|
||||
// will also succeed. If we had listed LedgerRequestExpandedTransactionsOnly
|
||||
// first, TypeScript would have tried to match the request type to
|
||||
// LedgerRequestExpandedTransactionsOnly, which would have succeeded, but
|
||||
// then we'd get the wrong response type, LedgerResponse, instead of
|
||||
// LedgerResponseExpanded.
|
||||
T extends LedgerRequestExpandedTransactionsBinary
|
||||
? LedgerVersionResponseMap<Version>
|
||||
: T extends LedgerRequestExpandedAccountsAndTransactions
|
||||
? LedgerResponseExpanded<Version>
|
||||
: T extends LedgerRequestExpandedTransactionsOnly
|
||||
? LedgerResponseExpanded<Version>
|
||||
: T extends LedgerRequestExpandedAccountsOnly
|
||||
? LedgerResponseExpanded<Version>
|
||||
: T extends LedgerRequest
|
||||
? LedgerVersionResponseMap<Version>
|
||||
: T extends LedgerClosedRequest
|
||||
? LedgerClosedResponse
|
||||
: T extends LedgerCurrentRequest
|
||||
? LedgerCurrentResponse
|
||||
: T extends LedgerDataRequest
|
||||
? LedgerDataResponse
|
||||
: T extends LedgerEntryRequest
|
||||
? LedgerEntryResponse
|
||||
: T extends SubmitRequest
|
||||
? SubmitResponse
|
||||
: T extends SubmitMultisignedRequest
|
||||
? SubmitMultisignedVersionResponseMap<Version>
|
||||
: T extends TransactionEntryRequest
|
||||
? TransactionEntryResponse
|
||||
: T extends TxRequest
|
||||
? TxVersionResponseMap<Version>
|
||||
: T extends BookOffersRequest
|
||||
? BookOffersResponse
|
||||
: T extends DepositAuthorizedRequest
|
||||
? DepositAuthorizedResponse
|
||||
: T extends PathFindRequest
|
||||
? PathFindResponse
|
||||
: T extends RipplePathFindRequest
|
||||
? RipplePathFindResponse
|
||||
: T extends ChannelVerifyRequest
|
||||
? ChannelVerifyResponse
|
||||
: T extends SubscribeRequest
|
||||
? SubscribeResponse
|
||||
: T extends UnsubscribeRequest
|
||||
? UnsubscribeResponse
|
||||
: T extends FeeRequest
|
||||
? FeeResponse
|
||||
: T extends ManifestRequest
|
||||
? ManifestResponse
|
||||
: T extends ServerInfoRequest
|
||||
? ServerInfoResponse
|
||||
: T extends ServerStateRequest
|
||||
? ServerStateResponse
|
||||
: T extends ServerDefinitionsRequest
|
||||
? ServerDefinitionsResponse
|
||||
: T extends FeatureAllRequest
|
||||
? FeatureAllResponse
|
||||
: T extends FeatureOneRequest
|
||||
? FeatureOneResponse
|
||||
: T extends PingRequest
|
||||
? PingResponse
|
||||
: T extends RandomRequest
|
||||
? RandomResponse
|
||||
: Response<Version>
|
||||
|
||||
export type MarkerRequest = Request & {
|
||||
limit?: number
|
||||
marker?: unknown
|
||||
}
|
||||
|
||||
export type MarkerResponse<
|
||||
Version extends APIVersion = typeof DEFAULT_API_VERSION,
|
||||
> = Response<Version> & {
|
||||
result: {
|
||||
marker?: unknown
|
||||
}
|
||||
}
|
||||
|
||||
export type RequestAllResponseMap<
|
||||
T,
|
||||
Version extends APIVersion = typeof DEFAULT_API_VERSION,
|
||||
> = T extends AccountChannelsRequest
|
||||
? AccountChannelsResponse
|
||||
: T extends AccountLinesRequest
|
||||
? AccountLinesResponse
|
||||
: T extends AccountObjectsRequest
|
||||
? AccountObjectsResponse
|
||||
: T extends AccountOffersRequest
|
||||
? AccountOffersResponse
|
||||
: T extends AccountTxRequest
|
||||
? AccountTxVersionResponseMap<Version>
|
||||
: T extends LedgerDataRequest
|
||||
? LedgerDataResponse
|
||||
: T extends BookOffersRequest
|
||||
? BookOffersResponse
|
||||
: MarkerResponse<Version>
|
||||
|
||||
export {
|
||||
// Allow users to define their own requests and responses. This is useful for releasing experimental versions
|
||||
BaseRequest,
|
||||
BaseResponse,
|
||||
Request,
|
||||
Response,
|
||||
ResponseWarning,
|
||||
// account methods with types
|
||||
Channel,
|
||||
AccountChannelsRequest,
|
||||
AccountChannelsResponse,
|
||||
AccountCurrenciesRequest,
|
||||
AccountCurrenciesResponse,
|
||||
AccountInfoAccountFlags,
|
||||
AccountInfoRequest,
|
||||
AccountInfoResponse,
|
||||
AccountInfoV1Response,
|
||||
AccountQueueData,
|
||||
AccountQueueTransaction,
|
||||
AccountLinesRequest,
|
||||
AccountLinesResponse,
|
||||
AccountLinesTrustline,
|
||||
AccountObject,
|
||||
AccountObjectType,
|
||||
AccountObjectsRequest,
|
||||
AccountObjectsResponse,
|
||||
AccountOffer,
|
||||
AccountOffersRequest,
|
||||
AccountOffersResponse,
|
||||
AccountTxRequest,
|
||||
AccountTxResponse,
|
||||
AccountTxV1Response,
|
||||
AccountTxTransaction,
|
||||
GatewayBalance,
|
||||
GatewayBalancesRequest,
|
||||
GatewayBalancesResponse,
|
||||
NoRippleCheckRequest,
|
||||
NoRippleCheckResponse,
|
||||
// ledger methods
|
||||
LedgerRequest,
|
||||
LedgerResponse,
|
||||
LedgerV1Response,
|
||||
LedgerQueueData,
|
||||
LedgerBinary,
|
||||
LedgerModifiedOfferCreateTransaction,
|
||||
LedgerClosedRequest,
|
||||
LedgerClosedResponse,
|
||||
LedgerCurrentRequest,
|
||||
LedgerCurrentResponse,
|
||||
LedgerDataRequest,
|
||||
LedgerDataLabeledLedgerEntry,
|
||||
LedgerDataBinaryLedgerEntry,
|
||||
LedgerDataResponse,
|
||||
LedgerDataLedgerState,
|
||||
LedgerEntryRequest,
|
||||
LedgerEntryResponse,
|
||||
// transaction methods with types
|
||||
SubmitRequest,
|
||||
SubmitResponse,
|
||||
SubmitMultisignedRequest,
|
||||
SubmitMultisignedResponse,
|
||||
SubmitMultisignedV1Response,
|
||||
TransactionEntryRequest,
|
||||
TransactionEntryResponse,
|
||||
TxRequest,
|
||||
TxResponse,
|
||||
TxV1Response,
|
||||
// path and order book methods with types
|
||||
BookOffersRequest,
|
||||
BookOffer,
|
||||
BookOfferCurrency,
|
||||
BookOffersResponse,
|
||||
DepositAuthorizedRequest,
|
||||
DepositAuthorizedResponse,
|
||||
PathFindRequest,
|
||||
PathFindCreateRequest,
|
||||
PathFindCloseRequest,
|
||||
PathFindPathOption,
|
||||
PathFindStatusRequest,
|
||||
PathFindResponse,
|
||||
RipplePathFindPathOption,
|
||||
RipplePathFindRequest,
|
||||
RipplePathFindResponse,
|
||||
SourceCurrencyAmount,
|
||||
// payment channel methods
|
||||
ChannelVerifyRequest,
|
||||
ChannelVerifyResponse,
|
||||
// Subscribe methods/streams with types
|
||||
SubscribeRequest,
|
||||
SubscribeResponse,
|
||||
SubscribeBook,
|
||||
Stream,
|
||||
BooksSnapshot,
|
||||
LedgerStream,
|
||||
LedgerStreamResponse,
|
||||
ValidationStream,
|
||||
TransactionStream,
|
||||
TransactionV1Stream,
|
||||
PathFindStream,
|
||||
PeerStatusStream,
|
||||
OrderBookStream,
|
||||
ConsensusStream,
|
||||
UnsubscribeRequest,
|
||||
UnsubscribeResponse,
|
||||
UnsubscribeBook,
|
||||
// server info methods with types
|
||||
FeeRequest,
|
||||
FeeResponse,
|
||||
ManifestRequest,
|
||||
ManifestResponse,
|
||||
ServerDefinitionsRequest,
|
||||
ServerDefinitionsResponse,
|
||||
ServerInfoRequest,
|
||||
ServerInfoResponse,
|
||||
ServerStateRequest,
|
||||
ServerStateResponse,
|
||||
JobType,
|
||||
ServerState,
|
||||
StateAccountingFinal,
|
||||
StateAccounting,
|
||||
FeatureRequest,
|
||||
FeatureResponse,
|
||||
// utility methods
|
||||
PingRequest,
|
||||
PingResponse,
|
||||
RandomRequest,
|
||||
RandomResponse,
|
||||
ErrorResponse,
|
||||
}
|
||||
295
packages/xahau/src/models/methods/ledger.ts
Normal file
295
packages/xahau/src/models/methods/ledger.ts
Normal file
@@ -0,0 +1,295 @@
|
||||
import { APIVersion, DEFAULT_API_VERSION, XAHAUD_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'
|
||||
|
||||
import { BaseRequest, BaseResponse, LookupByLedgerRequest } from './baseMethod'
|
||||
|
||||
/**
|
||||
* Retrieve information about the public ledger. Expects a response in the form
|
||||
* of a {@link LedgerResponse}.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const ledger: LedgerRequest = {
|
||||
* "id": 14,
|
||||
* "command": "ledger",
|
||||
* "ledger_index": "validated",
|
||||
* "full": false,
|
||||
* "accounts": false,
|
||||
* "transactions": false,
|
||||
* "expand": false,
|
||||
* "owner_funds": false
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @category Requests
|
||||
*/
|
||||
export interface LedgerRequest extends BaseRequest, LookupByLedgerRequest {
|
||||
command: 'ledger'
|
||||
/**
|
||||
* Admin required If true, return full information on the entire ledger.
|
||||
* Ignored if you did not specify a ledger version. Defaults to false.
|
||||
*/
|
||||
full?: boolean
|
||||
/**
|
||||
* Admin required. If true, return information on accounts in the ledger.
|
||||
* Ignored if you did not specify a ledger version. Defaults to false.
|
||||
*/
|
||||
accounts?: boolean
|
||||
/**
|
||||
* If true, return information on transactions in the specified ledger
|
||||
* version. Defaults to false. Ignored if you did not specify a ledger
|
||||
* version.
|
||||
*/
|
||||
transactions?: boolean
|
||||
/**
|
||||
* Provide full JSON-formatted information for transaction/account
|
||||
* information instead of only hashes. Defaults to false. Ignored unless you
|
||||
* request transactions, accounts, or both.
|
||||
*/
|
||||
expand?: boolean
|
||||
/**
|
||||
* If true, include owner_funds field in the metadata of OfferCreate
|
||||
* transactions in the response. Defaults to false. Ignored unless
|
||||
* transactions are included and expand is true.
|
||||
*/
|
||||
owner_funds?: boolean
|
||||
/**
|
||||
* If true, and transactions and expand are both also true, return
|
||||
* transaction information in binary format (hexadecimal string) instead of
|
||||
* JSON format.
|
||||
*/
|
||||
binary?: boolean
|
||||
/**
|
||||
* If true, and the command is requesting the current ledger, includes an
|
||||
* array of queued transactions in the results.
|
||||
*/
|
||||
queue?: boolean
|
||||
/**
|
||||
* If included, filter results to include only this type of ledger object.
|
||||
*/
|
||||
type?: LedgerEntryFilter
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve information about the public ledger. Expects a response in the form
|
||||
* of a {@link LedgerResponseExpanded}. Will return full JSON-formatted transaction data instead of string hashes.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const ledger: LedgerRequest = {
|
||||
* "id": 14,
|
||||
* "command": "ledger",
|
||||
* "ledger_index": "validated",
|
||||
* "full": false,
|
||||
* "accounts": false,
|
||||
* "transactions": false,
|
||||
* "expand": true,
|
||||
* "owner_funds": false
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @category Requests
|
||||
*/
|
||||
export interface LedgerRequestExpandedTransactionsOnly extends LedgerRequest {
|
||||
expand: true
|
||||
transactions: true
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve information about the public ledger. Expects a response in the form
|
||||
* of a {@link LedgerResponseExpanded}. Will return full JSON-formatted `accountState` data instead of string hashes.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const ledger: LedgerRequest = {
|
||||
* "id": 14,
|
||||
* "command": "ledger",
|
||||
* "ledger_index": "validated",
|
||||
* "full": false,
|
||||
* "accounts": true,
|
||||
* "transactions": false,
|
||||
* "expand": true,
|
||||
* "owner_funds": false
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @category Requests
|
||||
*/
|
||||
export interface LedgerRequestExpandedAccountsOnly extends LedgerRequest {
|
||||
expand: true
|
||||
accounts: true
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve information about the public ledger. Expects a response in the form
|
||||
* of a {@link LedgerResponseExpanded}. Will return full JSON-formatted `accountState` and `transactions`
|
||||
* data instead of string hashes.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const ledger: LedgerRequest = {
|
||||
* "id": 14,
|
||||
* "command": "ledger",
|
||||
* "ledger_index": "validated",
|
||||
* "full": false,
|
||||
* "accounts": true,
|
||||
* "transactions": true,
|
||||
* "expand": true,
|
||||
* "owner_funds": false
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @category Requests
|
||||
*/
|
||||
export interface LedgerRequestExpandedAccountsAndTransactions
|
||||
extends LedgerRequest {
|
||||
expand: true
|
||||
accounts: true
|
||||
transactions: true
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve information about the public ledger. Expects a response in the form
|
||||
* of a {@link LedgerResponse}. Will return binary (hexadecimal string) format
|
||||
* instead of JSON or string hashes for `transactions` data.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const ledger: LedgerRequest = {
|
||||
* "id": 14,
|
||||
* "command": "ledger",
|
||||
* "ledger_index": "validated",
|
||||
* "full": false,
|
||||
* "accounts": true,
|
||||
* "transactions": true,
|
||||
* "expand": true,
|
||||
* "owner_funds": false,
|
||||
* "binary": true
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @category Requests
|
||||
*/
|
||||
export interface LedgerRequestExpandedTransactionsBinary extends LedgerRequest {
|
||||
expand: true
|
||||
transactions: true
|
||||
binary: true
|
||||
}
|
||||
|
||||
/**
|
||||
* Special case transaction definition when the request contains `owner_funds: true`.
|
||||
*/
|
||||
export interface LedgerModifiedOfferCreateTransaction {
|
||||
transaction: Transaction
|
||||
metadata: TransactionMetadata & { owner_funds: string }
|
||||
}
|
||||
|
||||
export interface LedgerQueueData {
|
||||
account: string
|
||||
tx:
|
||||
| TransactionAndMetadata
|
||||
| LedgerModifiedOfferCreateTransaction
|
||||
| { tx_blob: string }
|
||||
retries_remaining: number
|
||||
preflight_result: string
|
||||
last_result?: string
|
||||
auth_change?: boolean
|
||||
fee?: string
|
||||
fee_level?: string
|
||||
max_spend_drops?: string
|
||||
}
|
||||
|
||||
export interface LedgerBinary
|
||||
extends Omit<Omit<Ledger, 'transactions'>, 'accountState'> {
|
||||
accountState?: string[]
|
||||
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
|
||||
/** The Ledger Index of this ledger. */
|
||||
ledger_index: number
|
||||
/**
|
||||
* If true, this is a validated ledger version. If omitted or set to false,
|
||||
* this ledger's data is not final.
|
||||
*/
|
||||
queue_data?: Array<LedgerQueueData | string>
|
||||
/**
|
||||
* Array of objects describing queued transactions, in the same order as
|
||||
* the queue. If the request specified expand as true, members contain full
|
||||
* representations of the transactions, in either JSON or binary depending
|
||||
* on whether the request specified binary as true.
|
||||
*/
|
||||
validated?: boolean
|
||||
}
|
||||
|
||||
interface LedgerResponseResult extends LedgerResponseBase {
|
||||
/** The complete header data of this {@link Ledger}. */
|
||||
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.
|
||||
*
|
||||
* @category Responses
|
||||
*/
|
||||
export interface LedgerResponse extends BaseResponse {
|
||||
result: LedgerResponseResult
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 XAHAUD_API_V1 ? LedgerV1Response : LedgerResponse
|
||||
|
||||
interface LedgerResponseExpandedResult<
|
||||
Version extends APIVersion = typeof DEFAULT_API_VERSION,
|
||||
> extends LedgerResponseBase {
|
||||
/** The complete header data of this {@link Ledger}. */
|
||||
ledger: LedgerVersionMap<Version>
|
||||
}
|
||||
|
||||
/**
|
||||
* Response expected from a {@link LedgerRequest} when the request contains `expanded` is true. See {@link LedgerRequestExpanded}.
|
||||
* This response will contain full JSON-formatted data instead of string hashes.
|
||||
* The response will contain either `accounts` or `transactions` or both.
|
||||
* `binary` will be missing altogether.
|
||||
*
|
||||
* @category Responses
|
||||
*/
|
||||
export interface LedgerResponseExpanded<
|
||||
Version extends APIVersion = typeof DEFAULT_API_VERSION,
|
||||
> extends BaseResponse {
|
||||
result: LedgerResponseExpandedResult<Version>
|
||||
}
|
||||
32
packages/xahau/src/models/methods/ledgerClosed.ts
Normal file
32
packages/xahau/src/models/methods/ledgerClosed.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import { BaseRequest, BaseResponse } from './baseMethod'
|
||||
|
||||
/**
|
||||
* The ledger_closed method returns the unique identifiers of the most recently
|
||||
* closed ledger. Expects a response in the form of a {@link
|
||||
* LedgerClosedResponse}.
|
||||
*
|
||||
* @example
|
||||
* *
|
||||
* ```ts
|
||||
* const ledgerClosed: LedgerClosedRequest = {
|
||||
* "command": "ledger_closed"
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @category Requests
|
||||
*/
|
||||
export interface LedgerClosedRequest extends BaseRequest {
|
||||
command: 'ledger_closed'
|
||||
}
|
||||
|
||||
/**
|
||||
* The response expected from a {@link LedgerClosedRequest}.
|
||||
*
|
||||
* @category Responses
|
||||
*/
|
||||
export interface LedgerClosedResponse extends BaseResponse {
|
||||
result: {
|
||||
ledger_hash: string
|
||||
ledger_index: number
|
||||
}
|
||||
}
|
||||
31
packages/xahau/src/models/methods/ledgerCurrent.ts
Normal file
31
packages/xahau/src/models/methods/ledgerCurrent.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import { BaseRequest, BaseResponse } from './baseMethod'
|
||||
|
||||
/**
|
||||
* The ledger_current method returns the unique identifiers of the current
|
||||
* in-progress ledger. Expects a response in the form of a {@link
|
||||
* LedgerCurrentResponse}.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const ledgerCurrent: LedgerCurrentRequest = {
|
||||
* "command": "ledger_current"
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @category Requests
|
||||
*/
|
||||
export interface LedgerCurrentRequest extends BaseRequest {
|
||||
command: 'ledger_current'
|
||||
}
|
||||
|
||||
/**
|
||||
* Response expected from a {@link LedgerCurrentRequest}.
|
||||
*
|
||||
* @category Responses
|
||||
*/
|
||||
export interface LedgerCurrentResponse extends BaseResponse {
|
||||
result: {
|
||||
/** The ledger index of this ledger version. */
|
||||
ledger_current_index: number
|
||||
}
|
||||
}
|
||||
82
packages/xahau/src/models/methods/ledgerData.ts
Normal file
82
packages/xahau/src/models/methods/ledgerData.ts
Normal file
@@ -0,0 +1,82 @@
|
||||
import { LedgerEntry, LedgerEntryFilter } from '../ledger'
|
||||
|
||||
import { BaseRequest, BaseResponse, LookupByLedgerRequest } from './baseMethod'
|
||||
|
||||
/**
|
||||
* The `ledger_data` method retrieves contents of the specified ledger. You can
|
||||
* iterate through several calls to retrieve the entire contents of a single
|
||||
* ledger version.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const ledgerData: LedgerDataRequest = {
|
||||
* "id": 2,
|
||||
* "ledger_hash": "842B57C1CC0613299A686D3E9F310EC0422C84D3911E5056389AA7E5808A93C8",
|
||||
* "command": "ledger_data",
|
||||
* "limit": 5,
|
||||
* "binary": true
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @category Requests
|
||||
*/
|
||||
export interface LedgerDataRequest extends BaseRequest, LookupByLedgerRequest {
|
||||
command: 'ledger_data'
|
||||
/**
|
||||
* If set to true, return ledger objects as hashed hex strings instead of
|
||||
* JSON.
|
||||
*/
|
||||
binary?: boolean
|
||||
/**
|
||||
* Limit the number of ledger objects to retrieve. The server is not required
|
||||
* to honor this value.
|
||||
*/
|
||||
limit?: number
|
||||
/**
|
||||
* Value from a previous paginated response. Resume retrieving data where
|
||||
* that response left off.
|
||||
*/
|
||||
marker?: unknown
|
||||
/**
|
||||
* If included, filter results to include only this type of ledger object.
|
||||
*/
|
||||
type?: LedgerEntryFilter
|
||||
}
|
||||
|
||||
export type LedgerDataLabeledLedgerEntry = {
|
||||
ledgerEntryType: string
|
||||
} & LedgerEntry
|
||||
|
||||
export interface LedgerDataBinaryLedgerEntry {
|
||||
data: string
|
||||
}
|
||||
|
||||
export type LedgerDataLedgerState = { index: string } & (
|
||||
| LedgerDataBinaryLedgerEntry
|
||||
| LedgerDataLabeledLedgerEntry
|
||||
)
|
||||
|
||||
/**
|
||||
* The response expected from a {@link LedgerDataRequest}.
|
||||
*
|
||||
* @category Responses
|
||||
*/
|
||||
export interface LedgerDataResponse extends BaseResponse {
|
||||
result: {
|
||||
/** The ledger index of this ledger version. */
|
||||
ledger_index: number
|
||||
/** Unique identifying hash of this ledger version. */
|
||||
ledger_hash: string
|
||||
/**
|
||||
* Array of JSON objects containing data from the ledger's state tree,
|
||||
* as defined below.
|
||||
*/
|
||||
state: LedgerDataLedgerState[]
|
||||
/**
|
||||
* Server-defined value indicating the response is paginated. Pass this to
|
||||
* the next call to resume where this call left off.
|
||||
*/
|
||||
marker?: unknown
|
||||
validated?: boolean
|
||||
}
|
||||
}
|
||||
219
packages/xahau/src/models/methods/ledgerEntry.ts
Normal file
219
packages/xahau/src/models/methods/ledgerEntry.ts
Normal file
@@ -0,0 +1,219 @@
|
||||
import { Currency, XChainBridge } from '../common'
|
||||
import { LedgerEntry } from '../ledger'
|
||||
|
||||
import { BaseRequest, BaseResponse, LookupByLedgerRequest } from './baseMethod'
|
||||
|
||||
/**
|
||||
* The `ledger_entry` method returns a single ledger object from the XAH Ledger
|
||||
* in its raw format. Expects a response in the form of a {@link
|
||||
* LedgerEntryResponse}.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const ledgerEntry: LedgerEntryRequest = {
|
||||
* command: "ledger_entry",
|
||||
* ledger_index: 60102302,
|
||||
* index: "7DB0788C020F02780A673DC74757F23823FA3014C1866E72CC4CD8B226CD6EF4"
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @category Requests
|
||||
*/
|
||||
export interface LedgerEntryRequest extends BaseRequest, LookupByLedgerRequest {
|
||||
command: 'ledger_entry'
|
||||
/**
|
||||
* Retrieve an Automated Market Maker (AMM) object from the ledger.
|
||||
* This is similar to amm_info method, but the ledger_entry version returns only the ledger entry as stored.
|
||||
*/
|
||||
amm?: {
|
||||
asset: {
|
||||
currency: string
|
||||
issuer?: string
|
||||
}
|
||||
asset2: {
|
||||
currency: string
|
||||
issuer?: string
|
||||
}
|
||||
}
|
||||
/**
|
||||
* (Optional) If set to true and the queried object has been deleted,
|
||||
* return its complete data prior to its deletion.
|
||||
* If set to false or not provided and the queried object has been deleted,
|
||||
* return objectNotFound (current behavior).
|
||||
* This parameter is supported only by Clio servers
|
||||
*/
|
||||
include_deleted?: boolean
|
||||
/**
|
||||
* If true, return the requested ledger object's contents as a hex string in
|
||||
* the XAH Ledger's binary format. Otherwise, return data in JSON format. The
|
||||
* default is false.
|
||||
*/
|
||||
binary?: boolean
|
||||
|
||||
/*
|
||||
* Only one of the following properties should be defined in a single request
|
||||
* https://xrpl.org/ledger_entry.html.
|
||||
*
|
||||
* Retrieve any type of ledger object by its unique ID.
|
||||
*/
|
||||
index?: string
|
||||
|
||||
/**
|
||||
* Retrieve an AccountRoot object by its address. This is roughly equivalent
|
||||
* to the an {@link AccountInfoRequest}.
|
||||
*/
|
||||
account_root?: string
|
||||
|
||||
/** The object ID of a Check object to retrieve. */
|
||||
check?: string
|
||||
|
||||
/**
|
||||
* Specify a DepositPreauth object to retrieve. If a string, must be the
|
||||
* object ID of the DepositPreauth object, as hexadecimal. If an object,
|
||||
* requires owner and authorized sub-fields.
|
||||
*/
|
||||
deposit_preauth?:
|
||||
| {
|
||||
/** The account that provided the preauthorization. */
|
||||
owner: string
|
||||
/** The account that received the preauthorization. */
|
||||
authorized: string
|
||||
}
|
||||
| string
|
||||
|
||||
/**
|
||||
* Specify a DID object to retrieve. If a string, must be the
|
||||
* object ID of the DID object, as hexadecimal, or the account ID.
|
||||
*/
|
||||
did?: string
|
||||
|
||||
/**
|
||||
* The DirectoryNode to retrieve. If a string, must be the object ID of the
|
||||
* directory, as hexadecimal. If an object, requires either `dir_root` o
|
||||
* Owner as a sub-field, plus optionally a `sub_index` sub-field.
|
||||
*/
|
||||
directory?:
|
||||
| {
|
||||
/** If provided, jumps to a later "page" of the DirectoryNode. */
|
||||
sub_index?: number
|
||||
/** Unique index identifying the directory to retrieve, as a hex string. */
|
||||
dir_root?: string
|
||||
/** Unique address of the account associated with this directory. */
|
||||
owner?: string
|
||||
}
|
||||
| string
|
||||
|
||||
/**
|
||||
* The Escrow object to retrieve. If a string, must be the object ID of the
|
||||
* escrow, as hexadecimal. If an object, requires owner and seq sub-fields.
|
||||
*/
|
||||
escrow?:
|
||||
| {
|
||||
/** The owner (sender) of the Escrow object. */
|
||||
owner: string
|
||||
/** Sequence Number of the transaction that created the Escrow object. */
|
||||
seq: number
|
||||
}
|
||||
| string
|
||||
|
||||
/**
|
||||
* The Offer object to retrieve. If a string, interpret as the unique object
|
||||
* ID to the Offer. If an object, requires the sub-fields `account` and `seq`
|
||||
* to uniquely identify the offer.
|
||||
*/
|
||||
offer?:
|
||||
| {
|
||||
/** The account that placed the offer. */
|
||||
account: string
|
||||
/** Sequence Number of the transaction that created the Offer object. */
|
||||
seq: number
|
||||
}
|
||||
| string
|
||||
|
||||
/** The object ID of a PayChannel object to retrieve. */
|
||||
payment_channel?: string
|
||||
|
||||
/**
|
||||
* Object specifying the RippleState (trust line) object to retrieve. The
|
||||
* accounts and currency sub-fields are required to uniquely specify the
|
||||
* rippleState entry to retrieve.
|
||||
*/
|
||||
ripple_state?: {
|
||||
/**
|
||||
* 2-length array of account Addresses, defining the two accounts linked by
|
||||
* this RippleState object.
|
||||
*/
|
||||
accounts: string[]
|
||||
/** Currency Code of the RippleState object to retrieve. */
|
||||
currency: string
|
||||
}
|
||||
|
||||
/**
|
||||
* The Ticket object to retrieve. If a string, must be the object ID of the
|
||||
* Ticket, as hexadecimal. If an object, the `owner` and `ticket_sequence`
|
||||
* sub-fields are required to uniquely specify the Ticket entry.
|
||||
*/
|
||||
ticket?:
|
||||
| {
|
||||
/** The owner of the Ticket object. */
|
||||
owner: string
|
||||
/** The Ticket Sequence number of the Ticket entry to retrieve. */
|
||||
ticket_sequence: number
|
||||
}
|
||||
| string
|
||||
|
||||
/**
|
||||
* Must be the object ID of the NFToken page, as hexadecimal
|
||||
*/
|
||||
nft_page?: string
|
||||
|
||||
bridge_account?: string
|
||||
|
||||
bridge?: XChainBridge
|
||||
|
||||
xchain_owned_claim_id?:
|
||||
| {
|
||||
locking_chain_door: string
|
||||
locking_chain_issue: Currency
|
||||
issuing_chain_door: string
|
||||
issuing_chain_issue: Currency
|
||||
xchain_owned_claim_id: string | number
|
||||
}
|
||||
| string
|
||||
|
||||
xchain_owned_create_account_claim_id?:
|
||||
| {
|
||||
locking_chain_door: string
|
||||
locking_chain_issue: Currency
|
||||
issuing_chain_door: string
|
||||
issuing_chain_issue: Currency
|
||||
xchain_owned_create_account_claim_id: string | number
|
||||
}
|
||||
| string
|
||||
}
|
||||
|
||||
/**
|
||||
* Response expected from a {@link LedgerEntryRequest}.
|
||||
*
|
||||
* @category Responses
|
||||
*/
|
||||
export interface LedgerEntryResponse<T = LedgerEntry> extends BaseResponse {
|
||||
result: {
|
||||
/** The unique ID of this ledger object. */
|
||||
index: string
|
||||
/** The ledger index of the ledger that was used when retrieving this data. */
|
||||
ledger_current_index: number
|
||||
/**
|
||||
* Object containing the data of this ledger object, according to the
|
||||
* ledger format.
|
||||
*/
|
||||
node?: T
|
||||
/** The binary representation of the ledger object, as hexadecimal. */
|
||||
node_binary?: string
|
||||
validated?: boolean
|
||||
/**
|
||||
* (Optional) Indicates the ledger index at which the object was deleted.
|
||||
*/
|
||||
deleted_ledger_index?: number
|
||||
}
|
||||
}
|
||||
54
packages/xahau/src/models/methods/manifest.ts
Normal file
54
packages/xahau/src/models/methods/manifest.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
import { BaseRequest, BaseResponse } from './baseMethod'
|
||||
|
||||
/**
|
||||
* The `manifest` method reports the current "manifest" information for a given
|
||||
* validator public key. The "manifest" is the public portion of that
|
||||
* validator's configured token. Expects a response in the form of a {@link
|
||||
* ManifestResponse}.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const manifest: ManifestRequest = {
|
||||
* "command": "manifest",
|
||||
* "public_key": "nHUFE9prPXPrHcG3SkwP1UzAQbSphqyQkQK9ATXLZsfkezhhda3p"
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @category Requests
|
||||
*/
|
||||
export interface ManifestRequest extends BaseRequest {
|
||||
command: 'manifest'
|
||||
/**
|
||||
* The base58-encoded public key of the validator to look up. This can be the
|
||||
* master public key or ephemeral public key.
|
||||
*/
|
||||
public_key: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Response expected from a {@link ManifestRequest}.
|
||||
*
|
||||
* @category Responses
|
||||
*/
|
||||
export interface ManifestResponse extends BaseResponse {
|
||||
result: {
|
||||
/**
|
||||
* The data contained in this manifest. Omitted if the server does not have
|
||||
* A manifest for the public_key from the request.
|
||||
*/
|
||||
details?: {
|
||||
domain: string
|
||||
ephemeral_key: string
|
||||
master_key: string
|
||||
seq: number
|
||||
}
|
||||
/**
|
||||
* The full manifest data in base64 format. This data is serialized to
|
||||
* binary before being base64-encoded. Omitted if the server does not have a
|
||||
* manifest for the public_key from the request.
|
||||
*/
|
||||
manifest?: string
|
||||
/** The public_key from the request. */
|
||||
requested: string
|
||||
}
|
||||
}
|
||||
82
packages/xahau/src/models/methods/norippleCheck.ts
Normal file
82
packages/xahau/src/models/methods/norippleCheck.ts
Normal file
@@ -0,0 +1,82 @@
|
||||
import { LedgerIndex, ResponseOnlyTxInfo } from '../common'
|
||||
import { Transaction } from '../transactions'
|
||||
|
||||
import { BaseRequest, BaseResponse } from './baseMethod'
|
||||
|
||||
/**
|
||||
* The `noripple_check` command provides a quick way to check the status of th
|
||||
* default xahau field for an account and the No Ripple flag of its trust
|
||||
* lines, compared with the recommended settings. Expects a response in the form
|
||||
* of an {@link NoRippleCheckResponse}.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const noRipple: NoRippleCheckRequest = {
|
||||
* "id": 0,
|
||||
* "command": "noripple_check",
|
||||
* "account": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59",
|
||||
* "role": "gateway",
|
||||
* "ledger_index": "current",
|
||||
* "limit": 2,
|
||||
* "transactions": true
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @category Requests
|
||||
*/
|
||||
export interface NoRippleCheckRequest extends BaseRequest {
|
||||
command: 'noripple_check'
|
||||
/** A unique identifier for the account, most commonly the account's address. */
|
||||
account: string
|
||||
/**
|
||||
* Whether the address refers to a gateway or user. Recommendations depend on
|
||||
* the role of the account. Issuers must have Default Ripple enabled and must
|
||||
* disable No Ripple on all trust lines. Users should have Default Ripple
|
||||
* disabled, and should enable No Ripple on all trust lines.
|
||||
*/
|
||||
role: 'gateway' | 'user'
|
||||
/**
|
||||
* If true, include an array of suggested transactions, as JSON objects,
|
||||
* that you can sign and submit to fix the problems. Defaults to false.
|
||||
*/
|
||||
transactions?: boolean
|
||||
/**
|
||||
* The maximum number of trust line problems to include in the results.
|
||||
* Defaults to 300.
|
||||
*/
|
||||
limit?: number
|
||||
/** A 20-byte hex string for the ledger version to use. */
|
||||
ledger_hash?: string
|
||||
/**
|
||||
* The ledger index of the ledger to use, or a shortcut string to choose a
|
||||
* ledger automatically.
|
||||
*/
|
||||
ledger_index?: LedgerIndex
|
||||
}
|
||||
|
||||
/**
|
||||
* Response expected by a {@link NoRippleCheckRequest}.
|
||||
*
|
||||
* @category Responses
|
||||
*/
|
||||
export interface NoRippleCheckResponse extends BaseResponse {
|
||||
result: {
|
||||
/** The ledger index of the ledger used to calculate these results. */
|
||||
ledger_current_index: number
|
||||
/**
|
||||
* Array of strings with human-readable descriptions of the problems.
|
||||
* This includes up to one entry if the account's Default Ripple setting is
|
||||
* not as recommended, plus up to limit entries for trust lines whose no
|
||||
* xahau setting is not as recommended.
|
||||
*/
|
||||
problems: string[]
|
||||
/**
|
||||
* If the request specified transactions as true, this is an array of JSON
|
||||
* objects, each of which is the JSON form of a transaction that should fix
|
||||
* one of the described problems. The length of this array is the same as
|
||||
* the problems array, and each entry is intended to fix the problem
|
||||
* described at the same index into that array.
|
||||
*/
|
||||
transactions: Array<Transaction & ResponseOnlyTxInfo>
|
||||
}
|
||||
}
|
||||
116
packages/xahau/src/models/methods/pathFind.ts
Normal file
116
packages/xahau/src/models/methods/pathFind.ts
Normal file
@@ -0,0 +1,116 @@
|
||||
import { Amount, Path } from '../common'
|
||||
|
||||
import { BaseRequest, BaseResponse } from './baseMethod'
|
||||
|
||||
interface BasePathFindRequest extends BaseRequest {
|
||||
command: 'path_find'
|
||||
subcommand: string
|
||||
}
|
||||
|
||||
/** Start sending pathfinding information. */
|
||||
export interface PathFindCreateRequest extends BasePathFindRequest {
|
||||
subcommand: 'create'
|
||||
/**
|
||||
* Unique address of the account to find a path from. In other words, the.
|
||||
* Account that would be sending a payment.
|
||||
*/
|
||||
source_account: string
|
||||
/** Unique address of the account to find a path to. */
|
||||
destination_account: string
|
||||
/**
|
||||
* Currency Amount that the destination account would receive in a
|
||||
* transaction.
|
||||
*/
|
||||
destination_amount: Amount
|
||||
/** Currency amount that would be spent in the transaction. */
|
||||
send_max?: Amount
|
||||
/**
|
||||
* Array of arrays of objects, representing payment paths to check. You can
|
||||
* use this to keep updated on changes to particular paths you already know
|
||||
* about, or to check the overall cost to make a payment along a certain path.
|
||||
*/
|
||||
paths?: Path[]
|
||||
}
|
||||
|
||||
/** Stop sending pathfinding information. */
|
||||
export interface PathFindCloseRequest extends BasePathFindRequest {
|
||||
subcommand: 'close'
|
||||
}
|
||||
|
||||
/** Get the information of the currently-open pathfinding request. */
|
||||
export interface PathFindStatusRequest extends BasePathFindRequest {
|
||||
subcommand: 'status'
|
||||
}
|
||||
|
||||
/**
|
||||
* The `path_find` method searches for a path along which a transaction can
|
||||
* possibly be made, and periodically sends updates when the path changes over
|
||||
* time. For a simpler version that is supported by JSON-RPC, see the
|
||||
* `ripple_path_find` method.
|
||||
*
|
||||
* @category Requests
|
||||
*/
|
||||
export type PathFindRequest =
|
||||
| PathFindCreateRequest
|
||||
| PathFindCloseRequest
|
||||
| PathFindStatusRequest
|
||||
|
||||
export interface PathFindPathOption {
|
||||
/** Array of arrays of objects defining payment paths. */
|
||||
paths_computed: Path[]
|
||||
/**
|
||||
* Currency Amount that the source would have to send along this path for the.
|
||||
* Destination to receive the desired amount.
|
||||
*/
|
||||
source_amount: Amount
|
||||
/**
|
||||
* Destination Amount that the destination would receive along this path.
|
||||
* If the `send_max` field is set, this field will be set.
|
||||
*/
|
||||
destination_amount?: Amount
|
||||
}
|
||||
|
||||
/**
|
||||
* Response expected from a {@link PathFindRequest}.
|
||||
*
|
||||
* @category Responses
|
||||
*/
|
||||
export interface PathFindResponse extends BaseResponse {
|
||||
result: {
|
||||
/**
|
||||
* Array of objects with suggested paths to take, as described below. If
|
||||
* empty, then no paths were found connecting the source and destination
|
||||
* accounts.
|
||||
*/
|
||||
alternatives: PathFindPathOption[]
|
||||
/** Unique address of the account that would receive a transaction. */
|
||||
destination_account: string
|
||||
/** Currency amount provided in the WebSocket request. */
|
||||
destination_amount: Amount
|
||||
/** Unique address that would send a transaction. */
|
||||
source_account: string
|
||||
/**
|
||||
* If false, this is the result of an incomplete search. A later reply
|
||||
* may have a better path. If true, then this is the best path found. (It is
|
||||
* still theoretically possible that a better path could exist, but xahaud
|
||||
* won't find it.) Until you close the pathfinding request, xahaud.
|
||||
* Continues to send updates each time a new ledger closes.
|
||||
*/
|
||||
full_reply: boolean
|
||||
/**
|
||||
* The ID provided in the WebSocket request is included again at this
|
||||
* level.
|
||||
*/
|
||||
id?: number | string
|
||||
/**
|
||||
* The value true indicates this reply is in response to a path_find close
|
||||
* command.
|
||||
*/
|
||||
closed?: true
|
||||
/**
|
||||
* The value true indicates this reply is in response to a `path_find`
|
||||
* status command.
|
||||
*/
|
||||
status?: true
|
||||
}
|
||||
}
|
||||
21
packages/xahau/src/models/methods/ping.ts
Normal file
21
packages/xahau/src/models/methods/ping.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import type { BaseRequest, BaseResponse } from './baseMethod'
|
||||
|
||||
/**
|
||||
* The ping command returns an acknowledgement, so that clients can test the
|
||||
* connection status and latency. Expects a response in the form of a {@link
|
||||
* PingResponse}.
|
||||
*
|
||||
* @category Requests
|
||||
*/
|
||||
export interface PingRequest extends BaseRequest {
|
||||
command: 'ping'
|
||||
}
|
||||
|
||||
/**
|
||||
* Response expected from a {@link PingRequest}.
|
||||
*
|
||||
* @category Responses
|
||||
*/
|
||||
export interface PingResponse extends BaseResponse {
|
||||
result: { role?: string; unlimited?: boolean }
|
||||
}
|
||||
23
packages/xahau/src/models/methods/random.ts
Normal file
23
packages/xahau/src/models/methods/random.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { BaseRequest, BaseResponse } from './baseMethod'
|
||||
|
||||
/**
|
||||
* The random command provides a random number to be used as a source of
|
||||
* entropy for random number generation by clients. Expects a response in the
|
||||
* form of a {@link RandomResponse}.
|
||||
*
|
||||
* @category Requests
|
||||
*/
|
||||
export interface RandomRequest extends BaseRequest {
|
||||
command: 'random'
|
||||
}
|
||||
|
||||
/**
|
||||
* Response expected from a {@link RandomRequest}.
|
||||
*
|
||||
* @category Responses
|
||||
*/
|
||||
export interface RandomResponse extends BaseResponse {
|
||||
result: {
|
||||
random: string
|
||||
}
|
||||
}
|
||||
81
packages/xahau/src/models/methods/ripplePathFind.ts
Normal file
81
packages/xahau/src/models/methods/ripplePathFind.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
import { Amount, Path } from '../common'
|
||||
|
||||
import { BaseRequest, BaseResponse, LookupByLedgerRequest } from './baseMethod'
|
||||
|
||||
export interface SourceCurrencyAmount {
|
||||
currency: string
|
||||
issuer?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* The `ripple_path_find` method is a simplified version of the path_find method
|
||||
* that provides a single response with a payment path you can use right away.
|
||||
* Expects a response in the form of a {@link RipplePathFindResponse}.
|
||||
*
|
||||
* @category Requests
|
||||
*/
|
||||
export interface RipplePathFindRequest
|
||||
extends BaseRequest,
|
||||
LookupByLedgerRequest {
|
||||
command: 'ripple_path_find'
|
||||
/** Unique address of the account that would send funds in a transaction. */
|
||||
source_account: string
|
||||
/** Unique address of the account that would receive funds in a transaction. */
|
||||
destination_account: string
|
||||
/**
|
||||
* Currency Amount that the destination account would receive in a
|
||||
* transaction.
|
||||
*/
|
||||
destination_amount: Amount
|
||||
/**
|
||||
* Currency Amount that would be spent in the transaction. Cannot be used
|
||||
* with `source_currencies`.
|
||||
*/
|
||||
send_max?: Amount
|
||||
/**
|
||||
* Array of currencies that the source account might want to spend. Each
|
||||
* entry in the array should be a JSON object with a mandatory currency field
|
||||
* and optional issuer field, like how currency amounts are specified.
|
||||
*/
|
||||
source_currencies?: SourceCurrencyAmount[]
|
||||
}
|
||||
|
||||
export interface RipplePathFindPathOption {
|
||||
/** Array of arrays of objects defining payment paths. */
|
||||
paths_computed: Path[]
|
||||
/**
|
||||
* Currency amount that the source would have to send along this path for the
|
||||
* destination to receive the desired amount.
|
||||
*/
|
||||
source_amount: Amount
|
||||
}
|
||||
|
||||
/**
|
||||
* Response expected from a {@link RipplePathFindRequest}.
|
||||
*
|
||||
* @category Responses
|
||||
*/
|
||||
export interface RipplePathFindResponse extends BaseResponse {
|
||||
result: {
|
||||
/**
|
||||
* Array of objects with possible paths to take, as described below. If
|
||||
* empty, then there are no paths connecting the source and destination
|
||||
* accounts.
|
||||
*/
|
||||
alternatives: RipplePathFindPathOption[]
|
||||
/** Unique address of the account that would receive a payment transaction. */
|
||||
destination_account: string
|
||||
/**
|
||||
* Array of strings representing the currencies that the destination
|
||||
* accepts, as 3-letter codes like "USD" or as 40-character hex like
|
||||
* "015841551A748AD2C1F76FF6ECB0CCCD00000000".
|
||||
*/
|
||||
destination_currencies: string[]
|
||||
destination_amount: Amount
|
||||
full_reply?: boolean
|
||||
id?: number | string
|
||||
ledger_current_index?: number
|
||||
source_account: string
|
||||
validated: boolean
|
||||
}
|
||||
}
|
||||
61
packages/xahau/src/models/methods/serverDefinitions.ts
Normal file
61
packages/xahau/src/models/methods/serverDefinitions.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
import { BaseRequest, BaseResponse } from './baseMethod'
|
||||
|
||||
/**
|
||||
* The `server_definitions` method retrieves information about the definition
|
||||
* enums available in this xahaud node. Expects a response in the form of a
|
||||
* {@link ServerDefinitionsResponse}.
|
||||
*
|
||||
* @category Requests
|
||||
*/
|
||||
export interface ServerDefinitionsRequest extends BaseRequest {
|
||||
command: 'server_definitions'
|
||||
/**
|
||||
* The hash of a `server_definitions` response.
|
||||
*/
|
||||
hash?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Response expected from an {@link ServerDefinitionsRequest}.
|
||||
*
|
||||
* @category Responses
|
||||
*/
|
||||
export interface ServerDefinitionsResponse extends BaseResponse {
|
||||
result: {
|
||||
hash: string
|
||||
} & (
|
||||
| {
|
||||
FIELDS: Array<
|
||||
[
|
||||
string,
|
||||
{
|
||||
nth: number
|
||||
isVLEncoded: boolean
|
||||
isSerialized: boolean
|
||||
isSigningField: boolean
|
||||
type: string
|
||||
},
|
||||
]
|
||||
>
|
||||
|
||||
LEDGER_ENTRY_TYPES: Record<string, number>
|
||||
|
||||
TRANSACTION_RESULTS: Record<string, number>
|
||||
|
||||
TRANSACTION_TYPES: Record<string, number>
|
||||
|
||||
TYPES: Record<string, number>
|
||||
}
|
||||
| {
|
||||
FIELDS?: never
|
||||
|
||||
LEDGER_ENTRY_TYPES?: never
|
||||
|
||||
TRANSACTION_RESULTS?: never
|
||||
|
||||
TRANSACTION_TYPES?: never
|
||||
|
||||
TYPES?: never
|
||||
}
|
||||
)
|
||||
}
|
||||
278
packages/xahau/src/models/methods/serverInfo.ts
Normal file
278
packages/xahau/src/models/methods/serverInfo.ts
Normal file
@@ -0,0 +1,278 @@
|
||||
import { BaseRequest, BaseResponse } from './baseMethod'
|
||||
|
||||
/**
|
||||
* The `server_info` command asks the server for a human-readable version of
|
||||
* various information about the xahaud server being queried. Expects a
|
||||
* response in the form of a {@link ServerInfoResponse}.
|
||||
*
|
||||
* @category Requests
|
||||
*/
|
||||
export interface ServerInfoRequest extends BaseRequest {
|
||||
command: 'server_info'
|
||||
}
|
||||
|
||||
export type ServerState =
|
||||
| 'disconnected'
|
||||
| 'connected'
|
||||
| 'syncing'
|
||||
| 'tracking'
|
||||
| 'full'
|
||||
| 'validating'
|
||||
| 'proposing'
|
||||
|
||||
export interface StateAccounting {
|
||||
duration_us: string
|
||||
transitions: string
|
||||
}
|
||||
|
||||
export interface JobType {
|
||||
job_type: string
|
||||
per_second: number
|
||||
peak_time?: number
|
||||
avg_time?: number
|
||||
in_progress?: number
|
||||
}
|
||||
|
||||
export type protocol =
|
||||
| 'http'
|
||||
| 'https'
|
||||
| 'grpc'
|
||||
| 'peer'
|
||||
| 'ws'
|
||||
| 'ws2'
|
||||
| 'wss'
|
||||
| 'wss2'
|
||||
|
||||
export interface ServerPort {
|
||||
port: string
|
||||
/** The values in protocol are sorted in alphabetical order */
|
||||
protocol: protocol[]
|
||||
}
|
||||
|
||||
// The states for validating and proposing do not exist in the field state_accounting
|
||||
// See https://github.com/XRPLF/xahaud/blob/develop/src/xahau/app/misc/NetworkOPs.cpp#L4545
|
||||
// https://github.com/XRPLF/xahaud/blob/develop/src/xahau/app/misc/NetworkOPs.h#L66
|
||||
export type StateAccountingFinal = Record<
|
||||
Exclude<ServerState, 'validating' | 'proposing'>,
|
||||
StateAccounting
|
||||
>
|
||||
|
||||
/**
|
||||
* Response expected from a {@link ServerInfoRequest}.
|
||||
*
|
||||
* @category Responses
|
||||
*/
|
||||
export interface ServerInfoResponse extends BaseResponse {
|
||||
result: {
|
||||
info: {
|
||||
/**
|
||||
* If true, this server is amendment blocked. If the server is not
|
||||
* amendment blocked, the response omits this field.
|
||||
*/
|
||||
amendment_blocked?: boolean
|
||||
/** The version number of the running xahaud version. */
|
||||
build_version: string
|
||||
/**
|
||||
* Information on the most recently closed ledger that has not been
|
||||
* validated by consensus. If the most recently validated ledger is
|
||||
* available, the response omits this field and includes
|
||||
* `validated_ledger` instead. The member fields are the same as the.
|
||||
* `validated_ledger` field.
|
||||
*/
|
||||
closed_ledger?: {
|
||||
age: number
|
||||
base_fee_xrp: number
|
||||
hash: string
|
||||
reserve_base_xrp: number
|
||||
reserve_inc_xrp: number
|
||||
seq: number
|
||||
}
|
||||
/**
|
||||
* Range expression indicating the sequence numbers of the ledger
|
||||
* versions the local xahaud has in its database.
|
||||
*/
|
||||
complete_ledgers: string
|
||||
/**
|
||||
* On an admin request, returns the hostname of the server running the
|
||||
* xahaud instance; otherwise, returns a single RFC-1751 word based on
|
||||
* the node public key.
|
||||
*/
|
||||
hostid: string
|
||||
/**
|
||||
* Amount of time spent waiting for I/O operations, in milliseconds. If
|
||||
* this number is not very, very low, then the xahaud server is probably
|
||||
* having serious load issues.
|
||||
*/
|
||||
io_latency_ms: number
|
||||
/**
|
||||
* The number of times (since starting up) that this server has had over
|
||||
* 250 transactions waiting to be processed at once. A large number here
|
||||
* may mean that your server is unable to handle the transaction load of
|
||||
* the XAH Ledger network.
|
||||
*/
|
||||
jq_trans_overflow: string
|
||||
/**
|
||||
* Information about the last time the server closed a ledger, including
|
||||
* the amount of time it took to reach a consensus and the number of
|
||||
* trusted validators participating.
|
||||
*/
|
||||
last_close: {
|
||||
/**
|
||||
* The amount of time it took to reach a consensus on the most recently
|
||||
* validated ledger version, in seconds.
|
||||
*/
|
||||
converge_time_s: number
|
||||
/**
|
||||
* How many trusted validators the server considered (including itself,
|
||||
* if configured as a validator) in the consensus process for the most
|
||||
* recently validated ledger version.
|
||||
*/
|
||||
proposers: number
|
||||
}
|
||||
/**
|
||||
* (Admin only) Detailed information about the current load state of the
|
||||
* server.
|
||||
*/
|
||||
load?: {
|
||||
/**
|
||||
* (Admin only) Information about the rate of different types of jobs
|
||||
* the server is doing and how much time it spends on each.
|
||||
*/
|
||||
job_types: JobType[]
|
||||
/** (Admin only) The number of threads in the server's main job pool. */
|
||||
threads: number
|
||||
}
|
||||
/**
|
||||
* The load-scaled open ledger transaction cost the server is currently
|
||||
* enforcing, as a multiplier on the base transaction cost. For example,
|
||||
* at 1000 load factor and a reference transaction cost of 10 drops of
|
||||
* XAH, the load-scaled transaction cost is 10,000 drops (0.01 XAH). The
|
||||
* load factor is determined by the highest of the individual server's
|
||||
* load factor, the cluster's load factor, the open ledger cost and the
|
||||
* overall network's load factor.
|
||||
*/
|
||||
load_factor?: number
|
||||
/**
|
||||
* The network id of the server.
|
||||
*/
|
||||
network_id?: number
|
||||
/**
|
||||
* Current multiplier to the transaction cost based on
|
||||
* load to this server.
|
||||
*/
|
||||
load_factor_local?: number
|
||||
/**
|
||||
* Current multiplier to the transaction cost being used by the rest of
|
||||
* the network.
|
||||
*/
|
||||
load_factor_net?: number
|
||||
/**
|
||||
* Current multiplier to the transaction cost based on load to servers
|
||||
* in this cluster.
|
||||
*/
|
||||
load_factor_cluster?: number
|
||||
/**
|
||||
* The current multiplier to the transaction cost that a transaction must
|
||||
* pay to get into the open ledger.
|
||||
*/
|
||||
load_factor_fee_escalation?: number
|
||||
/**
|
||||
* The current multiplier to the transaction cost that a transaction must
|
||||
* pay to get into the queue, if the queue is full.
|
||||
*/
|
||||
load_factor_fee_queue?: number
|
||||
/**
|
||||
* The load factor the server is enforcing, not including the open ledger
|
||||
* cost.
|
||||
*/
|
||||
load_factor_server?: number
|
||||
/**
|
||||
* The number of peer connections which were severed.
|
||||
*/
|
||||
peer_disconnects?: string
|
||||
/**
|
||||
* The number of peer connections which were severed due to excess resource consumption.
|
||||
*/
|
||||
peer_disconnects_resources?: string
|
||||
network_ledger?: 'waiting'
|
||||
/** How many other xahaud servers this one is currently connected to. */
|
||||
peers: number
|
||||
/**
|
||||
* What Websocket/RPC ports xahaud is listening on. This allows crawlers to build a richer topology without needing to
|
||||
* port-scan nodes. For non-admin users (including peers), info about admin ports is excluded.
|
||||
*/
|
||||
ports: ServerPort[]
|
||||
/**
|
||||
* Public key used to verify this server for peer-to-peer communications.
|
||||
* This node key pair is automatically generated by the server the first
|
||||
* time it starts up. (If deleted, the server can create a new pair of
|
||||
* Keys.).
|
||||
*/
|
||||
pubkey_node: string
|
||||
/** Public key used by this node to sign ledger validations. */
|
||||
pubkey_validator?: string
|
||||
/**
|
||||
* A string indicating to what extent the server is participating in the
|
||||
* network.
|
||||
*/
|
||||
server_state: ServerState
|
||||
/**
|
||||
* The number of consecutive microseconds the server has been in the
|
||||
* current state.
|
||||
*/
|
||||
server_state_duration_us: string
|
||||
/**
|
||||
* A map of various server states with information about the time the
|
||||
* server spends in each. This can be useful for tracking the long-term
|
||||
* health of your server's connectivity to the network.
|
||||
*/
|
||||
state_accounting: StateAccountingFinal
|
||||
/** The current time in UTC, according to the server's clock. */
|
||||
time: string
|
||||
/** Number of consecutive seconds that the server has been operational. */
|
||||
uptime: number
|
||||
/** Information about the most recent fully-validated ledger. */
|
||||
validated_ledger?: {
|
||||
/** The time since the ledger was closed, in seconds. */
|
||||
age: number
|
||||
/**
|
||||
* Base fee, in XAH. This may be represented in scientific notation.
|
||||
* Such as 1e-05 for 0.00005.
|
||||
*/
|
||||
base_fee_xrp: number
|
||||
/** Unique hash for the ledger, as hexadecimal. */
|
||||
hash: string
|
||||
/**
|
||||
* Minimum amount of XAH (not drops) necessary for every account to.
|
||||
* Keep in reserve .
|
||||
*/
|
||||
reserve_base_xrp: number
|
||||
/**
|
||||
* Amount of XAH (not drops) added to the account reserve for each
|
||||
* object an account owns in the ledger.
|
||||
*/
|
||||
reserve_inc_xrp: number
|
||||
/** The ledger index of the latest validated ledger. */
|
||||
seq: number
|
||||
}
|
||||
/**
|
||||
* Minimum number of trusted validations required to validate a ledger
|
||||
* version. Some circumstances may cause the server to require more
|
||||
* validations.
|
||||
*/
|
||||
validation_quorum: number
|
||||
/**
|
||||
* Either the human readable time, in UTC, when the current validator
|
||||
* list will expire, the string unknown if the server has yet to load a
|
||||
* published validator list or the string never if the server uses a
|
||||
* static validator list.
|
||||
*/
|
||||
validator_list_expires?: string
|
||||
validator_list?: {
|
||||
count: number
|
||||
expiration: 'never' | 'unknown' | string
|
||||
status: 'active' | 'expired' | 'unknown'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
78
packages/xahau/src/models/methods/serverState.ts
Normal file
78
packages/xahau/src/models/methods/serverState.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
import { BaseRequest, BaseResponse } from './baseMethod'
|
||||
import { JobType, ServerState, StateAccountingFinal } from './serverInfo'
|
||||
|
||||
/**
|
||||
* The `server_state` command asks the server for various machine-readable
|
||||
* information about the xahaud server's current state. The response is almost
|
||||
* the same as the server_info method, but uses units that are easier to process
|
||||
* instead of easier to read.
|
||||
*
|
||||
* @category Requests
|
||||
*/
|
||||
export interface ServerStateRequest extends BaseRequest {
|
||||
command: 'server_state'
|
||||
}
|
||||
|
||||
/**
|
||||
* Response expected from a {@link ServerStateRequest}.
|
||||
*
|
||||
* @category Responses
|
||||
*/
|
||||
export interface ServerStateResponse extends BaseResponse {
|
||||
result: {
|
||||
state: {
|
||||
amendment_blocked?: boolean
|
||||
build_version: string
|
||||
complete_ledgers: string
|
||||
closed_ledger?: {
|
||||
age: number
|
||||
base_fee: number
|
||||
hash: string
|
||||
reserve_base: number
|
||||
reserve_inc: number
|
||||
seq: number
|
||||
}
|
||||
io_latency_ms: number
|
||||
jq_trans_overflow: string
|
||||
last_close: {
|
||||
// coverage_time_s only exists for `server_info` requests. `server_state` is a "non human" api request,
|
||||
// therefore the type is coverage_time
|
||||
// See https://github.com/XRPLF/xahaud/blob/83faf43140e27e5d6d6779eaa0ffb75c33d98029/src/xahau/app/misc/NetworkOPs.cpp#L2458
|
||||
converge_time: number
|
||||
proposers: number
|
||||
}
|
||||
load?: {
|
||||
job_types: JobType[]
|
||||
threads: number
|
||||
}
|
||||
load_base: number
|
||||
load_factor: number
|
||||
load_factor_fee_escalation?: number
|
||||
load_factor_fee_queue?: number
|
||||
load_factor_fee_reference?: number
|
||||
load_factor_server?: number
|
||||
network_id?: number
|
||||
peer_disconnects?: string
|
||||
peer_disconnects_resources?: string
|
||||
peers: number
|
||||
pubkey_node: string
|
||||
pubkey_validator?: string
|
||||
server_state: ServerState
|
||||
server_state_duration_us: string
|
||||
state_accounting: StateAccountingFinal
|
||||
time: string
|
||||
uptime: number
|
||||
validated_ledger?: {
|
||||
age?: number
|
||||
base_fee: number
|
||||
close_time: number
|
||||
hash: string
|
||||
reserve_base: number
|
||||
reserve_inc: number
|
||||
seq: number
|
||||
}
|
||||
validation_quorum: number
|
||||
validator_list_expires?: number
|
||||
}
|
||||
}
|
||||
}
|
||||
94
packages/xahau/src/models/methods/submit.ts
Normal file
94
packages/xahau/src/models/methods/submit.ts
Normal file
@@ -0,0 +1,94 @@
|
||||
import { SubmittableTransaction } from '../transactions'
|
||||
|
||||
import { BaseRequest, BaseResponse } from './baseMethod'
|
||||
|
||||
/**
|
||||
* The submit method applies a transaction and sends it to the network to be
|
||||
* confirmed and included in future ledgers. Expects a response in the form of a
|
||||
* {@link SubmitResponse}.
|
||||
*
|
||||
* @category Requests
|
||||
*/
|
||||
export interface SubmitRequest extends BaseRequest {
|
||||
command: 'submit'
|
||||
/** The complete transaction in hex string format. */
|
||||
tx_blob: string
|
||||
/**
|
||||
* If true, and the transaction fails locally, do not retry or relay the
|
||||
* transaction to other servers. The default is false.
|
||||
*/
|
||||
fail_hard?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Response expected from a {@link SubmitRequest}.
|
||||
*
|
||||
* @category Responses
|
||||
*/
|
||||
export interface SubmitResponse extends BaseResponse {
|
||||
result: {
|
||||
/**
|
||||
* Text result code indicating the preliminary result of the transaction,
|
||||
* for example `tesSUCCESS`.
|
||||
*/
|
||||
engine_result: string
|
||||
/** Numeric version of the result code. */
|
||||
engine_result_code: number
|
||||
/** Human-readable explanation of the transaction's preliminary result. */
|
||||
engine_result_message: string
|
||||
/** The complete transaction in hex string format. */
|
||||
tx_blob: string
|
||||
/** The complete transaction in JSON format. */
|
||||
tx_json: SubmittableTransaction & { hash?: string }
|
||||
/**
|
||||
* The value true indicates that the transaction was applied, queued,
|
||||
* broadcast, or kept for later. The value `false` indicates that none of
|
||||
* those happened, so the transaction cannot possibly succeed as long as you
|
||||
* do not submit it again and have not already submitted it another time.
|
||||
*/
|
||||
accepted: boolean
|
||||
/**
|
||||
* The next Sequence Number available for the sending account after all
|
||||
* pending and queued transactions.
|
||||
*/
|
||||
account_sequence_available: number
|
||||
/**
|
||||
* The next Sequence number for the sending account after all transactions
|
||||
* that have been provisionally applied, but not transactions in the queue.
|
||||
*/
|
||||
account_sequence_next: number
|
||||
/**
|
||||
* The value true indicates that this transaction was applied to the open
|
||||
* ledger. In this case, the transaction is likely, but not guaranteed, to
|
||||
* be validated in the next ledger version.
|
||||
*/
|
||||
applied: boolean
|
||||
/**
|
||||
* The value true indicates this transaction was broadcast to peer servers
|
||||
* in the peer-to-peer XAH Ledger network.
|
||||
*/
|
||||
broadcast: boolean
|
||||
/**
|
||||
* The value true indicates that the transaction was kept to be retried
|
||||
* later.
|
||||
*/
|
||||
kept: boolean
|
||||
/**
|
||||
* The value true indicates the transaction was put in the Transaction
|
||||
* Queue, which means it is likely to be included in a future ledger
|
||||
* version.
|
||||
*/
|
||||
queued: boolean
|
||||
/**
|
||||
* The current open ledger cost before processing this transaction
|
||||
* transactions with a lower cost are likely to be queued.
|
||||
*/
|
||||
open_ledger_cost: string
|
||||
/**
|
||||
* The ledger index of the newest validated ledger at the time of
|
||||
* submission. This provides a lower bound on the ledger versions that the
|
||||
* transaction can appear in as a result of this request.
|
||||
*/
|
||||
validated_ledger_index: number
|
||||
}
|
||||
}
|
||||
83
packages/xahau/src/models/methods/submitMultisigned.ts
Normal file
83
packages/xahau/src/models/methods/submitMultisigned.ts
Normal file
@@ -0,0 +1,83 @@
|
||||
import { APIVersion, DEFAULT_API_VERSION, XAHAUD_API_V1 } from '../common'
|
||||
import { Transaction } from '../transactions'
|
||||
|
||||
import { BaseRequest, BaseResponse } from './baseMethod'
|
||||
|
||||
/**
|
||||
* The `submit_multisigned` command applies a multi-signed transaction and sends
|
||||
* it to the network to be included in future ledgers. Expects a response in the
|
||||
* form of a {@link SubmitMultisignedRequest}.
|
||||
*
|
||||
* @category Requests
|
||||
*/
|
||||
export interface SubmitMultisignedRequest extends BaseRequest {
|
||||
command: 'submit_multisigned'
|
||||
/**
|
||||
* Transaction in JSON format with an array of Signers. To be successful, the
|
||||
* weights of the signatures must be equal or higher than the quorum of the.
|
||||
* {@link Transaction Type/SignerList}.
|
||||
*/
|
||||
tx_json: Transaction
|
||||
/**
|
||||
* If true, and the transaction fails locally, do not retry or relay the
|
||||
* transaction to other servers.
|
||||
*/
|
||||
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: 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 XAHAUD_API_V1
|
||||
? SubmitMultisignedV1Response
|
||||
: SubmitMultisignedResponse
|
||||
502
packages/xahau/src/models/methods/subscribe.ts
Normal file
502
packages/xahau/src/models/methods/subscribe.ts
Normal file
@@ -0,0 +1,502 @@
|
||||
import type {
|
||||
Amount,
|
||||
Currency,
|
||||
Path,
|
||||
StreamType,
|
||||
ResponseOnlyTxInfo,
|
||||
APIVersion,
|
||||
DEFAULT_API_VERSION,
|
||||
XAHAUD_API_V1,
|
||||
XAHAUD_API_V2,
|
||||
} from '../common'
|
||||
import { Offer } from '../ledger'
|
||||
import { OfferCreate, Transaction } from '../transactions'
|
||||
import { TransactionMetadata } from '../transactions/metadata'
|
||||
|
||||
import type { BaseRequest, BaseResponse } from './baseMethod'
|
||||
import { ManifestRequest } from './manifest'
|
||||
|
||||
export interface SubscribeBook {
|
||||
/**
|
||||
* Specification of which currency the account taking the Offer would
|
||||
* receive, as a currency object with no amount.
|
||||
*/
|
||||
taker_gets: Currency
|
||||
/**
|
||||
* Specification of which currency the account taking the Offer would pay, as
|
||||
* a currency object with no amount.
|
||||
*/
|
||||
taker_pays: Currency
|
||||
/**
|
||||
* Unique account address to use as a perspective for viewing offers, in the.
|
||||
* XAH Ledger's base58 format.
|
||||
*/
|
||||
taker: string
|
||||
/**
|
||||
* If true, return the current state of the order book once when you
|
||||
* subscribe before sending updates. The default is false.
|
||||
*/
|
||||
snapshot?: boolean
|
||||
/** If true, return both sides of the order book. The default is false. */
|
||||
both?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* The subscribe method requests periodic notifications from the server when
|
||||
* certain events happen. Expects a response in the form of a
|
||||
* {@link SubscribeResponse}.
|
||||
*
|
||||
* @category Requests
|
||||
*/
|
||||
export interface SubscribeRequest extends BaseRequest {
|
||||
command: 'subscribe'
|
||||
/** Array of string names of generic streams to subscribe to. */
|
||||
streams?: StreamType[]
|
||||
/**
|
||||
* Array with the unique addresses of accounts to monitor for validated
|
||||
* transactions. The addresses must be in the XAH Ledger's base58 format.
|
||||
* The server sends a notification for any transaction that affects at least
|
||||
* one of these accounts.
|
||||
*/
|
||||
accounts?: string[]
|
||||
/** Like accounts, but include transactions that are not yet finalized. */
|
||||
accounts_proposed?: string[]
|
||||
/**
|
||||
* Array of objects defining order books to monitor for updates, as detailed
|
||||
* Below.
|
||||
*/
|
||||
books?: SubscribeBook[]
|
||||
/**
|
||||
* URL where the server sends a JSON-RPC callbacks for each event.
|
||||
* Admin-only.
|
||||
*/
|
||||
url?: string
|
||||
/** Username to provide for basic authentication at the callback URL. */
|
||||
url_username?: string
|
||||
/** Password to provide for basic authentication at the callback URL. */
|
||||
url_password?: string
|
||||
}
|
||||
|
||||
export type BooksSnapshot = Offer[]
|
||||
|
||||
/**
|
||||
* Response expected from a {@link SubscribeRequest}.
|
||||
*
|
||||
* @category Responses
|
||||
*/
|
||||
export interface SubscribeResponse extends BaseResponse {
|
||||
result: Record<string, never> | LedgerStreamResponse | BooksSnapshot
|
||||
}
|
||||
|
||||
interface BaseStream {
|
||||
type: string
|
||||
}
|
||||
|
||||
/**
|
||||
* The `ledger` stream only sends `ledgerClosed` messages when the consensus
|
||||
* process declares a new validated ledger. The message identifies the ledger
|
||||
* And provides some information about its contents.
|
||||
*
|
||||
* @category Streams
|
||||
*/
|
||||
export interface LedgerStream extends BaseStream {
|
||||
type: 'ledgerClosed'
|
||||
/**
|
||||
* The reference transaction cost as of this ledger version, in drops of XAH.
|
||||
* If this ledger version includes a SetFee pseudo-transaction the new.
|
||||
* Transaction cost applies starting with the following ledger version.
|
||||
*/
|
||||
fee_base: number
|
||||
/** The reference transaction cost in "fee units". This is not returned after the SetFees amendment is enabled. */
|
||||
fee_ref?: number
|
||||
/** The identifying hash of the ledger version that was closed. */
|
||||
ledger_hash: string
|
||||
/** The ledger index of the ledger that was closed. */
|
||||
ledger_index: number
|
||||
/** The time this ledger was closed, in seconds since the Ripple Epoch. */
|
||||
ledger_time: number
|
||||
/**
|
||||
* The minimum reserve, in drops of XAH, that is required for an account. If
|
||||
* this ledger version includes a SetFee pseudo-transaction the new base reserve
|
||||
* applies starting with the following ledger version.
|
||||
*/
|
||||
reserve_base: number
|
||||
/**
|
||||
* The owner reserve for each object an account owns in the ledger, in drops
|
||||
* of XAH. If the ledger includes a SetFee pseudo-transaction the new owner
|
||||
* reserve applies after this ledger.
|
||||
*/
|
||||
reserve_inc: number
|
||||
/** Number of new transactions included in this ledger version. */
|
||||
txn_count: number
|
||||
/**
|
||||
* Range of ledgers that the server has available. This may be a disjoint
|
||||
* sequence such as 24900901-24900984,24901116-24901158. This field is not
|
||||
* returned if the server is not connected to the network, or if it is
|
||||
* connected but has not yet obtained a ledger from the network.
|
||||
*/
|
||||
validated_ledgers?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* This response mirrors the LedgerStream, except it does NOT include the 'type' nor 'txn_count' fields.
|
||||
*/
|
||||
export interface LedgerStreamResponse {
|
||||
/**
|
||||
* The reference transaction cost as of this ledger version, in drops of XAH.
|
||||
* If this ledger version includes a SetFee pseudo-transaction the new.
|
||||
* Transaction cost applies starting with the following ledger version.
|
||||
*/
|
||||
fee_base: number
|
||||
/** The reference transaction cost in "fee units". This is not returned after the SetFees amendment is enabled. */
|
||||
fee_ref?: number
|
||||
/** The identifying hash of the ledger version that was closed. */
|
||||
ledger_hash: string
|
||||
/** The ledger index of the ledger that was closed. */
|
||||
ledger_index: number
|
||||
/** The time this ledger was closed, in seconds since the Ripple Epoch. */
|
||||
ledger_time: number
|
||||
/**
|
||||
* The minimum reserve, in drops of XAH, that is required for an account. If
|
||||
* this ledger version includes a SetFee pseudo-transaction the new base reserve
|
||||
* applies starting with the following ledger version.
|
||||
*/
|
||||
reserve_base: number
|
||||
/**
|
||||
* The owner reserve for each object an account owns in the ledger, in drops
|
||||
* of XAH. If the ledger includes a SetFee pseudo-transaction the new owner
|
||||
* reserve applies after this ledger.
|
||||
*/
|
||||
reserve_inc: number
|
||||
/**
|
||||
* Range of ledgers that the server has available. This may be a disjoint
|
||||
* sequence such as 24900901-24900984,24901116-24901158. This field is not
|
||||
* returned if the server is not connected to the network, or if it is
|
||||
* connected but has not yet obtained a ledger from the network.
|
||||
*/
|
||||
validated_ledgers?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* The validations stream sends messages whenever it receives validation
|
||||
* messages, also called validation votes, regardless of whether or not the
|
||||
* validation message is from a trusted validator.
|
||||
*
|
||||
* @category Streams
|
||||
*/
|
||||
export interface ValidationStream extends BaseStream {
|
||||
type: 'validationReceived'
|
||||
/**
|
||||
* The value validationReceived indicates this is from the validations
|
||||
* Stream.
|
||||
*/
|
||||
amendments?: string[]
|
||||
/** The amendments this server wants to be added to the protocol. */
|
||||
base_fee?: number
|
||||
/**
|
||||
* An arbitrary value chosen by the server at startup.
|
||||
*
|
||||
* If the same validation key pair signs validations with different cookies
|
||||
* concurrently, that usually indicates that multiple servers are incorrectly
|
||||
* configured to use the same validation key pair.
|
||||
*/
|
||||
cookie?: string
|
||||
/**
|
||||
* The contents of the validation message in its canonical binary form
|
||||
*/
|
||||
data?: string
|
||||
/**
|
||||
* The unscaled transaction cost (reference_fee value) this server wants to
|
||||
* set by Fee voting.
|
||||
*/
|
||||
flags: number
|
||||
/**
|
||||
* Bit-mask of flags added to this validation message. The flag 0x80000000
|
||||
* indicates that the validation signature is fully-canonical. The flag
|
||||
* 0x00000001 indicates that this is a full validation; otherwise it's a
|
||||
* partial validation. Partial validations are not meant to vote for any
|
||||
* particular ledger. A partial validation indicates that the validator is
|
||||
* still online but not keeping up with consensus.
|
||||
*/
|
||||
full: boolean
|
||||
/**
|
||||
* If true, this is a full validation. Otherwise, this is a partial
|
||||
* validation. Partial validations are not meant to vote for any particular
|
||||
* ledger. A partial validation indicates that the validator is still online
|
||||
* but not keeping up with consensus.
|
||||
*/
|
||||
ledger_hash: string
|
||||
/** The ledger index of the proposed ledger. */
|
||||
ledger_index: string
|
||||
/**
|
||||
* The local load-scaled transaction cost this validator is currently
|
||||
* enforcing, in fee units.
|
||||
*/
|
||||
load_fee?: number
|
||||
/**
|
||||
* The validator's master public key, if the validator is using a validator
|
||||
* token, in the XAH Ledger's base58 format.
|
||||
*/
|
||||
master_key?: string
|
||||
/**
|
||||
* The minimum reserve requirement (`account_reserve` value) this validator
|
||||
* wants to set by fee voting.
|
||||
*/
|
||||
reserve_base?: number
|
||||
/**
|
||||
* The increment in the reserve requirement (owner_reserve value) this
|
||||
* validator wants to set by fee voting.
|
||||
*/
|
||||
reserve_inc?: number
|
||||
/** The signature that the validator used to sign its vote for this ledger. */
|
||||
signature: string
|
||||
/** When this validation vote was signed, in seconds since the Ripple Epoch. */
|
||||
signing_time: number
|
||||
/**
|
||||
* The public key from the key-pair that the validator used to sign the
|
||||
* message, in the XAH Ledger's base58 format. This identifies the validator
|
||||
* sending the message and can also be used to verify the signature. If the
|
||||
* validator is using a token, this is an ephemeral public key.
|
||||
*/
|
||||
validation_public_key: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Many subscriptions result in messages about transactions.
|
||||
*
|
||||
* @category Streams
|
||||
*/
|
||||
interface TransactionStreamBase<
|
||||
Version extends APIVersion = typeof DEFAULT_API_VERSION,
|
||||
> extends BaseStream {
|
||||
status: string
|
||||
type: 'transaction'
|
||||
/**
|
||||
* The approximate time this ledger was closed, in date time string format.
|
||||
* Always uses the UTC time zone.
|
||||
*/
|
||||
close_time_iso: string
|
||||
/** String Transaction result code. */
|
||||
engine_result: string
|
||||
/** Numeric transaction response code, if applicable. */
|
||||
engine_result_code: number
|
||||
/** Human-readable explanation for the transaction response. */
|
||||
engine_result_message: string
|
||||
/**
|
||||
* The ledger index of the current in-progress ledger version for which this
|
||||
* transaction is currently proposed.
|
||||
*/
|
||||
ledger_current_index?: number
|
||||
/** The identifying hash of the ledger version that includes this transaction. */
|
||||
ledger_hash?: string
|
||||
/** The ledger index of the ledger version that includes this transaction. */
|
||||
ledger_index?: number
|
||||
/**
|
||||
* The transaction metadata, which shows the exact outcome of the transaction
|
||||
* in detail.
|
||||
*/
|
||||
meta?: TransactionMetadata
|
||||
/** JSON object defining the transaction. */
|
||||
tx_json?: Version extends typeof XAHAUD_API_V2
|
||||
? Transaction & ResponseOnlyTxInfo
|
||||
: never
|
||||
/** JSON object defining the transaction in xahaud API v1. */
|
||||
transaction?: Version extends typeof XAHAUD_API_V1
|
||||
? Transaction & ResponseOnlyTxInfo
|
||||
: never
|
||||
/**
|
||||
* If true, this transaction is included in a validated ledger and its
|
||||
* outcome is final. Responses from the transaction stream should always be
|
||||
* validated.
|
||||
*/
|
||||
validated?: boolean
|
||||
warnings?: Array<{ id: number; message: string }>
|
||||
}
|
||||
|
||||
/**
|
||||
* Expected response from an {@link AccountTxRequest}.
|
||||
*
|
||||
* @category Streams
|
||||
*/
|
||||
export type TransactionStream = TransactionStreamBase
|
||||
|
||||
/**
|
||||
* Expected response from an {@link AccountTxRequest} with `api_version` set to 1.
|
||||
*
|
||||
* @category Streams
|
||||
*/
|
||||
export type TransactionV1Stream = TransactionStreamBase
|
||||
|
||||
/**
|
||||
* The admin-only `peer_status` stream reports a large amount of information on
|
||||
* the activities of other xahaud servers to which this server is connected, in
|
||||
* particular their status in the consensus process.
|
||||
*
|
||||
* @category Streams
|
||||
*/
|
||||
export interface PeerStatusStream extends BaseStream {
|
||||
type: 'peerStatusChange'
|
||||
/**
|
||||
* The type of event that prompted this message. See Peer Status Events for
|
||||
* possible values.
|
||||
*/
|
||||
action: 'CLOSING_LEDGER' | 'ACCEPTED_LEDGER' | 'SWITCHED_LEDGER' | 'LOST_SYNC'
|
||||
/** The time this event occurred, in seconds since the Ripple Epoch. */
|
||||
date: number
|
||||
/** The identifying Hash of a ledger version to which this message pertains. */
|
||||
ledger_hash?: string
|
||||
/** The Ledger Index of a ledger version to which this message pertains. */
|
||||
ledger_index?: number
|
||||
/** The largest Ledger Index the peer has currently available. */
|
||||
ledger_index_max?: number
|
||||
/** The smallest Ledger Index the peer has currently available. */
|
||||
ledger_index_min?: number
|
||||
}
|
||||
|
||||
/**
|
||||
* The format of an order book stream message is the same as that of
|
||||
* transaction stream messages, except that OfferCreate transactions also
|
||||
* contain the following field.
|
||||
*/
|
||||
interface ModifiedOfferCreateTransaction extends OfferCreate {
|
||||
/**
|
||||
* Numeric amount of the TakerGets currency that the Account sending this
|
||||
* OfferCreate transaction has after executing this transaction. This does not
|
||||
* check whether the currency amount is frozen.
|
||||
*/
|
||||
owner_funds: string
|
||||
}
|
||||
|
||||
/**
|
||||
* When you subscribe to one or more order books with the `books` field, you
|
||||
* get back any transactions that affect those order books. Has the same format
|
||||
* as a {@link TransactionStream} but the transaction can have a `owner_funds`
|
||||
* field.
|
||||
*
|
||||
* @category Streams
|
||||
*/
|
||||
export interface OrderBookStream extends BaseStream {
|
||||
status: string
|
||||
type: 'transaction'
|
||||
engine_result: string
|
||||
engine_result_code: number
|
||||
engine_result_message: string
|
||||
ledger_current_index?: number
|
||||
ledger_hash?: string
|
||||
ledger_index?: number
|
||||
meta: TransactionMetadata
|
||||
transaction: (Transaction | ModifiedOfferCreateTransaction) & {
|
||||
/**
|
||||
* This number measures the number of seconds since the "Ripple Epoch" of January 1, 2000 (00:00 UTC)
|
||||
*/
|
||||
date?: number
|
||||
/**
|
||||
* Every signed transaction has a unique "hash" that identifies it.
|
||||
* The transaction hash can be used to look up its final status, which may serve as a "proof of payment"
|
||||
*/
|
||||
hash?: string
|
||||
}
|
||||
validated: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* The consensus stream sends consensusPhase messages when the consensus
|
||||
* process changes phase. The message contains the new phase of consensus the
|
||||
* server is in.
|
||||
*
|
||||
* @category Streams
|
||||
*/
|
||||
export interface ConsensusStream extends BaseStream {
|
||||
type: 'consensusPhase'
|
||||
/**
|
||||
* The new consensus phase the server is in. Possible values are open,
|
||||
* establish, and accepted.
|
||||
*/
|
||||
consensus: 'open' | 'establish' | 'accepted'
|
||||
}
|
||||
|
||||
/**
|
||||
* The path_find method searches for a path along which a transaction can
|
||||
* possibly be made, and periodically sends updates when the path changes over
|
||||
* time.
|
||||
*
|
||||
* @category Streams
|
||||
*/
|
||||
export interface PathFindStream extends BaseStream {
|
||||
type: 'path_find'
|
||||
/** Unique address that would send a transaction. */
|
||||
source_account: string
|
||||
/** Unique address of the account that would receive a transaction. */
|
||||
destination_account: string
|
||||
/** Currency Amount that the destination would receive in a transaction. */
|
||||
destination_amount: Amount
|
||||
/**
|
||||
* If false, this is the result of an incomplete search. A later reply may
|
||||
* have a better path. If true, then this is the best path found. (It is still
|
||||
* theoretically possible that a better path could exist, but xahaud won't
|
||||
* find it.) Until you close the pathfinding request, xahaud continues to
|
||||
* send updates each time a new ledger closes.
|
||||
*/
|
||||
full_reply: boolean
|
||||
/** The ID provided in the WebSocket request is included again at this level. */
|
||||
id: number | string
|
||||
/** Currency Amount that would be spent in the transaction. */
|
||||
send_max?: Amount
|
||||
/**
|
||||
* Array of objects with suggested paths to take. If empty, then no paths
|
||||
* were found connecting the source and destination accounts.
|
||||
*/
|
||||
alternatives:
|
||||
| []
|
||||
| {
|
||||
paths_computed: Path[]
|
||||
source_amount: Amount
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @category Streams
|
||||
*/
|
||||
export type Stream =
|
||||
| LedgerStream
|
||||
| ValidationStream
|
||||
| TransactionStream
|
||||
| PathFindStream
|
||||
| PeerStatusStream
|
||||
| OrderBookStream
|
||||
| ConsensusStream
|
||||
|
||||
export type EventTypes =
|
||||
| 'connected'
|
||||
| 'disconnected'
|
||||
| 'ledgerClosed'
|
||||
| 'validationReceived'
|
||||
| 'transaction'
|
||||
| 'peerStatusChange'
|
||||
| 'consensusPhase'
|
||||
| 'manifestReceived'
|
||||
| 'path_find'
|
||||
| 'error'
|
||||
|
||||
export type OnEventToListenerMap<T extends EventTypes> = T extends 'connected'
|
||||
? () => void
|
||||
: T extends 'disconnected'
|
||||
? (code: number) => void
|
||||
: T extends 'ledgerClosed'
|
||||
? (ledger: LedgerStream) => void
|
||||
: T extends 'validationReceived'
|
||||
? (validation: ValidationStream) => void
|
||||
: T extends 'transaction'
|
||||
? (transaction: TransactionStream) => void
|
||||
: T extends 'peerStatusChange'
|
||||
? (peerStatus: PeerStatusStream) => void
|
||||
: T extends 'consensusPhase'
|
||||
? (consensus: ConsensusStream) => void
|
||||
: T extends 'manifestReceived'
|
||||
? (manifest: ManifestRequest) => void
|
||||
: T extends 'path_find'
|
||||
? (path: PathFindStream) => void
|
||||
: T extends 'error'
|
||||
? // eslint-disable-next-line @typescript-eslint/no-explicit-any -- needs to be any for overload
|
||||
(...err: any[]) => void
|
||||
: (...args: never[]) => void
|
||||
47
packages/xahau/src/models/methods/transactionEntry.ts
Normal file
47
packages/xahau/src/models/methods/transactionEntry.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import { ResponseOnlyTxInfo } from '../common'
|
||||
import { Transaction, TransactionMetadata } from '../transactions'
|
||||
|
||||
import { BaseRequest, BaseResponse, LookupByLedgerRequest } from './baseMethod'
|
||||
|
||||
/**
|
||||
* The `transaction_entry` method retrieves information on a single transaction
|
||||
* from a specific ledger version. Expects a response in the form of a
|
||||
* {@link TransactionEntryResponse}.
|
||||
*
|
||||
* @category Requests
|
||||
*/
|
||||
export interface TransactionEntryRequest
|
||||
extends BaseRequest,
|
||||
LookupByLedgerRequest {
|
||||
command: 'transaction_entry'
|
||||
|
||||
/** Unique hash of the transaction you are looking up. */
|
||||
tx_hash: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Response expected from a {@link TransactionEntryRequest}.
|
||||
*
|
||||
* @category Responses
|
||||
*/
|
||||
export interface TransactionEntryResponse extends BaseResponse {
|
||||
result: {
|
||||
/**
|
||||
* The identifying hash of the ledger version the transaction was found in;
|
||||
* this is the same as the one from the request.
|
||||
*/
|
||||
ledger_hash: string
|
||||
/**
|
||||
* The ledger index of the ledger version the transaction was found in;
|
||||
* this is the same as the one from the request.
|
||||
*/
|
||||
ledger_index: number
|
||||
/**
|
||||
* The transaction metadata, which shows the exact results of the
|
||||
* transaction in detail.
|
||||
*/
|
||||
metadata: TransactionMetadata
|
||||
/** JSON representation of the Transaction object. */
|
||||
tx_json: Transaction & ResponseOnlyTxInfo
|
||||
}
|
||||
}
|
||||
132
packages/xahau/src/models/methods/tx.ts
Normal file
132
packages/xahau/src/models/methods/tx.ts
Normal file
@@ -0,0 +1,132 @@
|
||||
import {
|
||||
APIVersion,
|
||||
DEFAULT_API_VERSION,
|
||||
XAHAUD_API_V1,
|
||||
XAHAUD_API_V2,
|
||||
} from '../common'
|
||||
import { Transaction, TransactionMetadata } from '../transactions'
|
||||
import { BaseTransaction } from '../transactions/common'
|
||||
|
||||
import { BaseRequest, BaseResponse } from './baseMethod'
|
||||
|
||||
/**
|
||||
* The tx method retrieves information on a single transaction, by its
|
||||
* identifying hash. Expects a response in the form of a {@link TxResponse}.
|
||||
*
|
||||
* @category Requests
|
||||
*/
|
||||
export interface TxRequest extends BaseRequest {
|
||||
command: 'tx'
|
||||
/**
|
||||
* The transaction hash to look up. Exactly one of `transaction` or `ctid` must be specified for a TxRequest.
|
||||
*/
|
||||
transaction?: string
|
||||
/**
|
||||
* The Concise Transaction ID to look up. Exactly one of `transaction` or `ctid` must be specified for a TxRequest.
|
||||
*/
|
||||
ctid?: string
|
||||
/**
|
||||
* If true, return transaction data and metadata as binary serialized to
|
||||
* hexadecimal strings. If false, return transaction data and metadata as.
|
||||
* JSON. The default is false.
|
||||
*/
|
||||
binary?: boolean
|
||||
/**
|
||||
* Use this with max_ledger to specify a range of up to 1000 ledger indexes,
|
||||
* starting with this ledger (inclusive). If the server cannot find the
|
||||
* transaction, it confirms whether it was able to search all the ledgers in
|
||||
* this range.
|
||||
*/
|
||||
min_ledger?: number
|
||||
/**
|
||||
* Use this with min_ledger to specify a range of up to 1000 ledger indexes,
|
||||
* ending with this ledger (inclusive). If the server cannot find the
|
||||
* transaction, it confirms whether it was able to search all the ledgers in
|
||||
* the requested range.
|
||||
*/
|
||||
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 XAHAUD_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}.
|
||||
*
|
||||
* @category Responses
|
||||
*/
|
||||
export interface TxResponse<T extends BaseTransaction = Transaction>
|
||||
extends BaseResponse {
|
||||
result: BaseTxResult<typeof XAHAUD_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
|
||||
* 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
|
||||
}
|
||||
|
||||
/**
|
||||
* Response expected from a {@link TxRequest} using API version 1.
|
||||
*
|
||||
* @category ResponsesV1
|
||||
*/
|
||||
export interface TxV1Response<T extends BaseTransaction = Transaction>
|
||||
extends BaseResponse {
|
||||
result: BaseTxResult<typeof XAHAUD_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 XAHAUD_API_V1 ? TxV1Response : TxResponse
|
||||
49
packages/xahau/src/models/methods/unsubscribe.ts
Normal file
49
packages/xahau/src/models/methods/unsubscribe.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import { Currency, StreamType } from '../common'
|
||||
|
||||
import type { BaseRequest, BaseResponse } from './baseMethod'
|
||||
|
||||
export interface UnsubscribeBook {
|
||||
taker_gets: Currency
|
||||
taker_pays: Currency
|
||||
both?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* The unsubscribe command tells the server to stop sending messages for a
|
||||
* particular subscription or set of subscriptions. Expects a response in the
|
||||
* form of an {@link UnsubscribeResponse}.
|
||||
*
|
||||
* @category Requests
|
||||
*/
|
||||
export interface UnsubscribeRequest extends BaseRequest {
|
||||
command: 'unsubscribe'
|
||||
/**
|
||||
* Array of string names of generic streams to unsubscribe from, including.
|
||||
* Ledger, server, transactions, and transactions_proposed.
|
||||
*/
|
||||
streams?: StreamType[]
|
||||
/**
|
||||
* Array of unique account addresses to stop receiving updates for, in the.
|
||||
* XAH Ledger's base58 format.
|
||||
*/
|
||||
accounts?: string[]
|
||||
/**
|
||||
* Like accounts, but for accounts_proposed subscriptions that included
|
||||
* not-yet-validated transactions.
|
||||
*/
|
||||
accounts_proposed?: string[]
|
||||
/**
|
||||
* Array of objects defining order books to unsubscribe from, as explained
|
||||
* below.
|
||||
*/
|
||||
books?: UnsubscribeBook[]
|
||||
}
|
||||
|
||||
/**
|
||||
* Response expected from a {@link UnsubscribeRequest}.
|
||||
*
|
||||
* @category Responses
|
||||
*/
|
||||
export interface UnsubscribeResponse extends BaseResponse {
|
||||
result: Record<string, never>
|
||||
}
|
||||
22
packages/xahau/src/models/transactions/UNLModify.ts
Normal file
22
packages/xahau/src/models/transactions/UNLModify.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { BaseTransaction } from './common'
|
||||
|
||||
/**
|
||||
* Mark a change to the Negative UNL.
|
||||
*
|
||||
* @category Pseudo Transaction Models
|
||||
*/
|
||||
export interface UNLModify extends BaseTransaction {
|
||||
TransactionType: 'UNLModify'
|
||||
/**
|
||||
* The ledger index where this pseudo-transaction appears.
|
||||
* This distinguishes the pseudo-transaction from other occurrences of the same change.
|
||||
*/
|
||||
LedgerSequence: number
|
||||
/**
|
||||
* If 0, this change represents removing a validator from the Negative UNL.
|
||||
* If 1, this change represents adding a validator to the Negative UNL.
|
||||
*/
|
||||
UNLModifyDisabling: 0 | 1
|
||||
/** The validator to add or remove, as identified by its master public key. */
|
||||
UNLModifyValidator: string
|
||||
}
|
||||
225
packages/xahau/src/models/transactions/accountSet.ts
Normal file
225
packages/xahau/src/models/transactions/accountSet.ts
Normal file
@@ -0,0 +1,225 @@
|
||||
import { ValidationError } from '../../errors'
|
||||
|
||||
import {
|
||||
Account,
|
||||
BaseTransaction,
|
||||
isAccount,
|
||||
validateBaseTransaction,
|
||||
validateOptionalField,
|
||||
} from './common'
|
||||
|
||||
/**
|
||||
* Enum for AccountSet Flags.
|
||||
*
|
||||
* @category Transaction Flags
|
||||
*/
|
||||
export enum AccountSetAsfFlags {
|
||||
/** Require a destination tag to send transactions to this account. */
|
||||
asfRequireDest = 1,
|
||||
/**
|
||||
* Require authorization for users to hold balances issued by this address
|
||||
* can only be enabled if the address has no trust lines connected to it.
|
||||
*/
|
||||
asfRequireAuth = 2,
|
||||
/** XAH should not be sent to this account. */
|
||||
asfDisallowXAH = 3,
|
||||
/**
|
||||
* Disallow use of the master key pair. Can only be enabled if the account
|
||||
* has configured another way to sign transactions, such as a Regular Key or a
|
||||
* Signer List.
|
||||
*/
|
||||
asfDisableMaster = 4,
|
||||
/**
|
||||
* Track the ID of this account's most recent transaction. Required for
|
||||
* AccountTxnID.
|
||||
*/
|
||||
asfAccountTxnID = 5,
|
||||
/**
|
||||
* Permanently give up the ability to freeze individual trust lines or
|
||||
* disable Global Freeze. This flag can never be disabled after being enabled.
|
||||
*/
|
||||
asfNoFreeze = 6,
|
||||
/** Freeze all assets issued by this account. */
|
||||
asfGlobalFreeze = 7,
|
||||
/** Enable rippling on this account's trust lines by default. */
|
||||
asfDefaultRipple = 8,
|
||||
/** Enable Deposit Authorization on this account. */
|
||||
asfDepositAuth = 9,
|
||||
/**
|
||||
* Allow another account to mint and burn tokens on behalf of this account.
|
||||
*/
|
||||
asfAuthorizedNFTokenMinter = 10,
|
||||
/** asf 11 is reserved for Hooks amendment */
|
||||
/** Disallow other accounts from creating incoming NFTOffers */
|
||||
asfDisallowIncomingNFTokenOffer = 12,
|
||||
/** Disallow other accounts from creating incoming Checks */
|
||||
asfDisallowIncomingCheck = 13,
|
||||
/** Disallow other accounts from creating incoming PayChannels */
|
||||
asfDisallowIncomingPayChan = 14,
|
||||
/** Disallow other accounts from creating incoming Trustlines */
|
||||
asfDisallowIncomingTrustline = 15,
|
||||
/** Permanently gain the ability to claw back issued IOUs */
|
||||
asfAllowTrustLineClawback = 16,
|
||||
}
|
||||
|
||||
/**
|
||||
* Enum for AccountSet Transaction Flags.
|
||||
*
|
||||
* @category Transaction Flags
|
||||
*/
|
||||
export enum AccountSetTfFlags {
|
||||
/** The same as SetFlag: asfRequireDest. */
|
||||
tfRequireDestTag = 0x00010000,
|
||||
/** The same as ClearFlag: asfRequireDest. */
|
||||
tfOptionalDestTag = 0x00020000,
|
||||
/** The same as SetFlag: asfRequireAuth. */
|
||||
tfRequireAuth = 0x00040000,
|
||||
/** The same as ClearFlag: asfRequireAuth. */
|
||||
tfOptionalAuth = 0x00080000,
|
||||
/** The same as SetFlag: asfDisallowXAH. */
|
||||
tfDisallowXAH = 0x00100000,
|
||||
/** The same as ClearFlag: asfDisallowXAH. */
|
||||
tfAllowXAH = 0x00200000,
|
||||
}
|
||||
|
||||
/**
|
||||
* Map of flags to boolean values representing {@link AccountSet} transaction
|
||||
* flags.
|
||||
*
|
||||
* @category Transaction Flags
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const accountSetTx: AccountSet = {
|
||||
* TransactionType: 'AccountSet',
|
||||
* Account: 'rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn',
|
||||
* Flags: {
|
||||
* tfOptionalDestTag: true,
|
||||
* tfRequireAuth: true
|
||||
* },
|
||||
* }
|
||||
*
|
||||
* // Autofill the tx to see how flags actually look compared to the interface usage.
|
||||
* const autofilledTx = await client.autofill(accountSetTx)
|
||||
* console.log(autofilledTx)
|
||||
* // {
|
||||
* // TransactionType: 'AccountSet',
|
||||
* // Account: 'rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn',
|
||||
* // Flags: 393216,
|
||||
* // Sequence: 1,
|
||||
* // Fee: '12',
|
||||
* // LastLedgerSequence: 21971793
|
||||
* // }
|
||||
* ```
|
||||
*/
|
||||
export interface AccountSetFlagsInterface {
|
||||
tfRequireDestTag?: boolean
|
||||
tfOptionalDestTag?: boolean
|
||||
tfRequireAuth?: boolean
|
||||
tfOptionalAuth?: boolean
|
||||
tfDisallowXAH?: boolean
|
||||
tfAllowXAH?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* An AccountSet transaction modifies the properties of an account in the XAH
|
||||
* Ledger.
|
||||
*
|
||||
* @category Transaction Models
|
||||
*/
|
||||
export interface AccountSet extends BaseTransaction {
|
||||
TransactionType: 'AccountSet'
|
||||
Flags?: number | AccountSetFlagsInterface
|
||||
/** Unique identifier of a flag to disable for this account. */
|
||||
ClearFlag?: number
|
||||
/**
|
||||
* The domain that owns this account, as a string of hex representing the.
|
||||
* ASCII for the domain in lowercase.
|
||||
*/
|
||||
Domain?: string
|
||||
/** Hash of an email address to be used for generating an avatar image. */
|
||||
EmailHash?: string
|
||||
/** Public key for sending encrypted messages to this account. */
|
||||
MessageKey?: string
|
||||
/** Integer flag to enable for this account. */
|
||||
SetFlag?: AccountSetAsfFlags
|
||||
/**
|
||||
* The fee to charge when users transfer this account's issued currencies,
|
||||
* represented as billionths of a unit. Cannot be more than 2000000000 or less
|
||||
* than 1000000000, except for the special case 0 meaning no fee.
|
||||
*/
|
||||
TransferRate?: number
|
||||
/**
|
||||
* Tick size to use for offers involving a currency issued by this address.
|
||||
* The exchange rates of those offers is rounded to this many significant
|
||||
* digits. Valid values are 3 to 15 inclusive, or 0 to disable.
|
||||
*/
|
||||
TickSize?: number
|
||||
/**
|
||||
* Sets an alternate account that is allowed to mint NFTokens on this
|
||||
* account's behalf using NFTokenMint's `Issuer` field.
|
||||
*/
|
||||
NFTokenMinter?: Account
|
||||
}
|
||||
|
||||
const MIN_TICK_SIZE = 3
|
||||
const MAX_TICK_SIZE = 15
|
||||
|
||||
/**
|
||||
* Verify the form and type of an AccountSet at runtime.
|
||||
*
|
||||
* @param tx - An AccountSet Transaction.
|
||||
* @throws When the AccountSet is Malformed.
|
||||
*/
|
||||
// eslint-disable-next-line max-lines-per-function -- okay for this method, only a little over
|
||||
export function validateAccountSet(tx: Record<string, unknown>): void {
|
||||
validateBaseTransaction(tx)
|
||||
|
||||
validateOptionalField(tx, 'NFTokenMinter', isAccount)
|
||||
|
||||
if (tx.ClearFlag !== undefined) {
|
||||
if (typeof tx.ClearFlag !== 'number') {
|
||||
throw new ValidationError('AccountSet: invalid ClearFlag')
|
||||
}
|
||||
if (!Object.values(AccountSetAsfFlags).includes(tx.ClearFlag)) {
|
||||
throw new ValidationError('AccountSet: invalid ClearFlag')
|
||||
}
|
||||
}
|
||||
|
||||
if (tx.Domain !== undefined && typeof tx.Domain !== 'string') {
|
||||
throw new ValidationError('AccountSet: invalid Domain')
|
||||
}
|
||||
|
||||
if (tx.EmailHash !== undefined && typeof tx.EmailHash !== 'string') {
|
||||
throw new ValidationError('AccountSet: invalid EmailHash')
|
||||
}
|
||||
|
||||
if (tx.MessageKey !== undefined && typeof tx.MessageKey !== 'string') {
|
||||
throw new ValidationError('AccountSet: invalid MessageKey')
|
||||
}
|
||||
|
||||
if (tx.SetFlag !== undefined) {
|
||||
if (typeof tx.SetFlag !== 'number') {
|
||||
throw new ValidationError('AccountSet: invalid SetFlag')
|
||||
}
|
||||
if (!Object.values(AccountSetAsfFlags).includes(tx.SetFlag)) {
|
||||
throw new ValidationError('AccountSet: invalid SetFlag')
|
||||
}
|
||||
}
|
||||
|
||||
if (tx.TransferRate !== undefined && typeof tx.TransferRate !== 'number') {
|
||||
throw new ValidationError('AccountSet: invalid TransferRate')
|
||||
}
|
||||
|
||||
if (tx.TickSize !== undefined) {
|
||||
if (typeof tx.TickSize !== 'number') {
|
||||
throw new ValidationError('AccountSet: invalid TickSize')
|
||||
}
|
||||
if (
|
||||
tx.TickSize !== 0 &&
|
||||
(tx.TickSize < MIN_TICK_SIZE || tx.TickSize > MAX_TICK_SIZE)
|
||||
) {
|
||||
throw new ValidationError('AccountSet: invalid TickSize')
|
||||
}
|
||||
}
|
||||
}
|
||||
34
packages/xahau/src/models/transactions/checkCancel.ts
Normal file
34
packages/xahau/src/models/transactions/checkCancel.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import { ValidationError } from '../../errors'
|
||||
|
||||
import { BaseTransaction, validateBaseTransaction } from './common'
|
||||
|
||||
/**
|
||||
* Cancels an unredeemed Check, removing it from the ledger without sending any
|
||||
* money. The source or the destination of the check can cancel a Check at any
|
||||
* time using this transaction type. If the Check has expired, any address can
|
||||
* cancel it.
|
||||
*
|
||||
* @category Transaction Models
|
||||
*/
|
||||
export interface CheckCancel extends BaseTransaction {
|
||||
TransactionType: 'CheckCancel'
|
||||
/**
|
||||
* The ID of the Check ledger object to cancel as a 64-character hexadecimal
|
||||
* string.
|
||||
*/
|
||||
CheckID: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the form and type of an CheckCancel at runtime.
|
||||
*
|
||||
* @param tx - An CheckCancel Transaction.
|
||||
* @throws When the CheckCancel is Malformed.
|
||||
*/
|
||||
export function validateCheckCancel(tx: Record<string, unknown>): void {
|
||||
validateBaseTransaction(tx)
|
||||
|
||||
if (tx.CheckID !== undefined && typeof tx.CheckID !== 'string') {
|
||||
throw new ValidationError('CheckCancel: invalid CheckID')
|
||||
}
|
||||
}
|
||||
72
packages/xahau/src/models/transactions/checkCash.ts
Normal file
72
packages/xahau/src/models/transactions/checkCash.ts
Normal file
@@ -0,0 +1,72 @@
|
||||
import { ValidationError } from '../../errors'
|
||||
import { Amount } from '../common'
|
||||
|
||||
import { BaseTransaction, validateBaseTransaction, isAmount } from './common'
|
||||
|
||||
/**
|
||||
* Attempts to redeem a Check object in the ledger to receive up to the amount
|
||||
* authorized by the corresponding CheckCreate transaction. Only the Destination
|
||||
* address of a Check can cash it with a CheckCash transaction.
|
||||
*
|
||||
* @category Transaction Models
|
||||
*/
|
||||
export interface CheckCash extends BaseTransaction {
|
||||
TransactionType: 'CheckCash'
|
||||
/**
|
||||
* The ID of the Check ledger object to cash as a 64-character hexadecimal
|
||||
* string.
|
||||
*/
|
||||
CheckID: string
|
||||
/**
|
||||
* Redeem the Check for exactly this amount, if possible. The currency must
|
||||
* match that of the SendMax of the corresponding CheckCreate transaction. You.
|
||||
* must provide either this field or DeliverMin.
|
||||
*/
|
||||
Amount?: Amount
|
||||
/**
|
||||
* Redeem the Check for at least this amount and for as much as possible. The
|
||||
* currency must match that of the SendMax of the corresponding CheckCreate.
|
||||
* transaction. You must provide either this field or Amount.
|
||||
*/
|
||||
DeliverMin?: Amount
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the form and type of an CheckCash at runtime.
|
||||
*
|
||||
* @param tx - An CheckCash Transaction.
|
||||
* @throws When the CheckCash is Malformed.
|
||||
*/
|
||||
export function validateCheckCash(tx: Record<string, unknown>): void {
|
||||
validateBaseTransaction(tx)
|
||||
|
||||
if (tx.Amount == null && tx.DeliverMin == null) {
|
||||
throw new ValidationError(
|
||||
'CheckCash: must have either Amount or DeliverMin',
|
||||
)
|
||||
}
|
||||
|
||||
if (tx.Amount != null && tx.DeliverMin != null) {
|
||||
throw new ValidationError(
|
||||
'CheckCash: cannot have both Amount and DeliverMin',
|
||||
)
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- Necessary check
|
||||
if (tx.Amount != null && tx.Amount !== undefined && !isAmount(tx.Amount)) {
|
||||
throw new ValidationError('CheckCash: invalid Amount')
|
||||
}
|
||||
|
||||
if (
|
||||
tx.DeliverMin != null &&
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- Necessary check
|
||||
tx.DeliverMin !== undefined &&
|
||||
!isAmount(tx.DeliverMin)
|
||||
) {
|
||||
throw new ValidationError('CheckCash: invalid DeliverMin')
|
||||
}
|
||||
|
||||
if (tx.CheckID !== undefined && typeof tx.CheckID !== 'string') {
|
||||
throw new ValidationError('CheckCash: invalid CheckID')
|
||||
}
|
||||
}
|
||||
82
packages/xahau/src/models/transactions/checkCreate.ts
Normal file
82
packages/xahau/src/models/transactions/checkCreate.ts
Normal file
@@ -0,0 +1,82 @@
|
||||
import { ValidationError } from '../../errors'
|
||||
import { Amount } from '../common'
|
||||
|
||||
import {
|
||||
BaseTransaction,
|
||||
validateBaseTransaction,
|
||||
isIssuedCurrency,
|
||||
isAccount,
|
||||
validateRequiredField,
|
||||
validateOptionalField,
|
||||
isNumber,
|
||||
Account,
|
||||
} from './common'
|
||||
|
||||
/**
|
||||
* Create a Check object in the ledger, which is a deferred payment that can be
|
||||
* cashed by its intended destination. The sender of this transaction is the
|
||||
* sender of the Check.
|
||||
*
|
||||
* @category Transaction Models
|
||||
*/
|
||||
export interface CheckCreate extends BaseTransaction {
|
||||
TransactionType: 'CheckCreate'
|
||||
/** The unique address of the account that can cash the Check. */
|
||||
Destination: Account
|
||||
/**
|
||||
* Maximum amount of source currency the Check is allowed to debit the
|
||||
* sender, including transfer fees on non-XAH currencies. The Check can only
|
||||
* credit the destination with the same currency (from the same issuer, for
|
||||
* non-XAH currencies). For non-XAH amounts, the nested field names MUST be.
|
||||
* lower-case.
|
||||
*/
|
||||
SendMax: Amount
|
||||
/**
|
||||
* Arbitrary tag that identifies the reason for the Check, or a hosted.
|
||||
* recipient to pay.
|
||||
*/
|
||||
DestinationTag?: number
|
||||
/**
|
||||
* Time after which the Check is no longer valid, in seconds since the Ripple.
|
||||
* Epoch.
|
||||
*/
|
||||
Expiration?: number
|
||||
/**
|
||||
* Arbitrary 256-bit hash representing a specific reason or identifier for.
|
||||
* this Check.
|
||||
*/
|
||||
InvoiceID?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the form and type of an CheckCreate at runtime.
|
||||
*
|
||||
* @param tx - An CheckCreate Transaction.
|
||||
* @throws When the CheckCreate is Malformed.
|
||||
*/
|
||||
export function validateCheckCreate(tx: Record<string, unknown>): void {
|
||||
validateBaseTransaction(tx)
|
||||
|
||||
if (tx.SendMax === undefined) {
|
||||
throw new ValidationError('CheckCreate: missing field SendMax')
|
||||
}
|
||||
|
||||
validateRequiredField(tx, 'Destination', isAccount)
|
||||
validateOptionalField(tx, 'DestinationTag', isNumber)
|
||||
|
||||
if (
|
||||
typeof tx.SendMax !== 'string' &&
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Only used by JS
|
||||
!isIssuedCurrency(tx.SendMax as Record<string, unknown>)
|
||||
) {
|
||||
throw new ValidationError('CheckCreate: invalid SendMax')
|
||||
}
|
||||
|
||||
if (tx.Expiration !== undefined && typeof tx.Expiration !== 'number') {
|
||||
throw new ValidationError('CheckCreate: invalid Expiration')
|
||||
}
|
||||
|
||||
if (tx.InvoiceID !== undefined && typeof tx.InvoiceID !== 'string') {
|
||||
throw new ValidationError('CheckCreate: invalid InvoiceID')
|
||||
}
|
||||
}
|
||||
368
packages/xahau/src/models/transactions/common.ts
Normal file
368
packages/xahau/src/models/transactions/common.ts
Normal file
@@ -0,0 +1,368 @@
|
||||
import { isValidClassicAddress, isValidXAddress } from 'xahau-address-codec'
|
||||
import { TRANSACTION_TYPES } from 'xahau-binary-codec'
|
||||
|
||||
import { ValidationError } from '../../errors'
|
||||
import {
|
||||
Amount,
|
||||
Currency,
|
||||
IssuedCurrencyAmount,
|
||||
Memo,
|
||||
Signer,
|
||||
XChainBridge,
|
||||
} from '../common'
|
||||
import { onlyHasFields } from '../utils'
|
||||
|
||||
const MEMO_SIZE = 3
|
||||
|
||||
function isMemo(obj: { Memo?: unknown }): boolean {
|
||||
if (obj.Memo == null) {
|
||||
return false
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Only used by JS
|
||||
const memo = obj.Memo as Record<string, unknown>
|
||||
const size = Object.keys(memo).length
|
||||
const validData = memo.MemoData == null || typeof memo.MemoData === 'string'
|
||||
const validFormat =
|
||||
memo.MemoFormat == null || typeof memo.MemoFormat === 'string'
|
||||
const validType = memo.MemoType == null || typeof memo.MemoType === 'string'
|
||||
|
||||
return (
|
||||
size >= 1 &&
|
||||
size <= MEMO_SIZE &&
|
||||
validData &&
|
||||
validFormat &&
|
||||
validType &&
|
||||
onlyHasFields(memo, ['MemoFormat', 'MemoData', 'MemoType'])
|
||||
)
|
||||
}
|
||||
|
||||
const SIGNER_SIZE = 3
|
||||
|
||||
function isSigner(obj: unknown): boolean {
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Only used by JS
|
||||
const signerWrapper = obj as Record<string, unknown>
|
||||
|
||||
if (signerWrapper.Signer == null) {
|
||||
return false
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Only used by JS and Signer is previously unknown
|
||||
const signer = signerWrapper.Signer as Record<string, unknown>
|
||||
return (
|
||||
Object.keys(signer).length === SIGNER_SIZE &&
|
||||
typeof signer.Account === 'string' &&
|
||||
typeof signer.TxnSignature === 'string' &&
|
||||
typeof signer.SigningPubKey === 'string'
|
||||
)
|
||||
}
|
||||
|
||||
const XAH_CURRENCY_SIZE = 1
|
||||
const ISSUE_SIZE = 2
|
||||
const ISSUED_CURRENCY_SIZE = 3
|
||||
const XCHAIN_BRIDGE_SIZE = 4
|
||||
|
||||
function isRecord(value: unknown): value is Record<string, unknown> {
|
||||
return value !== null && typeof value === 'object'
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the form and type of a string at runtime.
|
||||
*
|
||||
* @param str - The object to check the form and type of.
|
||||
* @returns Whether the string is properly formed.
|
||||
*/
|
||||
export function isString(str: unknown): str is string {
|
||||
return typeof str === 'string'
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the form and type of a number at runtime.
|
||||
*
|
||||
* @param num - The object to check the form and type of.
|
||||
* @returns Whether the number is properly formed.
|
||||
*/
|
||||
export function isNumber(num: unknown): num is number {
|
||||
return typeof num === 'number'
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the form and type of an IssuedCurrency at runtime.
|
||||
*
|
||||
* @param input - The input to check the form and type of.
|
||||
* @returns Whether the IssuedCurrency is properly formed.
|
||||
*/
|
||||
export function isCurrency(input: unknown): input is Currency {
|
||||
return (
|
||||
isRecord(input) &&
|
||||
((Object.keys(input).length === ISSUE_SIZE &&
|
||||
typeof input.issuer === 'string' &&
|
||||
typeof input.currency === 'string') ||
|
||||
(Object.keys(input).length === XAH_CURRENCY_SIZE &&
|
||||
input.currency === 'XAH'))
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the form and type of an IssuedCurrencyAmount at runtime.
|
||||
*
|
||||
* @param input - The input to check the form and type of.
|
||||
* @returns Whether the IssuedCurrencyAmount is properly formed.
|
||||
*/
|
||||
export function isIssuedCurrency(
|
||||
input: unknown,
|
||||
): input is IssuedCurrencyAmount {
|
||||
return (
|
||||
isRecord(input) &&
|
||||
Object.keys(input).length === ISSUED_CURRENCY_SIZE &&
|
||||
typeof input.value === 'string' &&
|
||||
typeof input.issuer === 'string' &&
|
||||
typeof input.currency === 'string'
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Must be a valid account address
|
||||
*/
|
||||
export type Account = string
|
||||
|
||||
/**
|
||||
* Verify a string is in fact a valid account address.
|
||||
*
|
||||
* @param account - The object to check the form and type of.
|
||||
* @returns Whether the account is properly formed account for a transaction.
|
||||
*/
|
||||
export function isAccount(account: unknown): account is Account {
|
||||
return (
|
||||
typeof account === 'string' &&
|
||||
(isValidClassicAddress(account) || isValidXAddress(account))
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the form and type of an Amount at runtime.
|
||||
*
|
||||
* @param amount - The object to check the form and type of.
|
||||
* @returns Whether the Amount is properly formed.
|
||||
*/
|
||||
export function isAmount(amount: unknown): amount is Amount {
|
||||
return typeof amount === 'string' || isIssuedCurrency(amount)
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the form and type of an XChainBridge at runtime.
|
||||
*
|
||||
* @param input - The input to check the form and type of.
|
||||
* @returns Whether the XChainBridge is properly formed.
|
||||
*/
|
||||
export function isXChainBridge(input: unknown): input is XChainBridge {
|
||||
return (
|
||||
isRecord(input) &&
|
||||
Object.keys(input).length === XCHAIN_BRIDGE_SIZE &&
|
||||
typeof input.LockingChainDoor === 'string' &&
|
||||
isCurrency(input.LockingChainIssue) &&
|
||||
typeof input.IssuingChainDoor === 'string' &&
|
||||
isCurrency(input.IssuingChainIssue)
|
||||
)
|
||||
}
|
||||
|
||||
/* eslint-disable @typescript-eslint/restrict-template-expressions -- tx.TransactionType is checked before any calls */
|
||||
|
||||
/**
|
||||
* Verify the form and type of a required type for a transaction at runtime.
|
||||
*
|
||||
* @param tx - The transaction input to check the form and type of.
|
||||
* @param paramName - The name of the transaction parameter.
|
||||
* @param checkValidity - The function to use to check the type.
|
||||
* @throws
|
||||
*/
|
||||
export function validateRequiredField(
|
||||
tx: Record<string, unknown>,
|
||||
paramName: string,
|
||||
checkValidity: (inp: unknown) => boolean,
|
||||
): void {
|
||||
if (tx[paramName] == null) {
|
||||
throw new ValidationError(
|
||||
`${tx.TransactionType}: missing field ${paramName}`,
|
||||
)
|
||||
}
|
||||
|
||||
if (!checkValidity(tx[paramName])) {
|
||||
throw new ValidationError(
|
||||
`${tx.TransactionType}: invalid field ${paramName}`,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the form and type of an optional type for a transaction at runtime.
|
||||
*
|
||||
* @param tx - The transaction input to check the form and type of.
|
||||
* @param paramName - The name of the transaction parameter.
|
||||
* @param checkValidity - The function to use to check the type.
|
||||
* @throws
|
||||
*/
|
||||
export function validateOptionalField(
|
||||
tx: Record<string, unknown>,
|
||||
paramName: string,
|
||||
checkValidity: (inp: unknown) => boolean,
|
||||
): void {
|
||||
if (tx[paramName] !== undefined && !checkValidity(tx[paramName])) {
|
||||
throw new ValidationError(
|
||||
`${tx.TransactionType}: invalid field ${paramName}`,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/* eslint-enable @typescript-eslint/restrict-template-expressions -- checked before */
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-interface -- no global flags right now, so this is fine
|
||||
export interface GlobalFlags {}
|
||||
|
||||
/**
|
||||
* Every transaction has the same set of common fields.
|
||||
*/
|
||||
export interface BaseTransaction {
|
||||
/** The unique address of the transaction sender. */
|
||||
Account: Account
|
||||
/**
|
||||
* The type of transaction. Valid types include: `Payment`, `OfferCreate`,
|
||||
* `TrustSet`, and many others.
|
||||
*/
|
||||
TransactionType: string
|
||||
/**
|
||||
* Integer amount of XAH, in drops, to be destroyed as a cost for
|
||||
* distributing this transaction to the network. Some transaction types have
|
||||
* different minimum requirements.
|
||||
*/
|
||||
Fee?: string
|
||||
/**
|
||||
* The sequence number of the account sending the transaction. A transaction
|
||||
* is only valid if the Sequence number is exactly 1 greater than the previous
|
||||
* transaction from the same account. The special case 0 means the transaction
|
||||
* is using a Ticket instead.
|
||||
*/
|
||||
Sequence?: number
|
||||
/**
|
||||
* Hash value identifying another transaction. If provided, this transaction
|
||||
* is only valid if the sending account's previously-sent transaction matches
|
||||
* the provided hash.
|
||||
*/
|
||||
AccountTxnID?: string
|
||||
/** Set of bit-flags for this transaction. */
|
||||
Flags?: number | GlobalFlags
|
||||
/**
|
||||
* Highest ledger index this transaction can appear in. Specifying this field
|
||||
* places a strict upper limit on how long the transaction can wait to be
|
||||
* validated or rejected.
|
||||
*/
|
||||
LastLedgerSequence?: number
|
||||
/**
|
||||
* Additional arbitrary information used to identify this transaction.
|
||||
*/
|
||||
Memos?: Memo[]
|
||||
/**
|
||||
* Array of objects that represent a multi-signature which authorizes this
|
||||
* transaction.
|
||||
*/
|
||||
Signers?: Signer[]
|
||||
/**
|
||||
* Arbitrary integer used to identify the reason for this payment, or a sender
|
||||
* on whose behalf this transaction is made. Conventionally, a refund should
|
||||
* specify the initial payment's SourceTag as the refund payment's
|
||||
* DestinationTag.
|
||||
*/
|
||||
SourceTag?: number
|
||||
/**
|
||||
* Hex representation of the public key that corresponds to the private key
|
||||
* used to sign this transaction. If an empty string, indicates a
|
||||
* multi-signature is present in the Signers field instead.
|
||||
*/
|
||||
SigningPubKey?: string
|
||||
/**
|
||||
* The sequence number of the ticket to use in place of a Sequence number. If
|
||||
* this is provided, Sequence must be 0. Cannot be used with AccountTxnID.
|
||||
*/
|
||||
TicketSequence?: number
|
||||
/**
|
||||
* The signature that verifies this transaction as originating from the
|
||||
* account it says it is from.
|
||||
*/
|
||||
TxnSignature?: string
|
||||
/**
|
||||
* The network id of the transaction.
|
||||
*/
|
||||
NetworkID?: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the common fields of a transaction. The validate functionality will be
|
||||
* optional, and will check transaction form at runtime. This should be called
|
||||
* any time a transaction will be verified.
|
||||
*
|
||||
* @param common - An interface w/ common transaction fields.
|
||||
* @throws When the common param is malformed.
|
||||
*/
|
||||
export function validateBaseTransaction(common: Record<string, unknown>): void {
|
||||
if (common.TransactionType === undefined) {
|
||||
throw new ValidationError('BaseTransaction: missing field TransactionType')
|
||||
}
|
||||
|
||||
if (typeof common.TransactionType !== 'string') {
|
||||
throw new ValidationError('BaseTransaction: TransactionType not string')
|
||||
}
|
||||
|
||||
if (!TRANSACTION_TYPES.includes(common.TransactionType)) {
|
||||
throw new ValidationError('BaseTransaction: Unknown TransactionType')
|
||||
}
|
||||
|
||||
validateRequiredField(common, 'Account', isString)
|
||||
|
||||
validateOptionalField(common, 'Fee', isString)
|
||||
|
||||
validateOptionalField(common, 'Sequence', isNumber)
|
||||
|
||||
validateOptionalField(common, 'AccountTxnID', isString)
|
||||
|
||||
validateOptionalField(common, 'LastLedgerSequence', isNumber)
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Only used by JS
|
||||
const memos = common.Memos as Array<{ Memo?: unknown }> | undefined
|
||||
if (memos !== undefined && !memos.every(isMemo)) {
|
||||
throw new ValidationError('BaseTransaction: invalid Memos')
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Only used by JS
|
||||
const signers = common.Signers as Array<Record<string, unknown>> | undefined
|
||||
|
||||
if (
|
||||
signers !== undefined &&
|
||||
(signers.length === 0 || !signers.every(isSigner))
|
||||
) {
|
||||
throw new ValidationError('BaseTransaction: invalid Signers')
|
||||
}
|
||||
|
||||
validateOptionalField(common, 'SourceTag', isNumber)
|
||||
|
||||
validateOptionalField(common, 'SigningPubKey', isString)
|
||||
|
||||
validateOptionalField(common, 'TicketSequence', isNumber)
|
||||
|
||||
validateOptionalField(common, 'TxnSignature', isString)
|
||||
|
||||
validateOptionalField(common, 'NetworkID', isNumber)
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the value of an amount, expressed either in XAH or as an Issued Currency, into a number.
|
||||
*
|
||||
* @param amount - An Amount to parse for its value.
|
||||
* @returns The parsed amount value, or NaN if the amount count not be parsed.
|
||||
*/
|
||||
export function parseAmountValue(amount: unknown): number {
|
||||
if (!isAmount(amount)) {
|
||||
return NaN
|
||||
}
|
||||
if (typeof amount === 'string') {
|
||||
return parseFloat(amount)
|
||||
}
|
||||
return parseFloat(amount.value)
|
||||
}
|
||||
67
packages/xahau/src/models/transactions/depositPreauth.ts
Normal file
67
packages/xahau/src/models/transactions/depositPreauth.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
import { ValidationError } from '../../errors'
|
||||
|
||||
import { BaseTransaction, validateBaseTransaction } from './common'
|
||||
|
||||
/**
|
||||
* A DepositPreauth transaction gives another account pre-approval to deliver
|
||||
* payments to the sender of this transaction. This is only useful if the sender
|
||||
* of this transaction is using (or plans to use) Deposit Authorization.
|
||||
*
|
||||
* @category Transaction Models
|
||||
*/
|
||||
export interface DepositPreauth extends BaseTransaction {
|
||||
TransactionType: 'DepositPreauth'
|
||||
/** The XAH Ledger address of the sender to preauthorize. */
|
||||
Authorize?: string
|
||||
/**
|
||||
* The XAH Ledger address of a sender whose preauthorization should be.
|
||||
* revoked.
|
||||
*/
|
||||
Unauthorize?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the form and type of a DepositPreauth at runtime.
|
||||
*
|
||||
* @param tx - A DepositPreauth Transaction.
|
||||
* @throws When the DepositPreauth is malformed.
|
||||
*/
|
||||
export function validateDepositPreauth(tx: Record<string, unknown>): void {
|
||||
validateBaseTransaction(tx)
|
||||
|
||||
if (tx.Authorize !== undefined && tx.Unauthorize !== undefined) {
|
||||
throw new ValidationError(
|
||||
"DepositPreauth: can't provide both Authorize and Unauthorize fields",
|
||||
)
|
||||
}
|
||||
|
||||
if (tx.Authorize === undefined && tx.Unauthorize === undefined) {
|
||||
throw new ValidationError(
|
||||
'DepositPreauth: must provide either Authorize or Unauthorize field',
|
||||
)
|
||||
}
|
||||
|
||||
if (tx.Authorize !== undefined) {
|
||||
if (typeof tx.Authorize !== 'string') {
|
||||
throw new ValidationError('DepositPreauth: Authorize must be a string')
|
||||
}
|
||||
|
||||
if (tx.Account === tx.Authorize) {
|
||||
throw new ValidationError(
|
||||
"DepositPreauth: Account can't preauthorize its own address",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (tx.Unauthorize !== undefined) {
|
||||
if (typeof tx.Unauthorize !== 'string') {
|
||||
throw new ValidationError('DepositPreauth: Unauthorize must be a string')
|
||||
}
|
||||
|
||||
if (tx.Account === tx.Unauthorize) {
|
||||
throw new ValidationError(
|
||||
"DepositPreauth: Account can't unauthorize its own address",
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
26
packages/xahau/src/models/transactions/enableAmendment.ts
Normal file
26
packages/xahau/src/models/transactions/enableAmendment.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { BaseTransaction } from './common'
|
||||
|
||||
/**
|
||||
* Transaction Flags for an EnableAmendment Transaction.
|
||||
*
|
||||
* @category Transaction Flags
|
||||
*/
|
||||
export enum EnableAmendmentFlags {
|
||||
/** Support for this amendment increased to at least 80% of trusted validators starting with this ledger version. */
|
||||
tfGotMajority = 0x00010000,
|
||||
/** Support for this amendment decreased to less than 80% of trusted validators starting with this ledger version. */
|
||||
tfLostMajority = 0x00020000,
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark a change in the status of a proposed amendment when it gains majority, looses majority, or is enabled.
|
||||
*
|
||||
* @category Pseudo Transaction Models
|
||||
*/
|
||||
export interface EnableAmendment extends BaseTransaction {
|
||||
TransactionType: 'EnableAmendment'
|
||||
/** A unique identifier for the amendment. */
|
||||
Amendment: string
|
||||
/** The ledger index where this pseudo-transaction appears. */
|
||||
LedgerSequence: number
|
||||
}
|
||||
49
packages/xahau/src/models/transactions/escrowCancel.ts
Normal file
49
packages/xahau/src/models/transactions/escrowCancel.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import { ValidationError } from '../../errors'
|
||||
|
||||
import {
|
||||
Account,
|
||||
BaseTransaction,
|
||||
isAccount,
|
||||
validateBaseTransaction,
|
||||
validateRequiredField,
|
||||
} from './common'
|
||||
|
||||
/**
|
||||
* Return escrowed XAH to the sender.
|
||||
*
|
||||
* @category Transaction Models
|
||||
*/
|
||||
export interface EscrowCancel extends BaseTransaction {
|
||||
TransactionType: 'EscrowCancel'
|
||||
/** Address of the source account that funded the escrow payment. */
|
||||
Owner: Account
|
||||
/**
|
||||
* Transaction sequence (or Ticket number) of EscrowCreate transaction that.
|
||||
* created the escrow to cancel.
|
||||
*/
|
||||
OfferSequence: number | string
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the form and type of an EscrowCancel at runtime.
|
||||
*
|
||||
* @param tx - An EscrowCancel Transaction.
|
||||
* @throws When the EscrowCancel is Malformed.
|
||||
*/
|
||||
export function validateEscrowCancel(tx: Record<string, unknown>): void {
|
||||
validateBaseTransaction(tx)
|
||||
|
||||
validateRequiredField(tx, 'Owner', isAccount)
|
||||
|
||||
if (tx.OfferSequence == null) {
|
||||
throw new ValidationError('EscrowCancel: missing OfferSequence')
|
||||
}
|
||||
|
||||
if (
|
||||
(typeof tx.OfferSequence !== 'number' &&
|
||||
typeof tx.OfferSequence !== 'string') ||
|
||||
Number.isNaN(Number(tx.OfferSequence))
|
||||
) {
|
||||
throw new ValidationError('EscrowCancel: OfferSequence must be a number')
|
||||
}
|
||||
}
|
||||
95
packages/xahau/src/models/transactions/escrowCreate.ts
Normal file
95
packages/xahau/src/models/transactions/escrowCreate.ts
Normal file
@@ -0,0 +1,95 @@
|
||||
import { ValidationError } from '../../errors'
|
||||
|
||||
import {
|
||||
Account,
|
||||
BaseTransaction,
|
||||
isAccount,
|
||||
isNumber,
|
||||
validateBaseTransaction,
|
||||
validateOptionalField,
|
||||
validateRequiredField,
|
||||
} from './common'
|
||||
|
||||
/**
|
||||
* Sequester XAH until the escrow process either finishes or is canceled.
|
||||
*
|
||||
* @category Transaction Models
|
||||
*/
|
||||
export interface EscrowCreate extends BaseTransaction {
|
||||
TransactionType: 'EscrowCreate'
|
||||
/**
|
||||
* Amount of XAH, in drops, to deduct from the sender's balance and escrow.
|
||||
* Once escrowed, the XAH can either go to the Destination address (after the.
|
||||
* FinishAfter time) or returned to the sender (after the CancelAfter time).
|
||||
*/
|
||||
Amount: string
|
||||
/** Address to receive escrowed XAH. */
|
||||
Destination: Account
|
||||
/**
|
||||
* The time, in seconds since the Ripple Epoch, when this escrow expires.
|
||||
* This value is immutable; the funds can only be returned the sender after.
|
||||
* this time.
|
||||
*/
|
||||
CancelAfter?: number
|
||||
/**
|
||||
* The time, in seconds since the Ripple Epoch, when the escrowed XAH can be
|
||||
* released to the recipient. This value is immutable; the funds cannot move.
|
||||
* until this time is reached.
|
||||
*/
|
||||
FinishAfter?: number
|
||||
/**
|
||||
* Hex value representing a PREIMAGE-SHA-256 crypto-condition . The funds can.
|
||||
* only be delivered to the recipient if this condition is fulfilled.
|
||||
*/
|
||||
Condition?: string
|
||||
/**
|
||||
* Arbitrary tag to further specify the destination for this escrowed.
|
||||
* payment, such as a hosted recipient at the destination address.
|
||||
*/
|
||||
DestinationTag?: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the form and type of an EscrowCreate at runtime.
|
||||
*
|
||||
* @param tx - An EscrowCreate Transaction.
|
||||
* @throws When the EscrowCreate is Malformed.
|
||||
*/
|
||||
export function validateEscrowCreate(tx: Record<string, unknown>): void {
|
||||
validateBaseTransaction(tx)
|
||||
|
||||
if (tx.Amount === undefined) {
|
||||
throw new ValidationError('EscrowCreate: missing field Amount')
|
||||
}
|
||||
|
||||
if (typeof tx.Amount !== 'string') {
|
||||
throw new ValidationError('EscrowCreate: Amount must be a string')
|
||||
}
|
||||
|
||||
validateRequiredField(tx, 'Destination', isAccount)
|
||||
validateOptionalField(tx, 'DestinationTag', isNumber)
|
||||
|
||||
if (tx.CancelAfter === undefined && tx.FinishAfter === undefined) {
|
||||
throw new ValidationError(
|
||||
'EscrowCreate: Either CancelAfter or FinishAfter must be specified',
|
||||
)
|
||||
}
|
||||
|
||||
if (tx.FinishAfter === undefined && tx.Condition === undefined) {
|
||||
throw new ValidationError(
|
||||
'EscrowCreate: Either Condition or FinishAfter must be specified',
|
||||
)
|
||||
}
|
||||
|
||||
if (tx.CancelAfter !== undefined && typeof tx.CancelAfter !== 'number') {
|
||||
throw new ValidationError('EscrowCreate: CancelAfter must be a number')
|
||||
}
|
||||
|
||||
if (tx.FinishAfter !== undefined && typeof tx.FinishAfter !== 'number') {
|
||||
throw new ValidationError('EscrowCreate: FinishAfter must be a number')
|
||||
}
|
||||
|
||||
if (tx.Condition !== undefined && typeof tx.Condition !== 'string') {
|
||||
throw new ValidationError('EscrowCreate: Condition must be a string')
|
||||
}
|
||||
}
|
||||
67
packages/xahau/src/models/transactions/escrowFinish.ts
Normal file
67
packages/xahau/src/models/transactions/escrowFinish.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
import { ValidationError } from '../../errors'
|
||||
|
||||
import {
|
||||
Account,
|
||||
BaseTransaction,
|
||||
isAccount,
|
||||
validateBaseTransaction,
|
||||
validateRequiredField,
|
||||
} from './common'
|
||||
|
||||
/**
|
||||
* Deliver XAH from a held payment to the recipient.
|
||||
*
|
||||
* @category Transaction Models
|
||||
*/
|
||||
export interface EscrowFinish extends BaseTransaction {
|
||||
TransactionType: 'EscrowFinish'
|
||||
/** Address of the source account that funded the held payment. */
|
||||
Owner: Account
|
||||
/**
|
||||
* Transaction sequence of EscrowCreate transaction that created the held.
|
||||
* payment to finish.
|
||||
*/
|
||||
OfferSequence: number | string
|
||||
/**
|
||||
* Hex value matching the previously-supplied PREIMAGE-SHA-256.
|
||||
* crypto-condition of the held payment.
|
||||
*/
|
||||
Condition?: string
|
||||
/**
|
||||
* Hex value of the PREIMAGE-SHA-256 crypto-condition fulfillment matching.
|
||||
* the held payment's Condition.
|
||||
*/
|
||||
Fulfillment?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the form and type of an EscrowFinish at runtime.
|
||||
*
|
||||
* @param tx - An EscrowFinish Transaction.
|
||||
* @throws When the EscrowFinish is Malformed.
|
||||
*/
|
||||
export function validateEscrowFinish(tx: Record<string, unknown>): void {
|
||||
validateBaseTransaction(tx)
|
||||
|
||||
validateRequiredField(tx, 'Owner', isAccount)
|
||||
|
||||
if (tx.OfferSequence == null) {
|
||||
throw new ValidationError('EscrowFinish: missing field OfferSequence')
|
||||
}
|
||||
|
||||
if (
|
||||
(typeof tx.OfferSequence !== 'number' &&
|
||||
typeof tx.OfferSequence !== 'string') ||
|
||||
Number.isNaN(Number(tx.OfferSequence))
|
||||
) {
|
||||
throw new ValidationError('EscrowFinish: OfferSequence must be a number')
|
||||
}
|
||||
|
||||
if (tx.Condition !== undefined && typeof tx.Condition !== 'string') {
|
||||
throw new ValidationError('EscrowFinish: Condition must be a string')
|
||||
}
|
||||
|
||||
if (tx.Fulfillment !== undefined && typeof tx.Fulfillment !== 'string') {
|
||||
throw new ValidationError('EscrowFinish: Fulfillment must be a string')
|
||||
}
|
||||
}
|
||||
43
packages/xahau/src/models/transactions/index.ts
Normal file
43
packages/xahau/src/models/transactions/index.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
export { BaseTransaction } from './common'
|
||||
export {
|
||||
validate,
|
||||
PseudoTransaction,
|
||||
SubmittableTransaction,
|
||||
TransactionAndMetadata,
|
||||
Transaction,
|
||||
} from './transaction'
|
||||
export * from './metadata'
|
||||
export {
|
||||
AccountSetAsfFlags,
|
||||
AccountSetTfFlags,
|
||||
AccountSetFlagsInterface,
|
||||
AccountSet,
|
||||
} from './accountSet'
|
||||
export { CheckCancel } from './checkCancel'
|
||||
export { CheckCash } from './checkCash'
|
||||
export { CheckCreate } from './checkCreate'
|
||||
export { DepositPreauth } from './depositPreauth'
|
||||
export { EscrowCancel } from './escrowCancel'
|
||||
export { EscrowCreate } from './escrowCreate'
|
||||
export { EscrowFinish } from './escrowFinish'
|
||||
export { EnableAmendment, EnableAmendmentFlags } from './enableAmendment'
|
||||
export { OfferCancel } from './offerCancel'
|
||||
export {
|
||||
OfferCreateFlags,
|
||||
OfferCreateFlagsInterface,
|
||||
OfferCreate,
|
||||
} from './offerCreate'
|
||||
export { PaymentFlags, PaymentFlagsInterface, Payment } from './payment'
|
||||
export {
|
||||
PaymentChannelClaimFlags,
|
||||
PaymentChannelClaimFlagsInterface,
|
||||
PaymentChannelClaim,
|
||||
} from './paymentChannelClaim'
|
||||
export { PaymentChannelCreate } from './paymentChannelCreate'
|
||||
export { PaymentChannelFund } from './paymentChannelFund'
|
||||
export { SetFee, SetFeePreAmendment, SetFeePostAmendment } from './setFee'
|
||||
export { SetRegularKey } from './setRegularKey'
|
||||
export { SignerListSet } from './signerListSet'
|
||||
export { TicketCreate } from './ticketCreate'
|
||||
export { TrustSetFlagsInterface, TrustSetFlags, TrustSet } from './trustSet'
|
||||
export { UNLModify } from './UNLModify'
|
||||
77
packages/xahau/src/models/transactions/metadata.ts
Normal file
77
packages/xahau/src/models/transactions/metadata.ts
Normal file
@@ -0,0 +1,77 @@
|
||||
import { Amount } from '../common'
|
||||
|
||||
import { BaseTransaction } from './common'
|
||||
import { Payment, PaymentMetadata } from './payment'
|
||||
import type { Transaction } from './transaction'
|
||||
|
||||
export interface CreatedNode {
|
||||
CreatedNode: {
|
||||
LedgerEntryType: string
|
||||
LedgerIndex: string
|
||||
NewFields: { [field: string]: unknown }
|
||||
}
|
||||
}
|
||||
|
||||
export interface ModifiedNode {
|
||||
ModifiedNode: {
|
||||
LedgerEntryType: string
|
||||
LedgerIndex: string
|
||||
FinalFields?: { [field: string]: unknown }
|
||||
PreviousFields?: { [field: string]: unknown }
|
||||
PreviousTxnID?: string
|
||||
PreviousTxnLgrSeq?: number
|
||||
}
|
||||
}
|
||||
|
||||
export interface DeletedNode {
|
||||
DeletedNode: {
|
||||
LedgerEntryType: string
|
||||
LedgerIndex: string
|
||||
PreviousFields?: { [field: string]: unknown }
|
||||
FinalFields: { [field: string]: unknown }
|
||||
}
|
||||
}
|
||||
|
||||
export type Node = CreatedNode | ModifiedNode | DeletedNode
|
||||
|
||||
/**
|
||||
* A typeguard to check if a node is a CreatedNode.
|
||||
*
|
||||
* @param node - A node from metadata.
|
||||
* @returns whether the given node is a CreatedNode.
|
||||
*/
|
||||
export function isCreatedNode(node: Node): node is CreatedNode {
|
||||
return Object.prototype.hasOwnProperty.call(node, `CreatedNode`)
|
||||
}
|
||||
|
||||
/**
|
||||
* A typeguard to check if a node is a ModifiedNode.
|
||||
*
|
||||
* @param node - A node from metadata.
|
||||
* @returns whether the given node is a ModifiedNode.
|
||||
*/
|
||||
export function isModifiedNode(node: Node): node is ModifiedNode {
|
||||
return Object.prototype.hasOwnProperty.call(node, `ModifiedNode`)
|
||||
}
|
||||
|
||||
/**
|
||||
* A typeguard to check if a node is a DeletedNode.
|
||||
*
|
||||
* @param node - A node from metadata.
|
||||
* @returns whether the given node is a DeletedNode.
|
||||
*/
|
||||
export function isDeletedNode(node: Node): node is DeletedNode {
|
||||
return Object.prototype.hasOwnProperty.call(node, `DeletedNode`)
|
||||
}
|
||||
|
||||
export interface TransactionMetadataBase {
|
||||
AffectedNodes: Node[]
|
||||
DeliveredAmount?: Amount
|
||||
// "unavailable" possible for transactions before 2014-01-20
|
||||
delivered_amount?: Amount | 'unavailable'
|
||||
TransactionIndex: number
|
||||
TransactionResult: string
|
||||
}
|
||||
|
||||
export type TransactionMetadata<T extends BaseTransaction = Transaction> =
|
||||
T extends Payment ? PaymentMetadata : TransactionMetadataBase
|
||||
37
packages/xahau/src/models/transactions/offerCancel.ts
Normal file
37
packages/xahau/src/models/transactions/offerCancel.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import { ValidationError } from '../../errors'
|
||||
|
||||
import { BaseTransaction, validateBaseTransaction } from './common'
|
||||
|
||||
/**
|
||||
* An OfferCancel transaction removes an Offer object from the XAH Ledger.
|
||||
*
|
||||
* @category Transaction Models
|
||||
*/
|
||||
export interface OfferCancel extends BaseTransaction {
|
||||
TransactionType: 'OfferCancel'
|
||||
/**
|
||||
* The sequence number (or Ticket number) of a previous OfferCreate
|
||||
* transaction. If specified, cancel any offer object in the ledger that was
|
||||
* created by that transaction. It is not considered an error if the offer.
|
||||
* specified does not exist.
|
||||
*/
|
||||
OfferSequence: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the form and type of an OfferCancel at runtime.
|
||||
*
|
||||
* @param tx - An OfferCancel Transaction.
|
||||
* @throws When the OfferCancel is Malformed.
|
||||
*/
|
||||
export function validateOfferCancel(tx: Record<string, unknown>): void {
|
||||
validateBaseTransaction(tx)
|
||||
|
||||
if (tx.OfferSequence === undefined) {
|
||||
throw new ValidationError('OfferCancel: missing field OfferSequence')
|
||||
}
|
||||
|
||||
if (typeof tx.OfferSequence !== 'number') {
|
||||
throw new ValidationError('OfferCancel: OfferSequence must be a number')
|
||||
}
|
||||
}
|
||||
143
packages/xahau/src/models/transactions/offerCreate.ts
Normal file
143
packages/xahau/src/models/transactions/offerCreate.ts
Normal file
@@ -0,0 +1,143 @@
|
||||
import { ValidationError } from '../../errors'
|
||||
import { Amount } from '../common'
|
||||
|
||||
import {
|
||||
BaseTransaction,
|
||||
GlobalFlags,
|
||||
validateBaseTransaction,
|
||||
isAmount,
|
||||
} from './common'
|
||||
|
||||
/**
|
||||
* Transaction Flags for an OfferCreate Transaction.
|
||||
*
|
||||
* @category Transaction Flags
|
||||
*/
|
||||
export enum OfferCreateFlags {
|
||||
/**
|
||||
* If enabled, the offer does not consume offers that exactly match it, and
|
||||
* instead becomes an Offer object in the ledger. It still consumes offers
|
||||
* that cross it.
|
||||
*/
|
||||
tfPassive = 0x00010000,
|
||||
/**
|
||||
* Treat the offer as an Immediate or Cancel order. If enabled, the offer
|
||||
* never becomes a ledger object: it only tries to match existing offers in
|
||||
* the ledger. If the offer cannot match any offers immediately, it executes
|
||||
* "successfully" without trading any currency. In this case, the transaction
|
||||
* has the result code tesSUCCESS, but creates no Offer objects in the ledger.
|
||||
*/
|
||||
tfImmediateOrCancel = 0x00020000,
|
||||
/**
|
||||
* Treat the offer as a Fill or Kill order . Only try to match existing
|
||||
* offers in the ledger, and only do so if the entire TakerPays quantity can
|
||||
* be obtained. If the fix1578 amendment is enabled and the offer cannot be
|
||||
* executed when placed, the transaction has the result code tecKILLED;
|
||||
* otherwise, the transaction uses the result code tesSUCCESS even when it was
|
||||
* killed without trading any currency.
|
||||
*/
|
||||
tfFillOrKill = 0x00040000,
|
||||
/**
|
||||
* Exchange the entire TakerGets amount, even if it means obtaining more than
|
||||
* the TakerPays amount in exchange.
|
||||
*/
|
||||
tfSell = 0x00080000,
|
||||
}
|
||||
|
||||
/**
|
||||
* Map of flags to boolean values representing {@link OfferCreate} transaction
|
||||
* flags.
|
||||
*
|
||||
* @category Transaction Flags
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const tx: OfferCreate = {
|
||||
* Account: 'rhFcpWDHLqpBmX4ezWiA5VLSS4e1BHqhHd',
|
||||
* TakerGets: '43000.51',
|
||||
* TakerPays: '12928290425',
|
||||
* TransactionType: 'OfferCreate',
|
||||
* Flags: {
|
||||
* tfPassive: true,
|
||||
* tfFillOrKill: true,
|
||||
* },
|
||||
* }
|
||||
*
|
||||
* // Autofill the tx to see how flags actually look compared to the interface usage.
|
||||
* const autofilledTx = await client.autofill(tx)
|
||||
* console.log(autofilledTx)
|
||||
* // {
|
||||
* // Account: 'rhFcpWDHLqpBmX4ezWiA5VLSS4e1BHqhHd',
|
||||
* // TakerGets: '43000.51',
|
||||
* // TakerPays: '12928290425',
|
||||
* // TransactionType: 'OfferCreate',
|
||||
* // Flags: 327680,
|
||||
* // Sequence: 21970384,
|
||||
* // Fee: '12',
|
||||
* // LastLedgerSequence: 21970404
|
||||
* // }
|
||||
* ```
|
||||
*/
|
||||
export interface OfferCreateFlagsInterface extends GlobalFlags {
|
||||
tfPassive?: boolean
|
||||
tfImmediateOrCancel?: boolean
|
||||
tfFillOrKill?: boolean
|
||||
tfSell?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* An OfferCreate transaction is effectively a limit order . It defines an
|
||||
* intent to exchange currencies, and creates an Offer object if not completely.
|
||||
* Fulfilled when placed. Offers can be partially fulfilled.
|
||||
*
|
||||
* @category Transaction Models
|
||||
*/
|
||||
export interface OfferCreate extends BaseTransaction {
|
||||
TransactionType: 'OfferCreate'
|
||||
Flags?: number | OfferCreateFlagsInterface
|
||||
/**
|
||||
* Time after which the offer is no longer active, in seconds since the.
|
||||
* Ripple Epoch.
|
||||
*/
|
||||
Expiration?: number
|
||||
/** An offer to delete first, specified in the same way as OfferCancel. */
|
||||
OfferSequence?: number
|
||||
/** The amount and type of currency being provided by the offer creator. */
|
||||
TakerGets: Amount
|
||||
/** The amount and type of currency being requested by the offer creator. */
|
||||
TakerPays: Amount
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the form and type of an OfferCreate at runtime.
|
||||
*
|
||||
* @param tx - An OfferCreate Transaction.
|
||||
* @throws When the OfferCreate is Malformed.
|
||||
*/
|
||||
export function validateOfferCreate(tx: Record<string, unknown>): void {
|
||||
validateBaseTransaction(tx)
|
||||
|
||||
if (tx.TakerGets === undefined) {
|
||||
throw new ValidationError('OfferCreate: missing field TakerGets')
|
||||
}
|
||||
|
||||
if (tx.TakerPays === undefined) {
|
||||
throw new ValidationError('OfferCreate: missing field TakerPays')
|
||||
}
|
||||
|
||||
if (typeof tx.TakerGets !== 'string' && !isAmount(tx.TakerGets)) {
|
||||
throw new ValidationError('OfferCreate: invalid TakerGets')
|
||||
}
|
||||
|
||||
if (typeof tx.TakerPays !== 'string' && !isAmount(tx.TakerPays)) {
|
||||
throw new ValidationError('OfferCreate: invalid TakerPays')
|
||||
}
|
||||
|
||||
if (tx.Expiration !== undefined && typeof tx.Expiration !== 'number') {
|
||||
throw new ValidationError('OfferCreate: invalid Expiration')
|
||||
}
|
||||
|
||||
if (tx.OfferSequence !== undefined && typeof tx.OfferSequence !== 'number') {
|
||||
throw new ValidationError('OfferCreate: invalid OfferSequence')
|
||||
}
|
||||
}
|
||||
277
packages/xahau/src/models/transactions/payment.ts
Normal file
277
packages/xahau/src/models/transactions/payment.ts
Normal file
@@ -0,0 +1,277 @@
|
||||
import { ValidationError } from '../../errors'
|
||||
import { Amount, Path } from '../common'
|
||||
import { isFlagEnabled } from '../utils'
|
||||
|
||||
import {
|
||||
BaseTransaction,
|
||||
isAmount,
|
||||
GlobalFlags,
|
||||
validateBaseTransaction,
|
||||
isAccount,
|
||||
validateRequiredField,
|
||||
validateOptionalField,
|
||||
isNumber,
|
||||
Account,
|
||||
} from './common'
|
||||
import type { TransactionMetadataBase } from './metadata'
|
||||
|
||||
/**
|
||||
* Enum representing values for Payment Transaction Flags.
|
||||
*
|
||||
* @category Transaction Flags
|
||||
*/
|
||||
export enum PaymentFlags {
|
||||
/**
|
||||
* Do not use the default path; only use paths included in the Paths field.
|
||||
* This is intended to force the transaction to take arbitrage opportunities.
|
||||
* Most clients do not need this.
|
||||
*/
|
||||
tfNoRippleDirect = 0x00010000,
|
||||
/**
|
||||
* If the specified Amount cannot be sent without spending more than SendMax,
|
||||
* reduce the received amount instead of failing outright. See Partial.
|
||||
* Payments for more details.
|
||||
*/
|
||||
tfPartialPayment = 0x00020000,
|
||||
/**
|
||||
* Only take paths where all the conversions have an input:output ratio that
|
||||
* is equal or better than the ratio of Amount:SendMax. See Limit Quality for
|
||||
* details.
|
||||
*/
|
||||
tfLimitQuality = 0x00040000,
|
||||
}
|
||||
|
||||
/**
|
||||
* Map of flags to boolean values representing {@link Payment} transaction
|
||||
* flags.
|
||||
*
|
||||
* @category Transaction Flags
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const partialPayment: Payment = {
|
||||
* TransactionType: 'Payment',
|
||||
* Account: 'rM9WCfJU6udpFkvKThRaFHDMsp7L8rpgN',
|
||||
* Amount: {
|
||||
* currency: 'FOO',
|
||||
* value: '4000',
|
||||
* issuer: 'rPzwM2JfCSDjhbesdTCqFjWWdK7eFtTwZz',
|
||||
* },
|
||||
* Destination: 'rPzwM2JfCSDjhbesdTCqFjWWdK7eFtTwZz',
|
||||
* Flags: {
|
||||
* tfPartialPayment: true
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* // Autofill the tx to see how flags actually look compared to the interface usage.
|
||||
* const autofilledTx = await client.autofill(partialPayment)
|
||||
* console.log(autofilledTx)
|
||||
* // {
|
||||
* // TransactionType: 'Payment',
|
||||
* // Account: 'rM9WCfJU6udpFkvKThRaFHDMsp7L8rpgN',
|
||||
* // Amount: {
|
||||
* // currency: 'FOO',
|
||||
* // value: '4000',
|
||||
* // issuer: 'rPzwM2JfCSDjhbesdTCqFjWWdK7eFtTwZz'
|
||||
* // },
|
||||
* // Destination: 'rPzwM2JfCSDjhbesdTCqFjWWdK7eFtTwZz',
|
||||
* // Flags: 131072,
|
||||
* // Sequence: 21970996,
|
||||
* // Fee: '12',
|
||||
* // LastLedgerSequence: 21971016
|
||||
* // }
|
||||
* ```
|
||||
*/
|
||||
export interface PaymentFlagsInterface extends GlobalFlags {
|
||||
/**
|
||||
* Do not use the default path; only use paths included in the Paths field.
|
||||
* This is intended to force the transaction to take arbitrage opportunities.
|
||||
* Most clients do not need this.
|
||||
*/
|
||||
tfNoRippleDirect?: boolean
|
||||
/**
|
||||
* If the specified Amount cannot be sent without spending more than SendMax,
|
||||
* reduce the received amount instead of failing outright. See Partial.
|
||||
* Payments for more details.
|
||||
*/
|
||||
tfPartialPayment?: boolean
|
||||
/**
|
||||
* Only take paths where all the conversions have an input:output ratio that
|
||||
* is equal or better than the ratio of Amount:SendMax. See Limit Quality for
|
||||
* details.
|
||||
*/
|
||||
tfLimitQuality?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* A Payment transaction represents a transfer of value from one account to
|
||||
* another.
|
||||
*
|
||||
* @category Transaction Models
|
||||
*/
|
||||
export interface Payment extends BaseTransaction {
|
||||
TransactionType: 'Payment'
|
||||
/**
|
||||
* The amount of currency to deliver. For non-XAH amounts, the nested field
|
||||
* names MUST be lower-case. If the tfPartialPayment flag is set, deliver up
|
||||
* to this amount instead.
|
||||
*/
|
||||
Amount: Amount
|
||||
/** The unique address of the account receiving the payment. */
|
||||
Destination: Account
|
||||
/**
|
||||
* Arbitrary tag that identifies the reason for the payment to the
|
||||
* destination, or a hosted recipient to pay.
|
||||
*/
|
||||
DestinationTag?: number
|
||||
/**
|
||||
* Arbitrary 256-bit hash representing a specific reason or identifier for
|
||||
* this payment.
|
||||
*/
|
||||
InvoiceID?: string
|
||||
/**
|
||||
* Array of payment paths to be used for this transaction. Must be omitted
|
||||
* for XAH-to-XAH transactions.
|
||||
*/
|
||||
Paths?: Path[]
|
||||
/**
|
||||
* Highest amount of source currency this transaction is allowed to cost,
|
||||
* including transfer fees, exchange rates, and slippage . Does not include
|
||||
* the XAH destroyed as a cost for submitting the transaction. For non-XAH
|
||||
* amounts, the nested field names MUST be lower-case. Must be supplied for
|
||||
* cross-currency/cross-issue payments. Must be omitted for XAH-to-XAH
|
||||
* Payments.
|
||||
*/
|
||||
SendMax?: Amount
|
||||
/**
|
||||
* Minimum amount of destination currency this transaction should deliver.
|
||||
* Only valid if this is a partial payment. For non-XAH amounts, the nested
|
||||
* field names are lower-case.
|
||||
*/
|
||||
DeliverMin?: Amount
|
||||
Flags?: number | PaymentFlagsInterface
|
||||
}
|
||||
|
||||
export interface PaymentMetadata extends TransactionMetadataBase {
|
||||
DeliveredAmount?: Amount
|
||||
delivered_amount?: Amount | 'unavailable'
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the form and type of a Payment at runtime.
|
||||
*
|
||||
* @param tx - A Payment Transaction.
|
||||
* @throws When the Payment is malformed.
|
||||
*/
|
||||
export function validatePayment(tx: Record<string, unknown>): void {
|
||||
validateBaseTransaction(tx)
|
||||
|
||||
if (tx.Amount === undefined) {
|
||||
throw new ValidationError('PaymentTransaction: missing field Amount')
|
||||
}
|
||||
|
||||
if (!isAmount(tx.Amount)) {
|
||||
throw new ValidationError('PaymentTransaction: invalid Amount')
|
||||
}
|
||||
|
||||
validateRequiredField(tx, 'Destination', isAccount)
|
||||
validateOptionalField(tx, 'DestinationTag', isNumber)
|
||||
|
||||
if (tx.InvoiceID !== undefined && typeof tx.InvoiceID !== 'string') {
|
||||
throw new ValidationError('PaymentTransaction: InvoiceID must be a string')
|
||||
}
|
||||
|
||||
if (
|
||||
tx.Paths !== undefined &&
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Only used by JS
|
||||
!isPaths(tx.Paths as Array<Array<Record<string, unknown>>>)
|
||||
) {
|
||||
throw new ValidationError('PaymentTransaction: invalid Paths')
|
||||
}
|
||||
|
||||
if (tx.SendMax !== undefined && !isAmount(tx.SendMax)) {
|
||||
throw new ValidationError('PaymentTransaction: invalid SendMax')
|
||||
}
|
||||
|
||||
checkPartialPayment(tx)
|
||||
}
|
||||
|
||||
function checkPartialPayment(tx: Record<string, unknown>): void {
|
||||
if (tx.DeliverMin != null) {
|
||||
if (tx.Flags == null) {
|
||||
throw new ValidationError(
|
||||
'PaymentTransaction: tfPartialPayment flag required with DeliverMin',
|
||||
)
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Only used by JS
|
||||
const flags = tx.Flags as number | PaymentFlagsInterface
|
||||
const isTfPartialPayment =
|
||||
typeof flags === 'number'
|
||||
? isFlagEnabled(flags, PaymentFlags.tfPartialPayment)
|
||||
: flags.tfPartialPayment ?? false
|
||||
|
||||
if (!isTfPartialPayment) {
|
||||
throw new ValidationError(
|
||||
'PaymentTransaction: tfPartialPayment flag required with DeliverMin',
|
||||
)
|
||||
}
|
||||
|
||||
if (!isAmount(tx.DeliverMin)) {
|
||||
throw new ValidationError('PaymentTransaction: invalid DeliverMin')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function isPathStep(pathStep: Record<string, unknown>): boolean {
|
||||
if (pathStep.account !== undefined && typeof pathStep.account !== 'string') {
|
||||
return false
|
||||
}
|
||||
if (
|
||||
pathStep.currency !== undefined &&
|
||||
typeof pathStep.currency !== 'string'
|
||||
) {
|
||||
return false
|
||||
}
|
||||
if (pathStep.issuer !== undefined && typeof pathStep.issuer !== 'string') {
|
||||
return false
|
||||
}
|
||||
if (
|
||||
pathStep.account !== undefined &&
|
||||
pathStep.currency === undefined &&
|
||||
pathStep.issuer === undefined
|
||||
) {
|
||||
return true
|
||||
}
|
||||
if (pathStep.currency !== undefined || pathStep.issuer !== undefined) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
function isPath(path: Array<Record<string, unknown>>): boolean {
|
||||
for (const pathStep of path) {
|
||||
if (!isPathStep(pathStep)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
function isPaths(paths: Array<Array<Record<string, unknown>>>): boolean {
|
||||
if (!Array.isArray(paths) || paths.length === 0) {
|
||||
return false
|
||||
}
|
||||
|
||||
for (const path of paths) {
|
||||
if (!Array.isArray(path) || path.length === 0) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (!isPath(path)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
164
packages/xahau/src/models/transactions/paymentChannelClaim.ts
Normal file
164
packages/xahau/src/models/transactions/paymentChannelClaim.ts
Normal file
@@ -0,0 +1,164 @@
|
||||
import { ValidationError } from '../../errors'
|
||||
|
||||
import { BaseTransaction, GlobalFlags, validateBaseTransaction } from './common'
|
||||
|
||||
/**
|
||||
* Enum representing values for PaymentChannelClaim transaction flags.
|
||||
*
|
||||
* @category Transaction Flags
|
||||
*/
|
||||
export enum PaymentChannelClaimFlags {
|
||||
/**
|
||||
* Clear the channel's Expiration time. (Expiration is different from the
|
||||
* channel's immutable CancelAfter time.) Only the source address of the
|
||||
* payment channel can use this flag.
|
||||
*/
|
||||
tfRenew = 0x00010000,
|
||||
/**
|
||||
* Request to close the channel. Only the channel source and destination
|
||||
* addresses can use this flag. This flag closes the channel immediately if it
|
||||
* has no more XAH allocated to it after processing the current claim, or if
|
||||
* the destination address uses it. If the source address uses this flag when
|
||||
* the channel still holds XAH, this schedules the channel to close after
|
||||
* SettleDelay seconds have passed. (Specifically, this sets the Expiration of
|
||||
* the channel to the close time of the previous ledger plus the channel's
|
||||
* SettleDelay time, unless the channel already has an earlier Expiration
|
||||
* time.) If the destination address uses this flag when the channel still
|
||||
* holds XAH, any XAH that remains after processing the claim is returned to
|
||||
* the source address.
|
||||
*/
|
||||
tfClose = 0x00020000,
|
||||
}
|
||||
|
||||
/**
|
||||
* Map of flags to boolean values representing {@link PaymentChannelClaim}
|
||||
* transaction flags.
|
||||
*
|
||||
* @category Transaction Flags
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const paymentChannelClaim: PaymentChannelClaim = {
|
||||
* Account: 'rMpxZpuy5RBSP47oK2hDWUtk3B5BNQHfGj,
|
||||
* TransactionType: 'PaymentChannelClaim',
|
||||
* Channel: hashes.hashPaymentChannel(
|
||||
* 'rMpxZpuy5RBSP47oK2hDWUtk3B5BNQHfGj',
|
||||
* 'rQGYqiyH5Ue9J96p4E6Qt6AvqxK4sDhnS5',
|
||||
* 21970712,
|
||||
* ),
|
||||
* Amount: '100',
|
||||
* Flags: {
|
||||
* tfClose: true
|
||||
* }
|
||||
*}
|
||||
*
|
||||
* // Autofill the tx to see how flags actually look compared to the interface usage.
|
||||
* const autofilledTx = await client.autofill(paymentChannelClaim)
|
||||
* console.log(autofilledTx)
|
||||
* // {
|
||||
* // Account: 'rMpxZpuy5RBSP47oK2hDWUtk3B5BNQHfGj',
|
||||
* // TransactionType: 'PaymentChannelClaim',
|
||||
* // Channel: 'FC14BF9245D731DC1749EE0F070765E4EB4E993F8ECEE3D00F7E6E26D6EF98CF',
|
||||
* // Amount: '100',
|
||||
* // Flags: 131072,
|
||||
* // Sequence: 21970713,
|
||||
* // Fee: '12',
|
||||
* // LastLedgerSequence: 21970658
|
||||
* // }
|
||||
* ```
|
||||
*/
|
||||
export interface PaymentChannelClaimFlagsInterface extends GlobalFlags {
|
||||
/**
|
||||
* Clear the channel's Expiration time. (Expiration is different from the
|
||||
* channel's immutable CancelAfter time.) Only the source address of the
|
||||
* payment channel can use this flag.
|
||||
*/
|
||||
tfRenew?: boolean
|
||||
/**
|
||||
* Request to close the channel. Only the channel source and destination
|
||||
* addresses can use this flag. This flag closes the channel immediately if it
|
||||
* has no more XAH allocated to it after processing the current claim, or if
|
||||
* the destination address uses it. If the source address uses this flag when
|
||||
* the channel still holds XAH, this schedules the channel to close after
|
||||
* SettleDelay seconds have passed. (Specifically, this sets the Expiration of
|
||||
* the channel to the close time of the previous ledger plus the channel's
|
||||
* SettleDelay time, unless the channel already has an earlier Expiration
|
||||
* time.) If the destination address uses this flag when the channel still
|
||||
* holds XAH, any XAH that remains after processing the claim is returned to
|
||||
* the source address.
|
||||
*/
|
||||
tfClose?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Claim XAH from a payment channel, adjust the payment channel's expiration,
|
||||
* or both.
|
||||
*
|
||||
* @category Transaction Models
|
||||
*/
|
||||
export interface PaymentChannelClaim extends BaseTransaction {
|
||||
TransactionType: 'PaymentChannelClaim'
|
||||
Flags?: number | PaymentChannelClaimFlagsInterface
|
||||
/** The unique ID of the channel as a 64-character hexadecimal string. */
|
||||
Channel: string
|
||||
/**
|
||||
* Total amount of XAH, in drops, delivered by this channel after processing
|
||||
* this claim. Required to deliver XAH. Must be more than the total amount
|
||||
* delivered by the channel so far, but not greater than the Amount of the
|
||||
* signed claim. Must be provided except when closing the channel.
|
||||
*/
|
||||
Balance?: string
|
||||
/**
|
||||
* The amount of XAH, in drops, authorized by the Signature. This must match
|
||||
* the amount in the signed message. This is the cumulative amount of XAH that
|
||||
* can be dispensed by the channel, including XAH previously redeemed.
|
||||
*/
|
||||
Amount?: string
|
||||
/**
|
||||
* The signature of this claim, as hexadecimal. The signed message contains
|
||||
* the channel ID and the amount of the claim. Required unless the sender of
|
||||
* the transaction is the source address of the channel.
|
||||
*/
|
||||
Signature?: string
|
||||
/**
|
||||
* The public key used for the signature, as hexadecimal. This must match the
|
||||
* PublicKey stored in the ledger for the channel. Required unless the sender
|
||||
* of the transaction is the source address of the channel and the Signature
|
||||
* field is omitted.
|
||||
*/
|
||||
PublicKey?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the form and type of an PaymentChannelClaim at runtime.
|
||||
*
|
||||
* @param tx - An PaymentChannelClaim Transaction.
|
||||
* @throws When the PaymentChannelClaim is Malformed.
|
||||
*/
|
||||
export function validatePaymentChannelClaim(tx: Record<string, unknown>): void {
|
||||
validateBaseTransaction(tx)
|
||||
|
||||
if (tx.Channel === undefined) {
|
||||
throw new ValidationError('PaymentChannelClaim: missing Channel')
|
||||
}
|
||||
|
||||
if (typeof tx.Channel !== 'string') {
|
||||
throw new ValidationError('PaymentChannelClaim: Channel must be a string')
|
||||
}
|
||||
|
||||
if (tx.Balance !== undefined && typeof tx.Balance !== 'string') {
|
||||
throw new ValidationError('PaymentChannelClaim: Balance must be a string')
|
||||
}
|
||||
|
||||
if (tx.Amount !== undefined && typeof tx.Amount !== 'string') {
|
||||
throw new ValidationError('PaymentChannelClaim: Amount must be a string')
|
||||
}
|
||||
|
||||
if (tx.Signature !== undefined && typeof tx.Signature !== 'string') {
|
||||
throw new ValidationError('PaymentChannelClaim: Signature must be a string')
|
||||
}
|
||||
|
||||
if (tx.PublicKey !== undefined && typeof tx.PublicKey !== 'string') {
|
||||
throw new ValidationError('PaymentChannelClaim: PublicKey must be a string')
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user