mirror of
https://github.com/Xahau/xahau.js.git
synced 2025-11-06 05:45:48 +00:00
Compare commits
7 Commits
sidechain-
...
dependabot
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e4910c9bef | ||
|
|
14ffaae960 | ||
|
|
8eab8b3c04 | ||
|
|
aff6988f09 | ||
|
|
9ff9fc7767 | ||
|
|
89240eae62 | ||
|
|
7732f22858 |
19
.github/workflows/nodejs.yml
vendored
19
.github/workflows/nodejs.yml
vendored
@@ -18,11 +18,12 @@ jobs:
|
||||
node-version: [14.x]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: 'npm'
|
||||
- run: npm install -g npm@7
|
||||
- run: npm ci
|
||||
- run: npm run build
|
||||
@@ -37,11 +38,13 @@ jobs:
|
||||
node-version: [12.x, 14.x, 16.x]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: 'npm'
|
||||
cache-dependency-path: '**/package-lock.json'
|
||||
- run: npm install -g npm@7
|
||||
- run: npm ci
|
||||
- run: npm run build
|
||||
@@ -63,11 +66,13 @@ jobs:
|
||||
--health-cmd="wget localhost:6006 || exit 1" --health-interval=5s --health-retries=10 --health-timeout=2s
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: 'npm'
|
||||
cache-dependency-path: '**/package-lock.json'
|
||||
- run: npm install -g npm@7
|
||||
- run: npm ci
|
||||
- run: npm run build
|
||||
@@ -97,6 +102,8 @@ jobs:
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: 'npm'
|
||||
cache-dependency-path: '**/package-lock.json'
|
||||
- run: npm install -g npm@7
|
||||
- run: npm ci
|
||||
- run: npm run build
|
||||
|
||||
@@ -68,7 +68,7 @@ Warning: Use at your own risk.
|
||||
|
||||
Attempts to detect RippleNet on-demand liquidity (ODL) transactions through known fiat corridors and report these transactions in real time.
|
||||
|
||||
- **[XRPL Rosetta](https://xrpl-rosetta-oepox.ondigitalocean.app)**
|
||||
- **[XRPL Rosetta](https://threexrp.dev/)**
|
||||
|
||||
3D Globe written in three.js connected to a Node.js websocket server that is listening to exchanges and the XRPL. The visualization aims to show trading, ODL, and liquidity at exchanges, intra-exchange volume, and flows.
|
||||
|
||||
|
||||
70
package-lock.json
generated
70
package-lock.json
generated
@@ -6998,7 +6998,8 @@
|
||||
},
|
||||
"node_modules/filter-obj": {
|
||||
"version": "1.1.0",
|
||||
"integrity": "sha1-mzERErxsYSehbgFsbF1/GeCAXFs=",
|
||||
"resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz",
|
||||
"integrity": "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
@@ -12616,8 +12617,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/parse-path": {
|
||||
"version": "4.0.3",
|
||||
"integrity": "sha512-9Cepbp2asKnWTJ9x2kpw6Fe8y9JDbqwahGCTvklzd/cEq5C5JC59x2Xb0Kx+x0QZ8bvNquGO8/BWP0cwBHzSAA==",
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/parse-path/-/parse-path-4.0.4.tgz",
|
||||
"integrity": "sha512-Z2lWUis7jlmXC1jeOG9giRO2+FsuyNipeQ43HAjqAZjwSe3SEf+q/84FGPHoso3kyntbxa4c4i77t3m6fGf8cw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"is-ssh": "^1.3.0",
|
||||
@@ -12627,13 +12629,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/parse-url": {
|
||||
"version": "6.0.0",
|
||||
"integrity": "sha512-cYyojeX7yIIwuJzledIHeLUBVJ6COVLeT4eF+2P6aKVzwvgKQPndCBv3+yQ7pcWjqToYwaligxzSYNNmGoMAvw==",
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/parse-url/-/parse-url-6.0.2.tgz",
|
||||
"integrity": "sha512-uCSjOvD3T+6B/sPWhR+QowAZcU/o4bjPrVBQBGFxcDF6J6FraCGIaDBsdoQawiaaAVdHvtqBe3w3vKlfBKySOQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"is-ssh": "^1.3.0",
|
||||
"normalize-url": "^6.1.0",
|
||||
"parse-path": "^4.0.0",
|
||||
"parse-path": "^4.0.4",
|
||||
"protocols": "^1.4.0"
|
||||
}
|
||||
},
|
||||
@@ -13105,8 +13108,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/qs": {
|
||||
"version": "6.10.1",
|
||||
"integrity": "sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg==",
|
||||
"version": "6.11.0",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
|
||||
"integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"side-channel": "^1.0.4"
|
||||
@@ -13120,6 +13124,7 @@
|
||||
},
|
||||
"node_modules/query-string": {
|
||||
"version": "6.14.1",
|
||||
"resolved": "https://registry.npmjs.org/query-string/-/query-string-6.14.1.tgz",
|
||||
"integrity": "sha512-XDxAeVmpfu1/6IjyT/gXHOl+S0vQ9owggJ30hhWKdHAsNPOcasn5o9BW0eejZqL2e4vMjhAxoW3jVHcD6mbcYw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
@@ -14590,6 +14595,7 @@
|
||||
},
|
||||
"node_modules/split-on-first": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz",
|
||||
"integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
@@ -14784,7 +14790,8 @@
|
||||
},
|
||||
"node_modules/strict-uri-encode": {
|
||||
"version": "2.0.0",
|
||||
"integrity": "sha1-ucczDHBChi9rFC3CdLvMWGbONUY=",
|
||||
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz",
|
||||
"integrity": "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
@@ -15684,9 +15691,9 @@
|
||||
"integrity": "sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g=="
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "4.6.4",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.4.tgz",
|
||||
"integrity": "sha512-9ia/jWHIEbo49HfjrLGfKbZSuWo9iTMwXO+Ca3pRsSpbsMbc7/IU8NKdCZVRRBafVPGnoJeFL76ZOAA84I9fEg==",
|
||||
"version": "4.7.4",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz",
|
||||
"integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
@@ -16704,7 +16711,7 @@
|
||||
}
|
||||
},
|
||||
"packages/ripple-binary-codec": {
|
||||
"version": "1.4.1",
|
||||
"version": "1.4.2",
|
||||
"integrity": "sha512-XMRCbFXyG+dGp3x7tMs9IwA+FVWPPaGjdHYW2+g4Q/WQJqFp5MRED+jjOBOUafmrW4TUsOn1PEEdbB4ozWbDBw==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
@@ -16743,7 +16750,7 @@
|
||||
}
|
||||
},
|
||||
"packages/xrpl": {
|
||||
"version": "2.3.0",
|
||||
"version": "2.3.1",
|
||||
"integrity": "sha512-NmrSYpXym7NzGABeXU1H8g4ZtCxRhr/3wu0lguxzcIYpcKPgWLYimg+s9NLLNbPWTZdxXu9SeSWu5zh4gyqAeA==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
@@ -16753,7 +16760,7 @@
|
||||
"https-proxy-agent": "^5.0.0",
|
||||
"lodash": "^4.17.4",
|
||||
"ripple-address-codec": "^4.2.4",
|
||||
"ripple-binary-codec": "^1.4.1",
|
||||
"ripple-binary-codec": "^1.4.2",
|
||||
"ripple-keypairs": "^1.1.4",
|
||||
"ws": "^8.2.2"
|
||||
},
|
||||
@@ -22214,7 +22221,8 @@
|
||||
},
|
||||
"filter-obj": {
|
||||
"version": "1.1.0",
|
||||
"integrity": "sha1-mzERErxsYSehbgFsbF1/GeCAXFs=",
|
||||
"resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz",
|
||||
"integrity": "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==",
|
||||
"dev": true
|
||||
},
|
||||
"find-cache-dir": {
|
||||
@@ -26428,8 +26436,9 @@
|
||||
}
|
||||
},
|
||||
"parse-path": {
|
||||
"version": "4.0.3",
|
||||
"integrity": "sha512-9Cepbp2asKnWTJ9x2kpw6Fe8y9JDbqwahGCTvklzd/cEq5C5JC59x2Xb0Kx+x0QZ8bvNquGO8/BWP0cwBHzSAA==",
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/parse-path/-/parse-path-4.0.4.tgz",
|
||||
"integrity": "sha512-Z2lWUis7jlmXC1jeOG9giRO2+FsuyNipeQ43HAjqAZjwSe3SEf+q/84FGPHoso3kyntbxa4c4i77t3m6fGf8cw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-ssh": "^1.3.0",
|
||||
@@ -26439,13 +26448,14 @@
|
||||
}
|
||||
},
|
||||
"parse-url": {
|
||||
"version": "6.0.0",
|
||||
"integrity": "sha512-cYyojeX7yIIwuJzledIHeLUBVJ6COVLeT4eF+2P6aKVzwvgKQPndCBv3+yQ7pcWjqToYwaligxzSYNNmGoMAvw==",
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/parse-url/-/parse-url-6.0.2.tgz",
|
||||
"integrity": "sha512-uCSjOvD3T+6B/sPWhR+QowAZcU/o4bjPrVBQBGFxcDF6J6FraCGIaDBsdoQawiaaAVdHvtqBe3w3vKlfBKySOQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-ssh": "^1.3.0",
|
||||
"normalize-url": "^6.1.0",
|
||||
"parse-path": "^4.0.0",
|
||||
"parse-path": "^4.0.4",
|
||||
"protocols": "^1.4.0"
|
||||
}
|
||||
},
|
||||
@@ -26799,8 +26809,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"qs": {
|
||||
"version": "6.10.1",
|
||||
"integrity": "sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg==",
|
||||
"version": "6.11.0",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
|
||||
"integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"side-channel": "^1.0.4"
|
||||
@@ -26808,6 +26819,7 @@
|
||||
},
|
||||
"query-string": {
|
||||
"version": "6.14.1",
|
||||
"resolved": "https://registry.npmjs.org/query-string/-/query-string-6.14.1.tgz",
|
||||
"integrity": "sha512-XDxAeVmpfu1/6IjyT/gXHOl+S0vQ9owggJ30hhWKdHAsNPOcasn5o9BW0eejZqL2e4vMjhAxoW3jVHcD6mbcYw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@@ -27950,6 +27962,7 @@
|
||||
},
|
||||
"split-on-first": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz",
|
||||
"integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==",
|
||||
"dev": true
|
||||
},
|
||||
@@ -28105,7 +28118,8 @@
|
||||
},
|
||||
"strict-uri-encode": {
|
||||
"version": "2.0.0",
|
||||
"integrity": "sha1-ucczDHBChi9rFC3CdLvMWGbONUY=",
|
||||
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz",
|
||||
"integrity": "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==",
|
||||
"dev": true
|
||||
},
|
||||
"string_decoder": {
|
||||
@@ -28752,9 +28766,9 @@
|
||||
"integrity": "sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g=="
|
||||
},
|
||||
"typescript": {
|
||||
"version": "4.6.4",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.4.tgz",
|
||||
"integrity": "sha512-9ia/jWHIEbo49HfjrLGfKbZSuWo9iTMwXO+Ca3pRsSpbsMbc7/IU8NKdCZVRRBafVPGnoJeFL76ZOAA84I9fEg==",
|
||||
"version": "4.7.4",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz",
|
||||
"integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==",
|
||||
"dev": true
|
||||
},
|
||||
"uglify-js": {
|
||||
@@ -29425,7 +29439,7 @@
|
||||
"https-proxy-agent": "^5.0.0",
|
||||
"lodash": "^4.17.4",
|
||||
"ripple-address-codec": "^4.2.4",
|
||||
"ripple-binary-codec": "^1.4.1",
|
||||
"ripple-binary-codec": "^1.4.2",
|
||||
"ripple-keypairs": "^1.1.4",
|
||||
"ws": "^8.2.2",
|
||||
"xrpl-local": "file:src"
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
# ripple-binary-codec Release History
|
||||
|
||||
## Unreleased
|
||||
### Added
|
||||
- Support for sidechain transactions
|
||||
|
||||
### Fixed
|
||||
## 1.4.2 (2022-06-27)
|
||||
- Fixed standard currency codes with lowercase and allowed symbols not decoding into standard codes.
|
||||
|
||||
## 1.4.1 (2022-06-02)
|
||||
- Added a clearer error message for trying to encode an invalid transaction. (Ex. With an incorrect TransactionType)
|
||||
|
||||
|
||||
## 1.4.0 (2022-04-18)
|
||||
- Updated NFT definitions to match 1.9.0's breaking naming changes
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ripple-binary-codec",
|
||||
"version": "1.4.1",
|
||||
"version": "1.4.2",
|
||||
"description": "XRP Ledger binary codec",
|
||||
"files": [
|
||||
"dist/*",
|
||||
@@ -24,10 +24,9 @@
|
||||
"build:default": "tsc -b && copy .\\src\\enums\\definitions.json .\\dist\\enums",
|
||||
"build:nix": "tsc -b && cp ./src/enums/definitions.json ./dist/enums",
|
||||
"clean": "rm -rf ./dist && rm -rf tsconfig.tsbuildinfo",
|
||||
"prepare": "npm run build",
|
||||
"prepare": "npm run build && npm test",
|
||||
"test": "jest",
|
||||
"lint": "eslint . --ext .ts --ext .test.js",
|
||||
"prepublishOnly": "npm run build && npm run test"
|
||||
"lint": "eslint . --ext .ts --ext .test.js"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -19,9 +19,7 @@
|
||||
"NotPresent": 0,
|
||||
"UInt64": 3,
|
||||
"UInt32": 2,
|
||||
"STArray": 15,
|
||||
"Sidechain": 24,
|
||||
"XChainClaimProof": 25
|
||||
"STArray": 15
|
||||
},
|
||||
"LEDGER_ENTRY_TYPES": {
|
||||
"Any": -3,
|
||||
@@ -33,10 +31,8 @@
|
||||
"Ticket": 84,
|
||||
"SignerList": 83,
|
||||
"Offer": 111,
|
||||
"Sidechain": 105,
|
||||
"LedgerHashes": 104,
|
||||
"Amendments": 102,
|
||||
"CrosschainSequenceNum": 113,
|
||||
"FeeSettings": 115,
|
||||
"Escrow": 117,
|
||||
"PayChannel": 120,
|
||||
@@ -829,16 +825,6 @@
|
||||
"type": "Amount"
|
||||
}
|
||||
],
|
||||
[
|
||||
"XChainFee",
|
||||
{
|
||||
"nth": 11,
|
||||
"isVLEncoded": false,
|
||||
"isSerialized": true,
|
||||
"isSigningField": true,
|
||||
"type": "Amount"
|
||||
}
|
||||
],
|
||||
[
|
||||
"MinimumOffer",
|
||||
{
|
||||
@@ -1189,26 +1175,6 @@
|
||||
"type": "AccountID"
|
||||
}
|
||||
],
|
||||
[
|
||||
"ThisChainAccount",
|
||||
{
|
||||
"nth": 17,
|
||||
"isVLEncoded": true,
|
||||
"isSerialized": true,
|
||||
"isSigningField": true,
|
||||
"type": "AccountID"
|
||||
}
|
||||
],
|
||||
[
|
||||
"OtherChainAccount",
|
||||
{
|
||||
"nth": 18,
|
||||
"isVLEncoded": true,
|
||||
"isSerialized": true,
|
||||
"isSigningField": true,
|
||||
"type": "AccountID"
|
||||
}
|
||||
],
|
||||
[
|
||||
"ObjectEndMarker",
|
||||
{
|
||||
@@ -1359,16 +1325,6 @@
|
||||
"type": "STObject"
|
||||
}
|
||||
],
|
||||
[
|
||||
"XChainProofSig",
|
||||
{
|
||||
"nth": 25,
|
||||
"isVLEncoded": false,
|
||||
"isSerialized": true,
|
||||
"isSigningField": true,
|
||||
"type": "STObject"
|
||||
}
|
||||
],
|
||||
[
|
||||
"ArrayEndMarker",
|
||||
{
|
||||
@@ -1479,16 +1435,6 @@
|
||||
"type": "STArray"
|
||||
}
|
||||
],
|
||||
[
|
||||
"XChainProofSigs",
|
||||
{
|
||||
"nth": 21,
|
||||
"isVLEncoded": false,
|
||||
"isSerialized": true,
|
||||
"isSigningField": true,
|
||||
"type": "STArray"
|
||||
}
|
||||
],
|
||||
[
|
||||
"CloseResolution",
|
||||
{
|
||||
@@ -1569,26 +1515,6 @@
|
||||
"type": "PathSet"
|
||||
}
|
||||
],
|
||||
[
|
||||
"Sidechain",
|
||||
{
|
||||
"nth": 1,
|
||||
"isVLEncoded": false,
|
||||
"isSerialized": true,
|
||||
"isSigningField": true,
|
||||
"type": "Sidechain"
|
||||
}
|
||||
],
|
||||
[
|
||||
"XChainClaimProof",
|
||||
{
|
||||
"nth": 1,
|
||||
"isVLEncoded": false,
|
||||
"isSerialized": true,
|
||||
"isSigningField": true,
|
||||
"type": "XChainClaimProof"
|
||||
}
|
||||
],
|
||||
[
|
||||
"Indexes",
|
||||
{
|
||||
@@ -1729,16 +1655,6 @@
|
||||
"type": "UInt32"
|
||||
}
|
||||
],
|
||||
[
|
||||
"XChainSequence",
|
||||
{
|
||||
"nth": 47,
|
||||
"isVLEncoded": false,
|
||||
"isSerialized": true,
|
||||
"isSigningField": true,
|
||||
"type": "UInt32"
|
||||
}
|
||||
],
|
||||
[
|
||||
"Channel",
|
||||
{
|
||||
@@ -1932,9 +1848,6 @@
|
||||
"temUNKNOWN": -265,
|
||||
"temSEQ_AND_TICKET": -264,
|
||||
"temBAD_NFTOKEN_TRANSFER_FEE": -263,
|
||||
"temEQUAL_DOOR_ACCOUNTS": -262,
|
||||
"temBAD_XChain_Proof": -261,
|
||||
"temSIDECHAIN_BAD_ISSUES": -260,
|
||||
|
||||
"tefFAILURE": -199,
|
||||
"tefALREADY": -198,
|
||||
@@ -2020,14 +1933,8 @@
|
||||
"tecINSUFFICIENT_FUNDS": 159,
|
||||
"tecOBJECT_NOT_FOUND": 160,
|
||||
"tecINSUFFICIENT_PAYMENT": 161,
|
||||
|
||||
"tecBAD_XCHAIN_TRANSFER_ISSUE": 162,
|
||||
"tecBAD_XCHAIN_TRANSFER_SEQ_NUM": 163,
|
||||
"tecXCHAIN_PROOF_NO_QUORUM": 164,
|
||||
"tecXCHAIN_PROOF_UNKNOWN_KEY": 165,
|
||||
"tecXCHAIN_CREATE_ACCOUNT_NONXRP_ISSUE": 166,
|
||||
"tecXCHAIN_CLAIM_ACCOUNT_DST_EXISTS": 167,
|
||||
"tecXCHAIN_CLAIM_WRONG_CHAIN": 168
|
||||
"tecINCORRECT_ASSET": 162,
|
||||
"tecTOO_MANY": 163
|
||||
},
|
||||
"TRANSACTION_TYPES": {
|
||||
"Invalid": -1,
|
||||
@@ -2059,13 +1966,6 @@
|
||||
"NFTokenCreateOffer": 27,
|
||||
"NFTokenCancelOffer": 28,
|
||||
"NFTokenAcceptOffer": 29,
|
||||
"XChainDoorCreate": 30,
|
||||
"XChainSeqNumCreate": 31,
|
||||
"XChainTransfer": 32,
|
||||
"XChainClaim": 33,
|
||||
"XChainAccountCreate": 34,
|
||||
"XChainAccountClaim": 35,
|
||||
|
||||
"EnableAmendment": 100,
|
||||
"SetFee": 101,
|
||||
"UNLModify": 102
|
||||
|
||||
@@ -147,8 +147,7 @@ class Amount extends SerializedType {
|
||||
*/
|
||||
toJSON(): AmountObject | string {
|
||||
if (this.isNative()) {
|
||||
const bytes = Buffer.alloc(this.bytes.length)
|
||||
this.bytes.copy(bytes)
|
||||
const bytes = this.bytes
|
||||
const isPositive = bytes[0] & 0x40
|
||||
const sign = isPositive ? '' : '-'
|
||||
bytes[0] &= 0x3f
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Hash160 } from './hash-160'
|
||||
import { Buffer } from 'buffer/'
|
||||
|
||||
const XRP_HEX_REGEX = /^0{40}$/
|
||||
const ISO_REGEX = /^[A-Z0-9]{3}$/
|
||||
const ISO_REGEX = /^[A-Z0-9a-z?!@#$%^&*(){}[\]|]{3}$/
|
||||
const HEX_REGEX = /^[A-F0-9]{40}$/
|
||||
// eslint-disable-next-line no-control-regex
|
||||
const STANDARD_FORMAT_HEX_REGEX = /^0{24}[\x00-\x7F]{6}0{10}$/
|
||||
|
||||
@@ -11,9 +11,7 @@ import { Currency } from './currency'
|
||||
import { Hash128 } from './hash-128'
|
||||
import { Hash160 } from './hash-160'
|
||||
import { Hash256 } from './hash-256'
|
||||
import { IssuedCurrency } from './issued-currency'
|
||||
import { PathSet } from './path-set'
|
||||
import { Sidechain } from './sidechain'
|
||||
import { STArray } from './st-array'
|
||||
import { STObject } from './st-object'
|
||||
import { UInt16 } from './uint-16'
|
||||
@@ -21,7 +19,6 @@ import { UInt32 } from './uint-32'
|
||||
import { UInt64 } from './uint-64'
|
||||
import { UInt8 } from './uint-8'
|
||||
import { Vector256 } from './vector-256'
|
||||
import { XChainClaimProof } from './xchain-claim-proof'
|
||||
|
||||
const coreTypes = {
|
||||
AccountID,
|
||||
@@ -31,9 +28,7 @@ const coreTypes = {
|
||||
Hash128,
|
||||
Hash160,
|
||||
Hash256,
|
||||
IssuedCurrency,
|
||||
PathSet,
|
||||
Sidechain,
|
||||
STArray,
|
||||
STObject,
|
||||
UInt8,
|
||||
@@ -41,7 +36,6 @@ const coreTypes = {
|
||||
UInt32,
|
||||
UInt64,
|
||||
Vector256,
|
||||
XChainClaimProof,
|
||||
}
|
||||
|
||||
Object.values(Field).forEach((field) => {
|
||||
|
||||
@@ -1,114 +0,0 @@
|
||||
import { BinaryParser } from '../serdes/binary-parser'
|
||||
|
||||
import { AccountID } from './account-id'
|
||||
import { Currency } from './currency'
|
||||
import { JsonObject, SerializedType } from './serialized-type'
|
||||
import { Buffer } from 'buffer/'
|
||||
|
||||
/**
|
||||
* Interface for JSON objects that represent amounts
|
||||
*/
|
||||
interface IssuedCurrencyObject extends JsonObject {
|
||||
currency: string
|
||||
issuer: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Type guard for AmountObject
|
||||
*/
|
||||
function isIssuedCurrencyObject(arg): arg is IssuedCurrencyObject {
|
||||
const keys = Object.keys(arg).sort()
|
||||
return keys.length === 2 && keys[0] === 'currency' && keys[1] === 'issuer'
|
||||
}
|
||||
|
||||
/**
|
||||
* Class for serializing/Deserializing Amounts
|
||||
*/
|
||||
class IssuedCurrency extends SerializedType {
|
||||
static readonly ZERO_ISSUED_CURRENCY: IssuedCurrency = new IssuedCurrency(
|
||||
Buffer.alloc(20),
|
||||
)
|
||||
|
||||
constructor(bytes: Buffer) {
|
||||
super(bytes ?? IssuedCurrency.ZERO_ISSUED_CURRENCY.bytes)
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an amount from an IOU or string amount
|
||||
*
|
||||
* @param value An Amount, object representing an IOU, or a string
|
||||
* representing an integer amount
|
||||
* @returns An Amount object
|
||||
*/
|
||||
static from<T extends IssuedCurrency | IssuedCurrencyObject | string>(
|
||||
value: T,
|
||||
): IssuedCurrency {
|
||||
if (value instanceof IssuedCurrency) {
|
||||
return value
|
||||
}
|
||||
|
||||
if (typeof value === 'string') {
|
||||
IssuedCurrency.assertXrpIsValid(value)
|
||||
|
||||
const currency = Currency.from(value).toBytes()
|
||||
|
||||
return new IssuedCurrency(currency)
|
||||
}
|
||||
|
||||
if (isIssuedCurrencyObject(value)) {
|
||||
const currency = Currency.from(value.currency).toBytes()
|
||||
const issuer = AccountID.from(value.issuer).toBytes()
|
||||
return new IssuedCurrency(Buffer.concat([currency, issuer]))
|
||||
}
|
||||
|
||||
throw new Error('Invalid type to construct an Amount')
|
||||
}
|
||||
|
||||
/**
|
||||
* Read an amount from a BinaryParser
|
||||
*
|
||||
* @param parser BinaryParser to read the Amount from
|
||||
* @returns An Amount object
|
||||
*/
|
||||
static fromParser(parser: BinaryParser): IssuedCurrency {
|
||||
const currency = parser.read(20)
|
||||
if (new Currency(currency).toJSON() === 'XRP') {
|
||||
return new IssuedCurrency(currency)
|
||||
}
|
||||
const currencyAndIssuer = [currency, parser.read(20)]
|
||||
return new IssuedCurrency(Buffer.concat(currencyAndIssuer))
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the JSON representation of this Amount
|
||||
*
|
||||
* @returns the JSON interpretation of this.bytes
|
||||
*/
|
||||
toJSON(): IssuedCurrencyObject | string {
|
||||
const parser = new BinaryParser(this.toString())
|
||||
const currency = Currency.fromParser(parser) as Currency
|
||||
if (currency.toJSON() === 'XRP') {
|
||||
return currency.toJSON()
|
||||
}
|
||||
const issuer = AccountID.fromParser(parser) as AccountID
|
||||
|
||||
return {
|
||||
currency: currency.toJSON(),
|
||||
issuer: issuer.toJSON(),
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate XRP amount
|
||||
*
|
||||
* @param value String representing XRP amount
|
||||
* @returns void, but will throw if invalid amount
|
||||
*/
|
||||
private static assertXrpIsValid(value: string): void {
|
||||
if (value !== 'XRP') {
|
||||
throw new Error(`${value} is an illegal amount`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export { IssuedCurrency, IssuedCurrencyObject }
|
||||
@@ -1,109 +0,0 @@
|
||||
import { BinaryParser } from '../serdes/binary-parser'
|
||||
|
||||
import { AccountID } from './account-id'
|
||||
import { JsonObject, SerializedType } from './serialized-type'
|
||||
import { Buffer } from 'buffer/'
|
||||
import { IssuedCurrency, IssuedCurrencyObject } from './issued-currency'
|
||||
|
||||
/**
|
||||
* Interface for JSON objects that represent sidechains
|
||||
*/
|
||||
interface SidechainObject extends JsonObject {
|
||||
dst_chain_door: string
|
||||
dst_chain_issue: IssuedCurrencyObject | string
|
||||
src_chain_door: string
|
||||
src_chain_issue: IssuedCurrencyObject | string
|
||||
}
|
||||
|
||||
/**
|
||||
* Type guard for SidechainObject
|
||||
*/
|
||||
function isSidechainObject(arg): arg is SidechainObject {
|
||||
const keys = Object.keys(arg).sort()
|
||||
return (
|
||||
keys.length === 4 &&
|
||||
keys[0] === 'dst_chain_door' &&
|
||||
keys[1] === 'dst_chain_issue' &&
|
||||
keys[2] === 'src_chain_door' &&
|
||||
keys[3] === 'src_chain_issue'
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Class for serializing/deserializing Sidechains
|
||||
*/
|
||||
class Sidechain extends SerializedType {
|
||||
static readonly ZERO_SIDECHAIN: Sidechain = new Sidechain(Buffer.alloc(80))
|
||||
|
||||
static readonly TYPE_ORDER: { name: string; type: typeof SerializedType }[] =
|
||||
[
|
||||
{ name: 'src_chain_door', type: AccountID },
|
||||
{ name: 'src_chain_issue', type: IssuedCurrency },
|
||||
{ name: 'dst_chain_door', type: AccountID },
|
||||
{ name: 'dst_chain_issue', type: IssuedCurrency },
|
||||
]
|
||||
|
||||
constructor(bytes: Buffer) {
|
||||
super(bytes ?? Sidechain.ZERO_SIDECHAIN.bytes)
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a sidechain from a JSON
|
||||
*
|
||||
* @param value Sidechain or JSON to parse into a Sidechain
|
||||
* @returns A Sidechain object
|
||||
*/
|
||||
static from<T extends Sidechain | SidechainObject>(value: T): Sidechain {
|
||||
if (value instanceof Sidechain) {
|
||||
return value
|
||||
}
|
||||
|
||||
if (isSidechainObject(value)) {
|
||||
const bytes: Array<Buffer> = []
|
||||
this.TYPE_ORDER.forEach((item) => {
|
||||
const { name, type } = item
|
||||
const object = type.from(value[name])
|
||||
bytes.push(object.toBytes())
|
||||
})
|
||||
return new Sidechain(Buffer.concat(bytes))
|
||||
}
|
||||
|
||||
throw new Error('Invalid type to construct a Sidechain')
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a Sidechain from a BinaryParser
|
||||
*
|
||||
* @param parser BinaryParser to read the Sidechain from
|
||||
* @returns A Sidechain object
|
||||
*/
|
||||
static fromParser(parser: BinaryParser): Sidechain {
|
||||
const bytes: Array<Buffer> = []
|
||||
|
||||
this.TYPE_ORDER.forEach((item) => {
|
||||
const { type } = item
|
||||
const object = type.fromParser(parser)
|
||||
bytes.push(object.toBytes())
|
||||
})
|
||||
|
||||
return new Sidechain(Buffer.concat(bytes))
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the JSON representation of this Sidechain
|
||||
*
|
||||
* @returns the JSON interpretation of this.bytes
|
||||
*/
|
||||
toJSON(): SidechainObject {
|
||||
const parser = new BinaryParser(this.toString())
|
||||
const json = {}
|
||||
Sidechain.TYPE_ORDER.forEach((item) => {
|
||||
const { name, type } = item
|
||||
const object = type.fromParser(parser).toJSON()
|
||||
json[name] = object
|
||||
})
|
||||
return json as SidechainObject
|
||||
}
|
||||
}
|
||||
|
||||
export { Sidechain, SidechainObject }
|
||||
@@ -6,7 +6,7 @@ import { Buffer } from 'buffer/'
|
||||
* Derived UInt class for serializing/deserializing 32 bit UInt
|
||||
*/
|
||||
class UInt32 extends UInt {
|
||||
public static readonly width: number = 32 / 8 // 4
|
||||
protected static readonly width: number = 32 / 8 // 4
|
||||
static readonly defaultUInt32: UInt32 = new UInt32(Buffer.alloc(UInt32.width))
|
||||
|
||||
constructor(bytes: Buffer) {
|
||||
|
||||
@@ -6,7 +6,7 @@ import { Buffer } from 'buffer/'
|
||||
* Derived UInt class for serializing/deserializing 8 bit UInt
|
||||
*/
|
||||
class UInt8 extends UInt {
|
||||
public static readonly width: number = 8 / 8 // 1
|
||||
protected static readonly width: number = 8 / 8 // 1
|
||||
static readonly defaultUInt8: UInt8 = new UInt8(Buffer.alloc(UInt8.width))
|
||||
|
||||
constructor(bytes: Buffer) {
|
||||
@@ -33,12 +33,6 @@ class UInt8 extends UInt {
|
||||
return new UInt8(buf)
|
||||
}
|
||||
|
||||
if (typeof val === 'boolean') {
|
||||
const buf = Buffer.alloc(UInt8.width)
|
||||
buf.writeUInt8(Number(val), 0)
|
||||
return new UInt8(buf)
|
||||
}
|
||||
|
||||
throw new Error('Cannot construct UInt8 from given value')
|
||||
}
|
||||
|
||||
|
||||
@@ -1,136 +0,0 @@
|
||||
import { BinaryParser } from '../serdes/binary-parser'
|
||||
|
||||
import { JsonObject, SerializedType } from './serialized-type'
|
||||
import { Buffer } from 'buffer/'
|
||||
import { Sidechain, SidechainObject } from './sidechain'
|
||||
import { Amount } from './amount'
|
||||
import { UInt8 } from './uint-8'
|
||||
import { UInt32 } from './uint-32'
|
||||
import { STArray } from './st-array'
|
||||
|
||||
/**
|
||||
* Interface for JSON objects that represent signatures
|
||||
*/
|
||||
interface SignatureObject extends JsonObject {
|
||||
XChainProofSig: {
|
||||
Signature: string
|
||||
PublicKey: string
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface for JSON objects that represent XChainClaimProofs
|
||||
*/
|
||||
interface XChainClaimProofObject extends JsonObject {
|
||||
amount: string
|
||||
sidechain: SidechainObject
|
||||
signatures: SignatureObject[]
|
||||
was_src_chain_send: boolean
|
||||
xchain_seq: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Type guard for XChainClaimProofObject
|
||||
*/
|
||||
function isProofObject(arg): arg is XChainClaimProofObject {
|
||||
const keys = Object.keys(arg).sort()
|
||||
return (
|
||||
keys.length === 5 &&
|
||||
keys[0] === 'amount' &&
|
||||
keys[1] === 'sidechain' &&
|
||||
keys[2] === 'signatures' &&
|
||||
keys[3] === 'was_src_chain_send' &&
|
||||
keys[4] === 'xchain_seq'
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Class for serializing/Deserializing XChainClaimProofs
|
||||
*/
|
||||
class XChainClaimProof extends SerializedType {
|
||||
static readonly ZERO_PROOF: XChainClaimProof = new XChainClaimProof(
|
||||
Buffer.concat([
|
||||
Sidechain.ZERO_SIDECHAIN.toBytes(),
|
||||
Amount.defaultAmount.toBytes(),
|
||||
UInt32.defaultUInt32.toBytes(),
|
||||
UInt8.defaultUInt8.toBytes(),
|
||||
]),
|
||||
)
|
||||
|
||||
static readonly TYPE_ORDER: { name: string; type: typeof SerializedType }[] =
|
||||
[
|
||||
{ name: 'sidechain', type: Sidechain },
|
||||
{ name: 'amount', type: Amount },
|
||||
{ name: 'xchain_seq', type: UInt32 },
|
||||
{ name: 'was_src_chain_send', type: UInt8 },
|
||||
{ name: 'signatures', type: STArray },
|
||||
]
|
||||
|
||||
constructor(bytes: Buffer) {
|
||||
super(bytes ?? XChainClaimProof.ZERO_PROOF.bytes)
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a XChainClaimProof from a JSON
|
||||
*
|
||||
* @param value XChainClaimProof or JSON to parse into an XChainClaimProof
|
||||
* @returns A XChainClaimProof object
|
||||
*/
|
||||
static from<T extends XChainClaimProof | XChainClaimProofObject>(
|
||||
value: T,
|
||||
): XChainClaimProof {
|
||||
if (value instanceof XChainClaimProof) {
|
||||
return value
|
||||
}
|
||||
|
||||
if (isProofObject(value)) {
|
||||
const bytes: Array<Buffer> = []
|
||||
this.TYPE_ORDER.forEach((item) => {
|
||||
const { name, type } = item
|
||||
const object = type.from(value[name])
|
||||
bytes.push(object.toBytes())
|
||||
})
|
||||
|
||||
return new XChainClaimProof(Buffer.concat(bytes))
|
||||
}
|
||||
|
||||
throw new Error('Invalid type to construct a XChainClaimProof')
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a XChainClaimProof from a BinaryParser
|
||||
*
|
||||
* @param parser BinaryParser to read the XChainClaimProof from
|
||||
* @returns A XChainClaimProof object
|
||||
*/
|
||||
static fromParser(parser: BinaryParser): XChainClaimProof {
|
||||
const bytes: Array<Buffer> = []
|
||||
|
||||
this.TYPE_ORDER.forEach((item) => {
|
||||
const { type } = item
|
||||
const object = type.fromParser(parser)
|
||||
bytes.push(object.toBytes())
|
||||
})
|
||||
|
||||
return new XChainClaimProof(Buffer.concat(bytes))
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the JSON representation of this XChainClaimProof
|
||||
*
|
||||
* @returns the JSON interpretation of this.bytes
|
||||
*/
|
||||
toJSON(): XChainClaimProofObject {
|
||||
const parser = new BinaryParser(this.toString())
|
||||
const json = {}
|
||||
XChainClaimProof.TYPE_ORDER.forEach((item) => {
|
||||
const { name, type } = item
|
||||
const object = type.fromParser(parser).toJSON()
|
||||
json[name] = object
|
||||
})
|
||||
json['was_src_chain_send'] = Boolean(json['was_src_chain_send'])
|
||||
return json as XChainClaimProofObject
|
||||
}
|
||||
}
|
||||
|
||||
export { XChainClaimProof, XChainClaimProofObject }
|
||||
@@ -105,10 +105,6 @@ let json_omitted = {
|
||||
}
|
||||
|
||||
const NegativeUNL = require('./fixtures/negative-unl.json')
|
||||
const XChainDoorCreate = require('./fixtures/xchain-door-create.json')
|
||||
const XChainSeqNumCreate = require('./fixtures/xchain-seqnum-create.json')
|
||||
const XChainTransfer = require('./fixtures/xchain-transfer.json')
|
||||
const XChainClaim = require('./fixtures/xchain-claim.json')
|
||||
|
||||
function bytesListTest() {
|
||||
const list = new BytesList()
|
||||
@@ -224,7 +220,7 @@ function PaymentChannelTest() {
|
||||
})
|
||||
}
|
||||
|
||||
function negativeUNLTest() {
|
||||
function NegativeUNLTest() {
|
||||
test('can serialize NegativeUNL', () => {
|
||||
expect(encode(NegativeUNL.tx)).toEqual(NegativeUNL.binary)
|
||||
})
|
||||
@@ -233,33 +229,6 @@ function negativeUNLTest() {
|
||||
})
|
||||
}
|
||||
|
||||
function sidechainTest() {
|
||||
test('can serialize XChainDoorCreate', () => {
|
||||
expect(encode(XChainDoorCreate.tx)).toEqual(XChainDoorCreate.binary)
|
||||
})
|
||||
test('can deserialize XChainDoorCreate', () => {
|
||||
expect(decode(XChainDoorCreate.binary)).toEqual(XChainDoorCreate.tx)
|
||||
})
|
||||
test('can serialize XChainSeqNumCreate', () => {
|
||||
expect(encode(XChainSeqNumCreate.tx)).toEqual(XChainSeqNumCreate.binary)
|
||||
})
|
||||
test('can deserialize XChainSeqNumCreate', () => {
|
||||
expect(decode(XChainSeqNumCreate.binary)).toEqual(XChainSeqNumCreate.tx)
|
||||
})
|
||||
test('can serialize XChainTransfer', () => {
|
||||
expect(encode(XChainTransfer.tx)).toEqual(XChainTransfer.binary)
|
||||
})
|
||||
test('can deserialize XChainTransfer', () => {
|
||||
expect(decode(XChainTransfer.binary)).toEqual(XChainTransfer.tx)
|
||||
})
|
||||
test('can serialize XChainClaim', () => {
|
||||
expect(encode(XChainClaim.tx)).toEqual(XChainClaim.binary)
|
||||
})
|
||||
test('can deserialize XChainClaim', () => {
|
||||
expect(decode(XChainClaim.binary)).toEqual(XChainClaim.tx)
|
||||
})
|
||||
}
|
||||
|
||||
function omitUndefinedTest() {
|
||||
test('omits fields with undefined value', () => {
|
||||
let encodedOmitted = encode(json_omitted)
|
||||
@@ -313,8 +282,7 @@ describe('Binary Serialization', function () {
|
||||
describe('SignerListSet', SignerListSetTest)
|
||||
describe('Escrow', EscrowTest)
|
||||
describe('PaymentChannel', PaymentChannelTest)
|
||||
describe('NegativeUNLTest', negativeUNLTest)
|
||||
describe('SidechainTest', sidechainTest)
|
||||
describe('NegativeUNLTest', NegativeUNLTest)
|
||||
describe('OmitUndefined', omitUndefinedTest)
|
||||
describe('TicketTest', ticketTest)
|
||||
describe('NFToken', nfTokenTest)
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
{
|
||||
"binary": "1200212280000000240000000168400000000000000A73210330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD0207446304402203CEE125C7EEA970DFC4DEFE89D79666C109EDD8B33FC006DBD8F2CCFC8CFAD4B02200E4210829E31079D623B8C5E6A634611688F50C9D41FF16341407B443B9605178114B5F762798A53D543A014CAF8B297CFF8F2F937E88314CA64525733C3BEED910CFE2AE280D3C078DABB4B0119C48CAD01682D7A86296EF14523074D4852C02EA90000000000000000000000000000000000000000CC86E58C9B58D4CF71CB8C1B41F21BB290CE13D40000000000000000000000000000000000000000400000003B9ACA000000000101E019712103ADB44CA8E56F78A0096825E5667C450ABD5C24C34E027BC1AAF7E5BD114CB5B5764730450221008CC9842A6855A37131FE7FB978675DCF329AC5CD7C881FAF6D13CDC23363059F02203A10475640C2C09541A55098109BB3326D3F49E2304710736A4E3C2773539B01E1E019712102A14E886B3C3579FBAE3139F29728B903E6F4295AEE92160C8480695524D66A1576473045022100B93B51FDBE42634828EEF7F2E5FA950557283648C5D39196ED1B08F8B394959102201F162F43B41D0D9316BF3B7AFA3BC9CA0EC1FCECF6EE8C94F58616BEA2D31F2CE1E019712102F7390DCF3352060847B81666EBAC79D52DEA2443BDF58439F75397C45334E2DC764630440220254038C5D6106246AEBB2A94E60CE79102321FDFD0468AA40C5E7F2DF1C205FE02204CEE5B3BFFDDCB67AE593348E8D8551E82770415BC9581EF0EF20DD000DD550CE1E019712102498BD8CD9CA6A4BA567A2ECFA163F118AFD30511CBBA71429C2EC2F74D76059276473045022100AA28592882A3B7C769B32564EDF9F816179D42D8C0E3988567F816E9A5453C6002202BA57DC085B9EB8427FBD58E05B3617183AC216EC7066F03FA4896D8B449490EE1E019712103219642288DEE8A3AA8FEA1F7DAE9ED4D9A9F0EADA1E2DE3DB56DD9598D9AD81776473045022100B9D649491723810B705282B66EAD6075235A1954BEEE054FF68066FADE11DA1C02205D977AE7C6706224A5A3AA75A53E13CA3DE9D67084405CD9BB474554EEE5C070E1",
|
||||
"tx": {
|
||||
"Account" : "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
||||
"Destination" : "rKT9gDkaedAosiHyHZTjyZs2HvXpzuiGmC",
|
||||
"Fee": "10",
|
||||
"Flags" : 2147483648,
|
||||
"Sequence": 1,
|
||||
"TransactionType" : "XChainClaim",
|
||||
"XChainClaimProof" :
|
||||
{
|
||||
"amount" : "1000000000",
|
||||
"sidechain" :
|
||||
{
|
||||
"dst_chain_door" : "rKeSSvHvaMZJp9ykaxutVwkhZgWuWMLnQt",
|
||||
"dst_chain_issue" : "XRP",
|
||||
"src_chain_door" : "rJvExveLEL4jNDEeLKCVdxaSCN9cEBnEQC",
|
||||
"src_chain_issue" : "XRP"
|
||||
},
|
||||
"signatures" :
|
||||
[
|
||||
{
|
||||
"XChainProofSig": {
|
||||
"Signature" : "30450221008CC9842A6855A37131FE7FB978675DCF329AC5CD7C881FAF6D13CDC23363059F02203A10475640C2C09541A55098109BB3326D3F49E2304710736A4E3C2773539B01",
|
||||
"PublicKey" : "03ADB44CA8E56F78A0096825E5667C450ABD5C24C34E027BC1AAF7E5BD114CB5B5"
|
||||
}
|
||||
},
|
||||
{
|
||||
"XChainProofSig": {
|
||||
"Signature" : "3045022100B93B51FDBE42634828EEF7F2E5FA950557283648C5D39196ED1B08F8B394959102201F162F43B41D0D9316BF3B7AFA3BC9CA0EC1FCECF6EE8C94F58616BEA2D31F2C",
|
||||
"PublicKey" : "02A14E886B3C3579FBAE3139F29728B903E6F4295AEE92160C8480695524D66A15"
|
||||
}
|
||||
},
|
||||
{
|
||||
"XChainProofSig": {
|
||||
"Signature" : "30440220254038C5D6106246AEBB2A94E60CE79102321FDFD0468AA40C5E7F2DF1C205FE02204CEE5B3BFFDDCB67AE593348E8D8551E82770415BC9581EF0EF20DD000DD550C",
|
||||
"PublicKey" : "02F7390DCF3352060847B81666EBAC79D52DEA2443BDF58439F75397C45334E2DC"
|
||||
}
|
||||
},
|
||||
{
|
||||
"XChainProofSig": {
|
||||
"Signature" : "3045022100AA28592882A3B7C769B32564EDF9F816179D42D8C0E3988567F816E9A5453C6002202BA57DC085B9EB8427FBD58E05B3617183AC216EC7066F03FA4896D8B449490E",
|
||||
"PublicKey" : "02498BD8CD9CA6A4BA567A2ECFA163F118AFD30511CBBA71429C2EC2F74D760592"
|
||||
}
|
||||
},
|
||||
{
|
||||
"XChainProofSig": {
|
||||
"Signature" : "3045022100B9D649491723810B705282B66EAD6075235A1954BEEE054FF68066FADE11DA1C02205D977AE7C6706224A5A3AA75A53E13CA3DE9D67084405CD9BB474554EEE5C070",
|
||||
"PublicKey" : "03219642288DEE8A3AA8FEA1F7DAE9ED4D9A9F0EADA1E2DE3DB56DD9598D9AD817"
|
||||
}
|
||||
}
|
||||
],
|
||||
"was_src_chain_send" : true,
|
||||
"xchain_seq" : 1
|
||||
},
|
||||
"SigningPubKey": "0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020",
|
||||
"TxnSignature": "304402203CEE125C7EEA970DFC4DEFE89D79666C109EDD8B33FC006DBD8F2CCFC8CFAD4B02200E4210829E31079D623B8C5E6A634611688F50C9D41FF16341407B443B960517"
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
{
|
||||
"binary": "12001E2280000000240000000220230000000468400000000000000C73210330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD02074473045022100B892F08A56487806BCC077CAA854341CEA6A8A2697D4FD068F4D4A391ADC16AE02203D0251CF521FC914CB3CC451A8553662CC9B4B5A6E0747F26C8B836DA2E8F82E8114B5F762798A53D543A014CAF8B297CFF8F2F937E8F4EB130001811474A41942D90FDD8E4E8BB25A7E91843CFEDB9A5DE1EB1300018114C287E75E44FEB7AF3537173BB3A866A652C91502E1EB1300018114F5B6BA5BA9F91592A4B607E0397E47A298B95EA2E1EB13000181145720A5ABFA7D844BD615F4E62FA7C963E85B0C7DE1EB1300018114B7521887260F712472A8E5775EE6234042641C0CE1F10118C48CAD01682D7A86296EF14523074D4852C02EA90000000000000000000000000000000000000000CC86E58C9B58D4CF71CB8C1B41F21BB290CE13D4000000000000000000000000555344000000000027B6C49755570AD538DDD42EE417A4708F17EF76",
|
||||
"tx": {
|
||||
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
||||
"Fee": "12",
|
||||
"Flags": 2147483648,
|
||||
"Sequence": 2,
|
||||
"Sidechain": {
|
||||
"dst_chain_door": "rKeSSvHvaMZJp9ykaxutVwkhZgWuWMLnQt",
|
||||
"dst_chain_issue": {
|
||||
"currency": "USD",
|
||||
"issuer": "rhczJR49YsdxwtYTPvxeSc1Jjr7R748cHv"
|
||||
},
|
||||
"src_chain_door": "rJvExveLEL4jNDEeLKCVdxaSCN9cEBnEQC",
|
||||
"src_chain_issue": "XRP"
|
||||
},
|
||||
"SignerEntries": [
|
||||
{
|
||||
"SignerEntry": {
|
||||
"Account": "rBdjyperRHKTzdxnZhyN94MpjN2aknRX8G",
|
||||
"SignerWeight": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"SignerEntry": {
|
||||
"Account": "rJj2ty2MDGu7dtm1bvZMA5KuhzreNL2HHo",
|
||||
"SignerWeight": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"SignerEntry": {
|
||||
"Account": "rPQDTwG7tWYNzqjytf8YCYX6hZemGG9TTh",
|
||||
"SignerWeight": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"SignerEntry": {
|
||||
"Account": "r3AguhaYj2enNDz37mzJNskxcQKb3sAYjE",
|
||||
"SignerWeight": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"SignerEntry": {
|
||||
"Account": "rH5KrD1ocKBWq3Mf7WGy8tTtEi84M1uwGm",
|
||||
"SignerWeight": 1
|
||||
}
|
||||
}
|
||||
],
|
||||
"SignerQuorum": 4,
|
||||
"SigningPubKey": "0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020",
|
||||
"TransactionType": "XChainDoorCreate",
|
||||
"TxnSignature": "3045022100B892F08A56487806BCC077CAA854341CEA6A8A2697D4FD068F4D4A391ADC16AE02203D0251CF521FC914CB3CC451A8553662CC9B4B5A6E0747F26C8B836DA2E8F82E"
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"binary": "12001F22800000008114621D345F8F094A085132431C69C89EC05D212CC20118C48CAD01682D7A86296EF14523074D4852C02EA90000000000000000000000000000000000000000CC86E58C9B58D4CF71CB8C1B41F21BB290CE13D40000000000000000000000000000000000000000",
|
||||
"tx": {
|
||||
"Account" : "r9A8UyNpW3X46FUc6P7JZqgn6WgAPjBwPg",
|
||||
"Flags" : 2147483648,
|
||||
"Sidechain" :
|
||||
{
|
||||
"dst_chain_door" : "rKeSSvHvaMZJp9ykaxutVwkhZgWuWMLnQt",
|
||||
"dst_chain_issue" : "XRP",
|
||||
"src_chain_door" : "rJvExveLEL4jNDEeLKCVdxaSCN9cEBnEQC",
|
||||
"src_chain_issue" : "XRP"
|
||||
},
|
||||
"TransactionType" : "XChainSeqNumCreate"
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
{
|
||||
"binary": "1200202280000000202F0000000161400000003B9ACA0081142F3CC37C1D5616B3BBF1AABC49F6BFF46A9200870118C48CAD01682D7A86296EF14523074D4852C02EA90000000000000000000000000000000000000000CC86E58C9B58D4CF71CB8C1B41F21BB290CE13D40000000000000000000000000000000000000000",
|
||||
"tx": {
|
||||
"Account" : "rnJmYAiqEVngtnb5ckRroXLtCbWC7CRUBx",
|
||||
"Amount" : "1000000000",
|
||||
"Flags" : 2147483648,
|
||||
"Sidechain" :
|
||||
{
|
||||
"dst_chain_door" : "rKeSSvHvaMZJp9ykaxutVwkhZgWuWMLnQt",
|
||||
"dst_chain_issue" : "XRP",
|
||||
"src_chain_door" : "rJvExveLEL4jNDEeLKCVdxaSCN9cEBnEQC",
|
||||
"src_chain_issue" : "XRP"
|
||||
},
|
||||
"TransactionType" : "XChainTransfer",
|
||||
"XChainSequence" : 1
|
||||
}
|
||||
}
|
||||
@@ -54,15 +54,19 @@ describe('Currency', function () {
|
||||
const currencyCode = '0000000000000000000000005852500000000000'
|
||||
expect(Currency.from(currencyCode).toJSON()).toBe(currencyCode)
|
||||
})
|
||||
test('Currency with lowercase letters decode to hex', () => {
|
||||
expect(Currency.from('xRp').toJSON()).toBe(
|
||||
'0000000000000000000000007852700000000000',
|
||||
test('Currency code with lowercase letters decodes to ISO code', () => {
|
||||
expect(Currency.from('xRp').toJSON()).toBe('xRp')
|
||||
})
|
||||
test('Currency codes with symbols decodes to ISO code', () => {
|
||||
expect(Currency.from('x|p').toJSON()).toBe('x|p')
|
||||
})
|
||||
test('Currency code with non-standard symbols decodes to hex', () => {
|
||||
expect(Currency.from(':::').toJSON()).toBe(
|
||||
'0000000000000000000000003A3A3A0000000000',
|
||||
)
|
||||
})
|
||||
test('Currency codes with symbols decode to hex', () => {
|
||||
expect(Currency.from('x|p').toJSON()).toBe(
|
||||
'000000000000000000000000787C700000000000',
|
||||
)
|
||||
test('Currency codes can be exclusively standard symbols', () => {
|
||||
expect(Currency.from('![]').toJSON()).toBe('![]')
|
||||
})
|
||||
test('Currency codes with uppercase and 0-9 decode to ISO codes', () => {
|
||||
expect(Currency.from('X8P').toJSON()).toBe('X8P')
|
||||
|
||||
@@ -4,6 +4,13 @@ Subscribe to [the **xrpl-announce** mailing list](https://groups.google.com/g/xr
|
||||
|
||||
## Unreleased
|
||||
|
||||
## 2.3.1 (2022-06-27)
|
||||
### Fixed
|
||||
* Signing tx with standard currency codes with lowercase and allowed symbols causing an error on decode.
|
||||
|
||||
### Added
|
||||
* When connected to nft-devnet, Client.fundWallet now defaults to using the nft-devnet faucet instead of requiring specification.
|
||||
|
||||
## 2.3.0 (2022-06-02)
|
||||
### Added
|
||||
* Sourcemap generation for browser bundle
|
||||
|
||||
2
packages/xrpl/package-lock.json
generated
2
packages/xrpl/package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "xrpl",
|
||||
"version": "2.3.0",
|
||||
"version": "2.3.1",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "xrpl",
|
||||
"version": "2.3.0",
|
||||
"version": "2.3.1",
|
||||
"license": "ISC",
|
||||
"description": "A TypeScript/JavaScript API for interacting with the XRP Ledger in Node.js and the browser",
|
||||
"files": [
|
||||
@@ -27,7 +27,7 @@
|
||||
"https-proxy-agent": "^5.0.0",
|
||||
"lodash": "^4.17.4",
|
||||
"ripple-address-codec": "^4.2.4",
|
||||
"ripple-binary-codec": "^1.4.1",
|
||||
"ripple-binary-codec": "^1.4.2",
|
||||
"ripple-keypairs": "^1.1.4",
|
||||
"ws": "^8.2.2"
|
||||
},
|
||||
|
||||
@@ -21,6 +21,7 @@ interface FaucetWallet {
|
||||
enum FaucetNetwork {
|
||||
Testnet = 'faucet.altnet.rippletest.net',
|
||||
Devnet = 'faucet.devnet.rippletest.net',
|
||||
NFTDevnet = 'faucet-nft.ripple.com',
|
||||
}
|
||||
|
||||
// Interval to check an account balance
|
||||
@@ -312,6 +313,10 @@ function getFaucetHost(client: Client): FaucetNetwork | undefined {
|
||||
return FaucetNetwork.Devnet
|
||||
}
|
||||
|
||||
if (connectionUrl.includes('xls20-sandbox')) {
|
||||
return FaucetNetwork.NFTDevnet
|
||||
}
|
||||
|
||||
throw new XRPLFaucetError('Faucet URL is not defined or inferrable.')
|
||||
}
|
||||
|
||||
|
||||
@@ -24,8 +24,10 @@ import {
|
||||
} from 'ripple-keypairs'
|
||||
|
||||
import ECDSA from '../ECDSA'
|
||||
import { ValidationError } from '../errors'
|
||||
import { ValidationError, XrplError } from '../errors'
|
||||
import { IssuedCurrencyAmount } from '../models/common'
|
||||
import { Transaction } from '../models/transactions'
|
||||
import { isIssuedCurrency } from '../models/transactions/common'
|
||||
import { isHex } from '../models/utils'
|
||||
import { ensureClassicAddress } from '../sugar/utils'
|
||||
import { hashSignedTx } from '../utils/hashes/hashLedger'
|
||||
@@ -303,6 +305,7 @@ class Wallet {
|
||||
* @param multisign - Specify true/false to use multisign or actual address (classic/x-address) to make multisign tx request.
|
||||
* @returns A signed transaction.
|
||||
* @throws ValidationError if the transaction is already signed or does not encode/decode to same result.
|
||||
* @throws XrplError if the issued currency being signed is XRP ignoring case.
|
||||
*/
|
||||
// eslint-disable-next-line max-lines-per-function -- introduced more checks to support both string and boolean inputs.
|
||||
public sign(
|
||||
@@ -351,6 +354,7 @@ class Wallet {
|
||||
this.privateKey,
|
||||
)
|
||||
}
|
||||
|
||||
const serialized = encode(txToSignAndEncode)
|
||||
this.checkTxSerialization(serialized, tx)
|
||||
return {
|
||||
@@ -392,6 +396,7 @@ class Wallet {
|
||||
* @param tx - The transaction prior to signing.
|
||||
* @throws A ValidationError if the transaction does not have a TxnSignature/Signers property, or if
|
||||
* the serialized Transaction desn't match the original transaction.
|
||||
* @throws XrplError if the transaction includes an issued currency which is equivalent to XRP ignoring case.
|
||||
*/
|
||||
// eslint-disable-next-line class-methods-use-this, max-lines-per-function -- Helper for organization purposes
|
||||
private checkTxSerialization(serialized: string, tx: Transaction): void {
|
||||
@@ -449,6 +454,38 @@ class Wallet {
|
||||
txCopy.URI = txCopy.URI.toUpperCase()
|
||||
}
|
||||
|
||||
/* eslint-disable @typescript-eslint/consistent-type-assertions -- We check at runtime that this is safe */
|
||||
Object.keys(txCopy).forEach((key) => {
|
||||
const standard_currency_code_len = 3
|
||||
if (txCopy[key] && isIssuedCurrency(txCopy[key])) {
|
||||
const decodedAmount = decoded[key] as unknown as IssuedCurrencyAmount
|
||||
const decodedCurrency = decodedAmount.currency
|
||||
const txCurrency = (txCopy[key] as IssuedCurrencyAmount).currency
|
||||
|
||||
if (
|
||||
txCurrency.length === standard_currency_code_len &&
|
||||
txCurrency.toUpperCase() === 'XRP'
|
||||
) {
|
||||
throw new XrplError(
|
||||
`Trying to sign an issued currency with a similar standard code to XRP (received '${txCurrency}'). XRP is not an issued currency.`,
|
||||
)
|
||||
}
|
||||
|
||||
// Standardize the format of currency codes to the 40 byte hex string for comparison
|
||||
const amount = txCopy[key] as IssuedCurrencyAmount
|
||||
if (amount.currency.length !== decodedCurrency.length) {
|
||||
/* eslint-disable-next-line max-depth -- Easier to read with two if-statements */
|
||||
if (decodedCurrency.length === standard_currency_code_len) {
|
||||
decodedAmount.currency = isoToHex(decodedCurrency)
|
||||
} else {
|
||||
/* eslint-disable-next-line @typescript-eslint/no-unsafe-member-access -- We need to update txCopy directly */
|
||||
txCopy[key].currency = isoToHex(txCopy[key].currency)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
/* eslint-enable @typescript-eslint/consistent-type-assertions -- Done with dynamic checking */
|
||||
|
||||
if (!_.isEqual(decoded, txCopy)) {
|
||||
const data = {
|
||||
decoded,
|
||||
@@ -509,4 +546,20 @@ function removeTrailingZeros(tx: Transaction): void {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an ISO code to a hex string representation
|
||||
*
|
||||
* @param iso - A 3 letter standard currency code
|
||||
*/
|
||||
/* eslint-disable @typescript-eslint/no-magic-numbers -- Magic numbers are from rippleds of currency code encoding */
|
||||
function isoToHex(iso: string): string {
|
||||
const bytes = Buffer.alloc(20)
|
||||
if (iso !== 'XRP') {
|
||||
const isoBytes = iso.split('').map((chr) => chr.charCodeAt(0))
|
||||
bytes.set(isoBytes, 12)
|
||||
}
|
||||
return bytes.toString('hex').toUpperCase()
|
||||
}
|
||||
/* eslint-enable @typescript-eslint/no-magic-numbers -- Only needed in this function */
|
||||
|
||||
export default Wallet
|
||||
|
||||
@@ -68,20 +68,6 @@ export interface SignerEntry {
|
||||
}
|
||||
}
|
||||
|
||||
export interface Sidechain {
|
||||
dst_chain_door: string
|
||||
dst_chain_issue: Currency
|
||||
src_chain_door: string
|
||||
src_chain_issue: Currency
|
||||
}
|
||||
|
||||
export interface XChainProofSig {
|
||||
XChainProofSig: {
|
||||
Signature: string
|
||||
PublicKey: string
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This information is added to Transactions in request responses, but is not part
|
||||
* of the canonical Transaction information on ledger. These fields are denoted with
|
||||
|
||||
78
packages/xrpl/src/models/methods/federatorInfo.ts
Normal file
78
packages/xrpl/src/models/methods/federatorInfo.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
import { BaseRequest, BaseResponse } from './baseMethod'
|
||||
|
||||
/**
|
||||
* The `federator_info` command asks the federator for information
|
||||
* about the door account and other bridge-related information. This
|
||||
* method only exists on sidechain federators. Expects a response in
|
||||
* the form of a {@link FederatorInfoResponse}.
|
||||
*
|
||||
* @category Requests
|
||||
*/
|
||||
export interface FederatorInfoRequest extends BaseRequest {
|
||||
command: 'federator_info'
|
||||
}
|
||||
|
||||
/**
|
||||
* Response expected from a {@link FederatorInfoRequest}.
|
||||
*
|
||||
* @category Responses
|
||||
*/
|
||||
export interface FederatorInfoResponse extends BaseResponse {
|
||||
result: {
|
||||
info: {
|
||||
mainchain: {
|
||||
door_status: {
|
||||
initialized: boolean
|
||||
status: 'open' | 'opening' | 'closed' | 'closing'
|
||||
}
|
||||
last_transaction_sent_seq: number
|
||||
listener_info: {
|
||||
state: 'syncing' | 'normal'
|
||||
}
|
||||
pending_transactions: Array<{
|
||||
amount: string
|
||||
destination_account: string
|
||||
signatures: Array<{
|
||||
public_key: string
|
||||
seq: number
|
||||
}>
|
||||
}>
|
||||
sequence: number
|
||||
tickets: {
|
||||
initialized: boolean
|
||||
tickets: Array<{
|
||||
status: 'taken' | 'available'
|
||||
ticket_seq: number
|
||||
}>
|
||||
}
|
||||
}
|
||||
public_key: string
|
||||
sidechain: {
|
||||
door_status: {
|
||||
initialized: boolean
|
||||
status: 'open' | 'opening' | 'closed' | 'closing'
|
||||
}
|
||||
last_transaction_sent_seq: number
|
||||
listener_info: {
|
||||
state: 'syncing' | 'normal'
|
||||
}
|
||||
pending_transactions: Array<{
|
||||
amount: string
|
||||
destination_account: string
|
||||
signatures: Array<{
|
||||
public_key: string
|
||||
seq: number
|
||||
}>
|
||||
}>
|
||||
sequence: number
|
||||
tickets: {
|
||||
initialized: boolean
|
||||
tickets: Array<{
|
||||
status: 'taken' | 'available'
|
||||
ticket_seq: number
|
||||
}>
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@ import {
|
||||
DepositAuthorizedRequest,
|
||||
DepositAuthorizedResponse,
|
||||
} from './depositAuthorized'
|
||||
import { FederatorInfoRequest, FederatorInfoResponse } from './federatorInfo'
|
||||
import { FeeRequest, FeeResponse } from './fee'
|
||||
import {
|
||||
GatewayBalancesRequest,
|
||||
@@ -120,6 +121,8 @@ type Request =
|
||||
// NFT methods
|
||||
| NFTBuyOffersRequest
|
||||
| NFTSellOffersRequest
|
||||
// sidechain methods
|
||||
| FederatorInfoRequest
|
||||
|
||||
/**
|
||||
* @category Responses
|
||||
@@ -168,6 +171,8 @@ type Response =
|
||||
// NFT methods
|
||||
| NFTBuyOffersResponse
|
||||
| NFTSellOffersResponse
|
||||
// sidechain methods
|
||||
| FederatorInfoResponse
|
||||
|
||||
export {
|
||||
Request,
|
||||
@@ -263,4 +268,7 @@ export {
|
||||
NFTBuyOffersResponse,
|
||||
NFTSellOffersRequest,
|
||||
NFTSellOffersResponse,
|
||||
// sidechain methods
|
||||
FederatorInfoRequest,
|
||||
FederatorInfoResponse,
|
||||
}
|
||||
|
||||
@@ -45,7 +45,3 @@ export { SetRegularKey } from './setRegularKey'
|
||||
export { SignerListSet } from './signerListSet'
|
||||
export { TicketCreate } from './ticketCreate'
|
||||
export { TrustSetFlagsInterface, TrustSetFlags, TrustSet } from './trustSet'
|
||||
export { XChainClaim } from './xChainClaim'
|
||||
export { XChainDoorCreate } from './xChainDoorCreate'
|
||||
export { XChainSeqNumCreate } from './xChainSeqNumCreate'
|
||||
export { XChainTransfer } from './xChainTransfer'
|
||||
|
||||
@@ -50,13 +50,6 @@ import { SetRegularKey, validateSetRegularKey } from './setRegularKey'
|
||||
import { SignerListSet, validateSignerListSet } from './signerListSet'
|
||||
import { TicketCreate, validateTicketCreate } from './ticketCreate'
|
||||
import { TrustSet, validateTrustSet } from './trustSet'
|
||||
import { XChainClaim, validateXChainClaim } from './xChainClaim'
|
||||
import { XChainDoorCreate, validateXChainDoorCreate } from './xChainDoorCreate'
|
||||
import {
|
||||
XChainSeqNumCreate,
|
||||
validateXChainSeqNumCreate,
|
||||
} from './xChainSeqNumCreate'
|
||||
import { XChainTransfer, validateXChainTransfer } from './xChainTransfer'
|
||||
|
||||
/**
|
||||
* @category Transaction Models
|
||||
@@ -86,10 +79,6 @@ export type Transaction =
|
||||
| SignerListSet
|
||||
| TicketCreate
|
||||
| TrustSet
|
||||
| XChainClaim
|
||||
| XChainDoorCreate
|
||||
| XChainSeqNumCreate
|
||||
| XChainTransfer
|
||||
|
||||
/**
|
||||
* @category Transaction Models
|
||||
@@ -214,22 +203,6 @@ export function validate(transaction: Record<string, unknown>): void {
|
||||
validateTrustSet(tx)
|
||||
break
|
||||
|
||||
case 'XChainClaim':
|
||||
validateXChainClaim(tx)
|
||||
break
|
||||
|
||||
case 'XChainDoorCreate':
|
||||
validateXChainDoorCreate(tx)
|
||||
break
|
||||
|
||||
case 'XChainSeqNumCreate':
|
||||
validateXChainSeqNumCreate(tx)
|
||||
break
|
||||
|
||||
case 'XChainTransfer':
|
||||
validateXChainTransfer(tx)
|
||||
break
|
||||
|
||||
default:
|
||||
throw new ValidationError(
|
||||
`Invalid field TransactionType: ${tx.TransactionType}`,
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
import { ValidationError } from '../../errors'
|
||||
import { Sidechain, XChainProofSig } from '../common'
|
||||
|
||||
import { BaseTransaction, validateBaseTransaction } from './common'
|
||||
|
||||
/**
|
||||
* A XChainClaim transaction assigns, changes, or removes the regular key
|
||||
* pair associated with an account.
|
||||
*
|
||||
* @category Transaction Models
|
||||
*/
|
||||
export interface XChainClaim extends BaseTransaction {
|
||||
TransactionType: 'XChainClaim'
|
||||
|
||||
XChainClaimProof: {
|
||||
amount: string
|
||||
|
||||
sidechain: Sidechain
|
||||
|
||||
signatures: XChainProofSig[]
|
||||
|
||||
was_src_chain_send: boolean
|
||||
|
||||
xchain_seq: number
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the form and type of a XChainClaim at runtime.
|
||||
*
|
||||
* @param tx - A XChainClaim Transaction.
|
||||
* @throws When the XChainClaim is malformed.
|
||||
*/
|
||||
export function validateXChainClaim(tx: Record<string, unknown>): void {
|
||||
validateBaseTransaction(tx)
|
||||
|
||||
if (tx.Sidechain !== undefined && typeof tx.Sidechain !== 'object') {
|
||||
throw new ValidationError('XChainClaim: Sidechain must be an object')
|
||||
}
|
||||
|
||||
if (tx.XChainSequence === undefined) {
|
||||
throw new ValidationError('EscrowCancel: missing XChainSequence')
|
||||
}
|
||||
|
||||
if (typeof tx.XChainSequence !== 'number') {
|
||||
throw new ValidationError('EscrowCancel: XChainSequence must be a number')
|
||||
}
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
import { ValidationError } from '../../errors'
|
||||
import { Sidechain, SignerEntry } from '../common'
|
||||
|
||||
import { BaseTransaction, validateBaseTransaction } from './common'
|
||||
|
||||
/**
|
||||
* A XChainDoorCreate transaction assigns, changes, or removes the regular key
|
||||
* pair associated with an account.
|
||||
*
|
||||
* @category Transaction Models
|
||||
*/
|
||||
export interface XChainDoorCreate extends BaseTransaction {
|
||||
TransactionType: 'XChainDoorCreate'
|
||||
|
||||
Sidechain: Sidechain
|
||||
|
||||
SignerEntries: SignerEntry[]
|
||||
|
||||
SignerQuorum: number
|
||||
}
|
||||
|
||||
const MAX_SIGNERS = 8
|
||||
|
||||
/**
|
||||
* Verify the form and type of a XChainDoorCreate at runtime.
|
||||
*
|
||||
* @param tx - A XChainDoorCreate Transaction.
|
||||
* @throws When the XChainDoorCreate is malformed.
|
||||
*/
|
||||
export function validateXChainDoorCreate(tx: Record<string, unknown>): void {
|
||||
validateBaseTransaction(tx)
|
||||
|
||||
if (tx.Sidechain !== undefined && typeof tx.Sidechain !== 'object') {
|
||||
throw new ValidationError('XChainDoorCreate: Sidechain must be an object')
|
||||
}
|
||||
|
||||
if (tx.SignerQuorum === undefined) {
|
||||
throw new ValidationError('SignerListSet: missing field SignerQuorum')
|
||||
}
|
||||
|
||||
if (typeof tx.SignerQuorum !== 'number') {
|
||||
throw new ValidationError('SignerListSet: invalid SignerQuorum')
|
||||
}
|
||||
|
||||
if (tx.SignerEntries === undefined) {
|
||||
throw new ValidationError('SignerListSet: missing field SignerEntries')
|
||||
}
|
||||
|
||||
if (!Array.isArray(tx.SignerEntries)) {
|
||||
throw new ValidationError('SignerListSet: invalid SignerEntries')
|
||||
}
|
||||
|
||||
if (tx.SignerEntries.length === 0) {
|
||||
throw new ValidationError(
|
||||
'SignerListSet: need atleast 1 member in SignerEntries',
|
||||
)
|
||||
}
|
||||
|
||||
if (tx.SignerEntries.length > MAX_SIGNERS) {
|
||||
throw new ValidationError(
|
||||
'SignerListSet: maximum of 8 members allowed in SignerEntries',
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
import { ValidationError } from '../../errors'
|
||||
import { Sidechain } from '../common'
|
||||
|
||||
import { BaseTransaction, validateBaseTransaction } from './common'
|
||||
|
||||
/**
|
||||
* A XChainSeqNumCreate transaction assigns, changes, or removes the regular key
|
||||
* pair associated with an account.
|
||||
*
|
||||
* @category Transaction Models
|
||||
*/
|
||||
export interface XChainSeqNumCreate extends BaseTransaction {
|
||||
TransactionType: 'XChainSeqNumCreate'
|
||||
|
||||
Sidechain: Sidechain
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the form and type of a XChainSeqNumCreate at runtime.
|
||||
*
|
||||
* @param tx - A XChainSeqNumCreate Transaction.
|
||||
* @throws When the XChainSeqNumCreate is malformed.
|
||||
*/
|
||||
export function validateXChainSeqNumCreate(tx: Record<string, unknown>): void {
|
||||
validateBaseTransaction(tx)
|
||||
|
||||
if (tx.Sidechain !== undefined && typeof tx.Sidechain !== 'object') {
|
||||
throw new ValidationError('XChainSeqNumCreate: Sidechain must be an object')
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
import { ValidationError } from '../../errors'
|
||||
import { Sidechain } from '../common'
|
||||
|
||||
import { BaseTransaction, validateBaseTransaction } from './common'
|
||||
|
||||
/**
|
||||
* A XChainTransfer transaction assigns, changes, or removes the regular key
|
||||
* pair associated with an account.
|
||||
*
|
||||
* @category Transaction Models
|
||||
*/
|
||||
export interface XChainTransfer extends BaseTransaction {
|
||||
TransactionType: 'XChainTransfer'
|
||||
|
||||
Sidechain: Sidechain
|
||||
|
||||
XChainSequence: 1
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the form and type of a XChainTransfer at runtime.
|
||||
*
|
||||
* @param tx - A XChainTransfer Transaction.
|
||||
* @throws When the XChainTransfer is malformed.
|
||||
*/
|
||||
export function validateXChainTransfer(tx: Record<string, unknown>): void {
|
||||
validateBaseTransaction(tx)
|
||||
|
||||
if (tx.Sidechain !== undefined && typeof tx.Sidechain !== 'object') {
|
||||
throw new ValidationError('XChainTransfer: Sidechain must be an object')
|
||||
}
|
||||
|
||||
if (tx.XChainSequence === undefined) {
|
||||
throw new ValidationError('EscrowCancel: missing XChainSequence')
|
||||
}
|
||||
|
||||
if (typeof tx.XChainSequence !== 'number') {
|
||||
throw new ValidationError('EscrowCancel: XChainSequence must be a number')
|
||||
}
|
||||
}
|
||||
40
packages/xrpl/src/utils/createCrossChainPayment.ts
Normal file
40
packages/xrpl/src/utils/createCrossChainPayment.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import { XrplError } from '../errors'
|
||||
import { Payment } from '../models'
|
||||
import { Memo } from '../models/common'
|
||||
|
||||
import { convertStringToHex } from './stringConversion'
|
||||
|
||||
/**
|
||||
* Creates a cross-chain payment transaction.
|
||||
*
|
||||
* @param payment - The initial payment transaction. If the transaction is
|
||||
* signed, then it will need to be re-signed. There must be no more than 2
|
||||
* memos, since one memo is used for the sidechain destination account. The
|
||||
* destination must be the sidechain's door account.
|
||||
* @param destAccount - the destination account on the sidechain.
|
||||
* @returns A cross-chain payment transaction, where the mainchain door account
|
||||
* is the `Destination` and the destination account on the sidechain is encoded
|
||||
* in the memos.
|
||||
* @throws XrplError - if there are more than 2 memos.
|
||||
* @category Utilities
|
||||
*/
|
||||
export default function createCrossChainPayment(
|
||||
payment: Payment,
|
||||
destAccount: string,
|
||||
): Payment {
|
||||
const destAccountHex = convertStringToHex(destAccount)
|
||||
const destAccountMemo: Memo = { Memo: { MemoData: destAccountHex } }
|
||||
|
||||
const memos = payment.Memos ?? []
|
||||
if (memos.length > 2) {
|
||||
throw new XrplError(
|
||||
'Cannot have more than 2 memos in a cross-chain transaction.',
|
||||
)
|
||||
}
|
||||
const newMemos = [destAccountMemo, ...memos]
|
||||
|
||||
const newPayment = { ...payment, Memos: newMemos }
|
||||
delete newPayment.TxnSignature
|
||||
|
||||
return newPayment
|
||||
}
|
||||
@@ -29,12 +29,6 @@ const ledgerSpaces = {
|
||||
paychan: 'x',
|
||||
check: 'C',
|
||||
depositPreauth: 'p',
|
||||
negativeUnl: 'N',
|
||||
nftokenOffer: 'q',
|
||||
nftokenBuyOffers: 'h',
|
||||
nftokenSellOffers: 'i',
|
||||
sidechain: 'H',
|
||||
xchainSeq: 'Q',
|
||||
}
|
||||
|
||||
export default ledgerSpaces
|
||||
|
||||
@@ -21,6 +21,7 @@ import { Response } from '../models/methods'
|
||||
import { PaymentChannelClaim } from '../models/transactions/paymentChannelClaim'
|
||||
import { Transaction } from '../models/transactions/transaction'
|
||||
|
||||
import createCrossChainPayment from './createCrossChainPayment'
|
||||
import { deriveKeypair, deriveAddress, deriveXAddress } from './derive'
|
||||
import getBalanceChanges from './getBalanceChanges'
|
||||
import {
|
||||
@@ -215,5 +216,6 @@ export {
|
||||
encodeForMultiSigning,
|
||||
encodeForSigning,
|
||||
encodeForSigningClaim,
|
||||
createCrossChainPayment,
|
||||
parseNFTokenID,
|
||||
}
|
||||
|
||||
@@ -69,6 +69,35 @@ describe('fundWallet', function () {
|
||||
await api.disconnect()
|
||||
})
|
||||
|
||||
it('can generate and fund wallets on nft-devnet', async function () {
|
||||
const api = new Client('ws://xls20-sandbox.rippletest.net:51233')
|
||||
|
||||
await api.connect()
|
||||
const { wallet, balance } = await api.fundWallet()
|
||||
assert.notEqual(wallet, undefined)
|
||||
assert(isValidClassicAddress(wallet.classicAddress))
|
||||
assert(isValidXAddress(wallet.getXAddress()))
|
||||
|
||||
const info = await api.request({
|
||||
command: 'account_info',
|
||||
account: wallet.classicAddress,
|
||||
})
|
||||
|
||||
assert.equal(dropsToXrp(info.result.account_data.Balance), balance)
|
||||
|
||||
const { balance: newBalance } = await api.fundWallet(wallet, {
|
||||
faucetHost: 'faucet-nft.ripple.com',
|
||||
})
|
||||
|
||||
const afterSent = await api.request({
|
||||
command: 'account_info',
|
||||
account: wallet.classicAddress,
|
||||
})
|
||||
assert.equal(dropsToXrp(afterSent.result.account_data.Balance), newBalance)
|
||||
|
||||
await api.disconnect()
|
||||
})
|
||||
|
||||
it('can generate and fund wallets using a custom host', async function () {
|
||||
const api = new Client('ws://xls20-sandbox.rippletest.net:51233')
|
||||
|
||||
|
||||
127
packages/xrpl/test/utils/createCrossChainPayment.ts
Normal file
127
packages/xrpl/test/utils/createCrossChainPayment.ts
Normal file
@@ -0,0 +1,127 @@
|
||||
import { assert } from 'chai'
|
||||
import {
|
||||
createCrossChainPayment,
|
||||
convertStringToHex,
|
||||
Payment,
|
||||
} from 'xrpl-local'
|
||||
|
||||
describe('createCrossChainPayment', function () {
|
||||
it('successful xchain payment creation', function () {
|
||||
const payment: Payment = {
|
||||
TransactionType: 'Payment',
|
||||
Account: 'rRandom',
|
||||
Destination: 'rRandom2',
|
||||
Amount: '3489303',
|
||||
}
|
||||
const sidechainAccount = 'rSidechain'
|
||||
|
||||
const expectedPayment = {
|
||||
...payment,
|
||||
Memos: [
|
||||
{
|
||||
Memo: {
|
||||
MemoData: convertStringToHex(sidechainAccount),
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const resultPayment = createCrossChainPayment(payment, sidechainAccount)
|
||||
assert.deepEqual(resultPayment, expectedPayment)
|
||||
|
||||
// ensure that the original object wasn't modified
|
||||
assert.notDeepEqual(resultPayment, payment)
|
||||
})
|
||||
|
||||
it('successful xchain payment creation with memo', function () {
|
||||
const memo = {
|
||||
Memo: {
|
||||
MemoData: 'deadbeef',
|
||||
},
|
||||
}
|
||||
const payment: Payment = {
|
||||
TransactionType: 'Payment',
|
||||
Account: 'rRandom',
|
||||
Destination: 'rRandom2',
|
||||
Amount: '3489303',
|
||||
Memos: [memo],
|
||||
}
|
||||
const sidechainAccount = 'rSidechain'
|
||||
|
||||
const expectedPayment = {
|
||||
...payment,
|
||||
Memos: [
|
||||
{
|
||||
Memo: {
|
||||
MemoData: convertStringToHex(sidechainAccount),
|
||||
},
|
||||
},
|
||||
memo,
|
||||
],
|
||||
}
|
||||
|
||||
const resultPayment = createCrossChainPayment(payment, sidechainAccount)
|
||||
assert.deepEqual(resultPayment, expectedPayment)
|
||||
|
||||
// ensure that the original object wasn't modified
|
||||
assert.notDeepEqual(resultPayment, payment)
|
||||
})
|
||||
|
||||
it('removes TxnSignature', function () {
|
||||
const payment: Payment = {
|
||||
TransactionType: 'Payment',
|
||||
Account: 'rRandom',
|
||||
Destination: 'rRandom2',
|
||||
Amount: '3489303',
|
||||
TxnSignature: 'asodfiuaosdfuaosd',
|
||||
}
|
||||
const sidechainAccount = 'rSidechain'
|
||||
|
||||
const expectedPayment = {
|
||||
...payment,
|
||||
Memos: [
|
||||
{
|
||||
Memo: {
|
||||
MemoData: convertStringToHex(sidechainAccount),
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
delete expectedPayment.TxnSignature
|
||||
|
||||
const resultPayment = createCrossChainPayment(payment, sidechainAccount)
|
||||
assert.deepEqual(resultPayment, expectedPayment)
|
||||
|
||||
// ensure that the original object wasn't modified
|
||||
assert.notDeepEqual(resultPayment, payment)
|
||||
})
|
||||
|
||||
it('fails with 3 memos', function () {
|
||||
const payment: Payment = {
|
||||
TransactionType: 'Payment',
|
||||
Account: 'rRandom',
|
||||
Destination: 'rRandom2',
|
||||
Amount: '3489303',
|
||||
Memos: [
|
||||
{
|
||||
Memo: {
|
||||
MemoData: '2934723843ace',
|
||||
},
|
||||
},
|
||||
{
|
||||
Memo: {
|
||||
MemoData: '2934723843ace',
|
||||
},
|
||||
},
|
||||
{
|
||||
Memo: {
|
||||
MemoData: '2934723843ace',
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
assert.throws(() => {
|
||||
createCrossChainPayment(payment, 'rSidechain')
|
||||
}, /Cannot have more than 2 memos/u)
|
||||
})
|
||||
})
|
||||
@@ -1,6 +1,6 @@
|
||||
import { assert } from 'chai'
|
||||
import { decode } from 'ripple-binary-codec/dist'
|
||||
import { NFTokenMint, Transaction } from 'xrpl-local'
|
||||
import { NFTokenMint, Payment, Transaction } from 'xrpl-local'
|
||||
import ECDSA from 'xrpl-local/ECDSA'
|
||||
import Wallet from 'xrpl-local/Wallet'
|
||||
|
||||
@@ -301,6 +301,7 @@ describe('Wallet', function () {
|
||||
})
|
||||
})
|
||||
|
||||
// eslint-disable-next-line max-statements -- Required for test coverage.
|
||||
describe('sign', function () {
|
||||
let wallet: Wallet
|
||||
|
||||
@@ -590,6 +591,114 @@ describe('Wallet', function () {
|
||||
}, /^1.1234567 is an illegal amount/u)
|
||||
})
|
||||
|
||||
const issuedCurrencyPayment: Transaction = {
|
||||
TransactionType: 'Payment',
|
||||
Account: 'r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59',
|
||||
Destination: 'rQ3PTWGLCbPz8ZCicV5tCX3xuymojTng5r',
|
||||
Amount: {
|
||||
currency: 'foo',
|
||||
issuer: 'rnURbz5HLbvqEq69b1B4TX6cUTNMmcrBqi',
|
||||
value: '123.40',
|
||||
},
|
||||
Flags: 2147483648,
|
||||
Sequence: 23,
|
||||
LastLedgerSequence: 8819954,
|
||||
Fee: '12',
|
||||
}
|
||||
|
||||
it('lowercase standard currency code signs successfully', async function () {
|
||||
const payment: Payment = { ...issuedCurrencyPayment }
|
||||
payment.Amount = {
|
||||
currency: 'foo',
|
||||
issuer: 'rnURbz5HLbvqEq69b1B4TX6cUTNMmcrBqi',
|
||||
value: '123.40',
|
||||
}
|
||||
|
||||
assert.deepEqual(wallet.sign(payment), {
|
||||
tx_blob:
|
||||
'12000022800000002400000017201B008694F261D504625103A72000000000000000000000000000666F6F00000000002E099DD75FDD96EB4A603037844F964832FED86B68400000000000000C732102A8A44DB3D4C73EEEE11DFE54D2029103B776AA8A8D293A91D645977C9DF5F54474473045022100D32EBD44F86FB6D0BE239A410B62A73A8B0C26CE3767321913D6FB7BE6FAC2410220430C011C25091DA9CD75E7C99BE406572FBB57B92132E39B4BF873863E744E2E81145E7B112523F68D2F5E879DB4EAC51C6698A693048314FDB08D07AAA0EB711793A3027304D688E10C3648',
|
||||
hash: 'F822EA1D7B2A3026E4654A9152896652C3843B5690F8A56C4217CB4690C5C95A',
|
||||
})
|
||||
})
|
||||
|
||||
it('issued currency in standard or hex format signs to the same transaction', async function () {
|
||||
const payment: Payment = { ...issuedCurrencyPayment }
|
||||
payment.Amount = {
|
||||
currency: '***',
|
||||
issuer: 'rnURbz5HLbvqEq69b1B4TX6cUTNMmcrBqi',
|
||||
value: '123.40',
|
||||
}
|
||||
|
||||
const payment2: Payment = { ...issuedCurrencyPayment }
|
||||
payment2.Amount = {
|
||||
currency: '0000000000000000000000002A2A2A0000000000',
|
||||
issuer: 'rnURbz5HLbvqEq69b1B4TX6cUTNMmcrBqi',
|
||||
value: '123.40',
|
||||
}
|
||||
|
||||
assert.deepEqual(wallet.sign(payment), wallet.sign(payment2))
|
||||
})
|
||||
|
||||
it('sign throws when a payment contains an issued currency like XRP', async function () {
|
||||
const payment: Payment = { ...issuedCurrencyPayment }
|
||||
payment.Amount = {
|
||||
currency: 'xrp',
|
||||
issuer: 'rnURbz5HLbvqEq69b1B4TX6cUTNMmcrBqi',
|
||||
value: '123.40',
|
||||
}
|
||||
assert.throws(() => {
|
||||
wallet.sign(payment)
|
||||
}, /^Trying to sign an issued currency with a similar standard code to XRP \(received 'xrp'\)\. XRP is not an issued currency\./u)
|
||||
})
|
||||
|
||||
it('sign does NOT throw when a payment contains an issued currency like xrp in hex string format', async function () {
|
||||
const payment: Payment = { ...issuedCurrencyPayment }
|
||||
payment.Amount = {
|
||||
currency: '0000000000000000000000007872700000000000',
|
||||
issuer: 'rnURbz5HLbvqEq69b1B4TX6cUTNMmcrBqi',
|
||||
value: '123.40',
|
||||
}
|
||||
assert.deepEqual(wallet.sign(payment), {
|
||||
tx_blob:
|
||||
'12000022800000002400000017201B008694F261D504625103A7200000000000000000000000000078727000000000002E099DD75FDD96EB4A603037844F964832FED86B68400000000000000C732102A8A44DB3D4C73EEEE11DFE54D2029103B776AA8A8D293A91D645977C9DF5F5447446304402202CD2BE27480860765B1B8DB6C499D299734C533F4FFA66317E46D1ADE5181EB7022066D2C65B975A6A9FEE56AB55211D5F2F65D6F988C8280019211874D11771A05D81145E7B112523F68D2F5E879DB4EAC51C6698A693048314FDB08D07AAA0EB711793A3027304D688E10C3648',
|
||||
hash: '1FEAA7894E507E36D73F60DED89852CE28994366879BC7D3D806E4C50D10B1EE',
|
||||
})
|
||||
})
|
||||
|
||||
it('sign succeeds with standard currency code with symbols', async function () {
|
||||
const payment: Payment = { ...issuedCurrencyPayment }
|
||||
payment.Amount = {
|
||||
currency: '***',
|
||||
issuer: 'rnURbz5HLbvqEq69b1B4TX6cUTNMmcrBqi',
|
||||
value: '123.40',
|
||||
}
|
||||
const result = wallet.sign(payment)
|
||||
const expectedResult = {
|
||||
tx_blob:
|
||||
'12000022800000002400000017201B008694F261D504625103A720000000000000000000000000002A2A2A00000000002E099DD75FDD96EB4A603037844F964832FED86B68400000000000000C732102A8A44DB3D4C73EEEE11DFE54D2029103B776AA8A8D293A91D645977C9DF5F54474463044022073E71588750C3D47D7D9A541F00FB897823DA67ED198D0A74404B6FE6D5E4AB5022021BE798D4159F375EBE13D0545F50EE864DF834D5A9F9A31504212156A57934C81145E7B112523F68D2F5E879DB4EAC51C6698A693048314FDB08D07AAA0EB711793A3027304D688E10C3648',
|
||||
hash: '95BF9931C1EA164960FE13A504D5FBAEB1E072C1D291D75B85BA3F22A50346DF',
|
||||
}
|
||||
|
||||
assert.deepEqual(result, expectedResult)
|
||||
})
|
||||
|
||||
it('sign succeeds with non-standard 3 digit currency code', async function () {
|
||||
const payment: Payment = { ...issuedCurrencyPayment }
|
||||
payment.Amount = {
|
||||
currency: ':::',
|
||||
issuer: 'rnURbz5HLbvqEq69b1B4TX6cUTNMmcrBqi',
|
||||
value: '123.40',
|
||||
}
|
||||
const result = wallet.sign(payment)
|
||||
const expectedResult = {
|
||||
tx_blob:
|
||||
'12000022800000002400000017201B008694F261D504625103A720000000000000000000000000003A3A3A00000000002E099DD75FDD96EB4A603037844F964832FED86B68400000000000000C732102A8A44DB3D4C73EEEE11DFE54D2029103B776AA8A8D293A91D645977C9DF5F5447446304402205952993DB235D3A6398E2CB5F91D7F0AD9067F02CB8E62FD335C516B64130F4702206777746CC516F95F39ADDD62CD395AF2F6BAFCCA355B5D23B9B4D9358474A11281145E7B112523F68D2F5E879DB4EAC51C6698A693048314FDB08D07AAA0EB711793A3027304D688E10C3648',
|
||||
hash: 'CE80072E6D70932BC7AA698B931BCF97B6CC3DD3984E08DF284B74E8CB4E543A',
|
||||
}
|
||||
|
||||
assert.deepEqual(result, expectedResult)
|
||||
})
|
||||
|
||||
it('sign handles non-XRP amount with a trailing zero', async function () {
|
||||
const payment: Transaction = {
|
||||
TransactionType: 'Payment',
|
||||
|
||||
Reference in New Issue
Block a user