mirror of
https://github.com/Xahau/xahau.js.git
synced 2025-11-20 04:05:52 +00:00
feat: add support for current sidechain design (#2039)
* Update definitions.json * add new st types * add tests * add XChainClaim tx * add XChainCommit tx * add XChainCreateBridge tx * add XChainCreateClaimID tx * update definitions.json * rename Bridge -> XChainBridge in binary codec, fix tests * rename Bridge -> XChainBridge in models * add codec support for XChainAddAttestation * add XChainAddAttestation model * undo debugging change * fix linting issues * update definitions.json for new rippled code, add new tests/update old tests * add/update models * update history * update binary-codec * add XChainModifyBridge model * update RPCs * update to latest rippled * more fixes * fix definitions.json * fix spacing * update definitions.json to avoid conflict with amm * update definitions.json to resolve amm conflicts * audit code * more updates * update rpcs * switch to beta version * add destination tag to XChainClaim * rename IssuedCurrency -> Issue to match rippled * update Issue form * fix account object filters * fix issue from typing * fix LedgerEntry types * fix attestation destination type * Update definitions.json * rename XChainAddAttestation -> XChainAddAttestationBatch * add XChainAddClaimAttestation * add XChainAddAccountCreateAttestation * remove XChainAddAttestationBatch * update definitions * fix attestation txns * fix attestation object * add validate for new txs * add Bridge ledger object * add XChainOwnedClaimID ledger object * add XChainOwnedCreateAccountClaimID ledger object * update account_objects * update models to latest rippled * fix minor issues * fix bridge ledger_entry * add XChainModifyBridge flag * Update definitions.json * add rbc tests for the new txs * update validateXChainModifyBridge * add validate methods to other xchain txs * fix isXChainBridge * fix isIssue typing * fix model types * update changelog * switch prepare to prepublishOnly * add docs * fix AccountObjectsType filter * export common types * fix account_objects filter * update LedgerEntry * add sidechain faucet info * add snippet * improve snippet * fix spacing issues * update ledger_entry * remove AMMDelete tests for now * Update definitions.json * fix unit tests * convert createValidate script to JS * remove unneeded linter ignores * respond to comments * more snippet fixes * make validate functions more readable * add getXChainClaimID method to parse metadata * re-add linter rules * clean up common * fix getXChainClaimID test * return undefined for failed tx * test: add model tests for new sidechain transactions (#2059) * add XChainAddAttestation tests, fix model * add XChainClaim model tests * add XChainCommit model tests, fix typo * add XChainCreateBridge model tests * add XChainCreateClaimID model tests * add XChainModifyBridge tests * update to most recent version of code * remove XChainAddAttestationBatch tests * add more validation tests * switch createValidateTests to JS
This commit is contained in:
@@ -84,7 +84,6 @@ module.exports = {
|
||||
'max-statements': 'off',
|
||||
// Snippets have logs on console to better understand the working.
|
||||
'no-console': 'off',
|
||||
'import/no-extraneous-dependencies': 'off',
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -147,5 +146,17 @@ module.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,9 +3,9 @@
|
||||
Subscribe to [the **xrpl-announce** mailing list](https://groups.google.com/g/xrpl-announce) for release announcements. We recommend that xrpl.js (ripple-lib) users stay up-to-date with the latest stable release.
|
||||
|
||||
## Unreleased
|
||||
|
||||
### Added
|
||||
* Added `ports` field to `ServerInfoResponse`
|
||||
* Support for the XChainBridge amendment.
|
||||
|
||||
### Fixed
|
||||
* Fix request model fields related to AMM
|
||||
|
||||
172
packages/xrpl/snippets/src/bridgeTransfer.ts
Normal file
172
packages/xrpl/snippets/src/bridgeTransfer.ts
Normal file
@@ -0,0 +1,172 @@
|
||||
/* eslint-disable max-depth -- needed for attestation checking */
|
||||
/* eslint-disable @typescript-eslint/consistent-type-assertions -- needed here */
|
||||
/* eslint-disable no-await-in-loop -- needed here */
|
||||
import {
|
||||
AccountObjectsRequest,
|
||||
LedgerEntry,
|
||||
Client,
|
||||
XChainAccountCreateCommit,
|
||||
XChainBridge,
|
||||
XChainCommit,
|
||||
XChainCreateClaimID,
|
||||
xrpToDrops,
|
||||
Wallet,
|
||||
getXChainClaimID,
|
||||
} from '../../src'
|
||||
|
||||
async function sleep(sec: number): Promise<void> {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(resolve, sec * 1000)
|
||||
})
|
||||
}
|
||||
|
||||
const lockingClient = new Client(
|
||||
'wss://sidechain-net1.devnet.rippletest.net:51233',
|
||||
)
|
||||
const issuingClient = new Client(
|
||||
'wss://sidechain-net2.devnet.rippletest.net:51233',
|
||||
)
|
||||
const MAX_LEDGERS_WAITED = 5
|
||||
const LEDGER_CLOSE_TIME = 4
|
||||
|
||||
void bridgeTransfer()
|
||||
|
||||
async function bridgeTransfer(): Promise<void> {
|
||||
await lockingClient.connect()
|
||||
await issuingClient.connect()
|
||||
const lockingChainDoor = 'rMAXACCrp3Y8PpswXcg3bKggHX76V3F8M4'
|
||||
|
||||
const accountObjectsRequest: AccountObjectsRequest = {
|
||||
command: 'account_objects',
|
||||
account: lockingChainDoor,
|
||||
type: 'bridge',
|
||||
}
|
||||
const lockingAccountObjects = (
|
||||
await lockingClient.request(accountObjectsRequest)
|
||||
).result.account_objects
|
||||
// There will only be one here - a door account can only have one bridge per currency
|
||||
const bridgeData = lockingAccountObjects.filter(
|
||||
(obj) =>
|
||||
obj.LedgerEntryType === 'Bridge' &&
|
||||
obj.XChainBridge.LockingChainIssue.currency === 'XRP',
|
||||
)[0] as LedgerEntry.Bridge
|
||||
const bridge: XChainBridge = bridgeData.XChainBridge
|
||||
console.log(bridge)
|
||||
|
||||
console.log('Creating wallet on the locking chain via the faucet...')
|
||||
const { wallet: wallet1 } = await lockingClient.fundWallet()
|
||||
console.log(wallet1)
|
||||
const wallet2 = Wallet.generate()
|
||||
|
||||
console.log(
|
||||
`Creating ${wallet2.classicAddress} on the issuing chain via the bridge...`,
|
||||
)
|
||||
|
||||
const fundTx: XChainAccountCreateCommit = {
|
||||
TransactionType: 'XChainAccountCreateCommit',
|
||||
Account: wallet1.classicAddress,
|
||||
XChainBridge: bridge,
|
||||
SignatureReward: bridgeData.SignatureReward,
|
||||
Destination: wallet2.classicAddress,
|
||||
Amount: (
|
||||
parseInt(bridgeData.MinAccountCreateAmount as string, 10) * 2
|
||||
).toString(),
|
||||
}
|
||||
const fundResponse = await lockingClient.submitAndWait(fundTx, {
|
||||
wallet: wallet1,
|
||||
})
|
||||
console.log(fundResponse)
|
||||
|
||||
console.log(
|
||||
'Waiting for the attestation to go through... (usually 8-12 seconds)',
|
||||
)
|
||||
let ledgersWaited = 0
|
||||
let initialBalance = '0'
|
||||
while (ledgersWaited < MAX_LEDGERS_WAITED) {
|
||||
await sleep(LEDGER_CLOSE_TIME)
|
||||
try {
|
||||
initialBalance = await issuingClient.getXrpBalance(wallet2.classicAddress)
|
||||
console.log(
|
||||
`Wallet ${wallet2.classicAddress} has been funded with a balance of ${initialBalance} XRP`,
|
||||
)
|
||||
break
|
||||
} catch (_error) {
|
||||
ledgersWaited += 1
|
||||
if (ledgersWaited === MAX_LEDGERS_WAITED) {
|
||||
// This error should never be hit if the bridge is running
|
||||
throw Error('Destination account creation via the bridge failed.')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(
|
||||
`Transferring funds from ${wallet1.classicAddress} on the locking chain to ` +
|
||||
`${wallet2.classicAddress} on the issuing_chain...`,
|
||||
)
|
||||
|
||||
// Fetch the claim ID for the transfer
|
||||
console.log('Step 1: Fetching the claim ID for the transfer...')
|
||||
const claimIdTx: XChainCreateClaimID = {
|
||||
TransactionType: 'XChainCreateClaimID',
|
||||
Account: wallet2.classicAddress,
|
||||
XChainBridge: bridge,
|
||||
SignatureReward: bridgeData.SignatureReward,
|
||||
OtherChainSource: wallet1.classicAddress,
|
||||
}
|
||||
const claimIdResult = await issuingClient.submitAndWait(claimIdTx, {
|
||||
wallet: wallet2,
|
||||
})
|
||||
console.log(claimIdResult)
|
||||
|
||||
// Extract new claim ID from metadata
|
||||
const xchainClaimId = getXChainClaimID(claimIdResult.result.meta)
|
||||
if (xchainClaimId == null) {
|
||||
// This shouldn't trigger assuming the transaction succeeded
|
||||
throw Error('Could not extract XChainClaimID')
|
||||
}
|
||||
|
||||
console.log(`Claim ID for the transfer: ${xchainClaimId}`)
|
||||
|
||||
console.log(
|
||||
'Step 2: Locking the funds on the locking chain with an XChainCommit transaction...',
|
||||
)
|
||||
const commitTx: XChainCommit = {
|
||||
TransactionType: 'XChainCommit',
|
||||
Account: wallet1.classicAddress,
|
||||
Amount: xrpToDrops(1),
|
||||
XChainBridge: bridge,
|
||||
XChainClaimID: xchainClaimId,
|
||||
OtherChainDestination: wallet2.classicAddress,
|
||||
}
|
||||
const commitResult = await lockingClient.submitAndWait(commitTx, {
|
||||
wallet: wallet1,
|
||||
})
|
||||
console.log(commitResult)
|
||||
|
||||
console.log(
|
||||
'Waiting for the attestation to go through... (usually 8-12 seconds)',
|
||||
)
|
||||
ledgersWaited = 0
|
||||
while (ledgersWaited < MAX_LEDGERS_WAITED) {
|
||||
await sleep(LEDGER_CLOSE_TIME)
|
||||
const currentBalance = await issuingClient.getXrpBalance(
|
||||
wallet2.classicAddress,
|
||||
)
|
||||
console.log(initialBalance, currentBalance)
|
||||
if (parseFloat(currentBalance) > parseFloat(initialBalance)) {
|
||||
console.log('Transfer is complete')
|
||||
console.log(
|
||||
`New balance of ${wallet2.classicAddress} is ${currentBalance} XRP`,
|
||||
)
|
||||
break
|
||||
}
|
||||
|
||||
ledgersWaited += 1
|
||||
if (ledgersWaited === MAX_LEDGERS_WAITED) {
|
||||
throw Error('Bridge transfer failed.')
|
||||
}
|
||||
}
|
||||
|
||||
await lockingClient.disconnect()
|
||||
await issuingClient.disconnect()
|
||||
}
|
||||
@@ -2,7 +2,7 @@ export type LedgerIndex = number | ('validated' | 'closed' | 'current')
|
||||
|
||||
export interface XRP {
|
||||
currency: 'XRP'
|
||||
issuer: never
|
||||
issuer?: never
|
||||
}
|
||||
|
||||
export interface IssuedCurrency {
|
||||
@@ -148,3 +148,10 @@ export interface AuthAccount {
|
||||
Account: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface XChainBridge {
|
||||
LockingChainDoor: string
|
||||
LockingChainIssue: Currency
|
||||
IssuingChainDoor: string
|
||||
IssuingChainIssue: Currency
|
||||
}
|
||||
|
||||
84
packages/xrpl/src/models/ledger/Bridge.ts
Normal file
84
packages/xrpl/src/models/ledger/Bridge.ts
Normal file
@@ -0,0 +1,84 @@
|
||||
import { Amount, XChainBridge } from '../common'
|
||||
|
||||
import BaseLedgerEntry from './BaseLedgerEntry'
|
||||
|
||||
/**
|
||||
* A Bridge objects represents a cross-chain bridge and includes information about
|
||||
* the door accounts, assets, signature rewards, and the minimum account create
|
||||
* amount.
|
||||
*
|
||||
* @category Ledger Entries
|
||||
*/
|
||||
export default interface Bridge extends BaseLedgerEntry {
|
||||
LedgerEntryType: 'Bridge'
|
||||
|
||||
/** The door account that owns the bridge. */
|
||||
Account: string
|
||||
|
||||
/**
|
||||
* The total amount, in XRP, to be rewarded for providing a signature for
|
||||
* cross-chain transfer or for signing for the cross-chain reward. This amount
|
||||
* will be split among the signers.
|
||||
*/
|
||||
SignatureReward: Amount
|
||||
|
||||
/**
|
||||
* The minimum amount, in XRP, required for an {@link XChainAccountCreateCommit}
|
||||
* transaction. If this isn't present, the {@link XChainAccountCreateCommit}
|
||||
* transaction will fail. This field can only be present on XRP-XRP bridges.
|
||||
*/
|
||||
MinAccountCreateAmount?: string
|
||||
|
||||
/**
|
||||
* The door accounts and assets of the bridge this object correlates to.
|
||||
*/
|
||||
XChainBridge: XChainBridge
|
||||
|
||||
/**
|
||||
* The value of the next XChainClaimID to be created.
|
||||
*/
|
||||
XChainClaimID: string
|
||||
|
||||
/**
|
||||
* A counter used to order the execution of account create transactions. It is
|
||||
* incremented every time a successful {@link XChainAccountCreateCommit}
|
||||
* transaction is run for the source chain.
|
||||
*/
|
||||
XChainAccountCreateCount: string
|
||||
|
||||
/**
|
||||
* A counter used to order the execution of account create transactions. It is
|
||||
* incremented every time a {@link XChainAccountCreateCommit} transaction is
|
||||
* "claimed" on the destination chain. When the "claim" transaction is run on
|
||||
* the destination chain, the XChainAccountClaimCount must match the value that
|
||||
* the XChainAccountCreateCount had at the time the XChainAccountClaimCount was
|
||||
* run on the source chain. This orders the claims so that they run in the same
|
||||
* order that the XChainAccountCreateCommit transactions ran on the source chain,
|
||||
* to prevent transaction replay.
|
||||
*/
|
||||
XChainAccountClaimCount: string
|
||||
|
||||
/**
|
||||
* A bit-map of boolean flags. No flags are defined for Bridges, 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
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import AccountRoot from './AccountRoot'
|
||||
import Amendments from './Amendments'
|
||||
import AMM from './AMM'
|
||||
import Bridge from './Bridge'
|
||||
import Check from './Check'
|
||||
import DepositPreauth from './DepositPreauth'
|
||||
import DirectoryNode from './DirectoryNode'
|
||||
@@ -13,11 +14,14 @@ import PayChannel from './PayChannel'
|
||||
import RippleState from './RippleState'
|
||||
import SignerList from './SignerList'
|
||||
import Ticket from './Ticket'
|
||||
import XChainOwnedClaimID from './XChainOwnedClaimID'
|
||||
import XChainOwnedCreateAccountClaimID from './XChainOwnedCreateAccountClaimID'
|
||||
|
||||
type LedgerEntry =
|
||||
| AccountRoot
|
||||
| Amendments
|
||||
| AMM
|
||||
| Bridge
|
||||
| Check
|
||||
| DepositPreauth
|
||||
| DirectoryNode
|
||||
@@ -30,5 +34,7 @@ type LedgerEntry =
|
||||
| RippleState
|
||||
| SignerList
|
||||
| Ticket
|
||||
| XChainOwnedClaimID
|
||||
| XChainOwnedCreateAccountClaimID
|
||||
|
||||
export default LedgerEntry
|
||||
|
||||
89
packages/xrpl/src/models/ledger/XChainOwnedClaimID.ts
Normal file
89
packages/xrpl/src/models/ledger/XChainOwnedClaimID.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
import { Amount } from 'ripple-binary-codec/dist/types'
|
||||
|
||||
import { XChainBridge } from '../common'
|
||||
|
||||
import BaseLedgerEntry from './BaseLedgerEntry'
|
||||
|
||||
/**
|
||||
* An XChainOwnedClaimID object represents one cross-chain transfer of value
|
||||
* and includes information of the account on the source chain that locks or
|
||||
* burns the funds on the source chain.
|
||||
*
|
||||
* @category Ledger Entries
|
||||
*/
|
||||
export default interface XChainOwnedClaimID extends BaseLedgerEntry {
|
||||
LedgerEntryType: 'XChainOwnedClaimID'
|
||||
|
||||
/** The account that checked out this unique claim ID value. */
|
||||
Account: string
|
||||
|
||||
/**
|
||||
* The door accounts and assets of the bridge this object correlates to.
|
||||
*/
|
||||
XChainBridge: XChainBridge
|
||||
|
||||
/**
|
||||
* The unique sequence number for a cross-chain transfer.
|
||||
*/
|
||||
XChainClaimID: string
|
||||
|
||||
/**
|
||||
* The account that must send the corresponding {@link XChainCommit} on the
|
||||
* source chain. The destination may be specified in the {@link XChainCommit}
|
||||
* transaction, which means that if the OtherChainSource isn't specified,
|
||||
* another account can try to specify a different destination and steal the
|
||||
* funds. This also allows tracking only a single set of signatures, since we
|
||||
* know which account will send the {@link XChainCommit} transaction.
|
||||
*/
|
||||
OtherChainSource: string
|
||||
|
||||
/**
|
||||
* Attestations collected from the witness servers. This includes the parameters
|
||||
* needed to recreate the message that was signed, including the amount, which
|
||||
* chain (locking or issuing), optional destination, and reward account for that
|
||||
* signature.
|
||||
*/
|
||||
XChainClaimAttestations: Array<{
|
||||
// TODO: add docs
|
||||
XChainClaimProofSig: {
|
||||
Amount: Amount
|
||||
|
||||
AttestationRewardAccount: string
|
||||
|
||||
AttestationSignerAccount: string
|
||||
|
||||
Destination?: string
|
||||
|
||||
PublicKey: string
|
||||
|
||||
WasLockingChainSend: 0 | 1
|
||||
}
|
||||
}>
|
||||
|
||||
/**
|
||||
* The total amount to pay the witness servers for their signatures. It must be at
|
||||
* least the value of the SignatureReward in the {@link Bridge} ledger object.
|
||||
*/
|
||||
SignatureReward: string
|
||||
|
||||
/**
|
||||
* A bit-map of boolean flags. No flags are defined for XChainOwnedClaimIDs,
|
||||
* 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
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
import { XChainBridge } from '../common'
|
||||
|
||||
import BaseLedgerEntry from './BaseLedgerEntry'
|
||||
|
||||
/**
|
||||
* The XChainOwnedCreateAccountClaimID ledger object is used to collect attestations
|
||||
* for creating an account via a cross-chain transfer.
|
||||
*
|
||||
* @category Ledger Entries
|
||||
*/
|
||||
export default interface XChainOwnedCreateAccountClaimID
|
||||
extends BaseLedgerEntry {
|
||||
LedgerEntryType: 'XChainOwnedCreateAccountClaimID'
|
||||
|
||||
/** The account that owns this object. */
|
||||
Account: string
|
||||
|
||||
/**
|
||||
* The door accounts and assets of the bridge this object correlates to.
|
||||
*/
|
||||
XChainBridge: XChainBridge
|
||||
|
||||
/**
|
||||
* An integer that determines the order that accounts created through
|
||||
* cross-chain transfers must be performed. Smaller numbers must execute
|
||||
* before larger numbers.
|
||||
*/
|
||||
XChainAccountCreateCount: number
|
||||
|
||||
/**
|
||||
* Attestations collected from the witness servers. This includes the parameters
|
||||
* needed to recreate the message that was signed, including the amount, destination,
|
||||
* signature reward amount, and reward account for that signature. With the
|
||||
* exception of the reward account, all signatures must sign the message created with
|
||||
* common parameters.
|
||||
*/
|
||||
XChainCreateAccountAttestations: Array<{
|
||||
// TODO: add docs
|
||||
XChainCreateAccountProofSig: {
|
||||
Amount: string
|
||||
|
||||
AttestationRewardAccount: string
|
||||
|
||||
AttestationSignerAccount: string
|
||||
|
||||
Destination: string
|
||||
|
||||
PublicKey: string
|
||||
|
||||
WasLockingChainSend: 0 | 1
|
||||
}
|
||||
}>
|
||||
|
||||
/**
|
||||
* A bit-map of boolean flags. No flags are defined for,
|
||||
* XChainOwnedCreateAccountClaimIDs, 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
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import AccountRoot, {
|
||||
} from './AccountRoot'
|
||||
import Amendments, { Majority, AMENDMENTS_ID } from './Amendments'
|
||||
import AMM, { VoteSlot } from './AMM'
|
||||
import Bridge from './Bridge'
|
||||
import Check from './Check'
|
||||
import DepositPreauth from './DepositPreauth'
|
||||
import DirectoryNode from './DirectoryNode'
|
||||
@@ -24,6 +25,8 @@ import PayChannel from './PayChannel'
|
||||
import RippleState, { RippleStateFlags } from './RippleState'
|
||||
import SignerList, { SignerListFlags } from './SignerList'
|
||||
import Ticket from './Ticket'
|
||||
import XChainOwnedClaimID from './XChainOwnedClaimID'
|
||||
import XChainOwnedCreateAccountClaimID from './XChainOwnedCreateAccountClaimID'
|
||||
|
||||
export {
|
||||
AccountRoot,
|
||||
@@ -32,6 +35,7 @@ export {
|
||||
AMENDMENTS_ID,
|
||||
Amendments,
|
||||
AMM,
|
||||
Bridge,
|
||||
Check,
|
||||
DepositPreauth,
|
||||
DirectoryNode,
|
||||
@@ -57,5 +61,7 @@ export {
|
||||
SignerList,
|
||||
SignerListFlags,
|
||||
Ticket,
|
||||
XChainOwnedClaimID,
|
||||
XChainOwnedCreateAccountClaimID,
|
||||
VoteSlot,
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import {
|
||||
AMM,
|
||||
Bridge,
|
||||
Check,
|
||||
DepositPreauth,
|
||||
Escrow,
|
||||
@@ -8,12 +9,15 @@ import {
|
||||
RippleState,
|
||||
SignerList,
|
||||
Ticket,
|
||||
XChainOwnedClaimID,
|
||||
XChainOwnedCreateAccountClaimID,
|
||||
} from '../ledger'
|
||||
|
||||
import { BaseRequest, BaseResponse, LookupByLedgerRequest } from './baseMethod'
|
||||
|
||||
export type AccountObjectType =
|
||||
| 'amm'
|
||||
| 'bridge'
|
||||
| 'check'
|
||||
| 'deposit_preauth'
|
||||
| 'escrow'
|
||||
@@ -23,6 +27,8 @@ export type AccountObjectType =
|
||||
| 'signer_list'
|
||||
| 'state'
|
||||
| 'ticket'
|
||||
| 'xchain_owned_create_account_claim_id'
|
||||
| 'xchain_owned_claim_id'
|
||||
|
||||
/**
|
||||
* The account_objects command returns the raw ledger format for all objects
|
||||
@@ -67,6 +73,7 @@ export interface AccountObjectsRequest
|
||||
*/
|
||||
export type AccountObject =
|
||||
| AMM
|
||||
| Bridge
|
||||
| Check
|
||||
| DepositPreauth
|
||||
| Escrow
|
||||
@@ -75,6 +82,8 @@ export type AccountObject =
|
||||
| SignerList
|
||||
| RippleState
|
||||
| Ticket
|
||||
| XChainOwnedClaimID
|
||||
| XChainOwnedCreateAccountClaimID
|
||||
|
||||
/**
|
||||
* Response expected from an {@link AccountObjectsRequest}.
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Currency, XChainBridge } from '../common'
|
||||
import { LedgerEntry } from '../ledger'
|
||||
|
||||
import { BaseRequest, BaseResponse, LookupByLedgerRequest } from './baseMethod'
|
||||
@@ -152,6 +153,30 @@ export interface LedgerEntryRequest extends BaseRequest, LookupByLedgerRequest {
|
||||
* 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
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
import { isString } from 'lodash'
|
||||
|
||||
import { Amount, XChainBridge } from '../common'
|
||||
|
||||
import {
|
||||
BaseTransaction,
|
||||
isAmount,
|
||||
isXChainBridge,
|
||||
validateBaseTransaction,
|
||||
validateRequiredField,
|
||||
} from './common'
|
||||
|
||||
/**
|
||||
* The XChainAccountCreateCommit transaction creates a new account on one of the
|
||||
* chains a bridge connects, which serves as the bridge entrance for that chain.
|
||||
*
|
||||
* Warning: This transaction should only be executed if the witness attestations
|
||||
* will be reliably delivered to the destination chain. If the signatures aren't
|
||||
* delivered, then account creation will be blocked until attestations are received.
|
||||
* This can be used maliciously; to disable this transaction on XRP-XRP bridges,
|
||||
* the bridge's MinAccountCreateAmount shouldn't be present.
|
||||
*
|
||||
* @category Transaction Models
|
||||
*/
|
||||
export interface XChainAccountCreateCommit extends BaseTransaction {
|
||||
TransactionType: 'XChainAccountCreateCommit'
|
||||
|
||||
/**
|
||||
* The bridge to create accounts for.
|
||||
*/
|
||||
XChainBridge: XChainBridge
|
||||
|
||||
/**
|
||||
* The amount, in XRP, to be used to reward the witness servers for providing
|
||||
* signatures. This must match the amount on the {@link Bridge} ledger object.
|
||||
*/
|
||||
SignatureReward: Amount
|
||||
|
||||
/**
|
||||
* The destination account on the destination chain.
|
||||
*/
|
||||
Destination: string
|
||||
|
||||
/**
|
||||
* The amount, in XRP, to use for account creation. This must be greater than or
|
||||
* equal to the MinAccountCreateAmount specified in the {@link Bridge} ledger object.
|
||||
*/
|
||||
Amount: Amount
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the form and type of an XChainAccountCreateCommit at runtime.
|
||||
*
|
||||
* @param tx - An XChainAccountCreateCommit Transaction.
|
||||
* @throws When the XChainAccountCreateCommit is malformed.
|
||||
*/
|
||||
export function validateXChainAccountCreateCommit(
|
||||
tx: Record<string, unknown>,
|
||||
): void {
|
||||
validateBaseTransaction(tx)
|
||||
|
||||
validateRequiredField(tx, 'XChainBridge', isXChainBridge)
|
||||
|
||||
validateRequiredField(tx, 'SignatureReward', isAmount)
|
||||
|
||||
validateRequiredField(tx, 'Destination', isString)
|
||||
|
||||
validateRequiredField(tx, 'Amount', isAmount)
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
import { Amount, XChainBridge } from '../common'
|
||||
|
||||
import {
|
||||
BaseTransaction,
|
||||
isAmount,
|
||||
isNumber,
|
||||
isString,
|
||||
isXChainBridge,
|
||||
validateBaseTransaction,
|
||||
validateRequiredField,
|
||||
} from './common'
|
||||
|
||||
/**
|
||||
* The XChainAddAccountCreateAttestation transaction provides an attestation
|
||||
* from a witness server that a {@link XChainAccountCreateCommit} transaction
|
||||
* occurred on the other chain.
|
||||
*
|
||||
* @category Transaction Models
|
||||
*/
|
||||
export interface XChainAddAccountCreateAttestation extends BaseTransaction {
|
||||
TransactionType: 'XChainAddAccountCreateAttestation'
|
||||
|
||||
/**
|
||||
* The amount committed by the {@link XChainAccountCreateCommit} transaction
|
||||
* on the source chain.
|
||||
*/
|
||||
Amount: Amount
|
||||
|
||||
/**
|
||||
* The account that should receive this signer's share of the SignatureReward.
|
||||
*/
|
||||
AttestationRewardAccount: string
|
||||
|
||||
/**
|
||||
* The account on the door account's signer list that is signing the transaction.
|
||||
*/
|
||||
AttestationSignerAccount: string
|
||||
|
||||
/**
|
||||
* The destination account for the funds on the destination chain.
|
||||
*/
|
||||
Destination: string
|
||||
|
||||
/**
|
||||
* The account on the source chain that submitted the {@link XChainAccountCreateCommit}
|
||||
* transaction that triggered the event associated with the attestation.
|
||||
*/
|
||||
OtherChainSource: string
|
||||
|
||||
/**
|
||||
* The public key used to verify the signature.
|
||||
*/
|
||||
PublicKey: string
|
||||
|
||||
/**
|
||||
* The signature attesting to the event on the other chain.
|
||||
*/
|
||||
Signature: string
|
||||
|
||||
/**
|
||||
* The signature reward paid in the {@link XChainAccountCreateCommit} transaction.
|
||||
*/
|
||||
SignatureReward: Amount
|
||||
|
||||
/**
|
||||
* A boolean representing the chain where the event occurred.
|
||||
*/
|
||||
WasLockingChainSend: 0 | 1
|
||||
|
||||
/**
|
||||
* The counter that represents the order that the claims must be processed in.
|
||||
*/
|
||||
XChainAccountCreateCount: number | string
|
||||
|
||||
/**
|
||||
* The bridge associated with the attestation.
|
||||
*/
|
||||
XChainBridge: XChainBridge
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the form and type of an XChainAddAccountCreateAttestation at runtime.
|
||||
*
|
||||
* @param tx - An XChainAddAccountCreateAttestation Transaction.
|
||||
* @throws When the XChainAddAccountCreateAttestation is malformed.
|
||||
*/
|
||||
export function validateXChainAddAccountCreateAttestation(
|
||||
tx: Record<string, unknown>,
|
||||
): void {
|
||||
validateBaseTransaction(tx)
|
||||
|
||||
validateRequiredField(tx, 'Amount', isAmount)
|
||||
|
||||
validateRequiredField(tx, 'AttestationRewardAccount', isString)
|
||||
|
||||
validateRequiredField(tx, 'AttestationSignerAccount', isString)
|
||||
|
||||
validateRequiredField(tx, 'Destination', isString)
|
||||
|
||||
validateRequiredField(tx, 'OtherChainSource', isString)
|
||||
|
||||
validateRequiredField(tx, 'PublicKey', isString)
|
||||
|
||||
validateRequiredField(tx, 'Signature', isString)
|
||||
|
||||
validateRequiredField(tx, 'SignatureReward', isAmount)
|
||||
|
||||
validateRequiredField(
|
||||
tx,
|
||||
'WasLockingChainSend',
|
||||
(inp) => inp === 0 || inp === 1,
|
||||
)
|
||||
|
||||
validateRequiredField(
|
||||
tx,
|
||||
'XChainAccountCreateCount',
|
||||
(inp) => isNumber(inp) || isString(inp),
|
||||
)
|
||||
|
||||
validateRequiredField(tx, 'XChainBridge', isXChainBridge)
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
import { Amount, XChainBridge } from '../common'
|
||||
|
||||
import {
|
||||
BaseTransaction,
|
||||
isAmount,
|
||||
isNumber,
|
||||
isString,
|
||||
isXChainBridge,
|
||||
validateBaseTransaction,
|
||||
validateOptionalField,
|
||||
validateRequiredField,
|
||||
} from './common'
|
||||
|
||||
/**
|
||||
* The XChainAddClaimAttestation transaction provides proof from a witness server,
|
||||
* attesting to an {@link XChainCommit} transaction.
|
||||
*
|
||||
* @category Transaction Models
|
||||
*/
|
||||
export interface XChainAddClaimAttestation extends BaseTransaction {
|
||||
TransactionType: 'XChainAddClaimAttestation'
|
||||
|
||||
/**
|
||||
* The amount committed by the {@link XChainCommit} transaction on the source chain.
|
||||
*/
|
||||
Amount: Amount
|
||||
|
||||
/**
|
||||
* The account that should receive this signer's share of the SignatureReward.
|
||||
*/
|
||||
AttestationRewardAccount: string
|
||||
|
||||
/**
|
||||
* The account on the door account's signer list that is signing the transaction.
|
||||
*/
|
||||
AttestationSignerAccount: string
|
||||
|
||||
/**
|
||||
* The destination account for the funds on the destination chain (taken from
|
||||
* the {@link XChainCommit} transaction).
|
||||
*/
|
||||
Destination?: string
|
||||
|
||||
/**
|
||||
* The account on the source chain that submitted the {@link XChainCommit}
|
||||
* transaction that triggered the event associated with the attestation.
|
||||
*/
|
||||
OtherChainSource: string
|
||||
|
||||
/**
|
||||
* The public key used to verify the attestation signature.
|
||||
*/
|
||||
PublicKey: string
|
||||
|
||||
/**
|
||||
* The signature attesting to the event on the other chain.
|
||||
*/
|
||||
Signature: string
|
||||
|
||||
/**
|
||||
* A boolean representing the chain where the event occurred.
|
||||
*/
|
||||
WasLockingChainSend: 0 | 1
|
||||
|
||||
/**
|
||||
* The bridge to use to transfer funds.
|
||||
*/
|
||||
XChainBridge: XChainBridge
|
||||
|
||||
/**
|
||||
* The XChainClaimID associated with the transfer, which was included in the
|
||||
* {@link XChainCommit} transaction.
|
||||
*/
|
||||
XChainClaimID: number | string
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the form and type of an XChainAddClaimAttestation at runtime.
|
||||
*
|
||||
* @param tx - An XChainAddClaimAttestation Transaction.
|
||||
* @throws When the XChainAddClaimAttestation is malformed.
|
||||
*/
|
||||
export function validateXChainAddClaimAttestation(
|
||||
tx: Record<string, unknown>,
|
||||
): void {
|
||||
validateBaseTransaction(tx)
|
||||
|
||||
validateRequiredField(tx, 'Amount', isAmount)
|
||||
|
||||
validateRequiredField(tx, 'AttestationRewardAccount', isString)
|
||||
|
||||
validateRequiredField(tx, 'AttestationSignerAccount', isString)
|
||||
|
||||
validateOptionalField(tx, 'Destination', isString)
|
||||
|
||||
validateRequiredField(tx, 'OtherChainSource', isString)
|
||||
|
||||
validateRequiredField(tx, 'PublicKey', isString)
|
||||
|
||||
validateRequiredField(tx, 'Signature', isString)
|
||||
|
||||
validateRequiredField(
|
||||
tx,
|
||||
'WasLockingChainSend',
|
||||
(inp) => inp === 0 || inp === 1,
|
||||
)
|
||||
|
||||
validateRequiredField(tx, 'XChainBridge', isXChainBridge)
|
||||
|
||||
validateRequiredField(
|
||||
tx,
|
||||
'XChainClaimID',
|
||||
(inp) => isNumber(inp) || isString(inp),
|
||||
)
|
||||
}
|
||||
77
packages/xrpl/src/models/transactions/XChainClaim.ts
Normal file
77
packages/xrpl/src/models/transactions/XChainClaim.ts
Normal file
@@ -0,0 +1,77 @@
|
||||
import { Amount, XChainBridge } from '../common'
|
||||
|
||||
import {
|
||||
BaseTransaction,
|
||||
isAmount,
|
||||
isNumber,
|
||||
isString,
|
||||
isXChainBridge,
|
||||
validateBaseTransaction,
|
||||
validateOptionalField,
|
||||
validateRequiredField,
|
||||
} from './common'
|
||||
|
||||
/**
|
||||
* The XChainClaim transaction completes a cross-chain transfer of value. It
|
||||
* allows a user to claim the value on the destination chain - the equivalent
|
||||
* of the value locked on the source chain.
|
||||
*
|
||||
* @category Transaction Models
|
||||
*/
|
||||
export interface XChainClaim extends BaseTransaction {
|
||||
TransactionType: 'XChainClaim'
|
||||
|
||||
/**
|
||||
* The bridge to use for the transfer.
|
||||
*/
|
||||
XChainBridge: XChainBridge
|
||||
|
||||
/**
|
||||
* The unique integer ID for the cross-chain transfer that was referenced in the
|
||||
* corresponding {@link XChainCommit} transaction.
|
||||
*/
|
||||
XChainClaimID: number | string
|
||||
|
||||
/**
|
||||
* The destination account on the destination chain. It must exist or the
|
||||
* transaction will fail. However, if the transaction fails in this case, the
|
||||
* sequence number and collected signatures won't be destroyed, and the
|
||||
* transaction can be rerun with a different destination.
|
||||
*/
|
||||
Destination: string
|
||||
|
||||
/**
|
||||
* An integer destination tag.
|
||||
*/
|
||||
DestinationTag?: number
|
||||
|
||||
/**
|
||||
* The amount to claim on the destination chain. This must match the amount
|
||||
* attested to on the attestations associated with this XChainClaimID.
|
||||
*/
|
||||
Amount: Amount
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the form and type of an XChainClaim at runtime.
|
||||
*
|
||||
* @param tx - An XChainClaim Transaction.
|
||||
* @throws When the XChainClaim is malformed.
|
||||
*/
|
||||
export function validateXChainClaim(tx: Record<string, unknown>): void {
|
||||
validateBaseTransaction(tx)
|
||||
|
||||
validateRequiredField(tx, 'XChainBridge', isXChainBridge)
|
||||
|
||||
validateRequiredField(
|
||||
tx,
|
||||
'XChainClaimID',
|
||||
(inp) => isNumber(inp) || isString(inp),
|
||||
)
|
||||
|
||||
validateRequiredField(tx, 'Destination', isString)
|
||||
|
||||
validateOptionalField(tx, 'DestinationTag', isNumber)
|
||||
|
||||
validateRequiredField(tx, 'Amount', isAmount)
|
||||
}
|
||||
74
packages/xrpl/src/models/transactions/XChainCommit.ts
Normal file
74
packages/xrpl/src/models/transactions/XChainCommit.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
import { Amount, XChainBridge } from '../common'
|
||||
|
||||
import {
|
||||
BaseTransaction,
|
||||
isAmount,
|
||||
isNumber,
|
||||
isString,
|
||||
isXChainBridge,
|
||||
validateBaseTransaction,
|
||||
validateOptionalField,
|
||||
validateRequiredField,
|
||||
} from './common'
|
||||
|
||||
/**
|
||||
* The XChainCommit is the second step in a cross-chain transfer. It puts assets
|
||||
* into trust on the locking chain so that they can be wrapped on the issuing
|
||||
* chain, or burns wrapped assets on the issuing chain so that they can be returned
|
||||
* on the locking chain.
|
||||
*
|
||||
* @category Transaction Models
|
||||
*/
|
||||
export interface XChainCommit extends BaseTransaction {
|
||||
TransactionType: 'XChainCommit'
|
||||
|
||||
/**
|
||||
* The bridge to use to transfer funds.
|
||||
*/
|
||||
XChainBridge: XChainBridge
|
||||
|
||||
/**
|
||||
* The unique integer ID for a cross-chain transfer. This must be acquired on
|
||||
* the destination chain (via a {@link XChainCreateClaimID} transaction) and
|
||||
* checked from a validated ledger before submitting this transaction. If an
|
||||
* incorrect sequence number is specified, the funds will be lost.
|
||||
*/
|
||||
XChainClaimID: number | string
|
||||
|
||||
/**
|
||||
* The destination account on the destination chain. If this is not specified,
|
||||
* the account that submitted the {@link XChainCreateClaimID} transaction on the
|
||||
* destination chain will need to submit a {@link XChainClaim} transaction to
|
||||
* claim the funds.
|
||||
*/
|
||||
OtherChainDestination?: string
|
||||
|
||||
/**
|
||||
* The asset to commit, and the quantity. This must match the door account's
|
||||
* LockingChainIssue (if on the locking chain) or the door account's
|
||||
* IssuingChainIssue (if on the issuing chain).
|
||||
*/
|
||||
Amount: Amount
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the form and type of an XChainCommit at runtime.
|
||||
*
|
||||
* @param tx - An XChainCommit Transaction.
|
||||
* @throws When the XChainCommit is malformed.
|
||||
*/
|
||||
export function validateXChainCommit(tx: Record<string, unknown>): void {
|
||||
validateBaseTransaction(tx)
|
||||
|
||||
validateRequiredField(tx, 'XChainBridge', isXChainBridge)
|
||||
|
||||
validateRequiredField(
|
||||
tx,
|
||||
'XChainClaimID',
|
||||
(inp) => isNumber(inp) || isString(inp),
|
||||
)
|
||||
|
||||
validateOptionalField(tx, 'OtherChainDestination', isString)
|
||||
|
||||
validateRequiredField(tx, 'Amount', isAmount)
|
||||
}
|
||||
56
packages/xrpl/src/models/transactions/XChainCreateBridge.ts
Normal file
56
packages/xrpl/src/models/transactions/XChainCreateBridge.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import { Amount, XChainBridge } from '../common'
|
||||
|
||||
import {
|
||||
BaseTransaction,
|
||||
isAmount,
|
||||
isXChainBridge,
|
||||
validateBaseTransaction,
|
||||
validateOptionalField,
|
||||
validateRequiredField,
|
||||
} from './common'
|
||||
|
||||
/**
|
||||
* The XChainCreateBridge transaction creates a new {@link Bridge} ledger object
|
||||
* and defines a new cross-chain bridge entrance on the chain that the transaction
|
||||
* is submitted on. It includes information about door accounts and assets for the
|
||||
* bridge.
|
||||
*
|
||||
* @category Transaction Models
|
||||
*/
|
||||
export interface XChainCreateBridge extends BaseTransaction {
|
||||
TransactionType: 'XChainCreateBridge'
|
||||
|
||||
/**
|
||||
* The bridge (door accounts and assets) to create.
|
||||
*/
|
||||
XChainBridge: XChainBridge
|
||||
|
||||
/**
|
||||
* The total amount to pay the witness servers for their signatures. This amount
|
||||
* will be split among the signers.
|
||||
*/
|
||||
SignatureReward: Amount
|
||||
|
||||
/**
|
||||
* The minimum amount, in XRP, required for a {@link XChainAccountCreateCommit}
|
||||
* transaction. If this isn't present, the {@link XChainAccountCreateCommit}
|
||||
* transaction will fail. This field can only be present on XRP-XRP bridges.
|
||||
*/
|
||||
MinAccountCreateAmount?: Amount
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the form and type of an XChainCreateBridge at runtime.
|
||||
*
|
||||
* @param tx - An XChainCreateBridge Transaction.
|
||||
* @throws When the XChainCreateBridge is malformed.
|
||||
*/
|
||||
export function validateXChainCreateBridge(tx: Record<string, unknown>): void {
|
||||
validateBaseTransaction(tx)
|
||||
|
||||
validateRequiredField(tx, 'XChainBridge', isXChainBridge)
|
||||
|
||||
validateRequiredField(tx, 'SignatureReward', isAmount)
|
||||
|
||||
validateOptionalField(tx, 'MinAccountCreateAmount', isAmount)
|
||||
}
|
||||
53
packages/xrpl/src/models/transactions/XChainCreateClaimID.ts
Normal file
53
packages/xrpl/src/models/transactions/XChainCreateClaimID.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import { Amount, XChainBridge } from '../common'
|
||||
|
||||
import {
|
||||
BaseTransaction,
|
||||
isAmount,
|
||||
isString,
|
||||
isXChainBridge,
|
||||
validateBaseTransaction,
|
||||
validateRequiredField,
|
||||
} from './common'
|
||||
|
||||
/**
|
||||
* The XChainCreateClaimID transaction creates a new cross-chain claim ID that is
|
||||
* used for a cross-chain transfer. A cross-chain claim ID represents one
|
||||
* cross-chain transfer of value.
|
||||
*
|
||||
* @category Transaction Models
|
||||
*/
|
||||
export interface XChainCreateClaimID extends BaseTransaction {
|
||||
TransactionType: 'XChainCreateClaimID'
|
||||
|
||||
/**
|
||||
* The bridge to create the claim ID for.
|
||||
*/
|
||||
XChainBridge: XChainBridge
|
||||
|
||||
/**
|
||||
* The amount, in XRP, to reward the witness servers for providing signatures.
|
||||
* This must match the amount on the {@link Bridge} ledger object.
|
||||
*/
|
||||
SignatureReward: Amount
|
||||
|
||||
/**
|
||||
* The account that must send the {@link XChainCommit} transaction on the source chain.
|
||||
*/
|
||||
OtherChainSource: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the form and type of an XChainCreateClaimID at runtime.
|
||||
*
|
||||
* @param tx - An XChainCreateClaimID Transaction.
|
||||
* @throws When the XChainCreateClaimID is malformed.
|
||||
*/
|
||||
export function validateXChainCreateClaimID(tx: Record<string, unknown>): void {
|
||||
validateBaseTransaction(tx)
|
||||
|
||||
validateRequiredField(tx, 'XChainBridge', isXChainBridge)
|
||||
|
||||
validateRequiredField(tx, 'SignatureReward', isAmount)
|
||||
|
||||
validateRequiredField(tx, 'OtherChainSource', isString)
|
||||
}
|
||||
77
packages/xrpl/src/models/transactions/XChainModifyBridge.ts
Normal file
77
packages/xrpl/src/models/transactions/XChainModifyBridge.ts
Normal file
@@ -0,0 +1,77 @@
|
||||
import { Amount, XChainBridge } from '../common'
|
||||
|
||||
import {
|
||||
BaseTransaction,
|
||||
GlobalFlags,
|
||||
isAmount,
|
||||
isXChainBridge,
|
||||
validateBaseTransaction,
|
||||
validateOptionalField,
|
||||
validateRequiredField,
|
||||
} from './common'
|
||||
|
||||
/**
|
||||
* Enum representing values of {@link XChainModifyBridge} transaction flags.
|
||||
*
|
||||
* @category Transaction Flags
|
||||
*/
|
||||
export enum XChainModifyBridgeFlags {
|
||||
/** Clears the MinAccountCreateAmount of the bridge. */
|
||||
tfClearAccountCreateAmount = 0x00010000,
|
||||
}
|
||||
|
||||
/**
|
||||
* Map of flags to boolean values representing {@link XChainModifyBridge} transaction
|
||||
* flags.
|
||||
*
|
||||
* @category Transaction Flags
|
||||
*/
|
||||
export interface XChainModifyBridgeFlagsInterface extends GlobalFlags {
|
||||
/** Clears the MinAccountCreateAmount of the bridge. */
|
||||
tfClearAccountCreateAmount?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* The XChainModifyBridge transaction allows bridge managers to modify the parameters
|
||||
* of the bridge.
|
||||
*
|
||||
* @category Transaction Models
|
||||
*/
|
||||
export interface XChainModifyBridge extends BaseTransaction {
|
||||
TransactionType: 'XChainModifyBridge'
|
||||
|
||||
/**
|
||||
* The bridge to modify.
|
||||
*/
|
||||
XChainBridge: XChainBridge
|
||||
|
||||
/**
|
||||
* The signature reward split between the witnesses for submitting attestations.
|
||||
*/
|
||||
SignatureReward?: Amount
|
||||
|
||||
/**
|
||||
* The minimum amount, in XRP, required for a {@link XChainAccountCreateCommit}
|
||||
* transaction. If this is not present, the {@link XChainAccountCreateCommit}
|
||||
* transaction will fail. This field can only be present on XRP-XRP bridges.
|
||||
*/
|
||||
MinAccountCreateAmount?: Amount
|
||||
|
||||
Flags?: number | XChainModifyBridgeFlagsInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the form and type of an XChainModifyBridge at runtime.
|
||||
*
|
||||
* @param tx - An XChainModifyBridge Transaction.
|
||||
* @throws When the XChainModifyBridge is malformed.
|
||||
*/
|
||||
export function validateXChainModifyBridge(tx: Record<string, unknown>): void {
|
||||
validateBaseTransaction(tx)
|
||||
|
||||
validateRequiredField(tx, 'XChainBridge', isXChainBridge)
|
||||
|
||||
validateOptionalField(tx, 'SignatureReward', isAmount)
|
||||
|
||||
validateOptionalField(tx, 'MinAccountCreateAmount', isAmount)
|
||||
}
|
||||
@@ -1,9 +1,14 @@
|
||||
/* eslint-disable max-lines-per-function -- Necessary for validateBaseTransaction */
|
||||
/* eslint-disable max-statements -- Necessary for validateBaseTransaction */
|
||||
import { TRANSACTION_TYPES } from 'ripple-binary-codec'
|
||||
|
||||
import { ValidationError } from '../../errors'
|
||||
import { Amount, Currency, IssuedCurrencyAmount, Memo, Signer } from '../common'
|
||||
import {
|
||||
Amount,
|
||||
Currency,
|
||||
IssuedCurrencyAmount,
|
||||
Memo,
|
||||
Signer,
|
||||
XChainBridge,
|
||||
} from '../common'
|
||||
import { onlyHasFields } from '../utils'
|
||||
|
||||
const MEMO_SIZE = 3
|
||||
@@ -52,11 +57,32 @@ function isSigner(obj: unknown): boolean {
|
||||
const XRP_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.
|
||||
*
|
||||
@@ -102,6 +128,73 @@ 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 {}
|
||||
|
||||
@@ -190,14 +283,6 @@ export interface BaseTransaction {
|
||||
* @throws When the common param is malformed.
|
||||
*/
|
||||
export function validateBaseTransaction(common: Record<string, unknown>): void {
|
||||
if (common.Account === undefined) {
|
||||
throw new ValidationError('BaseTransaction: missing field Account')
|
||||
}
|
||||
|
||||
if (typeof common.Account !== 'string') {
|
||||
throw new ValidationError('BaseTransaction: Account not string')
|
||||
}
|
||||
|
||||
if (common.TransactionType === undefined) {
|
||||
throw new ValidationError('BaseTransaction: missing field TransactionType')
|
||||
}
|
||||
@@ -210,27 +295,15 @@ export function validateBaseTransaction(common: Record<string, unknown>): void {
|
||||
throw new ValidationError('BaseTransaction: Unknown TransactionType')
|
||||
}
|
||||
|
||||
if (common.Fee !== undefined && typeof common.Fee !== 'string') {
|
||||
throw new ValidationError('BaseTransaction: invalid Fee')
|
||||
}
|
||||
validateRequiredField(common, 'Account', isString)
|
||||
|
||||
if (common.Sequence !== undefined && typeof common.Sequence !== 'number') {
|
||||
throw new ValidationError('BaseTransaction: invalid Sequence')
|
||||
}
|
||||
validateOptionalField(common, 'Fee', isString)
|
||||
|
||||
if (
|
||||
common.AccountTxnID !== undefined &&
|
||||
typeof common.AccountTxnID !== 'string'
|
||||
) {
|
||||
throw new ValidationError('BaseTransaction: invalid AccountTxnID')
|
||||
}
|
||||
validateOptionalField(common, 'Sequence', isNumber)
|
||||
|
||||
if (
|
||||
common.LastLedgerSequence !== undefined &&
|
||||
typeof common.LastLedgerSequence !== 'number'
|
||||
) {
|
||||
throw new ValidationError('BaseTransaction: invalid LastLedgerSequence')
|
||||
}
|
||||
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
|
||||
@@ -248,33 +321,15 @@ export function validateBaseTransaction(common: Record<string, unknown>): void {
|
||||
throw new ValidationError('BaseTransaction: invalid Signers')
|
||||
}
|
||||
|
||||
if (common.SourceTag !== undefined && typeof common.SourceTag !== 'number') {
|
||||
throw new ValidationError('BaseTransaction: invalid SourceTag')
|
||||
}
|
||||
validateOptionalField(common, 'SourceTag', isNumber)
|
||||
|
||||
if (
|
||||
common.SigningPubKey !== undefined &&
|
||||
typeof common.SigningPubKey !== 'string'
|
||||
) {
|
||||
throw new ValidationError('BaseTransaction: invalid SigningPubKey')
|
||||
}
|
||||
validateOptionalField(common, 'SigningPubKey', isString)
|
||||
|
||||
if (
|
||||
common.TicketSequence !== undefined &&
|
||||
typeof common.TicketSequence !== 'number'
|
||||
) {
|
||||
throw new ValidationError('BaseTransaction: invalid TicketSequence')
|
||||
}
|
||||
validateOptionalField(common, 'TicketSequence', isNumber)
|
||||
|
||||
if (
|
||||
common.TxnSignature !== undefined &&
|
||||
typeof common.TxnSignature !== 'string'
|
||||
) {
|
||||
throw new ValidationError('BaseTransaction: invalid TxnSignature')
|
||||
}
|
||||
if (common.NetworkID !== undefined && typeof common.NetworkID !== 'number') {
|
||||
throw new ValidationError('BaseTransaction: invalid NetworkID')
|
||||
}
|
||||
validateOptionalField(common, 'TxnSignature', isString)
|
||||
|
||||
validateOptionalField(common, 'NetworkID', isNumber)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -25,6 +25,7 @@ export {
|
||||
export { CheckCancel } from './checkCancel'
|
||||
export { CheckCash } from './checkCash'
|
||||
export { CheckCreate } from './checkCreate'
|
||||
export { Clawback } from './clawback'
|
||||
export { DepositPreauth } from './depositPreauth'
|
||||
export { EscrowCancel } from './escrowCancel'
|
||||
export { EscrowCreate } from './escrowCreate'
|
||||
@@ -63,4 +64,15 @@ export { SignerListSet } from './signerListSet'
|
||||
export { TicketCreate } from './ticketCreate'
|
||||
export { TrustSetFlagsInterface, TrustSetFlags, TrustSet } from './trustSet'
|
||||
export { UNLModify } from './UNLModify'
|
||||
export { Clawback } from './clawback'
|
||||
export { XChainAddAccountCreateAttestation } from './XChainAddAccountCreateAttestation'
|
||||
export { XChainAddClaimAttestation } from './XChainAddClaimAttestation'
|
||||
export { XChainClaim } from './XChainClaim'
|
||||
export { XChainCommit } from './XChainCommit'
|
||||
export { XChainCreateBridge } from './XChainCreateBridge'
|
||||
export { XChainCreateClaimID } from './XChainCreateClaimID'
|
||||
export { XChainAccountCreateCommit } from './XChainAccountCreateCommit'
|
||||
export {
|
||||
XChainModifyBridge,
|
||||
XChainModifyBridgeFlags,
|
||||
XChainModifyBridgeFlagsInterface,
|
||||
} from './XChainModifyBridge'
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable max-lines -- need to work with a lot of transactions in a switch statement */
|
||||
/* eslint-disable max-lines-per-function -- need to work with a lot of Tx verifications */
|
||||
|
||||
import { ValidationError } from '../../errors'
|
||||
@@ -56,6 +57,32 @@ import { SetRegularKey, validateSetRegularKey } from './setRegularKey'
|
||||
import { SignerListSet, validateSignerListSet } from './signerListSet'
|
||||
import { TicketCreate, validateTicketCreate } from './ticketCreate'
|
||||
import { TrustSet, validateTrustSet } from './trustSet'
|
||||
import {
|
||||
XChainAccountCreateCommit,
|
||||
validateXChainAccountCreateCommit,
|
||||
} from './XChainAccountCreateCommit'
|
||||
import {
|
||||
XChainAddAccountCreateAttestation,
|
||||
validateXChainAddAccountCreateAttestation,
|
||||
} from './XChainAddAccountCreateAttestation'
|
||||
import {
|
||||
XChainAddClaimAttestation,
|
||||
validateXChainAddClaimAttestation,
|
||||
} from './XChainAddClaimAttestation'
|
||||
import { XChainClaim, validateXChainClaim } from './XChainClaim'
|
||||
import { XChainCommit, validateXChainCommit } from './XChainCommit'
|
||||
import {
|
||||
XChainCreateBridge,
|
||||
validateXChainCreateBridge,
|
||||
} from './XChainCreateBridge'
|
||||
import {
|
||||
XChainCreateClaimID,
|
||||
validateXChainCreateClaimID,
|
||||
} from './XChainCreateClaimID'
|
||||
import {
|
||||
XChainModifyBridge,
|
||||
validateXChainModifyBridge,
|
||||
} from './XChainModifyBridge'
|
||||
|
||||
/**
|
||||
* @category Transaction Models
|
||||
@@ -92,6 +119,14 @@ export type Transaction =
|
||||
| SignerListSet
|
||||
| TicketCreate
|
||||
| TrustSet
|
||||
| XChainAddAccountCreateAttestation
|
||||
| XChainAddClaimAttestation
|
||||
| XChainClaim
|
||||
| XChainCommit
|
||||
| XChainCreateBridge
|
||||
| XChainCreateClaimID
|
||||
| XChainAccountCreateCommit
|
||||
| XChainModifyBridge
|
||||
|
||||
/**
|
||||
* @category Transaction Models
|
||||
@@ -294,6 +329,38 @@ export function validate(transaction: Record<string, unknown>): void {
|
||||
validateTrustSet(tx)
|
||||
break
|
||||
|
||||
case 'XChainAddAccountCreateAttestation':
|
||||
validateXChainAddAccountCreateAttestation(tx)
|
||||
break
|
||||
|
||||
case 'XChainAddClaimAttestation':
|
||||
validateXChainAddClaimAttestation(tx)
|
||||
break
|
||||
|
||||
case 'XChainClaim':
|
||||
validateXChainClaim(tx)
|
||||
break
|
||||
|
||||
case 'XChainCommit':
|
||||
validateXChainCommit(tx)
|
||||
break
|
||||
|
||||
case 'XChainCreateBridge':
|
||||
validateXChainCreateBridge(tx)
|
||||
break
|
||||
|
||||
case 'XChainCreateClaimID':
|
||||
validateXChainCreateClaimID(tx)
|
||||
break
|
||||
|
||||
case 'XChainAccountCreateCommit':
|
||||
validateXChainAccountCreateCommit(tx)
|
||||
break
|
||||
|
||||
case 'XChainModifyBridge':
|
||||
validateXChainModifyBridge(tx)
|
||||
break
|
||||
|
||||
default:
|
||||
throw new ValidationError(
|
||||
`Invalid field TransactionType: ${tx.TransactionType}`,
|
||||
|
||||
@@ -15,6 +15,7 @@ import { PaymentFlags } from '../transactions/payment'
|
||||
import { PaymentChannelClaimFlags } from '../transactions/paymentChannelClaim'
|
||||
import type { Transaction } from '../transactions/transaction'
|
||||
import { TrustSetFlags } from '../transactions/trustSet'
|
||||
import { XChainModifyBridgeFlags } from '../transactions/XChainModifyBridge'
|
||||
|
||||
import { isFlagEnabled } from '.'
|
||||
|
||||
@@ -78,6 +79,9 @@ export function setTransactionFlagsToNumber(tx: Transaction): void {
|
||||
case 'TrustSet':
|
||||
tx.Flags = convertFlagsToNumber(tx.Flags, TrustSetFlags)
|
||||
return
|
||||
case 'XChainModifyBridge':
|
||||
tx.Flags = convertFlagsToNumber(tx.Flags, XChainModifyBridgeFlags)
|
||||
return
|
||||
default:
|
||||
tx.Flags = 0
|
||||
}
|
||||
|
||||
64
packages/xrpl/src/utils/getXChainClaimID.ts
Normal file
64
packages/xrpl/src/utils/getXChainClaimID.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
import { decode } from 'ripple-binary-codec'
|
||||
|
||||
import {
|
||||
CreatedNode,
|
||||
isCreatedNode,
|
||||
TransactionMetadata,
|
||||
} from '../models/transactions/metadata'
|
||||
|
||||
/**
|
||||
* Ensures that the metadata is in a deserialized format to parse.
|
||||
*
|
||||
* @param meta - the metadata from a `tx` method call. Can be in json format or binary format.
|
||||
* @returns the metadata in a deserialized format.
|
||||
*/
|
||||
function ensureDecodedMeta(
|
||||
meta: TransactionMetadata | string,
|
||||
): TransactionMetadata {
|
||||
if (typeof meta === 'string') {
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Meta is either metadata or serialized metadata.
|
||||
return decode(meta) as unknown as TransactionMetadata
|
||||
}
|
||||
return meta
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the XChainClaimID value from the metadata of an `XChainCreateClaimID` transaction.
|
||||
*
|
||||
* @param meta - Metadata from the response to submitting and waiting for an XChainCreateClaimID transaction
|
||||
* or from a `tx` method call.
|
||||
* @returns The XChainClaimID for the minted NFT.
|
||||
* @throws if meta is not TransactionMetadata.
|
||||
*/
|
||||
export default function getXChainClaimID(
|
||||
meta: TransactionMetadata | string | undefined,
|
||||
): string | undefined {
|
||||
if (typeof meta !== 'string' && meta?.AffectedNodes === undefined) {
|
||||
throw new TypeError(`Unable to parse the parameter given to getXChainClaimID.
|
||||
'meta' must be the metadata from an XChainCreateClaimID transaction. Received ${JSON.stringify(
|
||||
meta,
|
||||
)} instead.`)
|
||||
}
|
||||
|
||||
const decodedMeta = ensureDecodedMeta(meta)
|
||||
|
||||
if (!decodedMeta.TransactionResult) {
|
||||
throw new TypeError(
|
||||
'Cannot get XChainClaimID from un-validated transaction',
|
||||
)
|
||||
}
|
||||
|
||||
if (decodedMeta.TransactionResult !== 'tesSUCCESS') {
|
||||
return undefined
|
||||
}
|
||||
|
||||
const createdNode = decodedMeta.AffectedNodes.find(
|
||||
(node) =>
|
||||
isCreatedNode(node) &&
|
||||
node.CreatedNode.LedgerEntryType === 'XChainOwnedClaimID',
|
||||
)
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- necessary here
|
||||
return (createdNode as CreatedNode).CreatedNode.NewFields
|
||||
.XChainClaimID as string
|
||||
}
|
||||
@@ -25,6 +25,7 @@ import { Transaction } from '../models/transactions/transaction'
|
||||
import { deriveKeypair, deriveAddress, deriveXAddress } from './derive'
|
||||
import getBalanceChanges from './getBalanceChanges'
|
||||
import getNFTokenID from './getNFTokenID'
|
||||
import getXChainClaimID from './getXChainClaimID'
|
||||
import {
|
||||
hashSignedTx,
|
||||
hashTx,
|
||||
@@ -220,4 +221,5 @@ export {
|
||||
encodeForSigningClaim,
|
||||
getNFTokenID,
|
||||
parseNFTokenID,
|
||||
getXChainClaimID,
|
||||
}
|
||||
|
||||
8
packages/xrpl/test/fixtures/rippled/index.ts
vendored
8
packages/xrpl/test/fixtures/rippled/index.ts
vendored
@@ -25,8 +25,12 @@ import successSubmit from './submit.json'
|
||||
import successSubscribe from './subscribe.json'
|
||||
import errorSubscribe from './subscribeError.json'
|
||||
import transaction_entry from './transactionEntry.json'
|
||||
import NFTokenMint from './tx/NFTokenMint.json'
|
||||
import NFTokenMint2 from './tx/NFTokenMint2.json'
|
||||
import OfferCreateSell from './tx/offerCreateSell.json'
|
||||
import Payment from './tx/payment.json'
|
||||
import XChainCreateClaimID from './tx/XChainCreateClaimID.json'
|
||||
import XChainCreateClaimID2 from './tx/XChainCreateClaimID2.json'
|
||||
import unsubscribe from './unsubscribe.json'
|
||||
|
||||
const submit = {
|
||||
@@ -89,8 +93,12 @@ const server_info = {
|
||||
}
|
||||
|
||||
const tx = {
|
||||
NFTokenMint,
|
||||
NFTokenMint2,
|
||||
Payment,
|
||||
OfferCreateSell,
|
||||
XChainCreateClaimID,
|
||||
XChainCreateClaimID2,
|
||||
}
|
||||
|
||||
const rippled = {
|
||||
|
||||
118
packages/xrpl/test/fixtures/rippled/tx/XChainCreateClaimID.json
vendored
Normal file
118
packages/xrpl/test/fixtures/rippled/tx/XChainCreateClaimID.json
vendored
Normal file
@@ -0,0 +1,118 @@
|
||||
{
|
||||
"tx": {
|
||||
"Account": "rLVUz66tawieqTPAHuTyFTN6pLbHcXiTzd",
|
||||
"Fee": "20",
|
||||
"Flags": 2147483648,
|
||||
"NetworkID": 2552,
|
||||
"OtherChainSource": "rL5Zd9m5XEoGPddMwYY5H5C8ARcR47b6oM",
|
||||
"Sequence": 1007784,
|
||||
"SignatureReward": "100",
|
||||
"SigningPubKey": "039E925058C740A5B73E49300FC205D058520DE37F2C63C4EE3A0D1B50C4E44080",
|
||||
"TransactionType": "XChainCreateClaimID",
|
||||
"TxnSignature": "304402201C6F95B9997FB63DCD9854664707C58C46AA3207612FE32366B77DA084786CAF02205752C58821D7FAFAE26F77DC10AC0AFDDCBCCF4FCBED90E6B8C4523A0EB3E008",
|
||||
"XChainBridge": {
|
||||
"IssuingChainDoor": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
||||
"IssuingChainIssue": {
|
||||
"currency": "XRP"
|
||||
},
|
||||
"LockingChainDoor": "rMAXACCrp3Y8PpswXcg3bKggHX76V3F8M4",
|
||||
"LockingChainIssue": {
|
||||
"currency": "XRP"
|
||||
}
|
||||
},
|
||||
"date": 1695324353000
|
||||
},
|
||||
"meta": {
|
||||
"AffectedNodes": [
|
||||
{
|
||||
"ModifiedNode": {
|
||||
"FinalFields": {
|
||||
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
||||
"Flags": 0,
|
||||
"MinAccountCreateAmount": "10000000",
|
||||
"OwnerNode": "0",
|
||||
"SignatureReward": "100",
|
||||
"XChainAccountClaimCount": "e3",
|
||||
"XChainAccountCreateCount": "0",
|
||||
"XChainBridge": {
|
||||
"IssuingChainDoor": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
||||
"IssuingChainIssue": {
|
||||
"currency": "XRP"
|
||||
},
|
||||
"LockingChainDoor": "rMAXACCrp3Y8PpswXcg3bKggHX76V3F8M4",
|
||||
"LockingChainIssue": {
|
||||
"currency": "XRP"
|
||||
}
|
||||
},
|
||||
"XChainClaimID": "b0"
|
||||
},
|
||||
"LedgerEntryType": "Bridge",
|
||||
"LedgerIndex": "114C0DC89656D1B0FB1F4A3426034C3FCE75BCE65D9574B5D96ABC2B24D6C8F1",
|
||||
"PreviousFields": {
|
||||
"XChainClaimID": "af"
|
||||
},
|
||||
"PreviousTxnID": "3F6F3BBE584115D1A575AB24BA32B47184F2323B65DE5C8C8EE144A55115E0B9",
|
||||
"PreviousTxnLgrSeq": 1027822
|
||||
}
|
||||
},
|
||||
{
|
||||
"ModifiedNode": {
|
||||
"FinalFields": {
|
||||
"Flags": 0,
|
||||
"Owner": "rLVUz66tawieqTPAHuTyFTN6pLbHcXiTzd",
|
||||
"RootIndex": "6C1EA1A93D590E831CCC0EE2CBE26C146A3A6FD36F5854DC5E5AB5CE78FAE49C"
|
||||
},
|
||||
"LedgerEntryType": "DirectoryNode",
|
||||
"LedgerIndex": "6C1EA1A93D590E831CCC0EE2CBE26C146A3A6FD36F5854DC5E5AB5CE78FAE49C"
|
||||
}
|
||||
},
|
||||
{
|
||||
"CreatedNode": {
|
||||
"LedgerEntryType": "XChainOwnedClaimID",
|
||||
"LedgerIndex": "A00BD77AE864509D796B39041AD48E9DEFEC9AF20E5C09CEF2F5DA41D6CFEB1E",
|
||||
"NewFields": {
|
||||
"Account": "rLVUz66tawieqTPAHuTyFTN6pLbHcXiTzd",
|
||||
"OtherChainSource": "rL5Zd9m5XEoGPddMwYY5H5C8ARcR47b6oM",
|
||||
"SignatureReward": "100",
|
||||
"XChainBridge": {
|
||||
"IssuingChainDoor": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
||||
"IssuingChainIssue": {
|
||||
"currency": "XRP"
|
||||
},
|
||||
"LockingChainDoor": "rMAXACCrp3Y8PpswXcg3bKggHX76V3F8M4",
|
||||
"LockingChainIssue": {
|
||||
"currency": "XRP"
|
||||
}
|
||||
},
|
||||
"XChainClaimID": "b0"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ModifiedNode": {
|
||||
"FinalFields": {
|
||||
"Account": "rLVUz66tawieqTPAHuTyFTN6pLbHcXiTzd",
|
||||
"Balance": "39999940",
|
||||
"Flags": 0,
|
||||
"OwnerCount": 3,
|
||||
"Sequence": 1007785
|
||||
},
|
||||
"LedgerEntryType": "AccountRoot",
|
||||
"LedgerIndex": "FD919D0BAA90C759DA4C7130AEEF6AE7FA2AF074F5E867D40BCBE1ECD8D8D0EA",
|
||||
"PreviousFields": {
|
||||
"Balance": "39999960",
|
||||
"OwnerCount": 2,
|
||||
"Sequence": 1007784
|
||||
},
|
||||
"PreviousTxnID": "3F6F3BBE584115D1A575AB24BA32B47184F2323B65DE5C8C8EE144A55115E0B9",
|
||||
"PreviousTxnLgrSeq": 1027822
|
||||
}
|
||||
}
|
||||
],
|
||||
"TransactionIndex": 0,
|
||||
"TransactionResult": "tesSUCCESS"
|
||||
},
|
||||
"hash": "998E76B9840DA5A6009592A2674D0166A9C4862193193AA46EA6B77A64781FB4",
|
||||
"ledger_index": 1027837,
|
||||
"date": 1695324353000
|
||||
}
|
||||
118
packages/xrpl/test/fixtures/rippled/tx/XChainCreateClaimID2.json
vendored
Normal file
118
packages/xrpl/test/fixtures/rippled/tx/XChainCreateClaimID2.json
vendored
Normal file
@@ -0,0 +1,118 @@
|
||||
{
|
||||
"tx": {
|
||||
"Account": "rwmUSzi5Xp31AjMTEdbvxgWqLETcVNU6Fv",
|
||||
"Fee": "12",
|
||||
"Flags": 0,
|
||||
"LastLedgerSequence": 1027798,
|
||||
"NetworkID": 2552,
|
||||
"OtherChainSource": "rBXdfZ7NVpdjRfYajPMpviGgq7HLDeuBdR",
|
||||
"Sequence": 1027778,
|
||||
"SignatureReward": "100",
|
||||
"SigningPubKey": "EDDDD69DF802B8DB82D644EF92E2C1F06AC128A275CDFF86F013180D104ED39D3B",
|
||||
"TransactionType": "XChainCreateClaimID",
|
||||
"TxnSignature": "67BE63527EC8A0C872F23E2C4EB97C1F3E7D3FED6D10C8310B9235D3891B6B9343768A080E258F6C3687BFC4B7C5FD429ABB33654C99DE46471FD6F2A7035303",
|
||||
"XChainBridge": {
|
||||
"IssuingChainDoor": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
||||
"IssuingChainIssue": {
|
||||
"currency": "XRP"
|
||||
},
|
||||
"LockingChainDoor": "rMAXACCrp3Y8PpswXcg3bKggHX76V3F8M4",
|
||||
"LockingChainIssue": {
|
||||
"currency": "XRP"
|
||||
}
|
||||
},
|
||||
"date": 1695324182000
|
||||
},
|
||||
"meta": {
|
||||
"AffectedNodes": [
|
||||
{
|
||||
"ModifiedNode": {
|
||||
"FinalFields": {
|
||||
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
||||
"Flags": 0,
|
||||
"MinAccountCreateAmount": "10000000",
|
||||
"OwnerNode": "0",
|
||||
"SignatureReward": "100",
|
||||
"XChainAccountClaimCount": "e2",
|
||||
"XChainAccountCreateCount": "0",
|
||||
"XChainBridge": {
|
||||
"IssuingChainDoor": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
||||
"IssuingChainIssue": {
|
||||
"currency": "XRP"
|
||||
},
|
||||
"LockingChainDoor": "rMAXACCrp3Y8PpswXcg3bKggHX76V3F8M4",
|
||||
"LockingChainIssue": {
|
||||
"currency": "XRP"
|
||||
}
|
||||
},
|
||||
"XChainClaimID": "ac"
|
||||
},
|
||||
"LedgerEntryType": "Bridge",
|
||||
"LedgerIndex": "114C0DC89656D1B0FB1F4A3426034C3FCE75BCE65D9574B5D96ABC2B24D6C8F1",
|
||||
"PreviousFields": {
|
||||
"XChainClaimID": "ab"
|
||||
},
|
||||
"PreviousTxnID": "80C33D1FB349D698CFDB1A85E8368557C5B7219B74DFCB2B05E0B10E2667F902",
|
||||
"PreviousTxnLgrSeq": 1027779
|
||||
}
|
||||
},
|
||||
{
|
||||
"ModifiedNode": {
|
||||
"FinalFields": {
|
||||
"Account": "rwmUSzi5Xp31AjMTEdbvxgWqLETcVNU6Fv",
|
||||
"Balance": "19999988",
|
||||
"Flags": 0,
|
||||
"OwnerCount": 1,
|
||||
"Sequence": 1027779
|
||||
},
|
||||
"LedgerEntryType": "AccountRoot",
|
||||
"LedgerIndex": "33442CE111B258424548888D8999F6D064A0866B1300C44AB72E1C5A09765D9D",
|
||||
"PreviousFields": {
|
||||
"Balance": "20000000",
|
||||
"OwnerCount": 0,
|
||||
"Sequence": 1027778
|
||||
},
|
||||
"PreviousTxnID": "7C9ACA230488547B4F39EBCE332447FB90AE59B64C1B03BBF474B509B43739EC",
|
||||
"PreviousTxnLgrSeq": 1027778
|
||||
}
|
||||
},
|
||||
{
|
||||
"CreatedNode": {
|
||||
"LedgerEntryType": "DirectoryNode",
|
||||
"LedgerIndex": "439684B06C22596B5B86D2F50903B6AA6F68BD07BED636FC6325704B09DE5D61",
|
||||
"NewFields": {
|
||||
"Owner": "rwmUSzi5Xp31AjMTEdbvxgWqLETcVNU6Fv",
|
||||
"RootIndex": "439684B06C22596B5B86D2F50903B6AA6F68BD07BED636FC6325704B09DE5D61"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"CreatedNode": {
|
||||
"LedgerEntryType": "XChainOwnedClaimID",
|
||||
"LedgerIndex": "8097863E1200B0174006541763AA8F604782DA10C1BD37190D753C699D69C678",
|
||||
"NewFields": {
|
||||
"Account": "rwmUSzi5Xp31AjMTEdbvxgWqLETcVNU6Fv",
|
||||
"OtherChainSource": "rBXdfZ7NVpdjRfYajPMpviGgq7HLDeuBdR",
|
||||
"SignatureReward": "100",
|
||||
"XChainBridge": {
|
||||
"IssuingChainDoor": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
||||
"IssuingChainIssue": {
|
||||
"currency": "XRP"
|
||||
},
|
||||
"LockingChainDoor": "rMAXACCrp3Y8PpswXcg3bKggHX76V3F8M4",
|
||||
"LockingChainIssue": {
|
||||
"currency": "XRP"
|
||||
}
|
||||
},
|
||||
"XChainClaimID": "ac"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"TransactionIndex": 0,
|
||||
"TransactionResult": "tesSUCCESS"
|
||||
},
|
||||
"hash": "A42C4E7F5BAF8A9BEB56853114EE686D554F15F400B8DA885A344B13C32D07BC",
|
||||
"ledger_index": 1027780,
|
||||
"date": 1695324182000
|
||||
}
|
||||
161
packages/xrpl/test/models/XChainAccountCreateCommit.test.ts
Normal file
161
packages/xrpl/test/models/XChainAccountCreateCommit.test.ts
Normal file
@@ -0,0 +1,161 @@
|
||||
import { assert } from 'chai'
|
||||
|
||||
import { validate, ValidationError } from '../../src'
|
||||
import { validateXChainAccountCreateCommit } from '../../src/models/transactions/XChainAccountCreateCommit'
|
||||
|
||||
/**
|
||||
* XChainAccountCreateCommit Transaction Verification Testing.
|
||||
*
|
||||
* Providing runtime verification testing for each specific transaction type.
|
||||
*/
|
||||
describe('XChainAccountCreateCommit', function () {
|
||||
let tx
|
||||
|
||||
beforeEach(function () {
|
||||
tx = {
|
||||
Account: 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh',
|
||||
XChainBridge: {
|
||||
LockingChainDoor: 'rGzx83BVoqTYbGn7tiVAnFw7cbxjin13jL',
|
||||
LockingChainIssue: {
|
||||
currency: 'XRP',
|
||||
},
|
||||
IssuingChainDoor: 'r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV',
|
||||
IssuingChainIssue: {
|
||||
currency: 'XRP',
|
||||
},
|
||||
},
|
||||
Amount: '1000000',
|
||||
Fee: '10',
|
||||
Flags: 2147483648,
|
||||
Destination: 'rGzx83BVoqTYbGn7tiVAnFw7cbxjin13jL',
|
||||
Sequence: 1,
|
||||
SignatureReward: '10000',
|
||||
TransactionType: 'XChainAccountCreateCommit',
|
||||
} as any
|
||||
})
|
||||
|
||||
it('verifies valid XChainAccountCreateCommit', function () {
|
||||
assert.doesNotThrow(() => validateXChainAccountCreateCommit(tx))
|
||||
assert.doesNotThrow(() => validate(tx))
|
||||
})
|
||||
|
||||
it('throws w/ missing XChainBridge', function () {
|
||||
delete tx.XChainBridge
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainAccountCreateCommit(tx),
|
||||
ValidationError,
|
||||
'XChainAccountCreateCommit: missing field XChainBridge',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainAccountCreateCommit: missing field XChainBridge',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ invalid XChainBridge', function () {
|
||||
tx.XChainBridge = { XChainDoor: 'test' }
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainAccountCreateCommit(tx),
|
||||
ValidationError,
|
||||
'XChainAccountCreateCommit: invalid field XChainBridge',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainAccountCreateCommit: invalid field XChainBridge',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ missing SignatureReward', function () {
|
||||
delete tx.SignatureReward
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainAccountCreateCommit(tx),
|
||||
ValidationError,
|
||||
'XChainAccountCreateCommit: missing field SignatureReward',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainAccountCreateCommit: missing field SignatureReward',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ invalid SignatureReward', function () {
|
||||
tx.SignatureReward = { currency: 'ETH' }
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainAccountCreateCommit(tx),
|
||||
ValidationError,
|
||||
'XChainAccountCreateCommit: invalid field SignatureReward',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainAccountCreateCommit: invalid field SignatureReward',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ missing Destination', function () {
|
||||
delete tx.Destination
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainAccountCreateCommit(tx),
|
||||
ValidationError,
|
||||
'XChainAccountCreateCommit: missing field Destination',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainAccountCreateCommit: missing field Destination',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ invalid Destination', function () {
|
||||
tx.Destination = 123
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainAccountCreateCommit(tx),
|
||||
ValidationError,
|
||||
'XChainAccountCreateCommit: invalid field Destination',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainAccountCreateCommit: invalid field Destination',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ missing Amount', function () {
|
||||
delete tx.Amount
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainAccountCreateCommit(tx),
|
||||
ValidationError,
|
||||
'XChainAccountCreateCommit: missing field Amount',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainAccountCreateCommit: missing field Amount',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ invalid Amount', function () {
|
||||
tx.Amount = { currency: 'ETH' }
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainAccountCreateCommit(tx),
|
||||
ValidationError,
|
||||
'XChainAccountCreateCommit: invalid field Amount',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainAccountCreateCommit: invalid field Amount',
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,381 @@
|
||||
import { assert } from 'chai'
|
||||
|
||||
import { validate, ValidationError } from '../../src'
|
||||
import { validateXChainAddAccountCreateAttestation } from '../../src/models/transactions/XChainAddAccountCreateAttestation'
|
||||
|
||||
/**
|
||||
* XChainAddAccountCreateAttestation Transaction Verification Testing.
|
||||
*
|
||||
* Providing runtime verification testing for each specific transaction type.
|
||||
*/
|
||||
describe('XChainAddAccountCreateAttestation', function () {
|
||||
let tx
|
||||
|
||||
beforeEach(function () {
|
||||
tx = {
|
||||
Account: 'r9cYxdjQsoXAEz3qQJc961SNLaXRkWXCvT',
|
||||
Amount: '10000000',
|
||||
AttestationRewardAccount: 'r9cYxdjQsoXAEz3qQJc961SNLaXRkWXCvT',
|
||||
AttestationSignerAccount: 'r9cYxdjQsoXAEz3qQJc961SNLaXRkWXCvT',
|
||||
Destination: 'rJdTJRJZ6GXCCRaamHJgEqVzB7Zy4557Pi',
|
||||
Fee: '20',
|
||||
LastLedgerSequence: 13,
|
||||
OtherChainSource: 'raFcdz1g8LWJDJWJE2ZKLRGdmUmsTyxaym',
|
||||
PublicKey:
|
||||
'ED1F4A024ACFEBDB6C7AA88DEDE3364E060487EA31B14CC9E0D610D152B31AADC2',
|
||||
Sequence: 5,
|
||||
Signature:
|
||||
'EEFCFA3DC2AB4AB7C4D2EBBC168CB621A11B82BABD86534DFC8EFA72439A496' +
|
||||
'62D744073CD848E7A587A95B35162CDF9A69BB237E72C9537A987F5B8C394F30D',
|
||||
SignatureReward: '100',
|
||||
TransactionType: 'XChainAddAccountCreateAttestation',
|
||||
WasLockingChainSend: 1,
|
||||
XChainAccountCreateCount: '0000000000000006',
|
||||
XChainBridge: {
|
||||
IssuingChainDoor: 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh',
|
||||
IssuingChainIssue: {
|
||||
currency: 'XRP',
|
||||
},
|
||||
LockingChainDoor: 'rDJVtEuDKr4rj1B3qtW7R5TVWdXV2DY7Qg',
|
||||
LockingChainIssue: {
|
||||
currency: 'XRP',
|
||||
},
|
||||
},
|
||||
} as any
|
||||
})
|
||||
|
||||
it('verifies valid XChainAddAccountCreateAttestation', function () {
|
||||
assert.doesNotThrow(() => validateXChainAddAccountCreateAttestation(tx))
|
||||
assert.doesNotThrow(() => validate(tx))
|
||||
})
|
||||
|
||||
it('throws w/ missing Amount', function () {
|
||||
delete tx.Amount
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainAddAccountCreateAttestation(tx),
|
||||
ValidationError,
|
||||
'XChainAddAccountCreateAttestation: missing field Amount',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainAddAccountCreateAttestation: missing field Amount',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ invalid Amount', function () {
|
||||
tx.Amount = { currency: 'ETH' }
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainAddAccountCreateAttestation(tx),
|
||||
ValidationError,
|
||||
'XChainAddAccountCreateAttestation: invalid field Amount',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainAddAccountCreateAttestation: invalid field Amount',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ missing AttestationRewardAccount', function () {
|
||||
delete tx.AttestationRewardAccount
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainAddAccountCreateAttestation(tx),
|
||||
ValidationError,
|
||||
'XChainAddAccountCreateAttestation: missing field AttestationRewardAccount',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainAddAccountCreateAttestation: missing field AttestationRewardAccount',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ invalid AttestationRewardAccount', function () {
|
||||
tx.AttestationRewardAccount = 123
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainAddAccountCreateAttestation(tx),
|
||||
ValidationError,
|
||||
'XChainAddAccountCreateAttestation: invalid field AttestationRewardAccount',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainAddAccountCreateAttestation: invalid field AttestationRewardAccount',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ missing AttestationSignerAccount', function () {
|
||||
delete tx.AttestationSignerAccount
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainAddAccountCreateAttestation(tx),
|
||||
ValidationError,
|
||||
'XChainAddAccountCreateAttestation: missing field AttestationSignerAccount',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainAddAccountCreateAttestation: missing field AttestationSignerAccount',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ invalid AttestationSignerAccount', function () {
|
||||
tx.AttestationSignerAccount = 123
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainAddAccountCreateAttestation(tx),
|
||||
ValidationError,
|
||||
'XChainAddAccountCreateAttestation: invalid field AttestationSignerAccount',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainAddAccountCreateAttestation: invalid field AttestationSignerAccount',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ missing Destination', function () {
|
||||
delete tx.Destination
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainAddAccountCreateAttestation(tx),
|
||||
ValidationError,
|
||||
'XChainAddAccountCreateAttestation: missing field Destination',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainAddAccountCreateAttestation: missing field Destination',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ invalid Destination', function () {
|
||||
tx.Destination = 123
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainAddAccountCreateAttestation(tx),
|
||||
ValidationError,
|
||||
'XChainAddAccountCreateAttestation: invalid field Destination',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainAddAccountCreateAttestation: invalid field Destination',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ missing OtherChainSource', function () {
|
||||
delete tx.OtherChainSource
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainAddAccountCreateAttestation(tx),
|
||||
ValidationError,
|
||||
'XChainAddAccountCreateAttestation: missing field OtherChainSource',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainAddAccountCreateAttestation: missing field OtherChainSource',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ invalid OtherChainSource', function () {
|
||||
tx.OtherChainSource = 123
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainAddAccountCreateAttestation(tx),
|
||||
ValidationError,
|
||||
'XChainAddAccountCreateAttestation: invalid field OtherChainSource',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainAddAccountCreateAttestation: invalid field OtherChainSource',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ missing PublicKey', function () {
|
||||
delete tx.PublicKey
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainAddAccountCreateAttestation(tx),
|
||||
ValidationError,
|
||||
'XChainAddAccountCreateAttestation: missing field PublicKey',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainAddAccountCreateAttestation: missing field PublicKey',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ invalid PublicKey', function () {
|
||||
tx.PublicKey = 123
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainAddAccountCreateAttestation(tx),
|
||||
ValidationError,
|
||||
'XChainAddAccountCreateAttestation: invalid field PublicKey',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainAddAccountCreateAttestation: invalid field PublicKey',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ missing Signature', function () {
|
||||
delete tx.Signature
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainAddAccountCreateAttestation(tx),
|
||||
ValidationError,
|
||||
'XChainAddAccountCreateAttestation: missing field Signature',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainAddAccountCreateAttestation: missing field Signature',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ invalid Signature', function () {
|
||||
tx.Signature = 123
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainAddAccountCreateAttestation(tx),
|
||||
ValidationError,
|
||||
'XChainAddAccountCreateAttestation: invalid field Signature',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainAddAccountCreateAttestation: invalid field Signature',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ missing SignatureReward', function () {
|
||||
delete tx.SignatureReward
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainAddAccountCreateAttestation(tx),
|
||||
ValidationError,
|
||||
'XChainAddAccountCreateAttestation: missing field SignatureReward',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainAddAccountCreateAttestation: missing field SignatureReward',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ invalid SignatureReward', function () {
|
||||
tx.SignatureReward = { currency: 'ETH' }
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainAddAccountCreateAttestation(tx),
|
||||
ValidationError,
|
||||
'XChainAddAccountCreateAttestation: invalid field SignatureReward',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainAddAccountCreateAttestation: invalid field SignatureReward',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ missing WasLockingChainSend', function () {
|
||||
delete tx.WasLockingChainSend
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainAddAccountCreateAttestation(tx),
|
||||
ValidationError,
|
||||
'XChainAddAccountCreateAttestation: missing field WasLockingChainSend',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainAddAccountCreateAttestation: missing field WasLockingChainSend',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ invalid WasLockingChainSend', function () {
|
||||
tx.WasLockingChainSend = 2
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainAddAccountCreateAttestation(tx),
|
||||
ValidationError,
|
||||
'XChainAddAccountCreateAttestation: invalid field WasLockingChainSend',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainAddAccountCreateAttestation: invalid field WasLockingChainSend',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ missing XChainAccountCreateCount', function () {
|
||||
delete tx.XChainAccountCreateCount
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainAddAccountCreateAttestation(tx),
|
||||
ValidationError,
|
||||
'XChainAddAccountCreateAttestation: missing field XChainAccountCreateCount',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainAddAccountCreateAttestation: missing field XChainAccountCreateCount',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ invalid XChainAccountCreateCount', function () {
|
||||
tx.XChainAccountCreateCount = { currency: 'ETH' }
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainAddAccountCreateAttestation(tx),
|
||||
ValidationError,
|
||||
'XChainAddAccountCreateAttestation: invalid field XChainAccountCreateCount',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainAddAccountCreateAttestation: invalid field XChainAccountCreateCount',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ missing XChainBridge', function () {
|
||||
delete tx.XChainBridge
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainAddAccountCreateAttestation(tx),
|
||||
ValidationError,
|
||||
'XChainAddAccountCreateAttestation: missing field XChainBridge',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainAddAccountCreateAttestation: missing field XChainBridge',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ invalid XChainBridge', function () {
|
||||
tx.XChainBridge = { XChainDoor: 'test' }
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainAddAccountCreateAttestation(tx),
|
||||
ValidationError,
|
||||
'XChainAddAccountCreateAttestation: invalid field XChainBridge',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainAddAccountCreateAttestation: invalid field XChainBridge',
|
||||
)
|
||||
})
|
||||
})
|
||||
334
packages/xrpl/test/models/XChainAddClaimAttestation.test.ts
Normal file
334
packages/xrpl/test/models/XChainAddClaimAttestation.test.ts
Normal file
@@ -0,0 +1,334 @@
|
||||
import { assert } from 'chai'
|
||||
|
||||
import { validate, ValidationError } from '../../src'
|
||||
import { validateXChainAddClaimAttestation } from '../../src/models/transactions/XChainAddClaimAttestation'
|
||||
|
||||
/**
|
||||
* XChainAddClaimAttestation Transaction Verification Testing.
|
||||
*
|
||||
* Providing runtime verification testing for each specific transaction type.
|
||||
*/
|
||||
describe('XChainAddClaimAttestation', function () {
|
||||
let tx
|
||||
|
||||
beforeEach(function () {
|
||||
tx = {
|
||||
Account: 'rsqvD8WFFEBBv4nztpoW9YYXJ7eRzLrtc3',
|
||||
Amount: '10000000',
|
||||
AttestationRewardAccount: 'rsqvD8WFFEBBv4nztpoW9YYXJ7eRzLrtc3',
|
||||
AttestationSignerAccount: 'rsqvD8WFFEBBv4nztpoW9YYXJ7eRzLrtc3',
|
||||
Destination: 'rJdTJRJZ6GXCCRaamHJgEqVzB7Zy4557Pi',
|
||||
Fee: '20',
|
||||
LastLedgerSequence: 19,
|
||||
OtherChainSource: 'raFcdz1g8LWJDJWJE2ZKLRGdmUmsTyxaym',
|
||||
PublicKey:
|
||||
'ED7541DEC700470F54276C90C333A13CDBB5D341FD43C60CEA12170F6D6D4E1136',
|
||||
Sequence: 9,
|
||||
Signature:
|
||||
'7C175050B08000AD35EEB2D87E16CD3F95A0AEEBF2A049474275153D9D4DD44528FE99AA50E71660A15B0B768E1B90E609BBD5DC7AFAFD45D9705D72D40EA10C',
|
||||
TransactionType: 'XChainAddClaimAttestation',
|
||||
WasLockingChainSend: 1,
|
||||
XChainBridge: {
|
||||
IssuingChainDoor: 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh',
|
||||
IssuingChainIssue: {
|
||||
currency: 'XRP',
|
||||
},
|
||||
LockingChainDoor: 'rDJVtEuDKr4rj1B3qtW7R5TVWdXV2DY7Qg',
|
||||
LockingChainIssue: {
|
||||
currency: 'XRP',
|
||||
},
|
||||
},
|
||||
XChainClaimID: '0000000000000001',
|
||||
} as any
|
||||
})
|
||||
|
||||
it('verifies valid XChainAddClaimAttestation', function () {
|
||||
assert.doesNotThrow(() => validateXChainAddClaimAttestation(tx))
|
||||
assert.doesNotThrow(() => validate(tx))
|
||||
})
|
||||
|
||||
it('throws w/ missing Amount', function () {
|
||||
delete tx.Amount
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainAddClaimAttestation(tx),
|
||||
ValidationError,
|
||||
'XChainAddClaimAttestation: missing field Amount',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainAddClaimAttestation: missing field Amount',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ invalid Amount', function () {
|
||||
tx.Amount = { currency: 'ETH' }
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainAddClaimAttestation(tx),
|
||||
ValidationError,
|
||||
'XChainAddClaimAttestation: invalid field Amount',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainAddClaimAttestation: invalid field Amount',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ missing AttestationRewardAccount', function () {
|
||||
delete tx.AttestationRewardAccount
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainAddClaimAttestation(tx),
|
||||
ValidationError,
|
||||
'XChainAddClaimAttestation: missing field AttestationRewardAccount',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainAddClaimAttestation: missing field AttestationRewardAccount',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ invalid AttestationRewardAccount', function () {
|
||||
tx.AttestationRewardAccount = 123
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainAddClaimAttestation(tx),
|
||||
ValidationError,
|
||||
'XChainAddClaimAttestation: invalid field AttestationRewardAccount',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainAddClaimAttestation: invalid field AttestationRewardAccount',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ missing AttestationSignerAccount', function () {
|
||||
delete tx.AttestationSignerAccount
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainAddClaimAttestation(tx),
|
||||
ValidationError,
|
||||
'XChainAddClaimAttestation: missing field AttestationSignerAccount',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainAddClaimAttestation: missing field AttestationSignerAccount',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ invalid AttestationSignerAccount', function () {
|
||||
tx.AttestationSignerAccount = 123
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainAddClaimAttestation(tx),
|
||||
ValidationError,
|
||||
'XChainAddClaimAttestation: invalid field AttestationSignerAccount',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainAddClaimAttestation: invalid field AttestationSignerAccount',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ invalid Destination', function () {
|
||||
tx.Destination = 123
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainAddClaimAttestation(tx),
|
||||
ValidationError,
|
||||
'XChainAddClaimAttestation: invalid field Destination',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainAddClaimAttestation: invalid field Destination',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ missing OtherChainSource', function () {
|
||||
delete tx.OtherChainSource
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainAddClaimAttestation(tx),
|
||||
ValidationError,
|
||||
'XChainAddClaimAttestation: missing field OtherChainSource',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainAddClaimAttestation: missing field OtherChainSource',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ invalid OtherChainSource', function () {
|
||||
tx.OtherChainSource = 123
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainAddClaimAttestation(tx),
|
||||
ValidationError,
|
||||
'XChainAddClaimAttestation: invalid field OtherChainSource',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainAddClaimAttestation: invalid field OtherChainSource',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ missing PublicKey', function () {
|
||||
delete tx.PublicKey
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainAddClaimAttestation(tx),
|
||||
ValidationError,
|
||||
'XChainAddClaimAttestation: missing field PublicKey',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainAddClaimAttestation: missing field PublicKey',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ invalid PublicKey', function () {
|
||||
tx.PublicKey = 123
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainAddClaimAttestation(tx),
|
||||
ValidationError,
|
||||
'XChainAddClaimAttestation: invalid field PublicKey',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainAddClaimAttestation: invalid field PublicKey',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ missing Signature', function () {
|
||||
delete tx.Signature
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainAddClaimAttestation(tx),
|
||||
ValidationError,
|
||||
'XChainAddClaimAttestation: missing field Signature',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainAddClaimAttestation: missing field Signature',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ invalid Signature', function () {
|
||||
tx.Signature = 123
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainAddClaimAttestation(tx),
|
||||
ValidationError,
|
||||
'XChainAddClaimAttestation: invalid field Signature',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainAddClaimAttestation: invalid field Signature',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ missing WasLockingChainSend', function () {
|
||||
delete tx.WasLockingChainSend
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainAddClaimAttestation(tx),
|
||||
ValidationError,
|
||||
'XChainAddClaimAttestation: missing field WasLockingChainSend',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainAddClaimAttestation: missing field WasLockingChainSend',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ invalid WasLockingChainSend', function () {
|
||||
tx.WasLockingChainSend = 2
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainAddClaimAttestation(tx),
|
||||
ValidationError,
|
||||
'XChainAddClaimAttestation: invalid field WasLockingChainSend',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainAddClaimAttestation: invalid field WasLockingChainSend',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ missing XChainBridge', function () {
|
||||
delete tx.XChainBridge
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainAddClaimAttestation(tx),
|
||||
ValidationError,
|
||||
'XChainAddClaimAttestation: missing field XChainBridge',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainAddClaimAttestation: missing field XChainBridge',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ invalid XChainBridge', function () {
|
||||
tx.XChainBridge = { XChainDoor: 'test' }
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainAddClaimAttestation(tx),
|
||||
ValidationError,
|
||||
'XChainAddClaimAttestation: invalid field XChainBridge',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainAddClaimAttestation: invalid field XChainBridge',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ missing XChainClaimID', function () {
|
||||
delete tx.XChainClaimID
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainAddClaimAttestation(tx),
|
||||
ValidationError,
|
||||
'XChainAddClaimAttestation: missing field XChainClaimID',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainAddClaimAttestation: missing field XChainClaimID',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ invalid XChainClaimID', function () {
|
||||
tx.XChainClaimID = { currency: 'ETH' }
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainAddClaimAttestation(tx),
|
||||
ValidationError,
|
||||
'XChainAddClaimAttestation: invalid field XChainClaimID',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainAddClaimAttestation: invalid field XChainClaimID',
|
||||
)
|
||||
})
|
||||
})
|
||||
176
packages/xrpl/test/models/XChainClaim.test.ts
Normal file
176
packages/xrpl/test/models/XChainClaim.test.ts
Normal file
@@ -0,0 +1,176 @@
|
||||
import { assert } from 'chai'
|
||||
|
||||
import { validate, ValidationError } from '../../src'
|
||||
import { validateXChainClaim } from '../../src/models/transactions/XChainClaim'
|
||||
|
||||
/**
|
||||
* XChainClaim Transaction Verification Testing.
|
||||
*
|
||||
* Providing runtime verification testing for each specific transaction type.
|
||||
*/
|
||||
describe('XChainClaim', function () {
|
||||
let tx
|
||||
|
||||
beforeEach(function () {
|
||||
tx = {
|
||||
Account: 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh',
|
||||
Amount: '10000',
|
||||
XChainBridge: {
|
||||
LockingChainDoor: 'rGzx83BVoqTYbGn7tiVAnFw7cbxjin13jL',
|
||||
LockingChainIssue: {
|
||||
currency: 'XRP',
|
||||
},
|
||||
IssuingChainDoor: 'r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV',
|
||||
IssuingChainIssue: {
|
||||
currency: 'XRP',
|
||||
},
|
||||
},
|
||||
Destination: 'r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV',
|
||||
Fee: '10',
|
||||
Flags: 2147483648,
|
||||
Sequence: 1,
|
||||
TransactionType: 'XChainClaim',
|
||||
XChainClaimID: '0000000000000001',
|
||||
} as any
|
||||
})
|
||||
|
||||
it('verifies valid XChainClaim', function () {
|
||||
assert.doesNotThrow(() => validateXChainClaim(tx))
|
||||
assert.doesNotThrow(() => validate(tx))
|
||||
})
|
||||
|
||||
it('throws w/ missing XChainBridge', function () {
|
||||
delete tx.XChainBridge
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainClaim(tx),
|
||||
ValidationError,
|
||||
'XChainClaim: missing field XChainBridge',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainClaim: missing field XChainBridge',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ invalid XChainBridge', function () {
|
||||
tx.XChainBridge = { XChainDoor: 'test' }
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainClaim(tx),
|
||||
ValidationError,
|
||||
'XChainClaim: invalid field XChainBridge',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainClaim: invalid field XChainBridge',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ missing XChainClaimID', function () {
|
||||
delete tx.XChainClaimID
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainClaim(tx),
|
||||
ValidationError,
|
||||
'XChainClaim: missing field XChainClaimID',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainClaim: missing field XChainClaimID',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ invalid XChainClaimID', function () {
|
||||
tx.XChainClaimID = { currency: 'ETH' }
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainClaim(tx),
|
||||
ValidationError,
|
||||
'XChainClaim: invalid field XChainClaimID',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainClaim: invalid field XChainClaimID',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ missing Destination', function () {
|
||||
delete tx.Destination
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainClaim(tx),
|
||||
ValidationError,
|
||||
'XChainClaim: missing field Destination',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainClaim: missing field Destination',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ invalid Destination', function () {
|
||||
tx.Destination = 123
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainClaim(tx),
|
||||
ValidationError,
|
||||
'XChainClaim: invalid field Destination',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainClaim: invalid field Destination',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ invalid DestinationTag', function () {
|
||||
tx.DestinationTag = 'number'
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainClaim(tx),
|
||||
ValidationError,
|
||||
'XChainClaim: invalid field DestinationTag',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainClaim: invalid field DestinationTag',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ missing Amount', function () {
|
||||
delete tx.Amount
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainClaim(tx),
|
||||
ValidationError,
|
||||
'XChainClaim: missing field Amount',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainClaim: missing field Amount',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ invalid Amount', function () {
|
||||
tx.Amount = { currency: 'ETH' }
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainClaim(tx),
|
||||
ValidationError,
|
||||
'XChainClaim: invalid field Amount',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainClaim: invalid field Amount',
|
||||
)
|
||||
})
|
||||
})
|
||||
145
packages/xrpl/test/models/XChainCommit.test.ts
Normal file
145
packages/xrpl/test/models/XChainCommit.test.ts
Normal file
@@ -0,0 +1,145 @@
|
||||
import { assert } from 'chai'
|
||||
|
||||
import { validate, ValidationError } from '../../src'
|
||||
import { validateXChainCommit } from '../../src/models/transactions/XChainCommit'
|
||||
|
||||
/**
|
||||
* XChainCommit Transaction Verification Testing.
|
||||
*
|
||||
* Providing runtime verification testing for each specific transaction type.
|
||||
*/
|
||||
describe('XChainCommit', function () {
|
||||
let tx
|
||||
|
||||
beforeEach(function () {
|
||||
tx = {
|
||||
Account: 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh',
|
||||
Amount: '10000',
|
||||
XChainBridge: {
|
||||
LockingChainDoor: 'rGzx83BVoqTYbGn7tiVAnFw7cbxjin13jL',
|
||||
LockingChainIssue: {
|
||||
currency: 'XRP',
|
||||
},
|
||||
IssuingChainDoor: 'r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV',
|
||||
IssuingChainIssue: {
|
||||
currency: 'XRP',
|
||||
},
|
||||
},
|
||||
Fee: '10',
|
||||
Flags: 2147483648,
|
||||
Sequence: 1,
|
||||
TransactionType: 'XChainCommit',
|
||||
XChainClaimID: '0000000000000001',
|
||||
} as any
|
||||
})
|
||||
|
||||
it('verifies valid XChainCommit', function () {
|
||||
assert.doesNotThrow(() => validateXChainCommit(tx))
|
||||
assert.doesNotThrow(() => validate(tx))
|
||||
})
|
||||
|
||||
it('throws w/ missing XChainBridge', function () {
|
||||
delete tx.XChainBridge
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainCommit(tx),
|
||||
ValidationError,
|
||||
'XChainCommit: missing field XChainBridge',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainCommit: missing field XChainBridge',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ invalid XChainBridge', function () {
|
||||
tx.XChainBridge = { XChainDoor: 'test' }
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainCommit(tx),
|
||||
ValidationError,
|
||||
'XChainCommit: invalid field XChainBridge',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainCommit: invalid field XChainBridge',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ missing XChainClaimID', function () {
|
||||
delete tx.XChainClaimID
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainCommit(tx),
|
||||
ValidationError,
|
||||
'XChainCommit: missing field XChainClaimID',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainCommit: missing field XChainClaimID',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ invalid XChainClaimID', function () {
|
||||
tx.XChainClaimID = { currency: 'ETH' }
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainCommit(tx),
|
||||
ValidationError,
|
||||
'XChainCommit: invalid field XChainClaimID',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainCommit: invalid field XChainClaimID',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ invalid OtherChainDestination', function () {
|
||||
tx.OtherChainDestination = 123
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainCommit(tx),
|
||||
ValidationError,
|
||||
'XChainCommit: invalid field OtherChainDestination',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainCommit: invalid field OtherChainDestination',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ missing Amount', function () {
|
||||
delete tx.Amount
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainCommit(tx),
|
||||
ValidationError,
|
||||
'XChainCommit: missing field Amount',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainCommit: missing field Amount',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ invalid Amount', function () {
|
||||
tx.Amount = { currency: 'ETH' }
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainCommit(tx),
|
||||
ValidationError,
|
||||
'XChainCommit: invalid field Amount',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainCommit: invalid field Amount',
|
||||
)
|
||||
})
|
||||
})
|
||||
115
packages/xrpl/test/models/XChainCreateBridge.test.ts
Normal file
115
packages/xrpl/test/models/XChainCreateBridge.test.ts
Normal file
@@ -0,0 +1,115 @@
|
||||
import { assert } from 'chai'
|
||||
|
||||
import { validate, ValidationError } from '../../src'
|
||||
import { validateXChainCreateBridge } from '../../src/models/transactions/XChainCreateBridge'
|
||||
|
||||
/**
|
||||
* XChainCreateBridge Transaction Verification Testing.
|
||||
*
|
||||
* Providing runtime verification testing for each specific transaction type.
|
||||
*/
|
||||
describe('XChainCreateBridge', function () {
|
||||
let tx
|
||||
|
||||
beforeEach(function () {
|
||||
tx = {
|
||||
Account: 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh',
|
||||
XChainBridge: {
|
||||
LockingChainDoor: 'rGzx83BVoqTYbGn7tiVAnFw7cbxjin13jL',
|
||||
LockingChainIssue: {
|
||||
currency: 'XRP',
|
||||
},
|
||||
IssuingChainDoor: 'r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV',
|
||||
IssuingChainIssue: {
|
||||
currency: 'XRP',
|
||||
},
|
||||
},
|
||||
Fee: '10',
|
||||
Flags: 0,
|
||||
MinAccountCreateAmount: '10000',
|
||||
Sequence: 1,
|
||||
SignatureReward: '1000',
|
||||
TransactionType: 'XChainCreateBridge',
|
||||
} as any
|
||||
})
|
||||
|
||||
it('verifies valid XChainCreateBridge', function () {
|
||||
assert.doesNotThrow(() => validateXChainCreateBridge(tx))
|
||||
assert.doesNotThrow(() => validate(tx))
|
||||
})
|
||||
|
||||
it('throws w/ missing XChainBridge', function () {
|
||||
delete tx.XChainBridge
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainCreateBridge(tx),
|
||||
ValidationError,
|
||||
'XChainCreateBridge: missing field XChainBridge',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainCreateBridge: missing field XChainBridge',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ invalid XChainBridge', function () {
|
||||
tx.XChainBridge = { XChainDoor: 'test' }
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainCreateBridge(tx),
|
||||
ValidationError,
|
||||
'XChainCreateBridge: invalid field XChainBridge',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainCreateBridge: invalid field XChainBridge',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ missing SignatureReward', function () {
|
||||
delete tx.SignatureReward
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainCreateBridge(tx),
|
||||
ValidationError,
|
||||
'XChainCreateBridge: missing field SignatureReward',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainCreateBridge: missing field SignatureReward',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ invalid SignatureReward', function () {
|
||||
tx.SignatureReward = { currency: 'ETH' }
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainCreateBridge(tx),
|
||||
ValidationError,
|
||||
'XChainCreateBridge: invalid field SignatureReward',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainCreateBridge: invalid field SignatureReward',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ invalid MinAccountCreateAmount', function () {
|
||||
tx.MinAccountCreateAmount = { currency: 'ETH' }
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainCreateBridge(tx),
|
||||
ValidationError,
|
||||
'XChainCreateBridge: invalid field MinAccountCreateAmount',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainCreateBridge: invalid field MinAccountCreateAmount',
|
||||
)
|
||||
})
|
||||
})
|
||||
130
packages/xrpl/test/models/XChainCreateClaimID.test.ts
Normal file
130
packages/xrpl/test/models/XChainCreateClaimID.test.ts
Normal file
@@ -0,0 +1,130 @@
|
||||
import { assert } from 'chai'
|
||||
|
||||
import { validate, ValidationError } from '../../src'
|
||||
import { validateXChainCreateClaimID } from '../../src/models/transactions/XChainCreateClaimID'
|
||||
|
||||
/**
|
||||
* XChainCreateClaimID Transaction Verification Testing.
|
||||
*
|
||||
* Providing runtime verification testing for each specific transaction type.
|
||||
*/
|
||||
describe('XChainCreateClaimID', function () {
|
||||
let tx
|
||||
|
||||
beforeEach(function () {
|
||||
tx = {
|
||||
Account: 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh',
|
||||
XChainBridge: {
|
||||
LockingChainDoor: 'rGzx83BVoqTYbGn7tiVAnFw7cbxjin13jL',
|
||||
LockingChainIssue: {
|
||||
currency: 'XRP',
|
||||
},
|
||||
IssuingChainDoor: 'r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV',
|
||||
IssuingChainIssue: {
|
||||
currency: 'XRP',
|
||||
},
|
||||
},
|
||||
Fee: '10',
|
||||
Flags: 2147483648,
|
||||
OtherChainSource: 'rGzx83BVoqTYbGn7tiVAnFw7cbxjin13jL',
|
||||
Sequence: 1,
|
||||
SignatureReward: '10000',
|
||||
TransactionType: 'XChainCreateClaimID',
|
||||
} as any
|
||||
})
|
||||
|
||||
it('verifies valid XChainCreateClaimID', function () {
|
||||
assert.doesNotThrow(() => validateXChainCreateClaimID(tx))
|
||||
assert.doesNotThrow(() => validate(tx))
|
||||
})
|
||||
|
||||
it('throws w/ missing XChainBridge', function () {
|
||||
delete tx.XChainBridge
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainCreateClaimID(tx),
|
||||
ValidationError,
|
||||
'XChainCreateClaimID: missing field XChainBridge',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainCreateClaimID: missing field XChainBridge',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ invalid XChainBridge', function () {
|
||||
tx.XChainBridge = { XChainDoor: 'test' }
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainCreateClaimID(tx),
|
||||
ValidationError,
|
||||
'XChainCreateClaimID: invalid field XChainBridge',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainCreateClaimID: invalid field XChainBridge',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ missing SignatureReward', function () {
|
||||
delete tx.SignatureReward
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainCreateClaimID(tx),
|
||||
ValidationError,
|
||||
'XChainCreateClaimID: missing field SignatureReward',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainCreateClaimID: missing field SignatureReward',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ invalid SignatureReward', function () {
|
||||
tx.SignatureReward = { currency: 'ETH' }
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainCreateClaimID(tx),
|
||||
ValidationError,
|
||||
'XChainCreateClaimID: invalid field SignatureReward',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainCreateClaimID: invalid field SignatureReward',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ missing OtherChainSource', function () {
|
||||
delete tx.OtherChainSource
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainCreateClaimID(tx),
|
||||
ValidationError,
|
||||
'XChainCreateClaimID: missing field OtherChainSource',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainCreateClaimID: missing field OtherChainSource',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ invalid OtherChainSource', function () {
|
||||
tx.OtherChainSource = 123
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainCreateClaimID(tx),
|
||||
ValidationError,
|
||||
'XChainCreateClaimID: invalid field OtherChainSource',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainCreateClaimID: invalid field OtherChainSource',
|
||||
)
|
||||
})
|
||||
})
|
||||
100
packages/xrpl/test/models/XChainModifyBridge.test.ts
Normal file
100
packages/xrpl/test/models/XChainModifyBridge.test.ts
Normal file
@@ -0,0 +1,100 @@
|
||||
import { assert } from 'chai'
|
||||
|
||||
import { validate, ValidationError } from '../../src'
|
||||
import { validateXChainModifyBridge } from '../../src/models/transactions/XChainModifyBridge'
|
||||
|
||||
/**
|
||||
* XChainModifyBridge Transaction Verification Testing.
|
||||
*
|
||||
* Providing runtime verification testing for each specific transaction type.
|
||||
*/
|
||||
describe('XChainModifyBridge', function () {
|
||||
let tx
|
||||
|
||||
beforeEach(function () {
|
||||
tx = {
|
||||
Account: 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh',
|
||||
XChainBridge: {
|
||||
LockingChainDoor: 'rGzx83BVoqTYbGn7tiVAnFw7cbxjin13jL',
|
||||
LockingChainIssue: {
|
||||
currency: 'XRP',
|
||||
},
|
||||
IssuingChainDoor: 'r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV',
|
||||
IssuingChainIssue: {
|
||||
currency: 'XRP',
|
||||
},
|
||||
},
|
||||
Fee: '10',
|
||||
Flags: 0,
|
||||
MinAccountCreateAmount: '10000',
|
||||
Sequence: 1,
|
||||
SignatureReward: '1000',
|
||||
TransactionType: 'XChainModifyBridge',
|
||||
} as any
|
||||
})
|
||||
|
||||
it('verifies valid XChainModifyBridge', function () {
|
||||
assert.doesNotThrow(() => validateXChainModifyBridge(tx))
|
||||
assert.doesNotThrow(() => validate(tx))
|
||||
})
|
||||
|
||||
it('throws w/ missing XChainBridge', function () {
|
||||
delete tx.XChainBridge
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainModifyBridge(tx),
|
||||
ValidationError,
|
||||
'XChainModifyBridge: missing field XChainBridge',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainModifyBridge: missing field XChainBridge',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ invalid XChainBridge', function () {
|
||||
tx.XChainBridge = { XChainDoor: 'test' }
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainModifyBridge(tx),
|
||||
ValidationError,
|
||||
'XChainModifyBridge: invalid field XChainBridge',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainModifyBridge: invalid field XChainBridge',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ invalid SignatureReward', function () {
|
||||
tx.SignatureReward = { currency: 'ETH' }
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainModifyBridge(tx),
|
||||
ValidationError,
|
||||
'XChainModifyBridge: invalid field SignatureReward',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainModifyBridge: invalid field SignatureReward',
|
||||
)
|
||||
})
|
||||
|
||||
it('throws w/ invalid MinAccountCreateAmount', function () {
|
||||
tx.MinAccountCreateAmount = { currency: 'ETH' }
|
||||
|
||||
assert.throws(
|
||||
() => validateXChainModifyBridge(tx),
|
||||
ValidationError,
|
||||
'XChainModifyBridge: invalid field MinAccountCreateAmount',
|
||||
)
|
||||
assert.throws(
|
||||
() => validate(tx),
|
||||
ValidationError,
|
||||
'XChainModifyBridge: invalid field MinAccountCreateAmount',
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -78,7 +78,7 @@ describe('BaseTransaction', function () {
|
||||
assert.throws(
|
||||
() => validateBaseTransaction(invalidFee),
|
||||
ValidationError,
|
||||
'BaseTransaction: invalid Fee',
|
||||
'Payment: invalid field Fee',
|
||||
)
|
||||
})
|
||||
|
||||
@@ -92,7 +92,7 @@ describe('BaseTransaction', function () {
|
||||
assert.throws(
|
||||
() => validateBaseTransaction(invalidSeq),
|
||||
ValidationError,
|
||||
'BaseTransaction: invalid Sequence',
|
||||
'Payment: invalid field Sequence',
|
||||
)
|
||||
})
|
||||
|
||||
@@ -106,7 +106,7 @@ describe('BaseTransaction', function () {
|
||||
assert.throws(
|
||||
() => validateBaseTransaction(invalidID),
|
||||
ValidationError,
|
||||
'BaseTransaction: invalid AccountTxnID',
|
||||
'Payment: invalid field AccountTxnID',
|
||||
)
|
||||
})
|
||||
|
||||
@@ -120,7 +120,7 @@ describe('BaseTransaction', function () {
|
||||
assert.throws(
|
||||
() => validateBaseTransaction(invalidLastLedgerSequence),
|
||||
ValidationError,
|
||||
'BaseTransaction: invalid LastLedgerSequence',
|
||||
'Payment: invalid field LastLedgerSequence',
|
||||
)
|
||||
})
|
||||
|
||||
@@ -134,7 +134,7 @@ describe('BaseTransaction', function () {
|
||||
assert.throws(
|
||||
() => validateBaseTransaction(invalidSourceTag),
|
||||
ValidationError,
|
||||
'BaseTransaction: invalid SourceTag',
|
||||
'Payment: invalid field SourceTag',
|
||||
)
|
||||
})
|
||||
|
||||
@@ -148,7 +148,7 @@ describe('BaseTransaction', function () {
|
||||
assert.throws(
|
||||
() => validateBaseTransaction(invalidSigningPubKey),
|
||||
ValidationError,
|
||||
'BaseTransaction: invalid SigningPubKey',
|
||||
'Payment: invalid field SigningPubKey',
|
||||
)
|
||||
})
|
||||
|
||||
@@ -162,7 +162,7 @@ describe('BaseTransaction', function () {
|
||||
assert.throws(
|
||||
() => validateBaseTransaction(invalidTicketSequence),
|
||||
ValidationError,
|
||||
'BaseTransaction: invalid TicketSequence',
|
||||
'Payment: invalid field TicketSequence',
|
||||
)
|
||||
})
|
||||
|
||||
@@ -176,7 +176,7 @@ describe('BaseTransaction', function () {
|
||||
assert.throws(
|
||||
() => validateBaseTransaction(invalidTxnSignature),
|
||||
ValidationError,
|
||||
'BaseTransaction: invalid TxnSignature',
|
||||
'Payment: invalid field TxnSignature',
|
||||
)
|
||||
})
|
||||
|
||||
@@ -242,7 +242,7 @@ describe('BaseTransaction', function () {
|
||||
assert.throws(
|
||||
() => validateBaseTransaction(invalidNetworkID),
|
||||
ValidationError,
|
||||
'BaseTransaction: invalid NetworkID',
|
||||
'Payment: invalid field NetworkID',
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
import { assert } from 'chai'
|
||||
|
||||
import { getNFTokenID } from '../../src'
|
||||
import * as NFTokenResponse from '../fixtures/rippled/mintNFTMeta.json'
|
||||
import * as NFTokenResponse2 from '../fixtures/rippled/mintNFTMeta2.json'
|
||||
import fixtures from '../fixtures/rippled'
|
||||
|
||||
describe('getNFTokenID', function () {
|
||||
it('decode a valid NFTokenID', function () {
|
||||
const result = getNFTokenID(NFTokenResponse.meta)
|
||||
const result = getNFTokenID(fixtures.tx.NFTokenMint.meta)
|
||||
const expectedNFTokenID =
|
||||
'00081388DC1AB4937C899037B2FDFC3CB20F6F64E73120BB5F8AA66A00000228'
|
||||
assert.equal(result, expectedNFTokenID)
|
||||
})
|
||||
|
||||
it('decode a different valid NFTokenID', function () {
|
||||
const result = getNFTokenID(NFTokenResponse2.meta)
|
||||
const result = getNFTokenID(fixtures.tx.NFTokenMint2.meta)
|
||||
const expectedNFTokenID =
|
||||
'0008125CBE4B401B2F62ED35CC67362165AA813CCA06316FFA766254000003EE'
|
||||
assert.equal(result, expectedNFTokenID)
|
||||
@@ -21,8 +20,8 @@ describe('getNFTokenID', function () {
|
||||
|
||||
it('fails with nice error when given raw response instead of meta', function () {
|
||||
assert.throws(() => {
|
||||
// @ts-expect-error - Validating error for javascript users
|
||||
const _ = getNFTokenID(NFTokenResponse)
|
||||
// @ts-expect-error -- on purpose, to check the error
|
||||
const _ = getNFTokenID(fixtures.tx.NFTokenMint)
|
||||
}, /^Unable to parse the parameter given to getNFTokenID.*/u)
|
||||
})
|
||||
})
|
||||
|
||||
25
packages/xrpl/test/utils/getXChainClaimID.test.ts
Normal file
25
packages/xrpl/test/utils/getXChainClaimID.test.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { assert } from 'chai'
|
||||
|
||||
import { getXChainClaimID } from '../../src'
|
||||
import fixtures from '../fixtures/rippled'
|
||||
|
||||
describe('getXChainClaimID', function () {
|
||||
it('decode a valid XChainClaimID', function () {
|
||||
const result = getXChainClaimID(fixtures.tx.XChainCreateClaimID.meta)
|
||||
const expectedXChainClaimID = 'b0'
|
||||
assert.equal(result, expectedXChainClaimID)
|
||||
})
|
||||
|
||||
it('decode a different valid XChainClaimID', function () {
|
||||
const result = getXChainClaimID(fixtures.tx.XChainCreateClaimID2.meta)
|
||||
const expectedXChainClaimID = 'ac'
|
||||
assert.equal(result, expectedXChainClaimID)
|
||||
})
|
||||
|
||||
it('fails with nice error when given raw response instead of meta', function () {
|
||||
assert.throws(() => {
|
||||
// @ts-expect-error -- on purpose, to check the error
|
||||
const _ = getXChainClaimID(fixtures.tx.XChainCreateClaimID)
|
||||
}, /^Unable to parse the parameter given to getXChainClaimID.*/u)
|
||||
})
|
||||
})
|
||||
147
packages/xrpl/tools/createValidate.js
Normal file
147
packages/xrpl/tools/createValidate.js
Normal file
@@ -0,0 +1,147 @@
|
||||
/* eslint-disable no-continue -- unneeded here */
|
||||
/**
|
||||
* This file writes the `validate` function for a transaction, when provided the model name in the `src/models/transactions`
|
||||
* folder.
|
||||
*/
|
||||
const fs = require('fs')
|
||||
|
||||
const NORMAL_TYPES = ['number', 'string']
|
||||
const NUMBERS = ['0', '1']
|
||||
|
||||
// TODO: rewrite this to use regex
|
||||
|
||||
async function main() {
|
||||
if (process.argv.length < 3) {
|
||||
console.log(`Usage: ${process.argv[0]} ${process.argv[1]} TxName`)
|
||||
process.exit(1)
|
||||
}
|
||||
const modelName = process.argv[2]
|
||||
const filename = `./src/models/transactions/${modelName}.ts`
|
||||
const [model, txName] = await getModel(filename)
|
||||
return processModel(model, txName)
|
||||
}
|
||||
|
||||
async function getModel(filename) {
|
||||
let model = ''
|
||||
let started = false
|
||||
let ended = false
|
||||
const data = await fs.promises.readFile(filename, { encoding: 'utf8' })
|
||||
const lines = data.split('\n')
|
||||
for (const line of lines) {
|
||||
if (ended) {
|
||||
continue
|
||||
}
|
||||
if (!started && !line.startsWith('export')) {
|
||||
continue
|
||||
}
|
||||
if (!started && line.includes('Flags')) {
|
||||
continue
|
||||
}
|
||||
if (!started) {
|
||||
started = true
|
||||
}
|
||||
model += `${line}\n`
|
||||
if (line === '}') {
|
||||
ended = true
|
||||
}
|
||||
}
|
||||
const name_line = model.split('\n')[0].split(' ')
|
||||
const txName = name_line[2]
|
||||
return [model, txName]
|
||||
}
|
||||
|
||||
function getValidationFunction(paramType) {
|
||||
if (NORMAL_TYPES.includes(paramType)) {
|
||||
const paramTypeCapitalized =
|
||||
paramType.substring(0, 1).toUpperCase() + paramType.substring(1)
|
||||
return `is${paramTypeCapitalized}(inp)`
|
||||
}
|
||||
if (NUMBERS.includes(paramType)) {
|
||||
return `inp === ${paramType}`
|
||||
}
|
||||
return `is${paramType}(inp)`
|
||||
}
|
||||
|
||||
function getValidationLine(validationFns) {
|
||||
if (validationFns.length === 1) {
|
||||
if (!validationFns[0].includes('===')) {
|
||||
// Example: `validateRequiredFields(tx, 'Amount', isAmount)`
|
||||
const validationFn = validationFns[0]
|
||||
// strip the `(inp)` in e.g. `isAmount(inp)`
|
||||
return validationFn.substring(0, validationFn.length - 5)
|
||||
}
|
||||
}
|
||||
// Example:
|
||||
// `validateRequiredFields(tx, 'XChainAccountCreateCount',
|
||||
// (inp) => isNumber(inp) || isString(inp)))`
|
||||
return `(inp) => ${validationFns.join(' || ')}`
|
||||
}
|
||||
|
||||
function processModel(model, txName) {
|
||||
let output = ''
|
||||
// process the TS model and get the types of each parameter
|
||||
for (let line of model.split('\n')) {
|
||||
if (line === '') {
|
||||
continue
|
||||
}
|
||||
if (line.startsWith('export')) {
|
||||
continue
|
||||
}
|
||||
if (line === '}') {
|
||||
continue
|
||||
}
|
||||
line = line.trim()
|
||||
if (line.startsWith('TransactionType')) {
|
||||
continue
|
||||
}
|
||||
if (line.startsWith('Flags')) {
|
||||
continue
|
||||
}
|
||||
if (line.startsWith('/**')) {
|
||||
continue
|
||||
}
|
||||
if (line.startsWith('*')) {
|
||||
continue
|
||||
}
|
||||
|
||||
// process the line with a type
|
||||
const split = line.split(' ')
|
||||
const param = split[0].replace('?:', '').replace(':', '').trim()
|
||||
const paramTypes = split.slice(1)
|
||||
const optional = split[0].endsWith('?:')
|
||||
const functionName = optional
|
||||
? 'validateOptionalField'
|
||||
: 'validateRequiredField'
|
||||
|
||||
// process the types and turn them into a validation function
|
||||
let idx = 0
|
||||
const if_outputs = []
|
||||
while (idx < paramTypes.length) {
|
||||
const paramType = paramTypes[idx]
|
||||
if_outputs.push(getValidationFunction(paramType))
|
||||
idx += 2
|
||||
}
|
||||
|
||||
output += ` ${functionName}(tx, '${param}', ${getValidationLine(
|
||||
if_outputs,
|
||||
)})\n\n`
|
||||
}
|
||||
output = output.substring(0, output.length - 1)
|
||||
output += '}\n'
|
||||
|
||||
// initial output content
|
||||
output = `/**
|
||||
* Verify the form and type of a ${txName} at runtime.
|
||||
*
|
||||
* @param tx - A ${txName} Transaction.
|
||||
* @throws When the ${txName} is malformed.
|
||||
*/
|
||||
export function validate${txName}(tx: Record<string, unknown>): void {
|
||||
validateBaseTransaction(tx)
|
||||
|
||||
${output}`
|
||||
|
||||
return output
|
||||
}
|
||||
|
||||
main().then(console.log)
|
||||
@@ -6,6 +6,7 @@
|
||||
"./test/**/*.json",
|
||||
"./src/**/*.json",
|
||||
"./snippets/src/**/*.ts",
|
||||
".eslintrc.js"
|
||||
".eslintrc.js",
|
||||
],
|
||||
"exclude": ["./tools/*.js"]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user