mirror of
https://github.com/Xahau/xahau.js.git
synced 2026-07-17 04:00:16 +00:00
Compare commits
32 Commits
xahau@4.0.
...
xahau-bina
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
94751fc4bc | ||
|
|
c9a22ffa23 | ||
|
|
e351c57e88 | ||
|
|
8f1c5db1f3 | ||
|
|
18d343fcb5 | ||
|
|
0c6578156f | ||
|
|
4cd8736eb4 | ||
|
|
5e789b1d10 | ||
|
|
8dbe640aa9 | ||
|
|
4fc68a4bbf | ||
|
|
deaf6af88b | ||
|
|
64608cb9a6 | ||
|
|
cc5cf1f2ea | ||
|
|
b417d67b28 | ||
|
|
bf788fe7b9 | ||
|
|
3c7609429f | ||
|
|
b85f34d16f | ||
|
|
c70e4c1eee | ||
|
|
4918e914c5 | ||
|
|
7552ae8635 | ||
|
|
fd100f6e92 | ||
|
|
587a75403a | ||
|
|
9444693967 | ||
|
|
1de9e4e35b | ||
|
|
fd43b82827 | ||
|
|
b310c6c25a | ||
|
|
a8939c883b | ||
|
|
05e8c2dbda | ||
|
|
e838caaffc | ||
|
|
b9fb8a1924 | ||
|
|
de97ef13e9 | ||
|
|
c1aed4ef48 |
8
.ci-config/validators.txt
Normal file
8
.ci-config/validators.txt
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
[validator_list_sites]
|
||||||
|
http://vl/vl.json
|
||||||
|
|
||||||
|
[validator_list_keys]
|
||||||
|
ED87E0EA91AAFFA130B78B75D2CC3E53202AA1BD8AB3D5E7BAC530C8440E328501
|
||||||
|
|
||||||
|
[import_vl_keys]
|
||||||
|
ED74D4036C6591A4BDF9C54CEFA39B996A5DCE5F86D11FDA1874481CE9D5A1CDC1
|
||||||
@@ -101,69 +101,105 @@ r.ripple.com 51235
|
|||||||
# If you need the version of rippled to be more up to date, you may need to make a comment on this repo: https://github.com/WietseWind/docker-rippled
|
# If you need the version of rippled to be more up to date, you may need to make a comment on this repo: https://github.com/WietseWind/docker-rippled
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
# Amendments
|
fixGuardDepth32
|
||||||
NegativeUNL
|
NamedHooks
|
||||||
|
IOURewardClaim
|
||||||
|
fixIOULockedBalanceInvariant
|
||||||
|
fixImportIssuer
|
||||||
|
HookAPISerializedType240
|
||||||
|
# PermissionedDomains Supported::no
|
||||||
|
# DynamicNFT Supported::no
|
||||||
|
# Credentials Supported::no
|
||||||
|
AMMClawback
|
||||||
|
# MPTokensV1 Supported::no
|
||||||
|
# InvariantsV1_1 Supported::no
|
||||||
|
fixNFTokenPageLinks
|
||||||
|
fixEnforceNFTokenTrustline
|
||||||
|
fixReducedOffersV2
|
||||||
|
# NFTokenMintOffer Supported::no
|
||||||
|
fixPreviousTxnID
|
||||||
|
PriceOracle
|
||||||
|
fixInnerObjTemplate
|
||||||
|
fixNFTokenReserve
|
||||||
|
fixFillOrKill
|
||||||
|
# DID Supported::no
|
||||||
|
fixDisallowIncomingV1
|
||||||
|
# XChainBridge Supported::no
|
||||||
|
AMM
|
||||||
|
fixReducedOffersV1
|
||||||
|
HooksUpdate2
|
||||||
|
HookOnV2
|
||||||
|
fixHookAPI20251128
|
||||||
|
fixCronStacking
|
||||||
|
ExtendedHookState
|
||||||
|
fixInvalidTxFlags
|
||||||
|
Cron
|
||||||
|
IOUIssuerWeakTSH
|
||||||
|
DeepFreeze
|
||||||
|
fixProvisionalDoubleThreading
|
||||||
|
Clawback
|
||||||
|
fixRewardClaimFlags
|
||||||
|
HookCanEmit
|
||||||
|
fix20250131
|
||||||
|
fixXahauV3
|
||||||
|
fixReduceImport
|
||||||
|
Touch
|
||||||
|
Remarks
|
||||||
|
fixFloatDivide
|
||||||
|
fix240911
|
||||||
|
fixPageCap
|
||||||
|
fix240819
|
||||||
|
fixNSDelete
|
||||||
|
ZeroB2M
|
||||||
|
Remit
|
||||||
|
fixXahauV2
|
||||||
|
fixXahauV1
|
||||||
|
HooksUpdate1
|
||||||
|
XahauGenesis
|
||||||
|
Import
|
||||||
|
URIToken
|
||||||
|
PaychanAndEscrowForTokens
|
||||||
|
BalanceRewards
|
||||||
|
Hooks
|
||||||
|
fixNFTokenRemint
|
||||||
|
fixNonFungibleTokensV1_2
|
||||||
|
fixUniversalNumber
|
||||||
|
XRPFees
|
||||||
|
DisallowIncoming
|
||||||
|
ImmediateOfferKilled
|
||||||
fixRemoveNFTokenAutoTrustLine
|
fixRemoveNFTokenAutoTrustLine
|
||||||
NonFungibleTokensV1
|
fixTrustLinesToSelf
|
||||||
|
NonFungibleTokensV1_1
|
||||||
|
ExpandedSignerList
|
||||||
CheckCashMakesTrustLine
|
CheckCashMakesTrustLine
|
||||||
fixRmSmallIncreasedQOffers
|
fixRmSmallIncreasedQOffers
|
||||||
fixSTAmountCanonicalize
|
fixSTAmountCanonicalize
|
||||||
FlowSortStrands
|
FlowSortStrands
|
||||||
TicketBatch
|
TicketBatch
|
||||||
fixQualityUpperBound
|
NegativeUNL
|
||||||
FlowCross
|
|
||||||
HardenedValidations
|
|
||||||
DepositPreauth
|
|
||||||
MultiSignReserve
|
|
||||||
fix1623
|
|
||||||
fix1513
|
|
||||||
RequireFullyCanonicalSig
|
|
||||||
fix1543
|
|
||||||
fix1781
|
|
||||||
fixCheckThreading
|
|
||||||
fix1515
|
|
||||||
CryptoConditionsSuite
|
|
||||||
fixPayChanRecipientOwnerDir
|
|
||||||
fix1578
|
|
||||||
fix1571
|
|
||||||
fixAmendmentMajorityCalc
|
fixAmendmentMajorityCalc
|
||||||
fixTakerDryOfferRemoval
|
HardenedValidations
|
||||||
fixMasterKeyAsRegularKey
|
fix1781
|
||||||
Flow
|
RequireFullyCanonicalSig
|
||||||
|
fixQualityUpperBound
|
||||||
DeletableAccounts
|
DeletableAccounts
|
||||||
DepositAuth
|
fixPayChanRecipientOwnerDir
|
||||||
|
fixCheckThreading
|
||||||
|
fixMasterKeyAsRegularKey
|
||||||
|
fixTakerDryOfferRemoval
|
||||||
|
MultiSignReserve
|
||||||
|
fix1578
|
||||||
|
fix1515
|
||||||
|
DepositPreauth
|
||||||
|
fix1623
|
||||||
|
fix1543
|
||||||
|
fix1571
|
||||||
Checks
|
Checks
|
||||||
NonFungibleTokensV1_1
|
DepositAuth
|
||||||
DisallowIncoming
|
fix1513
|
||||||
fixNonFungibleTokensV1_2
|
FlowCross
|
||||||
fixUniversalNumber
|
Flow
|
||||||
ImmediateOfferKilled
|
# OwnerPaysFee Supported::no
|
||||||
XRPFees
|
|
||||||
ExpandedSignerList
|
|
||||||
fixNFTokenRemint
|
|
||||||
# Additional Amendments
|
|
||||||
BalanceRewards
|
|
||||||
Hooks
|
|
||||||
HooksUpdate1
|
|
||||||
Import
|
|
||||||
Remit
|
|
||||||
URIToken
|
|
||||||
XahauGenesis
|
|
||||||
ZeroB2M
|
|
||||||
fix240819
|
|
||||||
fix240911
|
|
||||||
fixFloatDivide
|
|
||||||
fixNFTokenDirV1
|
|
||||||
fixNFTokenNegOffer
|
|
||||||
fixNSDelete
|
|
||||||
fixPageCap
|
|
||||||
fixReduceImport
|
|
||||||
fixXahauV1
|
|
||||||
fixXahauV2
|
|
||||||
fixXahauV3
|
|
||||||
PaychanAndEscrowForTokens
|
|
||||||
DeepFreeze
|
|
||||||
Clawback
|
|
||||||
|
|
||||||
[network_id]
|
[network_id]
|
||||||
21337
|
21337
|
||||||
|
|||||||
67
.github/workflows/nodejs.yml
vendored
67
.github/workflows/nodejs.yml
vendored
@@ -4,7 +4,7 @@
|
|||||||
name: Node.js CI
|
name: Node.js CI
|
||||||
|
|
||||||
env:
|
env:
|
||||||
XAHAUD_DOCKER_IMAGE: xahauci/xahaud:2025.7.9
|
XAHAUD_VERSION: 2026.6.21-release+3350
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
@@ -19,7 +19,7 @@ jobs:
|
|||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
node-version: [18.x]
|
node-version: [20.x, 22.x, 24.x, 26.x]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
@@ -60,7 +60,7 @@ jobs:
|
|||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
node-version: [18.x, 20.x]
|
node-version: [20.x, 22.x, 24.x, 26.x]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
@@ -95,20 +95,55 @@ jobs:
|
|||||||
- run: npm run build
|
- run: npm run build
|
||||||
- run: npm test
|
- run: npm test
|
||||||
|
|
||||||
|
download-binary:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 10
|
||||||
|
steps:
|
||||||
|
- name: cache binary
|
||||||
|
id: cache-binary
|
||||||
|
uses: actions/cache@v5
|
||||||
|
with:
|
||||||
|
path: xahaud
|
||||||
|
key: ${{ runner.os }}-xahaud-${{ env.XAHAUD_VERSION }}
|
||||||
|
|
||||||
|
- name: Download binary
|
||||||
|
if: steps.cache-binary.outputs.cache-hit != 'true'
|
||||||
|
run: |
|
||||||
|
wget https://build.xahau.tech/${{ env.XAHAUD_VERSION }} -q -O xahaud
|
||||||
|
chmod +x xahaud
|
||||||
|
|
||||||
integration:
|
integration:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
needs: download-binary
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
node-version: [18.x, 20.x]
|
node-version: [20.x, 22.x, 24.x, 26.x]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Restore binary
|
||||||
|
uses: actions/cache/restore@v5
|
||||||
|
with:
|
||||||
|
path: xahaud
|
||||||
|
key: ${{ runner.os }}-xahaud-${{ env.XAHAUD_VERSION }}
|
||||||
|
|
||||||
- name: Run docker in background
|
- name: Run docker in background
|
||||||
run: |
|
run: |
|
||||||
docker run --detach --rm --name xahaud-service -p 6006:6006 --volume "${{ github.workspace }}/.ci-config/":"/opt/xahau/etc/" --health-cmd="wget localhost:6006 || exit 1" --health-interval=5s --health-retries=10 --health-timeout=2s --env GITHUB_ACTIONS=true --env CI=true ${{ env.XAHAUD_DOCKER_IMAGE }} /opt/xahau/bin/xahaud -a --conf /opt/xahau/etc/xahaud.cfg
|
docker run --detach --rm \
|
||||||
|
--name xahaud-service \
|
||||||
|
-p 6006:6006 \
|
||||||
|
--volume "${{ github.workspace }}/.ci-config/":"/opt/xahau/etc/" \
|
||||||
|
--volume "${{ github.workspace }}/xahaud":"/opt/xahau/bin/xahaud" \
|
||||||
|
--health-cmd="wget localhost:6006 || exit 1" \
|
||||||
|
--health-interval=5s \
|
||||||
|
--health-retries=10 \
|
||||||
|
--health-timeout=2s \
|
||||||
|
--env GITHUB_ACTIONS=true \
|
||||||
|
--env CI=true \
|
||||||
|
ubuntu:latest /opt/xahau/bin/xahaud -a --conf /opt/xahau/etc/xahaud.cfg
|
||||||
|
|
||||||
- name: Use Node.js ${{ matrix.node-version }}
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3
|
||||||
@@ -149,11 +184,12 @@ jobs:
|
|||||||
|
|
||||||
browser:
|
browser:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
needs: download-binary
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
node-version: [18.x]
|
node-version: [20.x, 22.x, 24.x, 26.x]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
@@ -163,9 +199,26 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
node-version: ${{ matrix.node-version }}
|
node-version: ${{ matrix.node-version }}
|
||||||
|
|
||||||
|
- name: Restore binary
|
||||||
|
uses: actions/cache/restore@v5
|
||||||
|
with:
|
||||||
|
path: xahaud
|
||||||
|
key: ${{ runner.os }}-xahaud-${{ env.XAHAUD_VERSION }}
|
||||||
|
|
||||||
- name: Run docker in background
|
- name: Run docker in background
|
||||||
run: |
|
run: |
|
||||||
docker run --detach --rm --name xahaud-service -p 6006:6006 --volume "${{ github.workspace }}/.ci-config/":"/opt/xahau/etc/" --health-cmd="wget localhost:6006 || exit 1" --health-interval=5s --health-retries=10 --health-timeout=2s --env GITHUB_ACTIONS=true --env CI=true ${{ env.XAHAUD_DOCKER_IMAGE }} /opt/xahau/bin/xahaud -a --conf /opt/xahau/etc/xahaud.cfg
|
docker run --detach --rm \
|
||||||
|
--name xahaud-service \
|
||||||
|
-p 6006:6006 \
|
||||||
|
--volume "${{ github.workspace }}/.ci-config/":"/opt/xahau/etc/" \
|
||||||
|
--volume "${{ github.workspace }}/xahaud":"/opt/xahau/bin/xahaud" \
|
||||||
|
--health-cmd="wget localhost:6006 || exit 1" \
|
||||||
|
--health-interval=5s \
|
||||||
|
--health-retries=10 \
|
||||||
|
--health-timeout=2s \
|
||||||
|
--env GITHUB_ACTIONS=true \
|
||||||
|
--env CI=true \
|
||||||
|
ubuntu:latest /opt/xahau/bin/xahaud -a --conf /opt/xahau/etc/xahaud.cfg
|
||||||
|
|
||||||
- name: Setup npm version 9
|
- name: Setup npm version 9
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
109
.github/workflows/npm-publish.yml
vendored
Normal file
109
.github/workflows/npm-publish.yml
vendored
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
name: Publish npm packages
|
||||||
|
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types: [published]
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: npm-publish-${{ github.event.release.tag_name }}
|
||||||
|
cancel-in-progress: false
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
publish:
|
||||||
|
name: Publish ${{ github.event.release.tag_name }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
environment: npm
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
id-token: write
|
||||||
|
steps:
|
||||||
|
- id: release
|
||||||
|
name: Resolve package from tag
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
case "$RELEASE_TAG" in
|
||||||
|
xahau@*) package_path="packages/xahau" ;;
|
||||||
|
xahau-address-codec@*) package_path="packages/xahau-address-codec" ;;
|
||||||
|
xahau-binary-codec@*) package_path="packages/xahau-binary-codec" ;;
|
||||||
|
xahau-keypairs@*) package_path="packages/xahau-keypairs" ;;
|
||||||
|
*)
|
||||||
|
echo "Unsupported release tag: $RELEASE_TAG" >&2
|
||||||
|
echo "Expected xahau@<version>, xahau-address-codec@<version>, xahau-binary-codec@<version>, or xahau-keypairs@<version>." >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
echo "package-path=$package_path" >> "$GITHUB_OUTPUT"
|
||||||
|
env:
|
||||||
|
RELEASE_TAG: ${{ github.event.release.tag_name }}
|
||||||
|
|
||||||
|
- uses: actions/checkout@v6
|
||||||
|
with:
|
||||||
|
ref: ${{ github.event.release.tag_name }}
|
||||||
|
|
||||||
|
- uses: actions/setup-node@v6
|
||||||
|
with:
|
||||||
|
node-version: "24"
|
||||||
|
registry-url: https://registry.npmjs.org
|
||||||
|
package-manager-cache: false
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm ci
|
||||||
|
|
||||||
|
- name: Build package
|
||||||
|
run: npm run build
|
||||||
|
|
||||||
|
- id: package
|
||||||
|
name: Read package metadata
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
package_json="${{ steps.release.outputs.package-path }}/package.json"
|
||||||
|
name="$(jq -r .name "$package_json")"
|
||||||
|
version="$(jq -r .version "$package_json")"
|
||||||
|
tag="$name@$version"
|
||||||
|
if [[ "$version" == *"-"* ]]; then
|
||||||
|
release_tag="${version#*-}"
|
||||||
|
release_tag="${release_tag%%.*}"
|
||||||
|
else
|
||||||
|
release_tag="latest"
|
||||||
|
fi
|
||||||
|
|
||||||
|
{
|
||||||
|
echo "name=$name"
|
||||||
|
echo "version=$version"
|
||||||
|
echo "tag=$tag"
|
||||||
|
echo "release_tag=$release_tag"
|
||||||
|
} >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
- name: Check release tag matches package version
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
if [[ "$RELEASE_TAG" != "$PACKAGE_TAG" ]]; then
|
||||||
|
echo "Release tag $RELEASE_TAG does not match package tag $PACKAGE_TAG." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
env:
|
||||||
|
RELEASE_TAG: ${{ github.event.release.tag_name }}
|
||||||
|
PACKAGE_TAG: ${{ steps.package.outputs.tag }}
|
||||||
|
|
||||||
|
- name: Check package version is unpublished
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
package_spec="${{ steps.package.outputs.tag }}"
|
||||||
|
stderr_file="$(mktemp)"
|
||||||
|
|
||||||
|
if npm view "$package_spec" version --registry https://registry.npmjs.org 2>"$stderr_file"; then
|
||||||
|
echo "$package_spec is already published." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if grep -Eq "E404|404 Not Found|is not in this registry" "$stderr_file"; then
|
||||||
|
echo "$package_spec is not published yet."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
cat "$stderr_file" >&2
|
||||||
|
exit 1
|
||||||
|
|
||||||
|
- name: Publish to npm
|
||||||
|
run: npm publish --workspace "${{ steps.release.outputs.package-path }}" --registry https://registry.npmjs.org --tag "${{ steps.package.outputs.release_tag }}"
|
||||||
@@ -270,6 +270,7 @@ This should almost always be done using the [`xrpl-codec-gen`](https://github.co
|
|||||||
3. Highlights of important changes
|
3. Highlights of important changes
|
||||||
|
|
||||||
|
|
||||||
|
<!--
|
||||||
## Mailing Lists
|
## Mailing Lists
|
||||||
|
|
||||||
We have a low-traffic mailing list for announcements of new `xahau.js` releases. (About 1 email every couple of weeks)
|
We have a low-traffic mailing list for announcements of new `xahau.js` releases. (About 1 email every couple of weeks)
|
||||||
@@ -279,3 +280,4 @@ We have a low-traffic mailing list for announcements of new `xahau.js` releases.
|
|||||||
If you're using the Xahau Ledger in production, you should run a [xahaud server](https://github.com/xahau/xahaud) and subscribe to the xahau-server mailing list as well.
|
If you're using the Xahau Ledger in production, you should run a [xahaud server](https://github.com/xahau/xahaud) and subscribe to the xahau-server mailing list as well.
|
||||||
|
|
||||||
- [Subscribe to xahau-server](https://groups.google.com/g/xahau-server)
|
- [Subscribe to xahau-server](https://groups.google.com/g/xahau-server)
|
||||||
|
-->
|
||||||
|
|||||||
@@ -86,6 +86,7 @@ As you develop with xahau.js, there's two sites you'll use extensively:
|
|||||||
- What kinds of transactions there are ([Transaction Types](https://docs.xahau.network/technical/protocol-reference/transactions/transaction-types))
|
- What kinds of transactions there are ([Transaction Types](https://docs.xahau.network/technical/protocol-reference/transactions/transaction-types))
|
||||||
- Requests you can send ([Public API Methods](https://docs.xahau.network/features/http-websocket-apis))
|
- Requests you can send ([Public API Methods](https://docs.xahau.network/features/http-websocket-apis))
|
||||||
|
|
||||||
|
<!--
|
||||||
### Mailing Lists
|
### Mailing Lists
|
||||||
|
|
||||||
If you want to hear when we release new versions of xahau.js, you can join our low-traffic mailing list (About 1 email per week):
|
If you want to hear when we release new versions of xahau.js, you can join our low-traffic mailing list (About 1 email per week):
|
||||||
@@ -97,3 +98,4 @@ If you're using the Xahau Ledger in production, you should run a [xahaud server]
|
|||||||
- [Subscribe to xahau-server](https://groups.google.com/g/xahau-server)
|
- [Subscribe to xahau-server](https://groups.google.com/g/xahau-server)
|
||||||
|
|
||||||
You are also welcome to create an [issue](https://github.com/Xahau/xahau.js/issues) here and we'll do our best to respond within 3 days.
|
You are also welcome to create an [issue](https://github.com/Xahau/xahau.js/issues) here and we'll do our best to respond within 3 days.
|
||||||
|
-->
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
{
|
{
|
||||||
"version": "independent",
|
"version": "independent",
|
||||||
"useWorkspaces": true,
|
|
||||||
"npmClient": "npm"
|
"npmClient": "npm"
|
||||||
}
|
}
|
||||||
|
|||||||
7772
package-lock.json
generated
7772
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -16,10 +16,10 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@xrplf/isomorphic": "file:packages/isomorphic",
|
"@xrplf/isomorphic": "file:packages/isomorphic",
|
||||||
"@xrplf/secret-numbers": "file:packages/secret-numbers",
|
"@xrplf/secret-numbers": "file:packages/secret-numbers",
|
||||||
|
"xahau": "file:packages/xahau",
|
||||||
"xahau-address-codec": "file:packages/xahau-address-codec",
|
"xahau-address-codec": "file:packages/xahau-address-codec",
|
||||||
"xahau-binary-codec": "file:packages/xahau-binary-codec",
|
"xahau-binary-codec": "file:packages/xahau-binary-codec",
|
||||||
"xahau-keypairs": "file:packages/xahau-keypairs",
|
"xahau-keypairs": "file:packages/xahau-keypairs"
|
||||||
"xahau": "file:packages/xahau"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/chai": "^4.2.21",
|
"@types/chai": "^4.2.21",
|
||||||
@@ -45,7 +45,7 @@
|
|||||||
"expect": "^29.3.1",
|
"expect": "^29.3.1",
|
||||||
"jest": "^29.3.1",
|
"jest": "^29.3.1",
|
||||||
"jest-mock": "^29.3.1",
|
"jest-mock": "^29.3.1",
|
||||||
"lerna": "^4.0.0",
|
"lerna": "^9.0.7",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"prettier": "^2.3.2",
|
"prettier": "^2.3.2",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "xahau-address-codec",
|
"name": "xahau-address-codec",
|
||||||
"version": "5.0.0",
|
"version": "5.0.0",
|
||||||
"description": "encodes/decodes base58 encoded XAH Ledger identifiers",
|
"description": "encodes/decodes base58 encoded Xahau Network identifiers",
|
||||||
"files": [
|
"files": [
|
||||||
"dist/*",
|
"dist/*",
|
||||||
"src/*"
|
"src/*"
|
||||||
|
|||||||
@@ -162,9 +162,9 @@ export {
|
|||||||
encodeAccountID,
|
encodeAccountID,
|
||||||
// Decode a classic address to its raw bytes
|
// Decode a classic address to its raw bytes
|
||||||
decodeAccountID,
|
decodeAccountID,
|
||||||
// Encode bytes to XAH Ledger node public key format
|
// Encode bytes to Xahau Network node public key format
|
||||||
encodeNodePublic,
|
encodeNodePublic,
|
||||||
// Decode an XAH Ledger node public key into its raw bytes
|
// Decode an Xahau Network node public key into its raw bytes
|
||||||
decodeNodePublic,
|
decodeNodePublic,
|
||||||
// Encode a public key, as for payment channels
|
// Encode a public key, as for payment channels
|
||||||
encodeAccountPublic,
|
encodeAccountPublic,
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
## 2.1.0 (2024-06-03)
|
## 2.1.0 (2026-06-23)
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
* Support for the Price Oracles amendment (XLS-47).
|
* Support for the Price Oracles amendment (XLS-47).
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "xahau-binary-codec",
|
"name": "xahau-binary-codec",
|
||||||
"version": "2.1.3",
|
"version": "2.2.0",
|
||||||
"description": "XAH Ledger binary codec",
|
"description": "Xahau Network binary codec",
|
||||||
"files": [
|
"files": [
|
||||||
"dist/*",
|
"dist/*",
|
||||||
"src/*"
|
"src/*"
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -4449,6 +4449,36 @@
|
|||||||
"Flags": 0,
|
"Flags": 0,
|
||||||
"Sequence": 62
|
"Sequence": 62
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"binary": "12003C2FFFFFFFFF2033000004D2750B6469645F6578616D706C65701D0863757272656E6379701E0870726F7669646572811401476926B590BA3245F63C829116A0A3AF7F382DF018E020301700000000000001E2041003011A0000000000000000000000000000000000000000021A0000000000000000000000005553440000000000E1F1",
|
||||||
|
"json": {
|
||||||
|
"TransactionType": "OracleSet",
|
||||||
|
"Account": "rfmDuhDyLGgx94qiwf3YF8BUV5j6KSvE8",
|
||||||
|
"OracleDocumentID": 1234,
|
||||||
|
"LastUpdateTime": 4294967295,
|
||||||
|
"PriceDataSeries": [
|
||||||
|
{
|
||||||
|
"PriceData": {
|
||||||
|
"BaseAsset": "XAH",
|
||||||
|
"QuoteAsset": "USD",
|
||||||
|
"AssetPrice": "00000000000001E2",
|
||||||
|
"Scale": 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Provider": "70726F7669646572",
|
||||||
|
"URI": "6469645F6578616D706C65",
|
||||||
|
"AssetClass": "63757272656E6379"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"binary": "12003D2033000004D2811401476926B590BA3245F63C829116A0A3AF7F382D",
|
||||||
|
"json": {
|
||||||
|
"TransactionType": "OracleDelete",
|
||||||
|
"Account": "rfmDuhDyLGgx94qiwf3YF8BUV5j6KSvE8",
|
||||||
|
"OracleDocumentID": 1234
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"ledgerData": [{
|
"ledgerData": [{
|
||||||
|
|||||||
@@ -73,7 +73,9 @@ describe('Signing data', function () {
|
|||||||
const customPaymentDefinitions = JSON.parse(
|
const customPaymentDefinitions = JSON.parse(
|
||||||
JSON.stringify(normalDefinitions),
|
JSON.stringify(normalDefinitions),
|
||||||
)
|
)
|
||||||
customPaymentDefinitions.TRANSACTION_TYPES.Payment = 31
|
|
||||||
|
// custom number would need to updated in case it has been used by an existing transaction type
|
||||||
|
customPaymentDefinitions.TRANSACTION_TYPES.Payment = 200
|
||||||
|
|
||||||
const newDefs = new XrplDefinitions(customPaymentDefinitions)
|
const newDefs = new XrplDefinitions(customPaymentDefinitions)
|
||||||
const actual = encodeForSigning(tx_json, newDefs)
|
const actual = encodeForSigning(tx_json, newDefs)
|
||||||
@@ -82,7 +84,7 @@ describe('Signing data', function () {
|
|||||||
'53545800', // signingPrefix
|
'53545800', // signingPrefix
|
||||||
// TransactionType
|
// TransactionType
|
||||||
'12',
|
'12',
|
||||||
'001F',
|
'00C8',
|
||||||
// Flags
|
// Flags
|
||||||
'22',
|
'22',
|
||||||
'80000000',
|
'80000000',
|
||||||
@@ -176,7 +178,9 @@ describe('Signing data', function () {
|
|||||||
const customPaymentDefinitions = JSON.parse(
|
const customPaymentDefinitions = JSON.parse(
|
||||||
JSON.stringify(normalDefinitions),
|
JSON.stringify(normalDefinitions),
|
||||||
)
|
)
|
||||||
customPaymentDefinitions.TRANSACTION_TYPES.Payment = 31
|
|
||||||
|
// custom number would need to updated in case it has been used by an existing transaction type
|
||||||
|
customPaymentDefinitions.TRANSACTION_TYPES.Payment = 200
|
||||||
|
|
||||||
const newDefs = new XrplDefinitions(customPaymentDefinitions)
|
const newDefs = new XrplDefinitions(customPaymentDefinitions)
|
||||||
const signingAccount = 'rJZdUusLDtY9NEsGea7ijqhVrXv98rYBYN'
|
const signingAccount = 'rJZdUusLDtY9NEsGea7ijqhVrXv98rYBYN'
|
||||||
@@ -187,7 +191,7 @@ describe('Signing data', function () {
|
|||||||
'534D5400', // signingPrefix
|
'534D5400', // signingPrefix
|
||||||
// TransactionType
|
// TransactionType
|
||||||
'12',
|
'12',
|
||||||
'001F',
|
'00C8',
|
||||||
// Flags
|
// Flags
|
||||||
'22',
|
'22',
|
||||||
'80000000',
|
'80000000',
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "xahau-keypairs",
|
"name": "xahau-keypairs",
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"description": "Cryptographic key pairs for the XAH Ledger",
|
"description": "Cryptographic key pairs for the Xahau Network",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsc --build tsconfig.build.json",
|
"build": "tsc --build tsconfig.build.json",
|
||||||
"test": "jest --verbose false --silent=false ./test/*.test.ts",
|
"test": "jest --verbose false --silent=false ./test/*.test.ts",
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ const ed25519: SigningScheme = {
|
|||||||
// ZIP 215 is a stricter Ed25519 signature verification scheme.
|
// ZIP 215 is a stricter Ed25519 signature verification scheme.
|
||||||
// However, setting it to false adheres to the more commonly used
|
// However, setting it to false adheres to the more commonly used
|
||||||
// RFC8032 / NIST186-5 standards, making it compatible with systems
|
// RFC8032 / NIST186-5 standards, making it compatible with systems
|
||||||
// like the XAH Ledger.
|
// like the Xahau Network.
|
||||||
{ zip215: false },
|
{ zip215: false },
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,12 +1,32 @@
|
|||||||
# xrpl.js Release History
|
# xahau.js Release History
|
||||||
|
|
||||||
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 Changes
|
## Unreleased Changes
|
||||||
|
|
||||||
|
## 4.1.0 (2026-06-23)
|
||||||
|
|
||||||
|
### Added
|
||||||
|
* Support for HookOnV2 Amendment
|
||||||
|
* Support for IOUClaimReward Amendment
|
||||||
|
* Support for NamedHooks
|
||||||
|
* Support for the `simulate` RPC ([XLS-69](https://github.com/XRPLF/XRPL-Standards/tree/master/XLS-0069-simulate))
|
||||||
|
* Support for the Price Oracles amendment (XLS-47).
|
||||||
|
|
||||||
|
## 4.0.4 (2026-05-27)
|
||||||
|
|
||||||
|
### Added
|
||||||
|
* Improve HookStateScale validation
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
* Add lsfTshCollect flag in AccountRoot
|
||||||
|
* Refactor amount assignment in partialPayment.ts
|
||||||
|
* Fix setTransactionFlagsToNumber for Xahau transactions
|
||||||
|
|
||||||
|
## 4.0.3 (2025-11-18)
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
* Fixed minified `build/xahau-latest-min.js` to have all the latest xahau package changes.
|
* Fixed minified `build/xahau-latest-min.js` to have all the latest xahau package changes.
|
||||||
|
|
||||||
## 4.0.1 (2025-11-12)
|
## 4.0.2 (2025-11-12)
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
* Support for Cron Amendment
|
* Support for Cron Amendment
|
||||||
@@ -48,6 +68,9 @@ Subscribe to [the **xrpl-announce** mailing list](https://groups.google.com/g/xr
|
|||||||
### Added
|
### Added
|
||||||
* Support for the Price Oracles amendment (XLS-47).
|
* Support for the Price Oracles amendment (XLS-47).
|
||||||
|
|
||||||
|
### Added
|
||||||
|
* Support for the Price Oracles amendment (XLS-47).
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
* Typo in `Channel` type `source_tab` -> `source_tag`
|
* Typo in `Channel` type `source_tab` -> `source_tag`
|
||||||
* Fix `client.requestAll` to handle filters better
|
* Fix `client.requestAll` to handle filters better
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"name": "xahau",
|
"name": "xahau",
|
||||||
"version": "4.0.3",
|
"version": "4.1.0",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"description": "A TypeScript/JavaScript API for interacting with the XAH Ledger in Node.js and the browser",
|
"description": "A TypeScript/JavaScript API for interacting with the Xahau Network in Node.js and the browser",
|
||||||
"files": [
|
"files": [
|
||||||
"build/xahau-latest-min.js",
|
"build/xahau-latest-min.js",
|
||||||
"build/xahau-latest-min.js.map",
|
"build/xahau-latest-min.js.map",
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
"bignumber.js": "^9.0.0",
|
"bignumber.js": "^9.0.0",
|
||||||
"eventemitter3": "^5.0.1",
|
"eventemitter3": "^5.0.1",
|
||||||
"xahau-address-codec": "^5.0.0",
|
"xahau-address-codec": "^5.0.0",
|
||||||
"xahau-binary-codec": "^2.1.3",
|
"xahau-binary-codec": "^2.2.0",
|
||||||
"xahau-keypairs": "^2.0.0"
|
"xahau-keypairs": "^2.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@@ -355,13 +355,13 @@ export class Wallet {
|
|||||||
* Output of `sign` includes a `tx_blob` and a `hash`, both of which are needed to submit & verify the results.
|
* Output of `sign` includes a `tx_blob` and a `hash`, both of which are needed to submit & verify the results.
|
||||||
* Note: If you pass a `Wallet` to `client.submit` or `client.submitAndWait` it will do signing like this under the hood.
|
* Note: If you pass a `Wallet` to `client.submit` or `client.submitAndWait` it will do signing like this under the hood.
|
||||||
*
|
*
|
||||||
* `tx_blob` is a binary representation of a transaction on the XAH Ledger. It's essentially a byte array
|
* `tx_blob` is a binary representation of a transaction on the Xahau Network. It's essentially a byte array
|
||||||
* that encodes all of the data necessary to execute the transaction, including the source address, the destination
|
* that encodes all of the data necessary to execute the transaction, including the source address, the destination
|
||||||
* address, the amount, and any additional fields required for the specific transaction type.
|
* address, the amount, and any additional fields required for the specific transaction type.
|
||||||
*
|
*
|
||||||
* `hash` is a unique identifier that's generated from the signed transaction data on the XAH Ledger. It's essentially
|
* `hash` is a unique identifier that's generated from the signed transaction data on the Xahau Network. It's essentially
|
||||||
* A cryptographic digest of the signed transaction blob, created using a hash function. The signed transaction hash is
|
* A cryptographic digest of the signed transaction blob, created using a hash function. The signed transaction hash is
|
||||||
* Useful for identifying and tracking specific transactions on the XAH Ledger. It can be used to query transaction
|
* Useful for identifying and tracking specific transactions on the Xahau Network. It can be used to query transaction
|
||||||
* Information, verify the authenticity of a transaction, and detect any tampering with the transaction data.
|
* Information, verify the authenticity of a transaction, and detect any tampering with the transaction data.
|
||||||
*
|
*
|
||||||
* @param this - Wallet instance.
|
* @param this - Wallet instance.
|
||||||
|
|||||||
@@ -40,8 +40,13 @@ import type {
|
|||||||
MarkerRequest,
|
MarkerRequest,
|
||||||
MarkerResponse,
|
MarkerResponse,
|
||||||
SubmitResponse,
|
SubmitResponse,
|
||||||
|
SimulateRequest,
|
||||||
} from '../models/methods'
|
} from '../models/methods'
|
||||||
import type { BookOffer, BookOfferCurrency } from '../models/methods/bookOffers'
|
import type { BookOffer, BookOfferCurrency } from '../models/methods/bookOffers'
|
||||||
|
import {
|
||||||
|
SimulateBinaryResponse,
|
||||||
|
SimulateJsonResponse,
|
||||||
|
} from '../models/methods/simulate'
|
||||||
import type {
|
import type {
|
||||||
EventTypes,
|
EventTypes,
|
||||||
OnEventToListenerMap,
|
OnEventToListenerMap,
|
||||||
@@ -655,7 +660,7 @@ class Client extends EventEmitter<EventTypes> {
|
|||||||
* @returns The autofilled transaction.
|
* @returns The autofilled transaction.
|
||||||
* @throws ValidationError If Amount and DeliverMax fields are not identical in a Payment Transaction
|
* @throws ValidationError If Amount and DeliverMax fields are not identical in a Payment Transaction
|
||||||
*/
|
*/
|
||||||
|
// eslint-disable-next-line complexity -- handling Payment transaction API v2 requires more logic
|
||||||
public async autofill<T extends SubmittableTransaction>(
|
public async autofill<T extends SubmittableTransaction>(
|
||||||
transaction: T,
|
transaction: T,
|
||||||
signersCount?: number,
|
signersCount?: number,
|
||||||
@@ -676,6 +681,34 @@ class Client extends EventEmitter<EventTypes> {
|
|||||||
promises.push(setLatestValidatedLedgerSequence(this, tx))
|
promises.push(setLatestValidatedLedgerSequence(this, tx))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment -- ignore type-assertions on the DeliverMax property
|
||||||
|
// @ts-expect-error -- DeliverMax property exists only at the RPC level, not at the protocol level
|
||||||
|
if (tx.TransactionType === 'Payment' && tx.DeliverMax != null) {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- This is a valid null check for Amount
|
||||||
|
if (tx.Amount == null) {
|
||||||
|
// If only DeliverMax is provided, use it to populate the Amount field
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment -- ignore type-assertions on the DeliverMax property
|
||||||
|
// @ts-expect-error -- DeliverMax property exists only at the RPC level, not at the protocol level
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- DeliverMax is a known RPC-level property
|
||||||
|
tx.Amount = tx.DeliverMax
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment -- ignore type-assertions on the DeliverMax property
|
||||||
|
// @ts-expect-error -- DeliverMax property exists only at the RPC level, not at the protocol level
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- This is a valid null check for Amount
|
||||||
|
if (tx.Amount != null && tx.Amount !== tx.DeliverMax) {
|
||||||
|
return Promise.reject(
|
||||||
|
new ValidationError(
|
||||||
|
'PaymentTransaction: Amount and DeliverMax fields must be identical when both are provided',
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment -- ignore type-assertions on the DeliverMax property
|
||||||
|
// @ts-expect-error -- DeliverMax property exists only at the RPC level, not at the protocol level
|
||||||
|
delete tx.DeliverMax
|
||||||
|
}
|
||||||
|
|
||||||
await Promise.all(promises).then(() => tx)
|
await Promise.all(promises).then(() => tx)
|
||||||
|
|
||||||
if (tx.Fee == null) {
|
if (tx.Fee == null) {
|
||||||
@@ -734,6 +767,41 @@ class Client extends EventEmitter<EventTypes> {
|
|||||||
return submitRequest(this, signedTx, opts?.failHard)
|
return submitRequest(this, signedTx, opts?.failHard)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simulates an unsigned transaction.
|
||||||
|
* Steps performed on a transaction:
|
||||||
|
* 1. Autofill.
|
||||||
|
* 2. Sign & Encode.
|
||||||
|
* 3. Submit.
|
||||||
|
*
|
||||||
|
* @category Core
|
||||||
|
*
|
||||||
|
* @param transaction - A transaction to autofill, sign & encode, and submit.
|
||||||
|
* @param opts - (Optional) Options used to sign and submit a transaction.
|
||||||
|
* @param opts.binary - If true, return the metadata in a binary encoding.
|
||||||
|
*
|
||||||
|
* @returns A promise that contains SimulateResponse.
|
||||||
|
* @throws RippledError if the simulate request fails.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public async simulate<Binary extends boolean = false>(
|
||||||
|
transaction: SubmittableTransaction | string,
|
||||||
|
opts?: {
|
||||||
|
// If true, return the binary-encoded representation of the results.
|
||||||
|
binary?: Binary
|
||||||
|
},
|
||||||
|
): Promise<
|
||||||
|
Binary extends true ? SimulateBinaryResponse : SimulateJsonResponse
|
||||||
|
> {
|
||||||
|
// send request
|
||||||
|
const binary = opts?.binary ?? false
|
||||||
|
const request: SimulateRequest =
|
||||||
|
typeof transaction === 'string'
|
||||||
|
? { command: 'simulate', tx_blob: transaction, binary }
|
||||||
|
: { command: 'simulate', tx_json: transaction, binary }
|
||||||
|
return this.request(request)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Asynchronously submits a transaction and verifies that it has been included in a
|
* Asynchronously submits a transaction and verifies that it has been included in a
|
||||||
* validated ledger (or has errored/will not be included for some reason).
|
* validated ledger (or has errored/will not be included for some reason).
|
||||||
@@ -1063,7 +1131,7 @@ class Client extends EventEmitter<EventTypes> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The fundWallet() method is used to send an amount of XAH (usually 1000) to a new (randomly generated)
|
* The fundWallet() method is used to send an amount of XAH (usually 1000) to a new (randomly generated)
|
||||||
* or existing XAH Ledger wallet.
|
* or existing Xahau Network wallet.
|
||||||
*
|
*
|
||||||
* @category Faucet
|
* @category Faucet
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -64,10 +64,11 @@ function isPartialPayment(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const delivered = meta.delivered_amount
|
const delivered = meta.delivered_amount
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment -- DeliverMax is a valid field on Payment response
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment -- DeliverMax is a valid field on Payment response
|
||||||
// @ts-expect-error -- DeliverMax is a valid field on Payment response
|
// @ts-expect-error -- DeliverMax is a valid field on Payment response
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- DeliverMax is a valid field on Payment response
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- DeliverMax is a valid field on Payment response
|
||||||
const amount = tx.DeliverMax
|
const amount = tx.DeliverMax ?? tx.Amount
|
||||||
|
|
||||||
if (delivered === undefined) {
|
if (delivered === undefined) {
|
||||||
return false
|
return false
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ export interface SignerEntry {
|
|||||||
*/
|
*/
|
||||||
SignerEntry: {
|
SignerEntry: {
|
||||||
/**
|
/**
|
||||||
* An XAH Ledger address whose signature contributes to the multi-signature.
|
* An Xahau Network address whose signature contributes to the multi-signature.
|
||||||
* It does not need to be a funded address in the ledger.
|
* It does not need to be a funded address in the ledger.
|
||||||
*/
|
*/
|
||||||
Account: string
|
Account: string
|
||||||
|
|||||||
@@ -1,5 +1,28 @@
|
|||||||
import { Amount } from '.'
|
import { Amount } from '.'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enum representing values for Hook Flags for SetHook Transaction.
|
||||||
|
*
|
||||||
|
* @category Transaction Flags
|
||||||
|
*/
|
||||||
|
export enum HookFlags {
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
hsfOverride = 0x00000001,
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
hsfNSDelete = 0x0000002,
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
hsfCollect = 0x00000004,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HookFlagsInterface {
|
||||||
|
hsfOverride?: boolean
|
||||||
|
hsfNSDelete?: boolean
|
||||||
|
hsfCollect?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
export interface AmountEntry {
|
export interface AmountEntry {
|
||||||
AmountEntry: { Amount: Amount }
|
AmountEntry: { Amount: Amount }
|
||||||
}
|
}
|
||||||
@@ -58,11 +81,19 @@ export interface Hook {
|
|||||||
/**
|
/**
|
||||||
* The flags that are set on the hook.
|
* The flags that are set on the hook.
|
||||||
*/
|
*/
|
||||||
Flags?: number
|
Flags?: number | HookFlagsInterface
|
||||||
/**
|
/**
|
||||||
* The transactions that triggers the hook. Represented as a 256Hash
|
* The transactions that triggers the hook. Represented as a 256Hash
|
||||||
*/
|
*/
|
||||||
HookOn?: string
|
HookOn?: string
|
||||||
|
/**
|
||||||
|
* The incoming transactions that triggers to the hook. Represented as a 256Hash
|
||||||
|
*/
|
||||||
|
HookOnIncoming?: string
|
||||||
|
/**
|
||||||
|
* The outgoing transactions that triggers from the hook. Represented as a 256Hash
|
||||||
|
*/
|
||||||
|
HookOnOutgoing?: string
|
||||||
/**
|
/**
|
||||||
* The transactions that can emit from the hook. Represented as a 256Hash
|
* The transactions that can emit from the hook. Represented as a 256Hash
|
||||||
*/
|
*/
|
||||||
@@ -83,6 +114,10 @@ export interface Hook {
|
|||||||
* The grants of the hook.
|
* The grants of the hook.
|
||||||
*/
|
*/
|
||||||
HookGrants?: HookGrant[]
|
HookGrants?: HookGrant[]
|
||||||
|
/**
|
||||||
|
* The name of the hook.
|
||||||
|
*/
|
||||||
|
HookName?: string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,6 +133,14 @@ export interface EmitDetails {
|
|||||||
sfEmitCallback?: string
|
sfEmitCallback?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum MintURITokenFlags {
|
||||||
|
tfBurnable = 0x00000001,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MintURITokenFlagsInterface {
|
||||||
|
tfBurnable?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The object that describes the uritoken in MintURIToken.
|
* The object that describes the uritoken in MintURIToken.
|
||||||
*/
|
*/
|
||||||
@@ -113,5 +156,5 @@ export interface MintURIToken {
|
|||||||
/**
|
/**
|
||||||
* The flags that are set on the uritoken.
|
* The flags that are set on the uritoken.
|
||||||
*/
|
*/
|
||||||
Flags?: number
|
Flags?: number | MintURITokenFlagsInterface
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -200,6 +200,10 @@ export enum AccountRootFlags {
|
|||||||
* (It has DepositAuth enabled.)
|
* (It has DepositAuth enabled.)
|
||||||
*/
|
*/
|
||||||
lsfDepositAuth = 0x01000000,
|
lsfDepositAuth = 0x01000000,
|
||||||
|
/**
|
||||||
|
* The TSH pays for the execution of their own Hook Chain. Added by the Hooks amendment.
|
||||||
|
*/
|
||||||
|
lsfTshCollect = 0x02000000,
|
||||||
/**
|
/**
|
||||||
* Disallow incoming NFTOffers from other accounts.
|
* Disallow incoming NFTOffers from other accounts.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export interface FeeSettingsPreAmendmentFields {
|
|||||||
BaseFee: string
|
BaseFee: string
|
||||||
/** The BaseFee translated into "fee units". */
|
/** The BaseFee translated into "fee units". */
|
||||||
ReferenceFeeUnits: number
|
ReferenceFeeUnits: number
|
||||||
/** The base reserve for an account in the XAH Ledger, as drops of XAH. */
|
/** The base reserve for an account in the Xahau Network, as drops of XAH. */
|
||||||
ReserveBase: number
|
ReserveBase: number
|
||||||
/** The incremental owner reserve for owning objects, as drops of XAH. */
|
/** The incremental owner reserve for owning objects, as drops of XAH. */
|
||||||
ReserveIncrement: number
|
ReserveIncrement: number
|
||||||
@@ -20,7 +20,7 @@ export interface FeeSettingsPreAmendmentFields {
|
|||||||
export interface FeeSettingsPostAmendmentFields {
|
export interface FeeSettingsPostAmendmentFields {
|
||||||
/** The transaction cost of the "reference transaction" in drops of XAH as hexadecimal. */
|
/** The transaction cost of the "reference transaction" in drops of XAH as hexadecimal. */
|
||||||
BaseFeeDrops: string
|
BaseFeeDrops: string
|
||||||
/** The base reserve for an account in the XAH Ledger, as drops of XAH. */
|
/** The base reserve for an account in the Xahau Network, as drops of XAH. */
|
||||||
ReserveBaseDrops: string
|
ReserveBaseDrops: string
|
||||||
/** The incremental owner reserve for owning objects, as drops of XAH. */
|
/** The incremental owner reserve for owning objects, as drops of XAH. */
|
||||||
ReserveIncrementDrops: string
|
ReserveIncrementDrops: string
|
||||||
|
|||||||
@@ -27,6 +27,16 @@ export default interface HookDefintion
|
|||||||
*/
|
*/
|
||||||
HookOn?: string
|
HookOn?: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The incoming transactions that triggers to the hook. Represented as a 256Hash
|
||||||
|
*/
|
||||||
|
HookOnIncoming?: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The outgoing transactions that triggers from the hook. Represented as a 256Hash
|
||||||
|
*/
|
||||||
|
HookOnOutgoing?: string
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The namespace of the hook.
|
* The namespace of the hook.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import ImportVLSequence from './ImportVLSequence'
|
|||||||
import LedgerHashes from './LedgerHashes'
|
import LedgerHashes from './LedgerHashes'
|
||||||
import NegativeUNL from './NegativeUNL'
|
import NegativeUNL from './NegativeUNL'
|
||||||
import Offer from './Offer'
|
import Offer from './Offer'
|
||||||
|
import Oracle from './Oracle'
|
||||||
import PayChannel from './PayChannel'
|
import PayChannel from './PayChannel'
|
||||||
import RippleState from './RippleState'
|
import RippleState from './RippleState'
|
||||||
import SignerList from './SignerList'
|
import SignerList from './SignerList'
|
||||||
@@ -38,6 +39,7 @@ type LedgerEntry =
|
|||||||
| LedgerHashes
|
| LedgerHashes
|
||||||
| NegativeUNL
|
| NegativeUNL
|
||||||
| Offer
|
| Offer
|
||||||
|
| Oracle
|
||||||
| PayChannel
|
| PayChannel
|
||||||
| RippleState
|
| RippleState
|
||||||
| SignerList
|
| SignerList
|
||||||
@@ -60,6 +62,7 @@ type LedgerEntryFilter =
|
|||||||
| 'import_vl_sequence'
|
| 'import_vl_sequence'
|
||||||
| 'hashes'
|
| 'hashes'
|
||||||
| 'offer'
|
| 'offer'
|
||||||
|
| 'oracle'
|
||||||
| 'payment_channel'
|
| 'payment_channel'
|
||||||
| 'signer_list'
|
| 'signer_list'
|
||||||
| 'state'
|
| 'state'
|
||||||
|
|||||||
43
packages/xahau/src/models/ledger/Oracle.ts
Normal file
43
packages/xahau/src/models/ledger/Oracle.ts
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
import { PriceData } from '../common'
|
||||||
|
|
||||||
|
import { BaseLedgerEntry, HasPreviousTxnID } from './BaseLedgerEntry'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Oracle object type describes a single Price Oracle instance.
|
||||||
|
*
|
||||||
|
* @category Ledger Entries
|
||||||
|
*/
|
||||||
|
export default interface Oracle extends BaseLedgerEntry, HasPreviousTxnID {
|
||||||
|
LedgerEntryType: 'Oracle'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The time the data was last updated, represented as a unix timestamp in seconds.
|
||||||
|
*/
|
||||||
|
LastUpdateTime: number
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The XRPL account with update and delete privileges for the oracle.
|
||||||
|
*/
|
||||||
|
Owner: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Describes the type of asset, such as "currency", "commodity", or "index".
|
||||||
|
*/
|
||||||
|
AssetClass: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The oracle provider, such as Chainlink, Band, or DIA.
|
||||||
|
*/
|
||||||
|
Provider: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An array of up to 10 PriceData objects.
|
||||||
|
*/
|
||||||
|
PriceDataSeries: PriceData[]
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A bit-map of boolean flags. No flags are defined for the Oracle object
|
||||||
|
* type, so this value is always 0.
|
||||||
|
*/
|
||||||
|
Flags: 0
|
||||||
|
}
|
||||||
@@ -2,6 +2,13 @@ import { IssuedCurrencyAmount } from '../common'
|
|||||||
|
|
||||||
import { BaseLedgerEntry, HasPreviousTxnID } from './BaseLedgerEntry'
|
import { BaseLedgerEntry, HasPreviousTxnID } from './BaseLedgerEntry'
|
||||||
|
|
||||||
|
export interface RippleStateReward {
|
||||||
|
RewardLgrFirst: number
|
||||||
|
RewardLgrLast: number
|
||||||
|
RewardTime: number
|
||||||
|
TrustLineRewardAccumulator: IssuedCurrencyAmount
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The RippleState object type connects two accounts in a single currency.
|
* The RippleState object type connects two accounts in a single currency.
|
||||||
*
|
*
|
||||||
@@ -61,6 +68,8 @@ export default interface RippleState extends BaseLedgerEntry, HasPreviousTxnID {
|
|||||||
* equivalent to 1 billion, or face value.
|
* equivalent to 1 billion, or face value.
|
||||||
*/
|
*/
|
||||||
HighQualityOut?: number
|
HighQualityOut?: number
|
||||||
|
HighReward?: RippleStateReward
|
||||||
|
LowReward?: RippleStateReward
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum RippleStateFlags {
|
export enum RippleStateFlags {
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import { LedgerEntry, LedgerEntryFilter } from './LedgerEntry'
|
|||||||
import LedgerHashes from './LedgerHashes'
|
import LedgerHashes from './LedgerHashes'
|
||||||
import NegativeUNL, { NEGATIVE_UNL_ID } from './NegativeUNL'
|
import NegativeUNL, { NEGATIVE_UNL_ID } from './NegativeUNL'
|
||||||
import Offer, { OfferFlags } from './Offer'
|
import Offer, { OfferFlags } from './Offer'
|
||||||
|
import Oracle from './Oracle'
|
||||||
import PayChannel from './PayChannel'
|
import PayChannel from './PayChannel'
|
||||||
import RippleState, { RippleStateFlags } from './RippleState'
|
import RippleState, { RippleStateFlags } from './RippleState'
|
||||||
import SignerList, { SignerListFlags } from './SignerList'
|
import SignerList, { SignerListFlags } from './SignerList'
|
||||||
@@ -60,6 +61,7 @@ export {
|
|||||||
NegativeUNL,
|
NegativeUNL,
|
||||||
Offer,
|
Offer,
|
||||||
OfferFlags,
|
OfferFlags,
|
||||||
|
Oracle,
|
||||||
PayChannel,
|
PayChannel,
|
||||||
RippleState,
|
RippleState,
|
||||||
RippleStateFlags,
|
RippleStateFlags,
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { Amount } from '../common'
|
|||||||
import { BaseRequest, BaseResponse, LookupByLedgerRequest } from './baseMethod'
|
import { BaseRequest, BaseResponse, LookupByLedgerRequest } from './baseMethod'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a payment channel in the XAH Ledger.
|
* Represents a payment channel in the Xahau Network.
|
||||||
*/
|
*/
|
||||||
export interface Channel {
|
export interface Channel {
|
||||||
/** The owner of the channel, as an Address. */
|
/** The owner of the channel, as an Address. */
|
||||||
@@ -38,7 +38,7 @@ export interface Channel {
|
|||||||
settle_delay: number
|
settle_delay: number
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The public key for the payment channel in the XAH Ledger's base58 format.
|
* The public key for the payment channel in the Xahau Network's base58 format.
|
||||||
* Signed claims against this channel must be redeemed with the matching key pair.
|
* Signed claims against this channel must be redeemed with the matching key pair.
|
||||||
*/
|
*/
|
||||||
public_key?: string
|
public_key?: string
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ export interface AccountCurrenciesRequest
|
|||||||
/** A unique identifier for the account, most commonly the account's address. */
|
/** A unique identifier for the account, most commonly the account's address. */
|
||||||
account: string
|
account: string
|
||||||
/**
|
/**
|
||||||
* If true, then the account field only accepts a public key or XAH Ledger
|
* If true, then the account field only accepts a public key or Xahau Network
|
||||||
* address. Otherwise, account can be a secret or passphrase (not
|
* address. Otherwise, account can be a secret or passphrase (not
|
||||||
* recommended). The default is false.
|
* recommended). The default is false.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export interface AccountInfoRequest extends BaseRequest, LookupByLedgerRequest {
|
|||||||
*/
|
*/
|
||||||
signer_lists?: boolean
|
signer_lists?: boolean
|
||||||
/**
|
/**
|
||||||
* If true, then the account field only accepts a public key or XAH Ledger
|
* If true, then the account field only accepts a public key or Xahau Network
|
||||||
* address. Otherwise, account can be a secret or passphrase (not
|
* address. Otherwise, account can be a secret or passphrase (not
|
||||||
* recommended). The default is false.
|
* recommended). The default is false.
|
||||||
*/
|
*/
|
||||||
@@ -159,7 +159,7 @@ interface BaseAccountInfoResponse extends BaseResponse {
|
|||||||
/**
|
/**
|
||||||
* Information about queued transactions sent by this account. This
|
* Information about queued transactions sent by this account. This
|
||||||
* information describes the state of the local xahaud server, which may be
|
* information describes the state of the local xahaud server, which may be
|
||||||
* different from other servers in the peer-to-peer XAH Ledger network. Some
|
* different from other servers in the peer-to-peer Xahau Network network. Some
|
||||||
* fields may be omitted because the values are calculated "lazily" by the
|
* fields may be omitted because the values are calculated "lazily" by the
|
||||||
* queuing mechanism.
|
* queuing mechanism.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ export interface AccountOffersRequest
|
|||||||
*/
|
*/
|
||||||
marker?: unknown
|
marker?: unknown
|
||||||
/**
|
/**
|
||||||
* If true, then the account field only accepts a public key or XAH Ledger
|
* If true, then the account field only accepts a public key or Xahau Network
|
||||||
* address. Otherwise, account can be a secret or passphrase (not
|
* address. Otherwise, account can be a secret or passphrase (not
|
||||||
* recommended). The default is false.
|
* recommended). The default is false.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ export interface ChannelVerifyRequest extends BaseRequest {
|
|||||||
channel_id: string
|
channel_id: string
|
||||||
/**
|
/**
|
||||||
* The public key of the channel and the key pair that was used to create the
|
* The public key of the channel and the key pair that was used to create the
|
||||||
* signature, in hexadecimal or the XAH Ledger's base58 format.
|
* signature, in hexadecimal or the Xahau Network's base58 format.
|
||||||
*/
|
*/
|
||||||
public_key: string
|
public_key: string
|
||||||
/** The signature to verify, in hexadecimal. */
|
/** The signature to verify, in hexadecimal. */
|
||||||
|
|||||||
119
packages/xahau/src/models/methods/getAggregatePrice.ts
Normal file
119
packages/xahau/src/models/methods/getAggregatePrice.ts
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
import { BaseRequest, BaseResponse } from './baseMethod'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The `get_aggregate_price` method retrieves the aggregate price of specified Oracle objects,
|
||||||
|
* returning three price statistics: mean, median, and trimmed mean.
|
||||||
|
* Returns an {@link GetAggregatePriceResponse}.
|
||||||
|
*
|
||||||
|
* @category Requests
|
||||||
|
*/
|
||||||
|
export interface GetAggregatePriceRequest extends BaseRequest {
|
||||||
|
command: 'get_aggregate_price'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The currency code of the asset to be priced.
|
||||||
|
*/
|
||||||
|
base_asset: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The currency code of the asset to quote the price of the base asset.
|
||||||
|
*/
|
||||||
|
quote_asset: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The oracle identifier.
|
||||||
|
*/
|
||||||
|
oracles: Array<{
|
||||||
|
/**
|
||||||
|
* The XRPL account that controls the Oracle object.
|
||||||
|
*/
|
||||||
|
account: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A unique identifier of the price oracle for the Account
|
||||||
|
*/
|
||||||
|
oracle_document_id: string | number
|
||||||
|
}>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The percentage of outliers to trim. Valid trim range is 1-25. If included, the API returns statistics for the trimmed mean.
|
||||||
|
*/
|
||||||
|
trim?: number
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines a time range in seconds for filtering out older price data. Default value is 0, which doesn't filter any data.
|
||||||
|
*/
|
||||||
|
trim_threshold?: number
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Response expected from an {@link GetAggregatePriceRequest}.
|
||||||
|
*
|
||||||
|
* @category Responses
|
||||||
|
*/
|
||||||
|
export interface GetAggregatePriceResponse extends BaseResponse {
|
||||||
|
result: {
|
||||||
|
/**
|
||||||
|
* The statistics from the collected oracle prices.
|
||||||
|
*/
|
||||||
|
entire_set: {
|
||||||
|
/**
|
||||||
|
* The simple mean.
|
||||||
|
*/
|
||||||
|
mean: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The size of the data set to calculate the mean.
|
||||||
|
*/
|
||||||
|
size: number
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The standard deviation.
|
||||||
|
*/
|
||||||
|
standard_deviation: string
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The trimmed statistics from the collected oracle prices. Only appears if the trim field was specified in the request.
|
||||||
|
*/
|
||||||
|
trimmed_set?: {
|
||||||
|
/**
|
||||||
|
* The simple mean of the trimmed data.
|
||||||
|
*/
|
||||||
|
mean: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The size of the data to calculate the trimmed mean.
|
||||||
|
*/
|
||||||
|
size: number
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The standard deviation of the trimmed data.
|
||||||
|
*/
|
||||||
|
standard_deviation: string
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The median of the collected oracle prices.
|
||||||
|
*/
|
||||||
|
median: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The most recent timestamp out of all LastUpdateTime values.
|
||||||
|
*/
|
||||||
|
time: number
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ledger index of the ledger version that was used to generate this
|
||||||
|
* response.
|
||||||
|
*/
|
||||||
|
ledger_current_index: number
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If included and set to true, the information in this response comes from
|
||||||
|
* a validated ledger version. Otherwise, the information is subject to
|
||||||
|
* change.
|
||||||
|
*/
|
||||||
|
validated: boolean
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -78,6 +78,10 @@ import {
|
|||||||
GatewayBalancesRequest,
|
GatewayBalancesRequest,
|
||||||
GatewayBalancesResponse,
|
GatewayBalancesResponse,
|
||||||
} from './gatewayBalances'
|
} from './gatewayBalances'
|
||||||
|
import {
|
||||||
|
GetAggregatePriceRequest,
|
||||||
|
GetAggregatePriceResponse,
|
||||||
|
} from './getAggregatePrice'
|
||||||
import {
|
import {
|
||||||
LedgerBinary,
|
LedgerBinary,
|
||||||
LedgerModifiedOfferCreateTransaction,
|
LedgerModifiedOfferCreateTransaction,
|
||||||
@@ -133,6 +137,14 @@ import {
|
|||||||
StateAccountingFinal,
|
StateAccountingFinal,
|
||||||
} from './serverInfo'
|
} from './serverInfo'
|
||||||
import { ServerStateRequest, ServerStateResponse } from './serverState'
|
import { ServerStateRequest, ServerStateResponse } from './serverState'
|
||||||
|
import {
|
||||||
|
SimulateBinaryRequest,
|
||||||
|
SimulateBinaryResponse,
|
||||||
|
SimulateJsonRequest,
|
||||||
|
SimulateJsonResponse,
|
||||||
|
SimulateRequest,
|
||||||
|
SimulateResponse,
|
||||||
|
} from './simulate'
|
||||||
import { SubmitRequest, SubmitResponse } from './submit'
|
import { SubmitRequest, SubmitResponse } from './submit'
|
||||||
import {
|
import {
|
||||||
SubmitMultisignedRequest,
|
SubmitMultisignedRequest,
|
||||||
@@ -188,6 +200,7 @@ type Request =
|
|||||||
| LedgerDataRequest
|
| LedgerDataRequest
|
||||||
| LedgerEntryRequest
|
| LedgerEntryRequest
|
||||||
// transaction methods
|
// transaction methods
|
||||||
|
| SimulateRequest
|
||||||
| SubmitRequest
|
| SubmitRequest
|
||||||
| SubmitMultisignedRequest
|
| SubmitMultisignedRequest
|
||||||
| TransactionEntryRequest
|
| TransactionEntryRequest
|
||||||
@@ -212,6 +225,8 @@ type Request =
|
|||||||
// utility methods
|
// utility methods
|
||||||
| PingRequest
|
| PingRequest
|
||||||
| RandomRequest
|
| RandomRequest
|
||||||
|
// Price Oracle methods
|
||||||
|
| GetAggregatePriceRequest
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @category Responses
|
* @category Responses
|
||||||
@@ -235,6 +250,7 @@ type Response<Version extends APIVersion = typeof DEFAULT_API_VERSION> =
|
|||||||
| LedgerDataResponse
|
| LedgerDataResponse
|
||||||
| LedgerEntryResponse
|
| LedgerEntryResponse
|
||||||
// transaction methods
|
// transaction methods
|
||||||
|
| SimulateResponse
|
||||||
| SubmitResponse
|
| SubmitResponse
|
||||||
| SubmitMultisignedVersionResponseMap<Version>
|
| SubmitMultisignedVersionResponseMap<Version>
|
||||||
| TransactionEntryResponse
|
| TransactionEntryResponse
|
||||||
@@ -259,6 +275,8 @@ type Response<Version extends APIVersion = typeof DEFAULT_API_VERSION> =
|
|||||||
// utility methods
|
// utility methods
|
||||||
| PingResponse
|
| PingResponse
|
||||||
| RandomResponse
|
| RandomResponse
|
||||||
|
// Price Oracle methods
|
||||||
|
| GetAggregatePriceResponse
|
||||||
|
|
||||||
export type RequestResponseMap<
|
export type RequestResponseMap<
|
||||||
T,
|
T,
|
||||||
@@ -279,6 +297,8 @@ export type RequestResponseMap<
|
|||||||
? AccountTxVersionResponseMap<Version>
|
? AccountTxVersionResponseMap<Version>
|
||||||
: T extends GatewayBalancesRequest
|
: T extends GatewayBalancesRequest
|
||||||
? GatewayBalancesResponse
|
? GatewayBalancesResponse
|
||||||
|
: T extends GetAggregatePriceRequest
|
||||||
|
? GetAggregatePriceResponse
|
||||||
: T extends NoRippleCheckRequest
|
: T extends NoRippleCheckRequest
|
||||||
? NoRippleCheckResponse
|
? NoRippleCheckResponse
|
||||||
: // NOTE: The order of these LedgerRequest types is important
|
: // NOTE: The order of these LedgerRequest types is important
|
||||||
@@ -355,6 +375,12 @@ export type RequestResponseMap<
|
|||||||
? LedgerDataResponse
|
? LedgerDataResponse
|
||||||
: T extends LedgerEntryRequest
|
: T extends LedgerEntryRequest
|
||||||
? LedgerEntryResponse
|
? LedgerEntryResponse
|
||||||
|
: T extends SimulateBinaryRequest
|
||||||
|
? SimulateBinaryResponse
|
||||||
|
: T extends SimulateJsonRequest
|
||||||
|
? SimulateJsonResponse
|
||||||
|
: T extends SimulateRequest
|
||||||
|
? SimulateJsonResponse
|
||||||
: T extends SubmitRequest
|
: T extends SubmitRequest
|
||||||
? SubmitResponse
|
? SubmitResponse
|
||||||
: T extends SubmitMultisignedRequest
|
: T extends SubmitMultisignedRequest
|
||||||
@@ -465,6 +491,8 @@ export {
|
|||||||
GatewayBalance,
|
GatewayBalance,
|
||||||
GatewayBalancesRequest,
|
GatewayBalancesRequest,
|
||||||
GatewayBalancesResponse,
|
GatewayBalancesResponse,
|
||||||
|
GetAggregatePriceRequest,
|
||||||
|
GetAggregatePriceResponse,
|
||||||
NoRippleCheckRequest,
|
NoRippleCheckRequest,
|
||||||
NoRippleCheckResponse,
|
NoRippleCheckResponse,
|
||||||
// ledger methods
|
// ledger methods
|
||||||
@@ -486,6 +514,8 @@ export {
|
|||||||
LedgerEntryRequest,
|
LedgerEntryRequest,
|
||||||
LedgerEntryResponse,
|
LedgerEntryResponse,
|
||||||
// transaction methods with types
|
// transaction methods with types
|
||||||
|
SimulateRequest,
|
||||||
|
SimulateResponse,
|
||||||
SubmitRequest,
|
SubmitRequest,
|
||||||
SubmitResponse,
|
SubmitResponse,
|
||||||
SubmitMultisignedRequest,
|
SubmitMultisignedRequest,
|
||||||
|
|||||||
@@ -203,13 +203,13 @@ export interface LedgerQueueData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface LedgerBinary
|
export interface LedgerBinary
|
||||||
extends Omit<Omit<Ledger, 'transactions'>, 'accountState'> {
|
extends Omit<Ledger, 'transactions' | 'accountState'> {
|
||||||
accountState?: string[]
|
accountState?: string[]
|
||||||
transactions?: string[]
|
transactions?: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LedgerBinaryV1
|
export interface LedgerBinaryV1
|
||||||
extends Omit<Omit<LedgerV1, 'transactions'>, 'accountState'> {
|
extends Omit<LedgerV1, 'transactions' | 'accountState'> {
|
||||||
accountState?: string[]
|
accountState?: string[]
|
||||||
transactions?: string[]
|
transactions?: string[]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { LedgerEntry } from '../ledger'
|
|||||||
import { BaseRequest, BaseResponse, LookupByLedgerRequest } from './baseMethod'
|
import { BaseRequest, BaseResponse, LookupByLedgerRequest } from './baseMethod'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `ledger_entry` method returns a single ledger object from the XAH Ledger
|
* The `ledger_entry` method returns a single ledger object from the Xahau Network
|
||||||
* in its raw format. Expects a response in the form of a {@link
|
* in its raw format. Expects a response in the form of a {@link
|
||||||
* LedgerEntryResponse}.
|
* LedgerEntryResponse}.
|
||||||
*
|
*
|
||||||
@@ -30,7 +30,7 @@ export interface LedgerEntryRequest extends BaseRequest, LookupByLedgerRequest {
|
|||||||
include_deleted?: boolean
|
include_deleted?: boolean
|
||||||
/**
|
/**
|
||||||
* If true, return the requested ledger object's contents as a hex string in
|
* If true, return the requested ledger object's contents as a hex string in
|
||||||
* the XAH Ledger's binary format. Otherwise, return data in JSON format. The
|
* the Xahau Network's binary format. Otherwise, return data in JSON format. The
|
||||||
* default is false.
|
* default is false.
|
||||||
*/
|
*/
|
||||||
binary?: boolean
|
binary?: boolean
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ export interface ServerInfoResponse extends BaseResponse {
|
|||||||
* The number of times (since starting up) that this server has had over
|
* The number of times (since starting up) that this server has had over
|
||||||
* 250 transactions waiting to be processed at once. A large number here
|
* 250 transactions waiting to be processed at once. A large number here
|
||||||
* may mean that your server is unable to handle the transaction load of
|
* may mean that your server is unable to handle the transaction load of
|
||||||
* the XAH Ledger network.
|
* the Xahau Network network.
|
||||||
*/
|
*/
|
||||||
jq_trans_overflow: string
|
jq_trans_overflow: string
|
||||||
/**
|
/**
|
||||||
|
|||||||
88
packages/xahau/src/models/methods/simulate.ts
Normal file
88
packages/xahau/src/models/methods/simulate.ts
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
import {
|
||||||
|
BaseTransaction,
|
||||||
|
Transaction,
|
||||||
|
TransactionMetadata,
|
||||||
|
} from '../transactions'
|
||||||
|
|
||||||
|
import { BaseRequest, BaseResponse } from './baseMethod'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The `simulate` method simulates a transaction without submitting it to the network.
|
||||||
|
* Returns a {@link SimulateResponse}.
|
||||||
|
*
|
||||||
|
* @category Requests
|
||||||
|
*/
|
||||||
|
export type SimulateRequest = BaseRequest & {
|
||||||
|
command: 'simulate'
|
||||||
|
|
||||||
|
binary?: boolean
|
||||||
|
} & (
|
||||||
|
| {
|
||||||
|
tx_blob: string
|
||||||
|
tx_json?: never
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
tx_json: Transaction
|
||||||
|
tx_blob?: never
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
export type SimulateBinaryRequest = SimulateRequest & {
|
||||||
|
binary: true
|
||||||
|
}
|
||||||
|
|
||||||
|
export type SimulateJsonRequest = SimulateRequest & {
|
||||||
|
binary?: false
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Response expected from an {@link SimulateRequest}.
|
||||||
|
*
|
||||||
|
* @category Responses
|
||||||
|
*/
|
||||||
|
export type SimulateResponse = SimulateJsonResponse | SimulateBinaryResponse
|
||||||
|
|
||||||
|
export interface SimulateBinaryResponse extends BaseResponse {
|
||||||
|
result: {
|
||||||
|
applied: false
|
||||||
|
|
||||||
|
engine_result: string
|
||||||
|
|
||||||
|
engine_result_code: number
|
||||||
|
|
||||||
|
engine_result_message: string
|
||||||
|
|
||||||
|
tx_blob: string
|
||||||
|
|
||||||
|
meta_blob: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ledger index of the ledger version that was used to generate this
|
||||||
|
* response.
|
||||||
|
*/
|
||||||
|
ledger_index: number
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SimulateJsonResponse<T extends BaseTransaction = Transaction>
|
||||||
|
extends BaseResponse {
|
||||||
|
result: {
|
||||||
|
applied: false
|
||||||
|
|
||||||
|
engine_result: string
|
||||||
|
|
||||||
|
engine_result_code: number
|
||||||
|
|
||||||
|
engine_result_message: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ledger index of the ledger version that was used to generate this
|
||||||
|
* response.
|
||||||
|
*/
|
||||||
|
ledger_index: number
|
||||||
|
|
||||||
|
tx_json: T
|
||||||
|
|
||||||
|
meta?: TransactionMetadata<T>
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -65,7 +65,7 @@ export interface SubmitResponse extends BaseResponse {
|
|||||||
applied: boolean
|
applied: boolean
|
||||||
/**
|
/**
|
||||||
* The value true indicates this transaction was broadcast to peer servers
|
* The value true indicates this transaction was broadcast to peer servers
|
||||||
* in the peer-to-peer XAH Ledger network.
|
* in the peer-to-peer Xahau Network network.
|
||||||
*/
|
*/
|
||||||
broadcast: boolean
|
broadcast: boolean
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ export interface SubscribeBook {
|
|||||||
taker_pays: Currency
|
taker_pays: Currency
|
||||||
/**
|
/**
|
||||||
* Unique account address to use as a perspective for viewing offers, in the.
|
* Unique account address to use as a perspective for viewing offers, in the.
|
||||||
* XAH Ledger's base58 format.
|
* Xahau Network's base58 format.
|
||||||
*/
|
*/
|
||||||
taker: string
|
taker: string
|
||||||
/**
|
/**
|
||||||
@@ -54,7 +54,7 @@ export interface SubscribeRequest extends BaseRequest {
|
|||||||
streams?: StreamType[]
|
streams?: StreamType[]
|
||||||
/**
|
/**
|
||||||
* Array with the unique addresses of accounts to monitor for validated
|
* Array with the unique addresses of accounts to monitor for validated
|
||||||
* transactions. The addresses must be in the XAH Ledger's base58 format.
|
* transactions. The addresses must be in the Xahau Network's base58 format.
|
||||||
* The server sends a notification for any transaction that affects at least
|
* The server sends a notification for any transaction that affects at least
|
||||||
* one of these accounts.
|
* one of these accounts.
|
||||||
*/
|
*/
|
||||||
@@ -235,7 +235,7 @@ export interface ValidationStream extends BaseStream {
|
|||||||
load_fee?: number
|
load_fee?: number
|
||||||
/**
|
/**
|
||||||
* The validator's master public key, if the validator is using a validator
|
* The validator's master public key, if the validator is using a validator
|
||||||
* token, in the XAH Ledger's base58 format.
|
* token, in the Xahau Network's base58 format.
|
||||||
*/
|
*/
|
||||||
master_key?: string
|
master_key?: string
|
||||||
/**
|
/**
|
||||||
@@ -254,7 +254,7 @@ export interface ValidationStream extends BaseStream {
|
|||||||
signing_time: number
|
signing_time: number
|
||||||
/**
|
/**
|
||||||
* The public key from the key-pair that the validator used to sign the
|
* The public key from the key-pair that the validator used to sign the
|
||||||
* message, in the XAH Ledger's base58 format. This identifies the validator
|
* message, in the Xahau Network's base58 format. This identifies the validator
|
||||||
* sending the message and can also be used to verify the signature. If the
|
* sending the message and can also be used to verify the signature. If the
|
||||||
* validator is using a token, this is an ephemeral public key.
|
* validator is using a token, this is an ephemeral public key.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ export interface UnsubscribeRequest extends BaseRequest {
|
|||||||
streams?: StreamType[]
|
streams?: StreamType[]
|
||||||
/**
|
/**
|
||||||
* Array of unique account addresses to stop receiving updates for, in the.
|
* Array of unique account addresses to stop receiving updates for, in the.
|
||||||
* XAH Ledger's base58 format.
|
* Xahau Network's base58 format.
|
||||||
*/
|
*/
|
||||||
accounts?: string[]
|
accounts?: string[]
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -173,6 +173,7 @@ export interface AccountSet extends BaseTransaction {
|
|||||||
const MIN_TICK_SIZE = 3
|
const MIN_TICK_SIZE = 3
|
||||||
const MAX_TICK_SIZE = 15
|
const MAX_TICK_SIZE = 15
|
||||||
const MAX_HOOK_STATE_SCALE = 16
|
const MAX_HOOK_STATE_SCALE = 16
|
||||||
|
const MIN_HOOK_STATE_SCALE = 1
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verify the form and type of an AccountSet at runtime.
|
* Verify the form and type of an AccountSet at runtime.
|
||||||
@@ -233,12 +234,22 @@ export function validateAccountSet(tx: Record<string, unknown>): void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
validateOptionalField(tx, 'HookStateScale', isNumber)
|
validateOptionalField(tx, 'HookStateScale', isNumber)
|
||||||
|
|
||||||
if (
|
if (
|
||||||
typeof tx.HookStateScale === 'number' &&
|
typeof tx.HookStateScale === 'number' &&
|
||||||
tx.HookStateScale > MAX_HOOK_STATE_SCALE
|
tx.HookStateScale > MAX_HOOK_STATE_SCALE
|
||||||
) {
|
) {
|
||||||
throw new ValidationError(
|
throw new ValidationError(
|
||||||
`AccountSet: HookStateScale must be less than ${MAX_HOOK_STATE_SCALE}`,
|
`AccountSet: HookStateScale must be less than or equal to ${MAX_HOOK_STATE_SCALE}`,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
typeof tx.HookStateScale === 'number' &&
|
||||||
|
tx.HookStateScale < MIN_HOOK_STATE_SCALE
|
||||||
|
) {
|
||||||
|
throw new ValidationError(
|
||||||
|
`AccountSet: HookStateScale must be greater than or equal to ${MIN_HOOK_STATE_SCALE}`,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { ValidationError } from '../../errors'
|
import { ValidationError } from '../../errors'
|
||||||
|
import { Currency } from '../common'
|
||||||
|
|
||||||
import { BaseTransaction, validateBaseTransaction } from './common'
|
import { BaseTransaction, GlobalFlags, validateBaseTransaction } from './common'
|
||||||
/**
|
/**
|
||||||
* Transaction Flags for an ClaimReward Transaction.
|
* Transaction Flags for an ClaimReward Transaction.
|
||||||
*
|
*
|
||||||
@@ -13,6 +14,39 @@ export enum ClaimRewardFlags {
|
|||||||
tfOptOut = 0x00000001,
|
tfOptOut = 0x00000001,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map of flags to boolean values representing {@link ClaimReward} transaction
|
||||||
|
* flags.
|
||||||
|
*
|
||||||
|
* @category Transaction Flags
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```typescript
|
||||||
|
* const tx: ClaimReward = {
|
||||||
|
* Account: 'rhFcpWDHLqpBmX4ezWiA5VLSS4e1BHqhHd',
|
||||||
|
* TransactionType: 'ClaimReward',
|
||||||
|
* Flags: {
|
||||||
|
* tfOptOut: true,
|
||||||
|
* },
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // Autofill the tx to see how flags actually look compared to the interface usage.
|
||||||
|
* const autofilledTx = await client.autofill(tx)
|
||||||
|
* console.log(autofilledTx)
|
||||||
|
* // {
|
||||||
|
* // Account: 'rhFcpWDHLqpBmX4ezWiA5VLSS4e1BHqhHd',
|
||||||
|
* // TransactionType: 'ClaimReward',
|
||||||
|
* // Flags: 0,
|
||||||
|
* // Sequence: 21970384,
|
||||||
|
* // Fee: '12',
|
||||||
|
* // LastLedgerSequence: 21970404
|
||||||
|
* // }
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
export interface ClaimRewardFlagsInterface extends GlobalFlags {
|
||||||
|
tfOptOut?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ClaimReward is a transaction model that allows an account to claim rewards.
|
* ClaimReward is a transaction model that allows an account to claim rewards.
|
||||||
*
|
*
|
||||||
@@ -20,9 +54,10 @@ export enum ClaimRewardFlags {
|
|||||||
*/
|
*/
|
||||||
export interface ClaimReward extends BaseTransaction {
|
export interface ClaimReward extends BaseTransaction {
|
||||||
TransactionType: 'ClaimReward'
|
TransactionType: 'ClaimReward'
|
||||||
Flags?: number | ClaimRewardFlags
|
Flags?: number | ClaimRewardFlagsInterface
|
||||||
/** The unique address of the issuer where the reward.c hook is installed. */
|
/** The unique address of the issuer where the reward.c hook is installed. */
|
||||||
Issuer?: string
|
Issuer?: string
|
||||||
|
ClaimCurrency?: Currency
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -275,6 +275,10 @@ export interface BaseTransaction {
|
|||||||
* The hook parameters of the transaction.
|
* The hook parameters of the transaction.
|
||||||
*/
|
*/
|
||||||
HookParameters?: HookParameter[]
|
HookParameters?: HookParameter[]
|
||||||
|
/**
|
||||||
|
* The name of the hooks triggered by the transaction.
|
||||||
|
*/
|
||||||
|
HookName?: string
|
||||||
/**
|
/**
|
||||||
* The hook parameters of the transaction.
|
* The hook parameters of the transaction.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { ValidationError } from '../../errors'
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
BaseTransaction,
|
BaseTransaction,
|
||||||
|
GlobalFlags,
|
||||||
isNumber,
|
isNumber,
|
||||||
validateBaseTransaction,
|
validateBaseTransaction,
|
||||||
validateOptionalField,
|
validateOptionalField,
|
||||||
@@ -19,6 +20,39 @@ export enum CronSetFlags {
|
|||||||
tfCronUnset = 0x00000001,
|
tfCronUnset = 0x00000001,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map of flags to boolean values representing {@link CronSet} transaction
|
||||||
|
* flags.
|
||||||
|
*
|
||||||
|
* @category Transaction Flags
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```typescript
|
||||||
|
* const tx: CronSet = {
|
||||||
|
* Account: 'rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo',
|
||||||
|
* TransactionType: 'CronSet',
|
||||||
|
* Flags: {
|
||||||
|
* tfCronUnset: true,
|
||||||
|
* },
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // Autofill the tx to see how flags actually look compared to the interface usage.
|
||||||
|
* const autofilledTx = await client.autofill(tx)
|
||||||
|
* console.log(autofilledTx)
|
||||||
|
* // {
|
||||||
|
* // Account: 'rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo',
|
||||||
|
* // TransactionType: 'CronSet',
|
||||||
|
* // Flags: 0,
|
||||||
|
* // Sequence: 21970384,
|
||||||
|
* // Fee: '12',
|
||||||
|
* // LastLedgerSequence: 21970404
|
||||||
|
* // }
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
export interface CronSetFlagsInterface extends GlobalFlags {
|
||||||
|
tfCronUnset?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CronSet is a transaction model that allows an account to set a cron job.
|
* CronSet is a transaction model that allows an account to set a cron job.
|
||||||
*
|
*
|
||||||
@@ -26,7 +60,7 @@ export enum CronSetFlags {
|
|||||||
*/
|
*/
|
||||||
export interface CronSet extends BaseTransaction {
|
export interface CronSet extends BaseTransaction {
|
||||||
TransactionType: 'CronSet'
|
TransactionType: 'CronSet'
|
||||||
Flags?: number | CronSetFlags
|
Flags?: number | CronSetFlagsInterface
|
||||||
RepeatCount?: number
|
RepeatCount?: number
|
||||||
DelaySeconds?: number
|
DelaySeconds?: number
|
||||||
StartTime?: number
|
StartTime?: number
|
||||||
|
|||||||
@@ -11,10 +11,10 @@ import { BaseTransaction, validateBaseTransaction } from './common'
|
|||||||
*/
|
*/
|
||||||
export interface DepositPreauth extends BaseTransaction {
|
export interface DepositPreauth extends BaseTransaction {
|
||||||
TransactionType: 'DepositPreauth'
|
TransactionType: 'DepositPreauth'
|
||||||
/** The XAH Ledger address of the sender to preauthorize. */
|
/** The Xahau Network address of the sender to preauthorize. */
|
||||||
Authorize?: string
|
Authorize?: string
|
||||||
/**
|
/**
|
||||||
* The XAH Ledger address of a sender whose preauthorization should be.
|
* The Xahau Network address of a sender whose preauthorization should be.
|
||||||
* revoked.
|
* revoked.
|
||||||
*/
|
*/
|
||||||
Unauthorize?: string
|
Unauthorize?: string
|
||||||
|
|||||||
@@ -32,6 +32,8 @@ export {
|
|||||||
OfferCreateFlagsInterface,
|
OfferCreateFlagsInterface,
|
||||||
OfferCreate,
|
OfferCreate,
|
||||||
} from './offerCreate'
|
} from './offerCreate'
|
||||||
|
export { OracleDelete } from './oracleDelete'
|
||||||
|
export { OracleSet } from './oracleSet'
|
||||||
export { PaymentFlags, PaymentFlagsInterface, Payment } from './payment'
|
export { PaymentFlags, PaymentFlagsInterface, Payment } from './payment'
|
||||||
export {
|
export {
|
||||||
PaymentChannelClaimFlags,
|
PaymentChannelClaimFlags,
|
||||||
@@ -41,7 +43,7 @@ export {
|
|||||||
export { PaymentChannelCreate } from './paymentChannelCreate'
|
export { PaymentChannelCreate } from './paymentChannelCreate'
|
||||||
export { PaymentChannelFund } from './paymentChannelFund'
|
export { PaymentChannelFund } from './paymentChannelFund'
|
||||||
export { Remit } from './remit'
|
export { Remit } from './remit'
|
||||||
export { SetHookFlagsInterface, SetHookFlags, SetHook } from './setHook'
|
export { SetHook } from './setHook'
|
||||||
export { SetFee, SetFeePreAmendment, SetFeePostAmendment } from './setFee'
|
export { SetFee, SetFeePreAmendment, SetFeePostAmendment } from './setFee'
|
||||||
export { SetRegularKey } from './setRegularKey'
|
export { SetRegularKey } from './setRegularKey'
|
||||||
export {
|
export {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { ValidationError } from '../../errors'
|
|||||||
import { BaseTransaction, validateBaseTransaction } from './common'
|
import { BaseTransaction, validateBaseTransaction } from './common'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An OfferCancel transaction removes an Offer object from the XAH Ledger.
|
* An OfferCancel transaction removes an Offer object from the Xahau Network.
|
||||||
*
|
*
|
||||||
* @category Transaction Models
|
* @category Transaction Models
|
||||||
*/
|
*/
|
||||||
|
|||||||
32
packages/xahau/src/models/transactions/oracleDelete.ts
Normal file
32
packages/xahau/src/models/transactions/oracleDelete.ts
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import {
|
||||||
|
BaseTransaction,
|
||||||
|
isNumber,
|
||||||
|
validateBaseTransaction,
|
||||||
|
validateRequiredField,
|
||||||
|
} from './common'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete an Oracle ledger entry.
|
||||||
|
*
|
||||||
|
* @category Transaction Models
|
||||||
|
*/
|
||||||
|
export interface OracleDelete extends BaseTransaction {
|
||||||
|
TransactionType: 'OracleDelete'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A unique identifier of the price oracle for the Account.
|
||||||
|
*/
|
||||||
|
OracleDocumentID: number
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify the form and type of a OracleDelete at runtime.
|
||||||
|
*
|
||||||
|
* @param tx - A OracleDelete Transaction.
|
||||||
|
* @throws When the OracleDelete is malformed.
|
||||||
|
*/
|
||||||
|
export function validateOracleDelete(tx: Record<string, unknown>): void {
|
||||||
|
validateBaseTransaction(tx)
|
||||||
|
|
||||||
|
validateRequiredField(tx, 'OracleDocumentID', isNumber)
|
||||||
|
}
|
||||||
198
packages/xahau/src/models/transactions/oracleSet.ts
Normal file
198
packages/xahau/src/models/transactions/oracleSet.ts
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
import { ValidationError } from '../../errors'
|
||||||
|
import { PriceData } from '../common'
|
||||||
|
import { isHex } from '../utils'
|
||||||
|
|
||||||
|
import {
|
||||||
|
BaseTransaction,
|
||||||
|
isNumber,
|
||||||
|
isString,
|
||||||
|
validateBaseTransaction,
|
||||||
|
validateOptionalField,
|
||||||
|
validateRequiredField,
|
||||||
|
} from './common'
|
||||||
|
|
||||||
|
const PRICE_DATA_SERIES_MAX_LENGTH = 10
|
||||||
|
const SCALE_MAX = 10
|
||||||
|
const MINIMUM_ASSET_PRICE_LENGTH = 1
|
||||||
|
const MAXIMUM_ASSET_PRICE_LENGTH = 16
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new Oracle ledger entry or updates the fields of an existing one, using the Oracle ID.
|
||||||
|
*
|
||||||
|
* The oracle provider must complete these steps before submitting this transaction:
|
||||||
|
* 1. Create or own the XRPL account in the Owner field and have enough XRP to meet the reserve and transaction fee requirements.
|
||||||
|
* 2. Publish the XRPL account public key, so it can be used for verification by dApps.
|
||||||
|
* 3. Publish a registry of available price oracles with their unique OracleDocumentID.
|
||||||
|
*
|
||||||
|
* @category Transaction Models
|
||||||
|
*/
|
||||||
|
export interface OracleSet extends BaseTransaction {
|
||||||
|
TransactionType: 'OracleSet'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A unique identifier of the price oracle for the Account.
|
||||||
|
*/
|
||||||
|
OracleDocumentID: number
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The time the data was last updated, represented as a unix timestamp in seconds.
|
||||||
|
*/
|
||||||
|
LastUpdateTime: number
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An array of up to 10 PriceData objects, each representing the price information
|
||||||
|
* for a token pair. More than five PriceData objects require two owner reserves.
|
||||||
|
*/
|
||||||
|
PriceDataSeries: PriceData[]
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An arbitrary value that identifies an oracle provider, such as Chainlink, Band,
|
||||||
|
* or DIA. This field is a string, up to 256 ASCII hex encoded characters (0x20-0x7E).
|
||||||
|
* This field is required when creating a new Oracle ledger entry, but is optional for updates.
|
||||||
|
*/
|
||||||
|
Provider?: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An optional Universal Resource Identifier to reference price data off-chain. This field is limited to 256 bytes.
|
||||||
|
*/
|
||||||
|
URI?: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Describes the type of asset, such as "currency", "commodity", or "index". This field is a string, up to 16 ASCII
|
||||||
|
* hex encoded characters (0x20-0x7E). This field is required when creating a new Oracle ledger entry, but is optional
|
||||||
|
* for updates.
|
||||||
|
*/
|
||||||
|
AssetClass?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify the form and type of a OracleSet at runtime.
|
||||||
|
*
|
||||||
|
* @param tx - A OracleSet Transaction.
|
||||||
|
* @throws When the OracleSet is malformed.
|
||||||
|
*/
|
||||||
|
// eslint-disable-next-line max-lines-per-function -- necessary to validate many fields
|
||||||
|
export function validateOracleSet(tx: Record<string, unknown>): void {
|
||||||
|
validateBaseTransaction(tx)
|
||||||
|
|
||||||
|
validateRequiredField(tx, 'OracleDocumentID', isNumber)
|
||||||
|
|
||||||
|
validateRequiredField(tx, 'LastUpdateTime', isNumber)
|
||||||
|
|
||||||
|
validateOptionalField(tx, 'Provider', isString)
|
||||||
|
|
||||||
|
validateOptionalField(tx, 'URI', isString)
|
||||||
|
|
||||||
|
validateOptionalField(tx, 'AssetClass', isString)
|
||||||
|
|
||||||
|
/* eslint-disable max-statements, max-lines-per-function -- necessary to validate many fields */
|
||||||
|
validateRequiredField(tx, 'PriceDataSeries', (value) => {
|
||||||
|
if (!Array.isArray(value)) {
|
||||||
|
throw new ValidationError('OracleSet: PriceDataSeries must be an array')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value.length > PRICE_DATA_SERIES_MAX_LENGTH) {
|
||||||
|
throw new ValidationError(
|
||||||
|
`OracleSet: PriceDataSeries must have at most ${PRICE_DATA_SERIES_MAX_LENGTH} PriceData objects`,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: add support for handling inner objects easier (similar to validateRequiredField/validateOptionalField)
|
||||||
|
for (const priceData of value) {
|
||||||
|
if (typeof priceData !== 'object') {
|
||||||
|
throw new ValidationError(
|
||||||
|
'OracleSet: PriceDataSeries must be an array of objects',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access -- we are validating the type
|
||||||
|
if (priceData.PriceData == null) {
|
||||||
|
throw new ValidationError(
|
||||||
|
'OracleSet: PriceDataSeries must have a `PriceData` object',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if priceData only has PriceData
|
||||||
|
if (Object.keys(priceData).length !== 1) {
|
||||||
|
throw new ValidationError(
|
||||||
|
'OracleSet: PriceDataSeries must only have a single PriceData object',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access -- we are validating the type
|
||||||
|
if (typeof priceData.PriceData.BaseAsset !== 'string') {
|
||||||
|
throw new ValidationError(
|
||||||
|
'OracleSet: PriceDataSeries must have a `BaseAsset` string',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access -- we are validating the type
|
||||||
|
if (typeof priceData.PriceData.QuoteAsset !== 'string') {
|
||||||
|
throw new ValidationError(
|
||||||
|
'OracleSet: PriceDataSeries must have a `QuoteAsset` string',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Either AssetPrice and Scale are both present or both excluded
|
||||||
|
if (
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access -- we are validating the type
|
||||||
|
(priceData.PriceData.AssetPrice == null) !==
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access -- we are validating the type
|
||||||
|
(priceData.PriceData.Scale == null)
|
||||||
|
) {
|
||||||
|
throw new ValidationError(
|
||||||
|
'OracleSet: PriceDataSeries must have both `AssetPrice` and `Scale` if any are present',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access, max-depth --
|
||||||
|
we need to validate priceData.PriceData.AssetPrice value */
|
||||||
|
if ('AssetPrice' in priceData.PriceData) {
|
||||||
|
if (!isNumber(priceData.PriceData.AssetPrice)) {
|
||||||
|
if (typeof priceData.PriceData.AssetPrice !== 'string') {
|
||||||
|
throw new ValidationError(
|
||||||
|
'OracleSet: Field AssetPrice must be a string or a number',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (!isHex(priceData.PriceData.AssetPrice)) {
|
||||||
|
throw new ValidationError(
|
||||||
|
'OracleSet: Field AssetPrice must be a valid hex string',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
priceData.PriceData.AssetPrice.length <
|
||||||
|
MINIMUM_ASSET_PRICE_LENGTH ||
|
||||||
|
priceData.PriceData.AssetPrice.length > MAXIMUM_ASSET_PRICE_LENGTH
|
||||||
|
) {
|
||||||
|
throw new ValidationError(
|
||||||
|
`OracleSet: Length of AssetPrice field must be between ${MINIMUM_ASSET_PRICE_LENGTH} and ${MAXIMUM_ASSET_PRICE_LENGTH} characters long`,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* eslint-enable @typescript-eslint/no-unsafe-member-access, max-depth */
|
||||||
|
|
||||||
|
if (
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access -- we are validating the type
|
||||||
|
'Scale' in priceData.PriceData &&
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access -- we are validating the type
|
||||||
|
!isNumber(priceData.PriceData.Scale)
|
||||||
|
) {
|
||||||
|
throw new ValidationError('OracleSet: invalid field Scale')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access -- we are validating the type
|
||||||
|
priceData.PriceData.Scale < 0 ||
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access -- we are validating the type
|
||||||
|
priceData.PriceData.Scale > SCALE_MAX
|
||||||
|
) {
|
||||||
|
throw new ValidationError(
|
||||||
|
`OracleSet: Scale must be in range 0-${SCALE_MAX}`,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
/* eslint-enable max-statements, max-lines-per-function */
|
||||||
|
}
|
||||||
@@ -1,30 +1,7 @@
|
|||||||
import { ValidationError } from '../../errors'
|
import { ValidationError } from '../../errors'
|
||||||
import { Hook } from '../common/xahau'
|
import { Hook } from '../common/xahau'
|
||||||
|
|
||||||
import { BaseTransaction, GlobalFlags, validateBaseTransaction } from './common'
|
import { BaseTransaction, validateBaseTransaction } from './common'
|
||||||
|
|
||||||
/**
|
|
||||||
* Enum representing values for Set Hook Transaction Flags.
|
|
||||||
*
|
|
||||||
* @category Transaction Flags
|
|
||||||
*/
|
|
||||||
export enum SetHookFlags {
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
hsfOverride = 0x00000001,
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
hsfNSDelete = 0x0000002,
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
hsfCollect = 0x00000004,
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface SetHookFlagsInterface extends GlobalFlags {
|
|
||||||
hsfOverride?: boolean
|
|
||||||
hsfNSDelete?: boolean
|
|
||||||
hsfCollect?: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -37,12 +14,14 @@ export interface SetHook extends BaseTransaction {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
Hooks: Hook[]
|
Hooks: Hook[]
|
||||||
|
|
||||||
Flags?: number | SetHookFlagsInterface
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const MAX_HOOKS = 10
|
const MAX_HOOKS = 10
|
||||||
const HEX_REGEX = /^[0-9A-Fa-f]{64}$/u
|
const HEX_REGEX = /^[0-9A-Fa-f]{64}$/u
|
||||||
|
/**
|
||||||
|
* 4-16 bytes in hex
|
||||||
|
*/
|
||||||
|
const HOOKNAME_REGEX = /^[0-9A-Fa-f]{8,32}$/u
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verify the form and type of an SetHook at runtime.
|
* Verify the form and type of an SetHook at runtime.
|
||||||
@@ -50,6 +29,7 @@ const HEX_REGEX = /^[0-9A-Fa-f]{64}$/u
|
|||||||
* @param tx - An SetHook Transaction.
|
* @param tx - An SetHook Transaction.
|
||||||
* @throws When the SetHook is Malformed.
|
* @throws When the SetHook is Malformed.
|
||||||
*/
|
*/
|
||||||
|
// eslint-disable-next-line max-lines-per-function -- okay for this method
|
||||||
export function validateSetHook(tx: Record<string, unknown>): void {
|
export function validateSetHook(tx: Record<string, unknown>): void {
|
||||||
validateBaseTransaction(tx)
|
validateBaseTransaction(tx)
|
||||||
|
|
||||||
@@ -66,12 +46,29 @@ export function validateSetHook(tx: Record<string, unknown>): void {
|
|||||||
for (const hook of tx.Hooks) {
|
for (const hook of tx.Hooks) {
|
||||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Should be a Hook
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Should be a Hook
|
||||||
const hookObject = hook as Hook
|
const hookObject = hook as Hook
|
||||||
const { HookOn, HookCanEmit, HookNamespace } = hookObject.Hook
|
const {
|
||||||
|
HookOn,
|
||||||
|
HookOnIncoming,
|
||||||
|
HookOnOutgoing,
|
||||||
|
HookCanEmit,
|
||||||
|
HookNamespace,
|
||||||
|
HookName,
|
||||||
|
} = hookObject.Hook
|
||||||
if (HookOn !== undefined && !HEX_REGEX.test(HookOn)) {
|
if (HookOn !== undefined && !HEX_REGEX.test(HookOn)) {
|
||||||
throw new ValidationError(
|
throw new ValidationError(
|
||||||
`SetHook: HookOn in Hook must be a 256-bit (32-byte) hexadecimal value`,
|
`SetHook: HookOn in Hook must be a 256-bit (32-byte) hexadecimal value`,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
if (HookOnIncoming !== undefined && !HEX_REGEX.test(HookOnIncoming)) {
|
||||||
|
throw new ValidationError(
|
||||||
|
`SetHook: HookOnIncoming in Hook must be a 256-bit (32-byte) hexadecimal value`,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (HookOnOutgoing !== undefined && !HEX_REGEX.test(HookOnOutgoing)) {
|
||||||
|
throw new ValidationError(
|
||||||
|
`SetHook: HookOnOutgoing in Hook must be a 256-bit (32-byte) hexadecimal value`,
|
||||||
|
)
|
||||||
|
}
|
||||||
if (HookCanEmit !== undefined && !HEX_REGEX.test(HookCanEmit)) {
|
if (HookCanEmit !== undefined && !HEX_REGEX.test(HookCanEmit)) {
|
||||||
throw new ValidationError(
|
throw new ValidationError(
|
||||||
`SetHook: HookCanEmit in Hook must be a 256-bit (32-byte) hexadecimal value`,
|
`SetHook: HookCanEmit in Hook must be a 256-bit (32-byte) hexadecimal value`,
|
||||||
@@ -82,5 +79,10 @@ export function validateSetHook(tx: Record<string, unknown>): void {
|
|||||||
`SetHook: HookNamespace in Hook must be a 256-bit (32-byte) hexadecimal value`,
|
`SetHook: HookNamespace in Hook must be a 256-bit (32-byte) hexadecimal value`,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
if (HookName !== undefined && !HOOKNAME_REGEX.test(HookName)) {
|
||||||
|
throw new ValidationError(
|
||||||
|
`SetHook: HookName in Hook must be a hex string of 8-32 hex characters`,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ import { Invoke, validateInvoke } from './invoke'
|
|||||||
import { TransactionMetadata } from './metadata'
|
import { TransactionMetadata } from './metadata'
|
||||||
import { OfferCancel, validateOfferCancel } from './offerCancel'
|
import { OfferCancel, validateOfferCancel } from './offerCancel'
|
||||||
import { OfferCreate, validateOfferCreate } from './offerCreate'
|
import { OfferCreate, validateOfferCreate } from './offerCreate'
|
||||||
|
import { OracleDelete, validateOracleDelete } from './oracleDelete'
|
||||||
|
import { OracleSet, validateOracleSet } from './oracleSet'
|
||||||
import { Payment, validatePayment } from './payment'
|
import { Payment, validatePayment } from './payment'
|
||||||
import {
|
import {
|
||||||
PaymentChannelClaim,
|
PaymentChannelClaim,
|
||||||
@@ -79,6 +81,8 @@ export type SubmittableTransaction =
|
|||||||
| Invoke
|
| Invoke
|
||||||
| OfferCancel
|
| OfferCancel
|
||||||
| OfferCreate
|
| OfferCreate
|
||||||
|
| OracleDelete
|
||||||
|
| OracleSet
|
||||||
| Payment
|
| Payment
|
||||||
| PaymentChannelClaim
|
| PaymentChannelClaim
|
||||||
| PaymentChannelCreate
|
| PaymentChannelCreate
|
||||||
@@ -249,6 +253,14 @@ export function validate(transaction: Record<string, unknown>): void {
|
|||||||
validateOfferCreate(tx)
|
validateOfferCreate(tx)
|
||||||
break
|
break
|
||||||
|
|
||||||
|
case 'OracleDelete':
|
||||||
|
validateOracleDelete(tx)
|
||||||
|
break
|
||||||
|
|
||||||
|
case 'OracleSet':
|
||||||
|
validateOracleSet(tx)
|
||||||
|
break
|
||||||
|
|
||||||
case 'Payment':
|
case 'Payment':
|
||||||
validatePayment(tx)
|
validatePayment(tx)
|
||||||
break
|
break
|
||||||
@@ -315,6 +327,7 @@ export function validate(transaction: Record<string, unknown>): void {
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
throw new ValidationError(
|
throw new ValidationError(
|
||||||
|
// eslint-disable-next-line max-lines -- allowed here
|
||||||
`Invalid field TransactionType: ${tx.TransactionType}`,
|
`Invalid field TransactionType: ${tx.TransactionType}`,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,25 +1,22 @@
|
|||||||
/* eslint-disable no-param-reassign -- param reassign is safe */
|
/* eslint-disable no-param-reassign -- param reassign is safe */
|
||||||
/* eslint-disable no-bitwise -- flags require bitwise operations */
|
/* eslint-disable no-bitwise -- flags require bitwise operations */
|
||||||
import { ValidationError } from '../../errors'
|
import { ValidationError } from '../../errors'
|
||||||
import { Hook } from '../common/xahau'
|
import { Hook, HookFlags, MintURITokenFlags } from '../common/xahau'
|
||||||
import {
|
import {
|
||||||
AccountRootFlagsInterface,
|
AccountRootFlagsInterface,
|
||||||
AccountRootFlags,
|
AccountRootFlags,
|
||||||
} from '../ledger/AccountRoot'
|
} from '../ledger/AccountRoot'
|
||||||
import { AccountSetTfFlags } from '../transactions/accountSet'
|
import { AccountSetTfFlags } from '../transactions/accountSet'
|
||||||
|
import { ClaimRewardFlags } from '../transactions/claimReward'
|
||||||
import { GlobalFlags } from '../transactions/common'
|
import { GlobalFlags } from '../transactions/common'
|
||||||
import { CronSetFlags } from '../transactions/cronSet'
|
import { CronSetFlags } from '../transactions/cronSet'
|
||||||
import { OfferCreateFlags } from '../transactions/offerCreate'
|
import { OfferCreateFlags } from '../transactions/offerCreate'
|
||||||
import { PaymentFlags } from '../transactions/payment'
|
import { PaymentFlags } from '../transactions/payment'
|
||||||
import { PaymentChannelClaimFlags } from '../transactions/paymentChannelClaim'
|
import { PaymentChannelClaimFlags } from '../transactions/paymentChannelClaim'
|
||||||
import { SetHookFlagsInterface, SetHookFlags } from '../transactions/setHook'
|
import { RemarkFlags, Remark } from '../transactions/setRemarks'
|
||||||
import {
|
|
||||||
RemarkFlagsInterface,
|
|
||||||
RemarkFlags,
|
|
||||||
Remark,
|
|
||||||
} from '../transactions/setRemarks'
|
|
||||||
import type { Transaction } from '../transactions/transaction'
|
import type { Transaction } from '../transactions/transaction'
|
||||||
import { TrustSetFlags } from '../transactions/trustSet'
|
import { TrustSetFlags } from '../transactions/trustSet'
|
||||||
|
import { URITokenMintFlags } from '../transactions/uriTokenMint'
|
||||||
|
|
||||||
import { isFlagEnabled } from '.'
|
import { isFlagEnabled } from '.'
|
||||||
|
|
||||||
@@ -53,6 +50,8 @@ const txToFlag = {
|
|||||||
PaymentChannelClaim: PaymentChannelClaimFlags,
|
PaymentChannelClaim: PaymentChannelClaimFlags,
|
||||||
Payment: PaymentFlags,
|
Payment: PaymentFlags,
|
||||||
TrustSet: TrustSetFlags,
|
TrustSet: TrustSetFlags,
|
||||||
|
URITokenMint: URITokenMintFlags,
|
||||||
|
ClaimReward: ClaimRewardFlags,
|
||||||
CronSet: CronSetFlags,
|
CronSet: CronSetFlags,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,6 +61,36 @@ const txToFlag = {
|
|||||||
* @param tx - A transaction to set its flags to its numeric representation.
|
* @param tx - A transaction to set its flags to its numeric representation.
|
||||||
*/
|
*/
|
||||||
export function setTransactionFlagsToNumber(tx: Transaction): void {
|
export function setTransactionFlagsToNumber(tx: Transaction): void {
|
||||||
|
if (tx.TransactionType === 'SetHook' && Array.isArray(tx.Hooks)) {
|
||||||
|
tx.Hooks.forEach((hook: Hook) => {
|
||||||
|
if (typeof hook.Hook.Flags === 'object') {
|
||||||
|
hook.Hook.Flags = convertFlagsToNumber(hook.Hook.Flags, HookFlags)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tx.TransactionType === 'Remit') {
|
||||||
|
if (tx.MintURIToken != null && typeof tx.MintURIToken.Flags === 'object') {
|
||||||
|
tx.MintURIToken.Flags = convertFlagsToNumber(
|
||||||
|
tx.MintURIToken.Flags,
|
||||||
|
MintURITokenFlags,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tx.TransactionType === 'SetRemarks') {
|
||||||
|
if (Array.isArray(tx.Remarks)) {
|
||||||
|
tx.Remarks.forEach((remark: Remark) => {
|
||||||
|
if (typeof remark.Remark.Flags === 'object') {
|
||||||
|
remark.Remark.Flags = convertFlagsToNumber(
|
||||||
|
remark.Remark.Flags,
|
||||||
|
RemarkFlags,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (tx.Flags == null) {
|
if (tx.Flags == null) {
|
||||||
tx.Flags = 0
|
tx.Flags = 0
|
||||||
return
|
return
|
||||||
@@ -70,25 +99,6 @@ export function setTransactionFlagsToNumber(tx: Transaction): void {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tx.TransactionType === 'SetHook') {
|
|
||||||
tx.Flags = convertFlagsToNumber(tx.Flags, SetHookFlags)
|
|
||||||
tx.Hooks.forEach((hook: Hook) => {
|
|
||||||
hook.Hook.Flags = convertFlagsToNumber(
|
|
||||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- idk
|
|
||||||
hook.Hook.Flags as SetHookFlagsInterface,
|
|
||||||
SetHookFlags,
|
|
||||||
)
|
|
||||||
})
|
|
||||||
} else if (tx.TransactionType === 'SetRemarks') {
|
|
||||||
tx.Remarks.forEach((remark: Remark) => {
|
|
||||||
remark.Remark.Flags = convertFlagsToNumber(
|
|
||||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- idk
|
|
||||||
remark.Remark.Flags as RemarkFlagsInterface,
|
|
||||||
RemarkFlags,
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
tx.Flags = txToFlag[tx.TransactionType]
|
tx.Flags = txToFlag[tx.TransactionType]
|
||||||
? convertFlagsToNumber(tx.Flags, txToFlag[tx.TransactionType])
|
? convertFlagsToNumber(tx.Flags, txToFlag[tx.TransactionType])
|
||||||
: 0
|
: 0
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
import { decode, encode } from 'xahau-binary-codec'
|
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
Client,
|
Client,
|
||||||
SubmitRequest,
|
SubmitRequest,
|
||||||
@@ -12,6 +10,7 @@ import { ValidationError, XahlError } from '../errors'
|
|||||||
import { Signer } from '../models/common'
|
import { Signer } from '../models/common'
|
||||||
import { TxResponse } from '../models/methods'
|
import { TxResponse } from '../models/methods'
|
||||||
import { BaseTransaction } from '../models/transactions/common'
|
import { BaseTransaction } from '../models/transactions/common'
|
||||||
|
import { decode, encode } from '../utils'
|
||||||
|
|
||||||
/** Approximate time for a ledger to close, in milliseconds */
|
/** Approximate time for a ledger to close, in milliseconds */
|
||||||
const LEDGER_CLOSE_TIME = 1000
|
const LEDGER_CLOSE_TIME = 1000
|
||||||
@@ -52,7 +51,7 @@ export async function submitRequest(
|
|||||||
failHard = false,
|
failHard = false,
|
||||||
): Promise<SubmitResponse> {
|
): Promise<SubmitResponse> {
|
||||||
if (!isSigned(signedTransaction)) {
|
if (!isSigned(signedTransaction)) {
|
||||||
throw new ValidationError('Transaction must be signed')
|
throw new ValidationError('Transaction must be signed.')
|
||||||
}
|
}
|
||||||
|
|
||||||
const signedTxEncoded =
|
const signedTxEncoded =
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* XAH Ledger namespace prefixes.
|
* Xahau Network namespace prefixes.
|
||||||
*
|
*
|
||||||
* The XAH Ledger is a key-value store. In order to avoid name collisions,
|
* The Xahau Network is a key-value store. In order to avoid name collisions,
|
||||||
* names are partitioned into namespaces.
|
* names are partitioned into namespaces.
|
||||||
*
|
*
|
||||||
* Each namespace is just a single character prefix.
|
* Each namespace is just a single character prefix.
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
import { assert } from 'chai'
|
import { assert } from 'chai'
|
||||||
|
|
||||||
import { EscrowFinish, Payment, Transaction } from '../../src'
|
import { EscrowFinish, Payment, Transaction } from '../../src'
|
||||||
|
import { ValidationError } from '../../src/errors'
|
||||||
import xahaud from '../fixtures/xahaud'
|
import xahaud from '../fixtures/xahaud'
|
||||||
import {
|
import {
|
||||||
setupClient,
|
setupClient,
|
||||||
teardownClient,
|
teardownClient,
|
||||||
type XrplTestContext,
|
type XrplTestContext,
|
||||||
} from '../setupClient'
|
} from '../setupClient'
|
||||||
|
import { assertRejects } from '../testUtils'
|
||||||
|
|
||||||
const NetworkID = 1025
|
const NetworkID = 1025
|
||||||
const Fee = '10'
|
const Fee = '10'
|
||||||
@@ -15,6 +17,8 @@ const LastLedgerSequence = 2908734
|
|||||||
|
|
||||||
describe('client.autofill', function () {
|
describe('client.autofill', function () {
|
||||||
let testContext: XrplTestContext
|
let testContext: XrplTestContext
|
||||||
|
const AMOUNT = '1234'
|
||||||
|
let paymentTx: Payment
|
||||||
|
|
||||||
async function setupMockRippledVersionAndID(
|
async function setupMockRippledVersionAndID(
|
||||||
buildVersion: string,
|
buildVersion: string,
|
||||||
@@ -38,6 +42,64 @@ describe('client.autofill', function () {
|
|||||||
})
|
})
|
||||||
afterAll(async () => teardownClient(testContext))
|
afterAll(async () => teardownClient(testContext))
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
paymentTx = {
|
||||||
|
TransactionType: 'Payment',
|
||||||
|
Account: 'rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo',
|
||||||
|
Amount: AMOUNT,
|
||||||
|
Destination: 'rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy',
|
||||||
|
DestinationTag: 1,
|
||||||
|
Fee: '12',
|
||||||
|
Flags: 2147483648,
|
||||||
|
LastLedgerSequence: 65953073,
|
||||||
|
Sequence: 65923914,
|
||||||
|
SigningPubKey:
|
||||||
|
'02F9E33F16DF9507705EC954E3F94EB5F10D1FC4A354606DBE6297DBB1096FE654',
|
||||||
|
TxnSignature:
|
||||||
|
'3045022100E3FAE0EDEC3D6A8FF6D81BC9CF8288A61B7EEDE8071E90FF9314CB4621058D10022043545CF631706D700CEE65A1DB83EFDD185413808292D9D90F14D87D3DC2D8CB',
|
||||||
|
InvoiceID:
|
||||||
|
'6F1DFD1D0FE8A32E40E1F2C05CF1C15545BAB56B617F9C6C2D63A6B704BEF59B',
|
||||||
|
Paths: [
|
||||||
|
[{ currency: 'BTC', issuer: 'r9vbV3EHvXWjSkeQ6CAcYVPGeq7TuiXY2X' }],
|
||||||
|
],
|
||||||
|
SendMax: '100000000',
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Validate Payment transaction API v2: Payment Transaction: Specify Only Amount field', async function () {
|
||||||
|
const txResult = await testContext.client.autofill(paymentTx)
|
||||||
|
|
||||||
|
assert.strictEqual(txResult.Amount, AMOUNT)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Validate Payment transaction API v2: Payment Transaction: Specify Only DeliverMax field', async function () {
|
||||||
|
// @ts-expect-error -- DeliverMax is a non-protocol, RPC level field in Payment transactions
|
||||||
|
paymentTx.DeliverMax = paymentTx.Amount
|
||||||
|
// @ts-expect-error -- DeliverMax is a non-protocol, RPC level field in Payment transactions
|
||||||
|
delete paymentTx.Amount
|
||||||
|
const txResult = await testContext.client.autofill(paymentTx)
|
||||||
|
|
||||||
|
assert.strictEqual(txResult.Amount, AMOUNT)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Validate Payment transaction API v2: Payment Transaction: identical DeliverMax and Amount fields', async function () {
|
||||||
|
// @ts-expect-error -- DeliverMax is a non-protocol, RPC level field in Payment transactions
|
||||||
|
paymentTx.DeliverMax = paymentTx.Amount
|
||||||
|
|
||||||
|
const txResult = await testContext.client.autofill(paymentTx)
|
||||||
|
|
||||||
|
assert.strictEqual(txResult.Amount, AMOUNT)
|
||||||
|
assert.strictEqual('DeliverMax' in txResult, false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Validate Payment transaction API v2: Payment Transaction: differing DeliverMax and Amount fields', async function () {
|
||||||
|
// @ts-expect-error -- DeliverMax is a non-protocol, RPC level field in Payment transactions
|
||||||
|
paymentTx.DeliverMax = '6789'
|
||||||
|
paymentTx.Amount = '1234'
|
||||||
|
|
||||||
|
await assertRejects(testContext.client.autofill(paymentTx), ValidationError)
|
||||||
|
})
|
||||||
|
|
||||||
it('should not autofill if fields are present', async function () {
|
it('should not autofill if fields are present', async function () {
|
||||||
const tx: Transaction = {
|
const tx: Transaction = {
|
||||||
TransactionType: 'DepositPreauth',
|
TransactionType: 'DepositPreauth',
|
||||||
|
|||||||
@@ -0,0 +1,78 @@
|
|||||||
|
import { stringToHex } from '@xrplf/isomorphic/utils'
|
||||||
|
import { assert } from 'chai'
|
||||||
|
|
||||||
|
import { OracleSet } from '../../../src'
|
||||||
|
import serverUrl from '../serverUrl'
|
||||||
|
import {
|
||||||
|
setupClient,
|
||||||
|
teardownClient,
|
||||||
|
type XrplIntegrationTestContext,
|
||||||
|
} from '../setup'
|
||||||
|
import { testTransaction } from '../utils'
|
||||||
|
|
||||||
|
// how long before each test case times out
|
||||||
|
const TIMEOUT = 20000
|
||||||
|
|
||||||
|
describe('get_aggregate_price', function () {
|
||||||
|
let testContext: XrplIntegrationTestContext
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
testContext = await setupClient(serverUrl)
|
||||||
|
})
|
||||||
|
afterEach(async () => teardownClient(testContext))
|
||||||
|
|
||||||
|
it(
|
||||||
|
'base',
|
||||||
|
async () => {
|
||||||
|
const tx: OracleSet = {
|
||||||
|
TransactionType: 'OracleSet',
|
||||||
|
Account: testContext.wallet.classicAddress,
|
||||||
|
OracleDocumentID: 1234,
|
||||||
|
LastUpdateTime: Math.floor(Date.now() / 1000),
|
||||||
|
PriceDataSeries: [
|
||||||
|
{
|
||||||
|
PriceData: {
|
||||||
|
BaseAsset: 'XRP',
|
||||||
|
QuoteAsset: 'USD',
|
||||||
|
AssetPrice: 740,
|
||||||
|
Scale: 3,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
Provider: stringToHex('chainlink'),
|
||||||
|
URI: '6469645F6578616D706C65',
|
||||||
|
AssetClass: stringToHex('currency'),
|
||||||
|
}
|
||||||
|
|
||||||
|
await testTransaction(testContext.client, tx, testContext.wallet)
|
||||||
|
|
||||||
|
// confirm that the Oracle was actually created
|
||||||
|
const getAggregatePriceResponse = await testContext.client.request({
|
||||||
|
command: 'get_aggregate_price',
|
||||||
|
account: testContext.wallet.classicAddress,
|
||||||
|
base_asset: 'XRP',
|
||||||
|
quote_asset: 'USD',
|
||||||
|
trim: 20,
|
||||||
|
oracles: [
|
||||||
|
{
|
||||||
|
account: testContext.wallet.classicAddress,
|
||||||
|
oracle_document_id: 1234,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
assert.deepEqual(getAggregatePriceResponse.result.entire_set, {
|
||||||
|
mean: '0.74',
|
||||||
|
size: 1,
|
||||||
|
standard_deviation: '0',
|
||||||
|
})
|
||||||
|
assert.deepEqual(getAggregatePriceResponse.result.trimmed_set, {
|
||||||
|
mean: '0.74',
|
||||||
|
size: 1,
|
||||||
|
standard_deviation: '0',
|
||||||
|
})
|
||||||
|
assert.equal(getAggregatePriceResponse.result.median, '0.74')
|
||||||
|
assert.equal(getAggregatePriceResponse.result.time, tx.LastUpdateTime)
|
||||||
|
},
|
||||||
|
TIMEOUT,
|
||||||
|
)
|
||||||
|
})
|
||||||
@@ -128,6 +128,7 @@ describe('server_info (xahaud)', function () {
|
|||||||
'node_size',
|
'node_size',
|
||||||
'initial_sync_duration_us',
|
'initial_sync_duration_us',
|
||||||
'ports',
|
'ports',
|
||||||
|
'git',
|
||||||
]
|
]
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
omit(response.result.info, removeKeys),
|
omit(response.result.info, removeKeys),
|
||||||
|
|||||||
@@ -118,6 +118,7 @@ describe('server_state', function () {
|
|||||||
'node_size',
|
'node_size',
|
||||||
'initial_sync_duration_us',
|
'initial_sync_duration_us',
|
||||||
'ports',
|
'ports',
|
||||||
|
'git',
|
||||||
]
|
]
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
omit(response.result.state, removeKeys),
|
omit(response.result.state, removeKeys),
|
||||||
|
|||||||
85
packages/xahau/test/integration/requests/simulate.test.ts
Normal file
85
packages/xahau/test/integration/requests/simulate.test.ts
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
import { assert } from 'chai'
|
||||||
|
|
||||||
|
import { AccountSet, SimulateRequest } from '../../../src'
|
||||||
|
import { SimulateBinaryRequest } from '../../../src/models/methods/simulate'
|
||||||
|
import serverUrl from '../serverUrl'
|
||||||
|
import {
|
||||||
|
setupClient,
|
||||||
|
teardownClient,
|
||||||
|
type XrplIntegrationTestContext,
|
||||||
|
} from '../setup'
|
||||||
|
|
||||||
|
// how long before each test case times out
|
||||||
|
const TIMEOUT = 20000
|
||||||
|
|
||||||
|
describe('simulate', function () {
|
||||||
|
let testContext: XrplIntegrationTestContext
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
testContext = await setupClient(serverUrl)
|
||||||
|
})
|
||||||
|
afterEach(async () => teardownClient(testContext))
|
||||||
|
|
||||||
|
it(
|
||||||
|
'json',
|
||||||
|
async () => {
|
||||||
|
const simulateRequest: SimulateRequest = {
|
||||||
|
command: 'simulate',
|
||||||
|
tx_json: {
|
||||||
|
TransactionType: 'AccountSet',
|
||||||
|
Account: testContext.wallet.address,
|
||||||
|
NFTokenMinter: testContext.wallet.address,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
const simulateResponse = await testContext.client.request(simulateRequest)
|
||||||
|
|
||||||
|
assert.equal(simulateResponse.type, 'response')
|
||||||
|
assert.typeOf(simulateResponse.result.meta, 'object')
|
||||||
|
assert.typeOf(simulateResponse.result.tx_json, 'object')
|
||||||
|
assert.equal(simulateResponse.result.engine_result, 'tesSUCCESS')
|
||||||
|
assert.isFalse(simulateResponse.result.applied)
|
||||||
|
},
|
||||||
|
TIMEOUT,
|
||||||
|
)
|
||||||
|
|
||||||
|
it(
|
||||||
|
'binary',
|
||||||
|
async () => {
|
||||||
|
const simulateRequest: SimulateBinaryRequest = {
|
||||||
|
command: 'simulate',
|
||||||
|
tx_json: {
|
||||||
|
TransactionType: 'AccountSet',
|
||||||
|
Account: testContext.wallet.address,
|
||||||
|
},
|
||||||
|
binary: true,
|
||||||
|
}
|
||||||
|
const simulateResponse = await testContext.client.request(simulateRequest)
|
||||||
|
|
||||||
|
assert.equal(simulateResponse.type, 'response')
|
||||||
|
assert.typeOf(simulateResponse.result.meta_blob, 'string')
|
||||||
|
assert.typeOf(simulateResponse.result.tx_blob, 'string')
|
||||||
|
assert.equal(simulateResponse.result.engine_result, 'tesSUCCESS')
|
||||||
|
assert.isFalse(simulateResponse.result.applied)
|
||||||
|
},
|
||||||
|
TIMEOUT,
|
||||||
|
)
|
||||||
|
|
||||||
|
it(
|
||||||
|
'sugar',
|
||||||
|
async () => {
|
||||||
|
const tx: AccountSet = {
|
||||||
|
TransactionType: 'AccountSet',
|
||||||
|
Account: testContext.wallet.address,
|
||||||
|
NFTokenMinter: testContext.wallet.address,
|
||||||
|
}
|
||||||
|
const simulateResponse = await testContext.client.simulate(tx)
|
||||||
|
|
||||||
|
assert.equal(simulateResponse.type, 'response')
|
||||||
|
assert.typeOf(simulateResponse.result.meta, 'object')
|
||||||
|
assert.typeOf(simulateResponse.result.tx_json, 'object')
|
||||||
|
assert.equal(simulateResponse.result.engine_result, 'tesSUCCESS')
|
||||||
|
assert.isFalse(simulateResponse.result.applied)
|
||||||
|
},
|
||||||
|
TIMEOUT,
|
||||||
|
)
|
||||||
|
})
|
||||||
@@ -1,24 +1,66 @@
|
|||||||
import { assert } from 'chai'
|
import { assert } from 'chai'
|
||||||
|
|
||||||
import { ClaimReward, ClaimRewardFlags } from '../../../src'
|
import {
|
||||||
|
ClaimReward,
|
||||||
|
ClaimRewardFlags,
|
||||||
|
SetHook,
|
||||||
|
TrustSet,
|
||||||
|
Wallet,
|
||||||
|
} from '../../../src'
|
||||||
|
import { RippleState } from '../../../src/models/ledger'
|
||||||
import serverUrl from '../serverUrl'
|
import serverUrl from '../serverUrl'
|
||||||
import {
|
import {
|
||||||
setupClient,
|
setupClient,
|
||||||
teardownClient,
|
teardownClient,
|
||||||
type XrplIntegrationTestContext,
|
type XrplIntegrationTestContext,
|
||||||
} from '../setup'
|
} from '../setup'
|
||||||
import { testTransaction } from '../utils'
|
import { generateFundedWallet, testTransaction } from '../utils'
|
||||||
|
|
||||||
// how long before each test case times out
|
// how long before each test case times out
|
||||||
const TIMEOUT = 20000
|
const TIMEOUT = 20000
|
||||||
|
|
||||||
describe('ClaimReward', function () {
|
const acceptHook =
|
||||||
let testContext: XrplIntegrationTestContext
|
'0061736D0100000001130360027F7F017F60037F7F7E017E60017F017E02170203656E76025F67000003656E760661636365707400010302010205030100020621057F01418088040B7F004180080B7F004180080B7F00418088040B7F004180080B07080104686F6F6B00020A9D80000199800000410141011080808080001A4100410042001081808080000B'
|
||||||
|
|
||||||
beforeEach(async () => {
|
describe('XAH ClaimReward', function () {
|
||||||
|
let testContext: XrplIntegrationTestContext
|
||||||
|
let genesisWallet: Wallet
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
genesisWallet = new Wallet(
|
||||||
|
'0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020',
|
||||||
|
'001ACAAEDECE405B2A958212629E16F2EB46B153EEE94CDD350FDEFF52795525B7',
|
||||||
|
)
|
||||||
testContext = await setupClient(serverUrl)
|
testContext = await setupClient(serverUrl)
|
||||||
|
|
||||||
|
const setHookTx: SetHook = {
|
||||||
|
TransactionType: 'SetHook',
|
||||||
|
Account: genesisWallet.classicAddress,
|
||||||
|
Hooks: [
|
||||||
|
{
|
||||||
|
Hook: {
|
||||||
|
CreateCode: acceptHook,
|
||||||
|
HookApiVersion: 0,
|
||||||
|
HookOn: '00'.repeat(32),
|
||||||
|
HookNamespace: '00'.repeat(32),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
await testTransaction(testContext.client, setHookTx, genesisWallet)
|
||||||
|
})
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
// reset Hook
|
||||||
|
const setHookTx: SetHook = {
|
||||||
|
TransactionType: 'SetHook',
|
||||||
|
Account: genesisWallet.classicAddress,
|
||||||
|
Hooks: [{ Hook: { CreateCode: '', Flags: { hsfOverride: true } } }],
|
||||||
|
}
|
||||||
|
await testTransaction(testContext.client, setHookTx, genesisWallet)
|
||||||
|
|
||||||
|
await teardownClient(testContext)
|
||||||
})
|
})
|
||||||
afterEach(async () => teardownClient(testContext))
|
|
||||||
|
|
||||||
it(
|
it(
|
||||||
'opt in',
|
'opt in',
|
||||||
@@ -26,7 +68,7 @@ describe('ClaimReward', function () {
|
|||||||
const tx: ClaimReward = {
|
const tx: ClaimReward = {
|
||||||
TransactionType: 'ClaimReward',
|
TransactionType: 'ClaimReward',
|
||||||
Account: testContext.wallet.classicAddress,
|
Account: testContext.wallet.classicAddress,
|
||||||
Issuer: 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh',
|
Issuer: genesisWallet.address,
|
||||||
}
|
}
|
||||||
|
|
||||||
await testTransaction(testContext.client, tx, testContext.wallet)
|
await testTransaction(testContext.client, tx, testContext.wallet)
|
||||||
@@ -42,6 +84,7 @@ describe('ClaimReward', function () {
|
|||||||
},
|
},
|
||||||
TIMEOUT,
|
TIMEOUT,
|
||||||
)
|
)
|
||||||
|
|
||||||
it(
|
it(
|
||||||
'opt out',
|
'opt out',
|
||||||
async () => {
|
async () => {
|
||||||
@@ -67,3 +110,135 @@ describe('ClaimReward', function () {
|
|||||||
TIMEOUT,
|
TIMEOUT,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('IOU ClaimReward', function () {
|
||||||
|
let testContext: XrplIntegrationTestContext
|
||||||
|
let issuerWallet: Wallet
|
||||||
|
let hookWallet: Wallet
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
testContext = await setupClient(serverUrl)
|
||||||
|
|
||||||
|
issuerWallet = await generateFundedWallet(testContext.client)
|
||||||
|
hookWallet = await generateFundedWallet(testContext.client)
|
||||||
|
|
||||||
|
const setHookTx: SetHook = {
|
||||||
|
TransactionType: 'SetHook',
|
||||||
|
Account: hookWallet.classicAddress,
|
||||||
|
Hooks: [
|
||||||
|
{
|
||||||
|
Hook: {
|
||||||
|
CreateCode: acceptHook,
|
||||||
|
HookApiVersion: 0,
|
||||||
|
HookOn: '00'.repeat(32),
|
||||||
|
HookNamespace: '00'.repeat(32),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
await testTransaction(testContext.client, setHookTx, hookWallet)
|
||||||
|
|
||||||
|
const trustSetTx: TrustSet = {
|
||||||
|
TransactionType: 'TrustSet',
|
||||||
|
Account: testContext.wallet.classicAddress,
|
||||||
|
LimitAmount: {
|
||||||
|
currency: 'USD',
|
||||||
|
issuer: issuerWallet.address,
|
||||||
|
value: '10000000',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
await testTransaction(testContext.client, trustSetTx, testContext.wallet)
|
||||||
|
})
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
// reset Hook
|
||||||
|
const setHookTx: SetHook = {
|
||||||
|
TransactionType: 'SetHook',
|
||||||
|
Account: hookWallet.classicAddress,
|
||||||
|
Hooks: [{ Hook: { CreateCode: '', Flags: { hsfOverride: true } } }],
|
||||||
|
}
|
||||||
|
await testTransaction(testContext.client, setHookTx, hookWallet)
|
||||||
|
|
||||||
|
await teardownClient(testContext)
|
||||||
|
})
|
||||||
|
|
||||||
|
it(
|
||||||
|
'opt in',
|
||||||
|
async () => {
|
||||||
|
const tx: ClaimReward = {
|
||||||
|
TransactionType: 'ClaimReward',
|
||||||
|
Account: testContext.wallet.classicAddress,
|
||||||
|
Issuer: hookWallet.classicAddress,
|
||||||
|
ClaimCurrency: {
|
||||||
|
currency: 'USD',
|
||||||
|
issuer: issuerWallet.address,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
await testTransaction(testContext.client, tx, testContext.wallet)
|
||||||
|
|
||||||
|
const rippleStateResponse = await testContext.client.request({
|
||||||
|
command: 'ledger_entry',
|
||||||
|
ripple_state: {
|
||||||
|
currency: 'USD',
|
||||||
|
accounts: [
|
||||||
|
testContext.wallet.classicAddress,
|
||||||
|
issuerWallet.classicAddress,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
const node = rippleStateResponse.result.node as RippleState
|
||||||
|
assert.exists(node)
|
||||||
|
|
||||||
|
// Either LowReward or HighReward must exist
|
||||||
|
expect(Boolean(node.LowReward) || Boolean(node.HighReward))
|
||||||
|
|
||||||
|
if (node.LowReward) {
|
||||||
|
assert.exists(node.LowReward.TrustLineRewardAccumulator)
|
||||||
|
assert.exists(node.LowReward.RewardLgrFirst)
|
||||||
|
assert.exists(node.LowReward.RewardLgrLast)
|
||||||
|
assert.exists(node.LowReward.RewardTime)
|
||||||
|
}
|
||||||
|
if (node.HighReward) {
|
||||||
|
assert.exists(node.HighReward.TrustLineRewardAccumulator)
|
||||||
|
assert.exists(node.HighReward.RewardLgrFirst)
|
||||||
|
assert.exists(node.HighReward.RewardLgrLast)
|
||||||
|
assert.exists(node.HighReward.RewardTime)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
TIMEOUT,
|
||||||
|
)
|
||||||
|
|
||||||
|
it(
|
||||||
|
'opt out',
|
||||||
|
async () => {
|
||||||
|
const tx: ClaimReward = {
|
||||||
|
TransactionType: 'ClaimReward',
|
||||||
|
Account: testContext.wallet.classicAddress,
|
||||||
|
Flags: ClaimRewardFlags.tfOptOut,
|
||||||
|
ClaimCurrency: {
|
||||||
|
currency: 'USD',
|
||||||
|
issuer: issuerWallet.address,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
await testTransaction(testContext.client, tx, testContext.wallet)
|
||||||
|
|
||||||
|
const rippleStateResponse = await testContext.client.request({
|
||||||
|
command: 'ledger_entry',
|
||||||
|
ripple_state: {
|
||||||
|
currency: 'USD',
|
||||||
|
accounts: [
|
||||||
|
testContext.wallet.classicAddress,
|
||||||
|
issuerWallet.classicAddress,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
const node = rippleStateResponse.result.node as RippleState
|
||||||
|
assert.exists(node)
|
||||||
|
assert.notExists(node.LowReward)
|
||||||
|
assert.notExists(node.HighReward)
|
||||||
|
},
|
||||||
|
TIMEOUT,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
import { stringToHex } from '@xrplf/isomorphic/utils'
|
||||||
|
import { assert } from 'chai'
|
||||||
|
|
||||||
|
import { OracleSet, OracleDelete } from '../../../src'
|
||||||
|
import serverUrl from '../serverUrl'
|
||||||
|
import {
|
||||||
|
setupClient,
|
||||||
|
teardownClient,
|
||||||
|
type XrplIntegrationTestContext,
|
||||||
|
} from '../setup'
|
||||||
|
import { testTransaction } from '../utils'
|
||||||
|
|
||||||
|
// how long before each test case times out
|
||||||
|
const TIMEOUT = 20000
|
||||||
|
|
||||||
|
describe('OracleDelete', function () {
|
||||||
|
let testContext: XrplIntegrationTestContext
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
testContext = await setupClient(serverUrl)
|
||||||
|
})
|
||||||
|
afterEach(async () => teardownClient(testContext))
|
||||||
|
|
||||||
|
it(
|
||||||
|
'base',
|
||||||
|
async () => {
|
||||||
|
const setTx: OracleSet = {
|
||||||
|
TransactionType: 'OracleSet',
|
||||||
|
Account: testContext.wallet.classicAddress,
|
||||||
|
OracleDocumentID: 1234,
|
||||||
|
LastUpdateTime: Math.floor(Date.now() / 1000),
|
||||||
|
PriceDataSeries: [
|
||||||
|
{
|
||||||
|
PriceData: {
|
||||||
|
BaseAsset: 'XRP',
|
||||||
|
QuoteAsset: 'USD',
|
||||||
|
AssetPrice: 740,
|
||||||
|
Scale: 3,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
Provider: stringToHex('chainlink'),
|
||||||
|
URI: '6469645F6578616D706C65',
|
||||||
|
AssetClass: stringToHex('currency'),
|
||||||
|
}
|
||||||
|
|
||||||
|
await testTransaction(testContext.client, setTx, testContext.wallet)
|
||||||
|
|
||||||
|
const aoResult = await testContext.client.request({
|
||||||
|
command: 'account_objects',
|
||||||
|
account: testContext.wallet.classicAddress,
|
||||||
|
type: 'oracle',
|
||||||
|
})
|
||||||
|
|
||||||
|
// confirm that the Oracle was created
|
||||||
|
assert.equal(aoResult.result.account_objects.length, 1)
|
||||||
|
|
||||||
|
const deleteTx: OracleDelete = {
|
||||||
|
TransactionType: 'OracleDelete',
|
||||||
|
Account: testContext.wallet.classicAddress,
|
||||||
|
OracleDocumentID: 1234,
|
||||||
|
}
|
||||||
|
|
||||||
|
await testTransaction(testContext.client, deleteTx, testContext.wallet)
|
||||||
|
|
||||||
|
const aoResult2 = await testContext.client.request({
|
||||||
|
command: 'account_objects',
|
||||||
|
account: testContext.wallet.classicAddress,
|
||||||
|
})
|
||||||
|
|
||||||
|
// confirm that the Oracle was actually deleted
|
||||||
|
assert.equal(aoResult2.result.account_objects.length, 0)
|
||||||
|
},
|
||||||
|
TIMEOUT,
|
||||||
|
)
|
||||||
|
})
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
import { stringToHex } from '@xrplf/isomorphic/utils'
|
||||||
|
import { assert } from 'chai'
|
||||||
|
|
||||||
|
import { OracleSet } from '../../../src'
|
||||||
|
import { Oracle } from '../../../src/models/ledger'
|
||||||
|
import serverUrl from '../serverUrl'
|
||||||
|
import {
|
||||||
|
setupClient,
|
||||||
|
teardownClient,
|
||||||
|
type XrplIntegrationTestContext,
|
||||||
|
} from '../setup'
|
||||||
|
import { testTransaction } from '../utils'
|
||||||
|
|
||||||
|
// how long before each test case times out
|
||||||
|
const TIMEOUT = 20000
|
||||||
|
|
||||||
|
describe('OracleSet', function () {
|
||||||
|
let testContext: XrplIntegrationTestContext
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
testContext = await setupClient(serverUrl)
|
||||||
|
})
|
||||||
|
afterEach(async () => teardownClient(testContext))
|
||||||
|
|
||||||
|
it(
|
||||||
|
'base',
|
||||||
|
async () => {
|
||||||
|
const tx: OracleSet = {
|
||||||
|
TransactionType: 'OracleSet',
|
||||||
|
Account: testContext.wallet.classicAddress,
|
||||||
|
OracleDocumentID: 1234,
|
||||||
|
LastUpdateTime: Math.floor(Date.now() / 1000),
|
||||||
|
PriceDataSeries: [
|
||||||
|
{
|
||||||
|
PriceData: {
|
||||||
|
BaseAsset: 'XRP',
|
||||||
|
QuoteAsset: 'USD',
|
||||||
|
AssetPrice: 740,
|
||||||
|
Scale: 3,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PriceData: {
|
||||||
|
BaseAsset: 'XRP',
|
||||||
|
QuoteAsset: 'INR',
|
||||||
|
// Upper bound admissible value for AssetPrice field
|
||||||
|
// large numeric values necessarily have to use str type in Javascript
|
||||||
|
// number type uses double-precision floating point representation, hence represents a smaller range of values
|
||||||
|
AssetPrice: 'ffffffffffffffff',
|
||||||
|
Scale: 3,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
Provider: stringToHex('chainlink'),
|
||||||
|
URI: '6469645F6578616D706C65',
|
||||||
|
AssetClass: stringToHex('currency'),
|
||||||
|
}
|
||||||
|
|
||||||
|
await testTransaction(testContext.client, tx, testContext.wallet)
|
||||||
|
|
||||||
|
const result = await testContext.client.request({
|
||||||
|
command: 'account_objects',
|
||||||
|
account: testContext.wallet.classicAddress,
|
||||||
|
type: 'oracle',
|
||||||
|
})
|
||||||
|
|
||||||
|
// confirm that the Oracle was actually created
|
||||||
|
assert.equal(result.result.account_objects.length, 1)
|
||||||
|
|
||||||
|
// confirm details of Oracle ledger entry object
|
||||||
|
const oracle = result.result.account_objects[0] as Oracle
|
||||||
|
assert.equal(oracle.LastUpdateTime, tx.LastUpdateTime)
|
||||||
|
assert.equal(oracle.Owner, testContext.wallet.classicAddress)
|
||||||
|
assert.equal(oracle.AssetClass, tx.AssetClass)
|
||||||
|
assert.equal(oracle.Provider, tx.Provider)
|
||||||
|
assert.equal(oracle.PriceDataSeries.length, 2)
|
||||||
|
assert.equal(oracle.PriceDataSeries[1].PriceData.BaseAsset, 'XRP')
|
||||||
|
assert.equal(oracle.PriceDataSeries[1].PriceData.QuoteAsset, 'USD')
|
||||||
|
assert.equal(oracle.PriceDataSeries[1].PriceData.AssetPrice, '2e4')
|
||||||
|
assert.equal(oracle.PriceDataSeries[1].PriceData.Scale, 3)
|
||||||
|
assert.equal(oracle.Flags, 0)
|
||||||
|
|
||||||
|
// validate the serialization of large AssetPrice values
|
||||||
|
assert.equal(
|
||||||
|
oracle.PriceDataSeries[0].PriceData.AssetPrice,
|
||||||
|
'ffffffffffffffff',
|
||||||
|
)
|
||||||
|
},
|
||||||
|
TIMEOUT,
|
||||||
|
)
|
||||||
|
})
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { assert } from 'chai'
|
||||||
|
|
||||||
import { Payment, Wallet } from '../../../src'
|
import { Payment, Wallet } from '../../../src'
|
||||||
import serverUrl from '../serverUrl'
|
import serverUrl from '../serverUrl'
|
||||||
import {
|
import {
|
||||||
@@ -12,9 +14,22 @@ const TIMEOUT = 20000
|
|||||||
|
|
||||||
describe('Payment', function () {
|
describe('Payment', function () {
|
||||||
let testContext: XrplIntegrationTestContext
|
let testContext: XrplIntegrationTestContext
|
||||||
|
let paymentTx: Payment
|
||||||
|
const AMOUNT = '10000000'
|
||||||
// This wallet is used for DeliverMax related tests
|
// This wallet is used for DeliverMax related tests
|
||||||
let senderWallet: Wallet
|
let senderWallet: Wallet
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
// this payment transaction JSON needs to be refreshed before every test.
|
||||||
|
// Because, we tinker with Amount and DeliverMax fields in the API v2 tests
|
||||||
|
paymentTx = {
|
||||||
|
TransactionType: 'Payment',
|
||||||
|
Account: senderWallet.classicAddress,
|
||||||
|
Amount: AMOUNT,
|
||||||
|
Destination: 'rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy',
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
testContext = await setupClient(serverUrl)
|
testContext = await setupClient(serverUrl)
|
||||||
senderWallet = await generateFundedWallet(testContext.client)
|
senderWallet = await generateFundedWallet(testContext.client)
|
||||||
@@ -34,4 +49,57 @@ describe('Payment', function () {
|
|||||||
},
|
},
|
||||||
TIMEOUT,
|
TIMEOUT,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
it(
|
||||||
|
'Validate Payment transaction API v2: Payment Transaction: Specify Only Amount field',
|
||||||
|
async () => {
|
||||||
|
const result = await testTransaction(
|
||||||
|
testContext.client,
|
||||||
|
paymentTx,
|
||||||
|
senderWallet,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert.equal(result.result.engine_result_code, 0)
|
||||||
|
assert.equal((result.result.tx_json as Payment).Amount, AMOUNT)
|
||||||
|
},
|
||||||
|
TIMEOUT,
|
||||||
|
)
|
||||||
|
|
||||||
|
it(
|
||||||
|
'Validate Payment transaction API v2: Payment Transaction: Specify Only DeliverMax field',
|
||||||
|
async () => {
|
||||||
|
// @ts-expect-error -- DeliverMax is a non-protocol, RPC level field in Payment transactions
|
||||||
|
paymentTx.DeliverMax = paymentTx.Amount
|
||||||
|
// @ts-expect-error -- DeliverMax is a non-protocol, RPC level field in Payment transactions
|
||||||
|
delete paymentTx.Amount
|
||||||
|
|
||||||
|
const result = await testTransaction(
|
||||||
|
testContext.client,
|
||||||
|
paymentTx,
|
||||||
|
senderWallet,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert.equal(result.result.engine_result_code, 0)
|
||||||
|
assert.equal((result.result.tx_json as Payment).Amount, AMOUNT)
|
||||||
|
},
|
||||||
|
TIMEOUT,
|
||||||
|
)
|
||||||
|
|
||||||
|
it(
|
||||||
|
'Validate Payment transaction API v2: Payment Transaction: identical DeliverMax and Amount fields',
|
||||||
|
async () => {
|
||||||
|
// @ts-expect-error -- DeliverMax is a non-protocol, RPC level field in Payment transactions
|
||||||
|
paymentTx.DeliverMax = paymentTx.Amount
|
||||||
|
|
||||||
|
const result = await testTransaction(
|
||||||
|
testContext.client,
|
||||||
|
paymentTx,
|
||||||
|
senderWallet,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert.equal(result.result.engine_result_code, 0)
|
||||||
|
assert.equal((result.result.tx_json as Payment).Amount, AMOUNT)
|
||||||
|
},
|
||||||
|
TIMEOUT,
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { stringToHex } from '@xrplf/isomorphic/src/utils'
|
import { stringToHex } from '@xrplf/isomorphic/utils'
|
||||||
|
|
||||||
import { Remit } from '../../../src'
|
import { Remit } from '../../../src'
|
||||||
import serverUrl from '../serverUrl'
|
import serverUrl from '../serverUrl'
|
||||||
@@ -65,6 +65,9 @@ describe('Remit', function () {
|
|||||||
Destination: wallet2.classicAddress,
|
Destination: wallet2.classicAddress,
|
||||||
MintURIToken: {
|
MintURIToken: {
|
||||||
URI: stringToHex('https://example.com'),
|
URI: stringToHex('https://example.com'),
|
||||||
|
Flags: {
|
||||||
|
tfBurnable: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
138
packages/xahau/test/integration/transactions/setHook.test.ts
Normal file
138
packages/xahau/test/integration/transactions/setHook.test.ts
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
import { SetHook, Wallet } from '../../../src'
|
||||||
|
import { Hook, HookDefinition } from '../../../src/models/ledger'
|
||||||
|
import serverUrl from '../serverUrl'
|
||||||
|
import {
|
||||||
|
setupClient,
|
||||||
|
teardownClient,
|
||||||
|
type XrplIntegrationTestContext,
|
||||||
|
} from '../setup'
|
||||||
|
import { generateFundedWallet, testTransaction } from '../utils'
|
||||||
|
|
||||||
|
// how long before each test case times out
|
||||||
|
const TIMEOUT = 20000
|
||||||
|
const acceptHook =
|
||||||
|
'0061736D0100000001130360027F7F017F60037F7F7E017E60017F017E02170203656E76025F67000003656E760661636365707400010302010205030100020621057F01418088040B7F004180080B7F004180080B7F00418088040B7F004180080B07080104686F6F6B00020A9D80000199800000410141011080808080001A4100410042001081808080000B'
|
||||||
|
|
||||||
|
describe('SetHook', function () {
|
||||||
|
let testContext: XrplIntegrationTestContext
|
||||||
|
let wallet: Wallet
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
testContext = await setupClient(serverUrl)
|
||||||
|
wallet = await generateFundedWallet(testContext.client)
|
||||||
|
})
|
||||||
|
afterEach(async () => {
|
||||||
|
// reset Hook
|
||||||
|
const setHookTx: SetHook = {
|
||||||
|
TransactionType: 'SetHook',
|
||||||
|
Account: wallet.classicAddress,
|
||||||
|
Hooks: [{ Hook: { CreateCode: '', Flags: { hsfOverride: true } } }],
|
||||||
|
}
|
||||||
|
await testTransaction(testContext.client, setHookTx, wallet)
|
||||||
|
await teardownClient(testContext)
|
||||||
|
})
|
||||||
|
|
||||||
|
it(
|
||||||
|
'base',
|
||||||
|
async () => {
|
||||||
|
const setHookTx: SetHook = {
|
||||||
|
TransactionType: 'SetHook',
|
||||||
|
Account: wallet.classicAddress,
|
||||||
|
Hooks: [
|
||||||
|
{
|
||||||
|
Hook: {
|
||||||
|
CreateCode: acceptHook,
|
||||||
|
HookApiVersion: 0,
|
||||||
|
HookOn: '00'.repeat(32),
|
||||||
|
HookCanEmit: '00'.repeat(32),
|
||||||
|
HookName: '484F4F4B',
|
||||||
|
HookParameters: [
|
||||||
|
{
|
||||||
|
HookParameter: {
|
||||||
|
HookParameterName: 'DEADBEEF',
|
||||||
|
HookParameterValue: 'DEADBEEF',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
HookNamespace: '00'.repeat(32),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
await testTransaction(testContext.client, setHookTx, wallet)
|
||||||
|
|
||||||
|
const ledgerEntryResponse = await testContext.client.request({
|
||||||
|
command: 'ledger_entry',
|
||||||
|
hook: { account: wallet.classicAddress },
|
||||||
|
})
|
||||||
|
const node = ledgerEntryResponse.result.node as Hook
|
||||||
|
expect(node.Hooks.length).toEqual(1)
|
||||||
|
const hook = node.Hooks[0].Hook
|
||||||
|
expect(Object.keys(hook).length).toEqual(2)
|
||||||
|
expect(hook.HookHash).toBeDefined()
|
||||||
|
expect(hook.HookName).toBeDefined()
|
||||||
|
const hookHash = hook.HookHash!
|
||||||
|
|
||||||
|
const hookDefinitionResponse = await testContext.client.request({
|
||||||
|
command: 'ledger_entry',
|
||||||
|
hook_definition: hookHash,
|
||||||
|
})
|
||||||
|
const hookDefinitionNode = hookDefinitionResponse.result
|
||||||
|
.node as HookDefinition
|
||||||
|
expect(hookDefinitionNode.HookHash).toEqual(hookHash)
|
||||||
|
expect(hookDefinitionNode.CreateCode).toEqual(acceptHook)
|
||||||
|
expect(hookDefinitionNode.HookApiVersion).toEqual(0)
|
||||||
|
expect(hookDefinitionNode.HookOn).toEqual('00'.repeat(32))
|
||||||
|
expect(hookDefinitionNode.HookNamespace).toEqual('00'.repeat(32))
|
||||||
|
// @ts-expect-error - HookName is not defined in HookDefinition
|
||||||
|
expect(hookDefinitionNode.HookName).toBeUndefined()
|
||||||
|
expect(hookDefinitionNode.HookParameters?.length).toEqual(1)
|
||||||
|
const parameter = hookDefinitionNode.HookParameters![0].HookParameter
|
||||||
|
expect(parameter.HookParameterName).toEqual('DEADBEEF')
|
||||||
|
expect(parameter.HookParameterValue).toEqual('DEADBEEF')
|
||||||
|
},
|
||||||
|
TIMEOUT,
|
||||||
|
)
|
||||||
|
|
||||||
|
it(
|
||||||
|
'hook on incoming/outgoing',
|
||||||
|
async () => {
|
||||||
|
const setHookTx: SetHook = {
|
||||||
|
TransactionType: 'SetHook',
|
||||||
|
Account: wallet.classicAddress,
|
||||||
|
Hooks: [
|
||||||
|
{
|
||||||
|
Hook: {
|
||||||
|
CreateCode: acceptHook,
|
||||||
|
HookApiVersion: 0,
|
||||||
|
HookOnIncoming: '00'.repeat(32),
|
||||||
|
// eslint-disable-next-line no-inline-comments -- for readability
|
||||||
|
HookOnOutgoing: `01${'00'.repeat(31)}`, // should be different from HookOnIncoming
|
||||||
|
HookNamespace: '00'.repeat(32),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
await testTransaction(testContext.client, setHookTx, wallet)
|
||||||
|
|
||||||
|
const ledgerEntryResponse = await testContext.client.request({
|
||||||
|
command: 'ledger_entry',
|
||||||
|
hook: { account: wallet.classicAddress },
|
||||||
|
})
|
||||||
|
const node = ledgerEntryResponse.result.node as Hook
|
||||||
|
const hook = node.Hooks[0].Hook
|
||||||
|
const hookHash = hook.HookHash!
|
||||||
|
|
||||||
|
const hookDefinitionResponse = await testContext.client.request({
|
||||||
|
command: 'ledger_entry',
|
||||||
|
hook_definition: hookHash,
|
||||||
|
})
|
||||||
|
const hookDefinitionNode = hookDefinitionResponse.result
|
||||||
|
.node as HookDefinition
|
||||||
|
expect(hookDefinitionNode.HookOn).toBeUndefined()
|
||||||
|
expect(hookDefinitionNode.HookOnIncoming).toBeDefined()
|
||||||
|
expect(hookDefinitionNode.HookOnOutgoing).toBeDefined()
|
||||||
|
},
|
||||||
|
TIMEOUT,
|
||||||
|
)
|
||||||
|
})
|
||||||
@@ -13,6 +13,8 @@ import {
|
|||||||
ECDSA,
|
ECDSA,
|
||||||
AccountLinesRequest,
|
AccountLinesRequest,
|
||||||
IssuedCurrency,
|
IssuedCurrency,
|
||||||
|
XAHAUD_API_V2,
|
||||||
|
TxResponse,
|
||||||
} from '../../src'
|
} from '../../src'
|
||||||
import {
|
import {
|
||||||
Payment,
|
Payment,
|
||||||
@@ -184,20 +186,22 @@ export async function verifySubmittedTransaction(
|
|||||||
hashTx?: string,
|
hashTx?: string,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const hash = hashTx ?? hashSignedTx(tx)
|
const hash = hashTx ?? hashSignedTx(tx)
|
||||||
const data = await client.request({
|
const data: TxResponse = await client.request({
|
||||||
command: 'tx',
|
command: 'tx',
|
||||||
transaction: hash,
|
transaction: hash,
|
||||||
|
// The current default version is v1, but we'll be using v2 for this test.
|
||||||
|
api_version: XAHAUD_API_V2,
|
||||||
})
|
})
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO: handle this API change for 2.0.0
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO: handle this API change for 2.0.0
|
||||||
const decodedTx: any = typeof tx === 'string' ? decode(tx) : tx
|
const decodedTx: any = typeof tx === 'string' ? decode(tx) : tx
|
||||||
if (decodedTx.TransactionType === 'Payment' && client.apiVersion !== 1) {
|
if (decodedTx.TransactionType === 'Payment') {
|
||||||
decodedTx.DeliverMax = decodedTx.Amount
|
decodedTx.DeliverMax = decodedTx.Amount
|
||||||
delete decodedTx.Amount
|
delete decodedTx.Amount
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(data.result)
|
assert(data.result)
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
omit(data.result, [
|
omit(data.result.tx_json, [
|
||||||
'ctid',
|
'ctid',
|
||||||
'date',
|
'date',
|
||||||
'hash',
|
'hash',
|
||||||
|
|||||||
@@ -182,12 +182,24 @@ describe('AccountSet', function () {
|
|||||||
assert.throws(
|
assert.throws(
|
||||||
() => validateAccountSet(account),
|
() => validateAccountSet(account),
|
||||||
ValidationError,
|
ValidationError,
|
||||||
'AccountSet: HookStateScale must be less than 16',
|
'AccountSet: HookStateScale must be less than or equal to 16',
|
||||||
)
|
)
|
||||||
assert.throws(
|
assert.throws(
|
||||||
() => validate(account),
|
() => validate(account),
|
||||||
ValidationError,
|
ValidationError,
|
||||||
'AccountSet: HookStateScale must be less than 16',
|
'AccountSet: HookStateScale must be less than or equal to 16',
|
||||||
|
)
|
||||||
|
|
||||||
|
account.HookStateScale = 0
|
||||||
|
assert.throws(
|
||||||
|
() => validateAccountSet(account),
|
||||||
|
ValidationError,
|
||||||
|
'AccountSet: HookStateScale must be greater than or equal to 1',
|
||||||
|
)
|
||||||
|
assert.throws(
|
||||||
|
() => validate(account),
|
||||||
|
ValidationError,
|
||||||
|
'AccountSet: HookStateScale must be greater than or equal to 1',
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
40
packages/xahau/test/models/oracleDelete.test.ts
Normal file
40
packages/xahau/test/models/oracleDelete.test.ts
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import { assert } from 'chai'
|
||||||
|
|
||||||
|
import { validate, ValidationError } from '../../src'
|
||||||
|
import { validateOracleDelete } from '../../src/models/transactions/oracleDelete'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OracleDelete Transaction Verification Testing.
|
||||||
|
*
|
||||||
|
* Providing runtime verification testing for each specific transaction type.
|
||||||
|
*/
|
||||||
|
describe('OracleDelete', function () {
|
||||||
|
let tx
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
tx = {
|
||||||
|
TransactionType: 'OracleDelete',
|
||||||
|
Account: 'rfmDuhDyLGgx94qiwf3YF8BUV5j6KSvE8',
|
||||||
|
OracleDocumentID: 1234,
|
||||||
|
} as any
|
||||||
|
})
|
||||||
|
|
||||||
|
it('verifies valid OracleDelete', function () {
|
||||||
|
assert.doesNotThrow(() => validateOracleDelete(tx))
|
||||||
|
assert.doesNotThrow(() => validate(tx))
|
||||||
|
})
|
||||||
|
|
||||||
|
it(`throws w/ missing field OracleDocumentID`, function () {
|
||||||
|
delete tx.OracleDocumentID
|
||||||
|
const errorMessage = 'OracleDelete: missing field OracleDocumentID'
|
||||||
|
assert.throws(() => validateOracleDelete(tx), ValidationError, errorMessage)
|
||||||
|
assert.throws(() => validate(tx), ValidationError, errorMessage)
|
||||||
|
})
|
||||||
|
|
||||||
|
it(`throws w/ invalid OracleDocumentID`, function () {
|
||||||
|
tx.OracleDocumentID = '1234'
|
||||||
|
const errorMessage = 'OracleDelete: invalid field OracleDocumentID'
|
||||||
|
assert.throws(() => validateOracleDelete(tx), ValidationError, errorMessage)
|
||||||
|
assert.throws(() => validate(tx), ValidationError, errorMessage)
|
||||||
|
})
|
||||||
|
})
|
||||||
212
packages/xahau/test/models/oracleSet.test.ts
Normal file
212
packages/xahau/test/models/oracleSet.test.ts
Normal file
@@ -0,0 +1,212 @@
|
|||||||
|
import { stringToHex } from '@xrplf/isomorphic/dist/utils'
|
||||||
|
import { assert } from 'chai'
|
||||||
|
|
||||||
|
import { validate, ValidationError } from '../../src'
|
||||||
|
import { validateOracleSet } from '../../src/models/transactions/oracleSet'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OracleSet Transaction Verification Testing.
|
||||||
|
*
|
||||||
|
* Providing runtime verification testing for each specific transaction type.
|
||||||
|
*/
|
||||||
|
describe('OracleSet', function () {
|
||||||
|
let tx
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
tx = {
|
||||||
|
TransactionType: 'OracleSet',
|
||||||
|
Account: 'rfmDuhDyLGgx94qiwf3YF8BUV5j6KSvE8',
|
||||||
|
OracleDocumentID: 1234,
|
||||||
|
LastUpdateTime: 768062172,
|
||||||
|
PriceDataSeries: [
|
||||||
|
{
|
||||||
|
PriceData: {
|
||||||
|
BaseAsset: 'XRP',
|
||||||
|
QuoteAsset: 'USD',
|
||||||
|
AssetPrice: 740,
|
||||||
|
Scale: 3,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
Provider: stringToHex('chainlink'),
|
||||||
|
URI: '6469645F6578616D706C65',
|
||||||
|
AssetClass: stringToHex('currency'),
|
||||||
|
} as any
|
||||||
|
})
|
||||||
|
|
||||||
|
it('verifies valid OracleSet', function () {
|
||||||
|
assert.doesNotThrow(() => validateOracleSet(tx))
|
||||||
|
assert.doesNotThrow(() => validate(tx))
|
||||||
|
})
|
||||||
|
|
||||||
|
it(`throws w/ missing field OracleDocumentID`, function () {
|
||||||
|
delete tx.OracleDocumentID
|
||||||
|
const errorMessage = 'OracleSet: missing field OracleDocumentID'
|
||||||
|
assert.throws(() => validateOracleSet(tx), ValidationError, errorMessage)
|
||||||
|
assert.throws(() => validate(tx), ValidationError, errorMessage)
|
||||||
|
})
|
||||||
|
|
||||||
|
it(`throws w/ invalid OracleDocumentID`, function () {
|
||||||
|
tx.OracleDocumentID = '1234'
|
||||||
|
const errorMessage = 'OracleSet: invalid field OracleDocumentID'
|
||||||
|
assert.throws(() => validateOracleSet(tx), ValidationError, errorMessage)
|
||||||
|
assert.throws(() => validate(tx), ValidationError, errorMessage)
|
||||||
|
})
|
||||||
|
|
||||||
|
it(`throws w/ missing field LastUpdateTime`, function () {
|
||||||
|
delete tx.LastUpdateTime
|
||||||
|
const errorMessage = 'OracleSet: missing field LastUpdateTime'
|
||||||
|
assert.throws(() => validateOracleSet(tx), ValidationError, errorMessage)
|
||||||
|
assert.throws(() => validate(tx), ValidationError, errorMessage)
|
||||||
|
})
|
||||||
|
|
||||||
|
it(`throws w/ invalid LastUpdateTime`, function () {
|
||||||
|
tx.LastUpdateTime = '768062172'
|
||||||
|
const errorMessage = 'OracleSet: invalid field LastUpdateTime'
|
||||||
|
assert.throws(() => validateOracleSet(tx), ValidationError, errorMessage)
|
||||||
|
assert.throws(() => validate(tx), ValidationError, errorMessage)
|
||||||
|
})
|
||||||
|
|
||||||
|
it(`throws w/ missing invalid Provider`, function () {
|
||||||
|
tx.Provider = 1234
|
||||||
|
const errorMessage = 'OracleSet: invalid field Provider'
|
||||||
|
assert.throws(() => validateOracleSet(tx), ValidationError, errorMessage)
|
||||||
|
assert.throws(() => validate(tx), ValidationError, errorMessage)
|
||||||
|
})
|
||||||
|
|
||||||
|
it(`throws w/ missing invalid URI`, function () {
|
||||||
|
tx.URI = 1234
|
||||||
|
const errorMessage = 'OracleSet: invalid field URI'
|
||||||
|
assert.throws(() => validateOracleSet(tx), ValidationError, errorMessage)
|
||||||
|
assert.throws(() => validate(tx), ValidationError, errorMessage)
|
||||||
|
})
|
||||||
|
|
||||||
|
it(`throws w/ missing invalid AssetClass`, function () {
|
||||||
|
tx.AssetClass = 1234
|
||||||
|
const errorMessage = 'OracleSet: invalid field AssetClass'
|
||||||
|
assert.throws(() => validateOracleSet(tx), ValidationError, errorMessage)
|
||||||
|
assert.throws(() => validate(tx), ValidationError, errorMessage)
|
||||||
|
})
|
||||||
|
|
||||||
|
it(`throws w/ invalid PriceDataSeries must be an array`, function () {
|
||||||
|
tx.PriceDataSeries = 1234
|
||||||
|
const errorMessage = 'OracleSet: PriceDataSeries must be an array'
|
||||||
|
assert.throws(() => validateOracleSet(tx), ValidationError, errorMessage)
|
||||||
|
assert.throws(() => validate(tx), ValidationError, errorMessage)
|
||||||
|
})
|
||||||
|
|
||||||
|
it(`throws w/ invalid PriceDataSeries must be an array of objects`, function () {
|
||||||
|
tx.PriceDataSeries = [1234]
|
||||||
|
const errorMessage =
|
||||||
|
'OracleSet: PriceDataSeries must be an array of objects'
|
||||||
|
assert.throws(() => validateOracleSet(tx), ValidationError, errorMessage)
|
||||||
|
assert.throws(() => validate(tx), ValidationError, errorMessage)
|
||||||
|
})
|
||||||
|
|
||||||
|
it(`throws w/ PriceDataSeries must have at most 10 PriceData objects`, function () {
|
||||||
|
tx.PriceDataSeries = new Array(11).fill({
|
||||||
|
PriceData: {
|
||||||
|
BaseAsset: 'XRP',
|
||||||
|
QuoteAsset: 'USD',
|
||||||
|
AssetPrice: 740,
|
||||||
|
Scale: 3,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
const errorMessage =
|
||||||
|
'OracleSet: PriceDataSeries must have at most 10 PriceData objects'
|
||||||
|
assert.throws(() => validateOracleSet(tx), ValidationError, errorMessage)
|
||||||
|
assert.throws(() => validate(tx), ValidationError, errorMessage)
|
||||||
|
})
|
||||||
|
|
||||||
|
it(`throws w/ PriceDataSeries must have a PriceData object`, function () {
|
||||||
|
delete tx.PriceDataSeries[0].PriceData
|
||||||
|
const errorMessage =
|
||||||
|
'OracleSet: PriceDataSeries must have a `PriceData` object'
|
||||||
|
assert.throws(() => validateOracleSet(tx), ValidationError, errorMessage)
|
||||||
|
assert.throws(() => validate(tx), ValidationError, errorMessage)
|
||||||
|
})
|
||||||
|
|
||||||
|
it(`throws w/ PriceDataSeries must only have a single PriceData object`, function () {
|
||||||
|
tx.PriceDataSeries[0].ExtraProp = 'extraprop'
|
||||||
|
const errorMessage =
|
||||||
|
'OracleSet: PriceDataSeries must only have a single PriceData object'
|
||||||
|
assert.throws(() => validateOracleSet(tx), ValidationError, errorMessage)
|
||||||
|
assert.throws(() => validate(tx), ValidationError, errorMessage)
|
||||||
|
})
|
||||||
|
|
||||||
|
it(`throws w/ missing BaseAsset of PriceDataSeries`, function () {
|
||||||
|
delete tx.PriceDataSeries[0].PriceData.BaseAsset
|
||||||
|
const errorMessage =
|
||||||
|
'OracleSet: PriceDataSeries must have a `BaseAsset` string'
|
||||||
|
assert.throws(() => validateOracleSet(tx), ValidationError, errorMessage)
|
||||||
|
assert.throws(() => validate(tx), ValidationError, errorMessage)
|
||||||
|
})
|
||||||
|
|
||||||
|
it(`throws w/ missing QuoteAsset of PriceDataSeries`, function () {
|
||||||
|
delete tx.PriceDataSeries[0].PriceData.QuoteAsset
|
||||||
|
const errorMessage =
|
||||||
|
'OracleSet: PriceDataSeries must have a `QuoteAsset` string'
|
||||||
|
assert.throws(() => validateOracleSet(tx), ValidationError, errorMessage)
|
||||||
|
assert.throws(() => validate(tx), ValidationError, errorMessage)
|
||||||
|
})
|
||||||
|
|
||||||
|
it(`throws w/ missing AssetPrice with Scale present of PriceDataSeries`, function () {
|
||||||
|
delete tx.PriceDataSeries[0].PriceData.AssetPrice
|
||||||
|
const errorMessage =
|
||||||
|
'OracleSet: PriceDataSeries must have both `AssetPrice` and `Scale` if any are present'
|
||||||
|
assert.throws(() => validateOracleSet(tx), ValidationError, errorMessage)
|
||||||
|
assert.throws(() => validate(tx), ValidationError, errorMessage)
|
||||||
|
})
|
||||||
|
|
||||||
|
it(`throws w/ missing Scale with AssetPrice present of PriceDataSeries`, function () {
|
||||||
|
delete tx.PriceDataSeries[0].PriceData.Scale
|
||||||
|
const errorMessage =
|
||||||
|
'OracleSet: PriceDataSeries must have both `AssetPrice` and `Scale` if any are present'
|
||||||
|
assert.throws(() => validateOracleSet(tx), ValidationError, errorMessage)
|
||||||
|
assert.throws(() => validate(tx), ValidationError, errorMessage)
|
||||||
|
})
|
||||||
|
|
||||||
|
it(`throws w/ invalid AssetPrice of PriceDataSeries`, function () {
|
||||||
|
// value cannot be parsed as hexadecimal number
|
||||||
|
tx.PriceDataSeries[0].PriceData.AssetPrice = 'ghij'
|
||||||
|
const errorMessage =
|
||||||
|
'OracleSet: Field AssetPrice must be a valid hex string'
|
||||||
|
assert.throws(() => validateOracleSet(tx), ValidationError, errorMessage)
|
||||||
|
assert.throws(() => validate(tx), ValidationError, errorMessage)
|
||||||
|
})
|
||||||
|
|
||||||
|
it(`verifies valid AssetPrice of PriceDataSeries`, function () {
|
||||||
|
// valid string which can be parsed as hexadecimal number
|
||||||
|
tx.PriceDataSeries[0].PriceData.AssetPrice = 'ab15'
|
||||||
|
assert.doesNotThrow(() => validate(tx))
|
||||||
|
})
|
||||||
|
|
||||||
|
it(`throws w/ invalid AssetPrice type in PriceDataSeries`, function () {
|
||||||
|
tx.PriceDataSeries[0].PriceData.AssetPrice = ['sample', 'invalid', 'type']
|
||||||
|
const errorMessage =
|
||||||
|
'OracleSet: Field AssetPrice must be a string or a number'
|
||||||
|
assert.throws(() => validateOracleSet(tx), ValidationError, errorMessage)
|
||||||
|
assert.throws(() => validate(tx), ValidationError, errorMessage)
|
||||||
|
})
|
||||||
|
|
||||||
|
it(`throws w/ invalid Scale of PriceDataSeries`, function () {
|
||||||
|
tx.PriceDataSeries[0].PriceData.Scale = '1234'
|
||||||
|
const errorMessage = 'OracleSet: invalid field Scale'
|
||||||
|
assert.throws(() => validateOracleSet(tx), ValidationError, errorMessage)
|
||||||
|
assert.throws(() => validate(tx), ValidationError, errorMessage)
|
||||||
|
})
|
||||||
|
|
||||||
|
it(`throws w/ Scale must be in range 0-10 when above max`, function () {
|
||||||
|
tx.PriceDataSeries[0].PriceData.Scale = 11
|
||||||
|
const errorMessage = 'OracleSet: Scale must be in range 0-10'
|
||||||
|
assert.throws(() => validateOracleSet(tx), ValidationError, errorMessage)
|
||||||
|
assert.throws(() => validate(tx), ValidationError, errorMessage)
|
||||||
|
})
|
||||||
|
|
||||||
|
it(`throws w/ Scale must be in range 0-10 when below min`, function () {
|
||||||
|
tx.PriceDataSeries[0].PriceData.Scale = -1
|
||||||
|
const errorMessage = 'OracleSet: Scale must be in range 0-10'
|
||||||
|
assert.throws(() => validateOracleSet(tx), ValidationError, errorMessage)
|
||||||
|
assert.throws(() => validate(tx), ValidationError, errorMessage)
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -24,12 +24,15 @@ describe('SetHook', function () {
|
|||||||
'0061736D01000000011C0460057F7F7F7F7F017E60037F7F7E017E60027F7F017F60017F017E02230303656E76057472616365000003656E7606616363657074000103656E76025F670002030201030503010002062B077F0141B088040B7F004180080B7F0041A6080B7F004180080B7F0041B088040B7F0041000B7F0041010B07080104686F6F6B00030AC4800001C0800001017F230041106B220124002001200036020C41920841134180084112410010001A410022002000420010011A41012200200010021A200141106A240042000B0B2C01004180080B254163636570742E633A2043616C6C65642E00224163636570742E633A2043616C6C65642E22',
|
'0061736D01000000011C0460057F7F7F7F7F017E60037F7F7E017E60027F7F017F60017F017E02230303656E76057472616365000003656E7606616363657074000103656E76025F670002030201030503010002062B077F0141B088040B7F004180080B7F0041A6080B7F004180080B7F0041B088040B7F0041000B7F0041010B07080104686F6F6B00030AC4800001C0800001017F230041106B220124002001200036020C41920841134180084112410010001A410022002000420010011A41012200200010021A200141106A240042000B0B2C01004180080B254163636570742E633A2043616C6C65642E00224163636570742E633A2043616C6C65642E22',
|
||||||
HookOn:
|
HookOn:
|
||||||
'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFFF7',
|
'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFFF7',
|
||||||
|
Flags: {
|
||||||
|
hsfOverride: true,
|
||||||
|
},
|
||||||
HookCanEmit:
|
HookCanEmit:
|
||||||
'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFFF7',
|
'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFFF7',
|
||||||
Flags: 1,
|
|
||||||
HookApiVersion: 0,
|
HookApiVersion: 0,
|
||||||
HookNamespace:
|
HookNamespace:
|
||||||
'4FF9961269BF7630D32E15276569C94470174A5DA79FA567C0F62251AA9A36B9',
|
'4FF9961269BF7630D32E15276569C94470174A5DA79FA567C0F62251AA9A36B9',
|
||||||
|
HookName: 'DEADBEEF',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -64,6 +67,10 @@ describe('SetHook', function () {
|
|||||||
'0061736D01000000011C0460057F7F7F7F7F017E60037F7F7E017E60027F7F017F60017F017E02230303656E76057472616365000003656E7606616363657074000103656E76025F670002030201030503010002062B077F0141B088040B7F004180080B7F0041A6080B7F004180080B7F0041B088040B7F0041000B7F0041010B07080104686F6F6B00030AC4800001C0800001017F230041106B220124002001200036020C41920841134180084112410010001A410022002000420010011A41012200200010021A200141106A240042000B0B2C01004180080B254163636570742E633A2043616C6C65642E00224163636570742E633A2043616C6C65642E22',
|
'0061736D01000000011C0460057F7F7F7F7F017E60037F7F7E017E60027F7F017F60017F017E02230303656E76057472616365000003656E7606616363657074000103656E76025F670002030201030503010002062B077F0141B088040B7F004180080B7F0041A6080B7F004180080B7F0041B088040B7F0041000B7F0041010B07080104686F6F6B00030AC4800001C0800001017F230041106B220124002001200036020C41920841134180084112410010001A410022002000420010011A41012200200010021A200141106A240042000B0B2C01004180080B254163636570742E633A2043616C6C65642E00224163636570742E633A2043616C6C65642E22',
|
||||||
HookOn:
|
HookOn:
|
||||||
'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFFF7',
|
'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFFF7',
|
||||||
|
HookOnIncoming:
|
||||||
|
'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFFF7',
|
||||||
|
HookOnOutgoing:
|
||||||
|
'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFFF7',
|
||||||
Flags: 1,
|
Flags: 1,
|
||||||
HookApiVersion: 0,
|
HookApiVersion: 0,
|
||||||
HookNamespace:
|
HookNamespace:
|
||||||
@@ -91,30 +98,31 @@ describe('SetHook', function () {
|
|||||||
assert.throws(() => validate(setHookTx), ValidationError, errorMessage)
|
assert.throws(() => validate(setHookTx), ValidationError, errorMessage)
|
||||||
})
|
})
|
||||||
|
|
||||||
it(`throws w/ invalid HookOn in Hooks`, function () {
|
it.each(['HookOn', 'HookOnIncoming', 'HookOnOutgoing'])(
|
||||||
setHookTx.SignerQuorum = 2
|
`throws w/ invalid %s in Hooks`,
|
||||||
setHookTx.Hooks = [
|
function (field: string) {
|
||||||
{
|
setHookTx.Hooks = [
|
||||||
Hook: {
|
{
|
||||||
CreateCode:
|
Hook: {
|
||||||
'0061736D01000000011C0460057F7F7F7F7F017E60037F7F7E017E60027F7F017F60017F017E02230303656E76057472616365000003656E7606616363657074000103656E76025F670002030201030503010002062B077F0141B088040B7F004180080B7F0041A6080B7F004180080B7F0041B088040B7F0041000B7F0041010B07080104686F6F6B00030AC4800001C0800001017F230041106B220124002001200036020C41920841134180084112410010001A410022002000420010011A41012200200010021A200141106A240042000B0B2C01004180080B254163636570742E633A2043616C6C65642E00224163636570742E633A2043616C6C65642E22',
|
CreateCode:
|
||||||
HookOn: '',
|
'0061736D01000000011C0460057F7F7F7F7F017E60037F7F7E017E60027F7F017F60017F017E02230303656E76057472616365000003656E7606616363657074000103656E76025F670002030201030503010002062B077F0141B088040B7F004180080B7F0041A6080B7F004180080B7F0041B088040B7F0041000B7F0041010B07080104686F6F6B00030AC4800001C0800001017F230041106B220124002001200036020C41920841134180084112410010001A410022002000420010011A41012200200010021A200141106A240042000B0B2C01004180080B254163636570742E633A2043616C6C65642E00224163636570742E633A2043616C6C65642E22',
|
||||||
Flags: 1,
|
[field]: '',
|
||||||
HookApiVersion: 0,
|
Flags: 1,
|
||||||
HookNamespace:
|
HookApiVersion: 0,
|
||||||
'4FF9961269BF7630D32E15276569C94470174A5DA79FA567C0F62251AA9A36B9',
|
HookNamespace:
|
||||||
|
'4FF9961269BF7630D32E15276569C94470174A5DA79FA567C0F62251AA9A36B9',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
]
|
||||||
]
|
const errorMessage = `SetHook: ${field} in Hook must be a 256-bit (32-byte) hexadecimal value`
|
||||||
const errorMessage =
|
assert.throws(
|
||||||
'SetHook: HookOn in Hook must be a 256-bit (32-byte) hexadecimal value'
|
() => validateSetHook(setHookTx),
|
||||||
assert.throws(
|
ValidationError,
|
||||||
() => validateSetHook(setHookTx),
|
errorMessage,
|
||||||
ValidationError,
|
)
|
||||||
errorMessage,
|
assert.throws(() => validate(setHookTx), ValidationError, errorMessage)
|
||||||
)
|
},
|
||||||
assert.throws(() => validate(setHookTx), ValidationError, errorMessage)
|
)
|
||||||
})
|
|
||||||
|
|
||||||
it(`throws w/ invalid HookCanEmit in Hooks`, function () {
|
it(`throws w/ invalid HookCanEmit in Hooks`, function () {
|
||||||
setHookTx.Hooks = [
|
setHookTx.Hooks = [
|
||||||
@@ -166,4 +174,25 @@ describe('SetHook', function () {
|
|||||||
)
|
)
|
||||||
assert.throws(() => validate(setHookTx), ValidationError, errorMessage)
|
assert.throws(() => validate(setHookTx), ValidationError, errorMessage)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it.each(['', '0'.repeat(7), '0'.repeat(33), 'ZZZZZZZZ'])(
|
||||||
|
`throws w/ invalid HookName in Hooks: %s`,
|
||||||
|
function (value: string) {
|
||||||
|
setHookTx.Hooks = [
|
||||||
|
{
|
||||||
|
Hook: {
|
||||||
|
HookName: value,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
const errorMessage =
|
||||||
|
'SetHook: HookName in Hook must be a hex string of 8-32 hex characters'
|
||||||
|
assert.throws(
|
||||||
|
() => validateSetHook(setHookTx),
|
||||||
|
ValidationError,
|
||||||
|
errorMessage,
|
||||||
|
)
|
||||||
|
assert.throws(() => validate(setHookTx), ValidationError, errorMessage)
|
||||||
|
},
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -11,7 +11,17 @@ import {
|
|||||||
PaymentFlags,
|
PaymentFlags,
|
||||||
TrustSet,
|
TrustSet,
|
||||||
TrustSetFlags,
|
TrustSetFlags,
|
||||||
|
Remit,
|
||||||
|
convertStringToHex,
|
||||||
|
SetHook,
|
||||||
|
URITokenMint,
|
||||||
|
URITokenMintFlags,
|
||||||
|
ClaimReward,
|
||||||
|
ClaimRewardFlags,
|
||||||
|
CronSet,
|
||||||
|
CronSetFlags,
|
||||||
} from '../../src'
|
} from '../../src'
|
||||||
|
import { HookFlags, MintURITokenFlags } from '../../src/models/common/xahau'
|
||||||
import { AccountRootFlags } from '../../src/models/ledger'
|
import { AccountRootFlags } from '../../src/models/ledger'
|
||||||
import { isFlagEnabled } from '../../src/models/utils'
|
import { isFlagEnabled } from '../../src/models/utils'
|
||||||
import {
|
import {
|
||||||
@@ -141,6 +151,94 @@ describe('Models Utils', function () {
|
|||||||
assert.strictEqual(tx.Flags, expected)
|
assert.strictEqual(tx.Flags, expected)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('sets URITokenMintFlags to its numeric value', function () {
|
||||||
|
const tx: URITokenMint = {
|
||||||
|
TransactionType: 'URITokenMint',
|
||||||
|
Account: 'rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo',
|
||||||
|
URI: convertStringToHex('https://xahau.network'),
|
||||||
|
Flags: {
|
||||||
|
tfBurnable: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
const { tfBurnable } = URITokenMintFlags
|
||||||
|
const expected: number = tfBurnable
|
||||||
|
|
||||||
|
setTransactionFlagsToNumber(tx)
|
||||||
|
assert.strictEqual(tx.Flags, expected)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('sets ClaimRewardFlags to its numeric value', function () {
|
||||||
|
const tx: ClaimReward = {
|
||||||
|
TransactionType: 'ClaimReward',
|
||||||
|
Account: 'rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo',
|
||||||
|
Flags: {
|
||||||
|
tfOptOut: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
const { tfOptOut } = ClaimRewardFlags
|
||||||
|
const expected: number = tfOptOut
|
||||||
|
|
||||||
|
setTransactionFlagsToNumber(tx)
|
||||||
|
assert.strictEqual(tx.Flags, expected)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('sets CronSetFlags to its numeric value', function () {
|
||||||
|
const tx: CronSet = {
|
||||||
|
TransactionType: 'CronSet',
|
||||||
|
Account: 'rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo',
|
||||||
|
Flags: {
|
||||||
|
tfCronUnset: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
const { tfCronUnset } = CronSetFlags
|
||||||
|
const expected: number = tfCronUnset
|
||||||
|
|
||||||
|
setTransactionFlagsToNumber(tx)
|
||||||
|
assert.strictEqual(tx.Flags, expected)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('sets MintURITokenFlags in Remit Transaction to its numeric value', function () {
|
||||||
|
const tx: Remit = {
|
||||||
|
TransactionType: 'Remit',
|
||||||
|
Account: 'rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo',
|
||||||
|
Destination: 'rcXY84C4g14iFp6taFXjjQGVeHqSCh9RX',
|
||||||
|
MintURIToken: {
|
||||||
|
URI: convertStringToHex('https://xahau.network'),
|
||||||
|
Flags: {
|
||||||
|
tfBurnable: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
setTransactionFlagsToNumber(tx)
|
||||||
|
const expected = MintURITokenFlags.tfBurnable
|
||||||
|
assert.strictEqual(tx.MintURIToken?.Flags, expected)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('sets HookFlags in SetHook Transaction to its numeric value', function () {
|
||||||
|
const tx: SetHook = {
|
||||||
|
TransactionType: 'SetHook',
|
||||||
|
Account: 'rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo',
|
||||||
|
Hooks: [
|
||||||
|
{
|
||||||
|
Hook: {
|
||||||
|
// invalid flags but for testing purposes
|
||||||
|
Flags: {
|
||||||
|
hsfCollect: true,
|
||||||
|
hsfNSDelete: true,
|
||||||
|
hsfOverride: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
setTransactionFlagsToNumber(tx)
|
||||||
|
const expected =
|
||||||
|
HookFlags.hsfCollect | HookFlags.hsfNSDelete | HookFlags.hsfOverride
|
||||||
|
assert.strictEqual(tx.Hooks[0].Hook.Flags, expected)
|
||||||
|
})
|
||||||
|
|
||||||
it('sets other transaction types flags to its numeric value', function () {
|
it('sets other transaction types flags to its numeric value', function () {
|
||||||
const tx: DepositPreauth = {
|
const tx: DepositPreauth = {
|
||||||
TransactionType: 'DepositPreauth',
|
TransactionType: 'DepositPreauth',
|
||||||
|
|||||||
Reference in New Issue
Block a user