ripple-binary-codec 1.6.0 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -321,6 +321,16 @@
321
321
  "type": "UInt16"
322
322
  }
323
323
  ],
324
+ [
325
+ "NetworkID",
326
+ {
327
+ "nth": 1,
328
+ "isVLEncoded": false,
329
+ "isSerialized": true,
330
+ "isSigningField": true,
331
+ "type": "UInt32"
332
+ }
333
+ ],
324
334
  [
325
335
  "Flags",
326
336
  {
@@ -2176,6 +2186,9 @@
2176
2186
  "telCAN_NOT_QUEUE_BLOCKED": -389,
2177
2187
  "telCAN_NOT_QUEUE_FEE": -388,
2178
2188
  "telCAN_NOT_QUEUE_FULL": -387,
2189
+ "telWRONG_NETWORK": -386,
2190
+ "telREQUIRES_NETWORK_ID": -385,
2191
+ "telNETWORK_ID_MAKES_TX_NON_CANONICAL": -384,
2179
2192
  "temMALFORMED": -299,
2180
2193
  "temBAD_AMOUNT": -298,
2181
2194
  "temBAD_CURRENCY": -297,
@@ -321,6 +321,16 @@
321
321
  "type": "UInt16"
322
322
  }
323
323
  ],
324
+ [
325
+ "NetworkID",
326
+ {
327
+ "nth": 1,
328
+ "isVLEncoded": false,
329
+ "isSerialized": true,
330
+ "isSigningField": true,
331
+ "type": "UInt32"
332
+ }
333
+ ],
324
334
  [
325
335
  "Flags",
326
336
  {
@@ -2176,6 +2186,9 @@
2176
2186
  "telCAN_NOT_QUEUE_BLOCKED": -389,
2177
2187
  "telCAN_NOT_QUEUE_FEE": -388,
2178
2188
  "telCAN_NOT_QUEUE_FULL": -387,
2189
+ "telWRONG_NETWORK": -386,
2190
+ "telREQUIRES_NETWORK_ID": -385,
2191
+ "telNETWORK_ID_MAKES_TX_NON_CANONICAL": -384,
2179
2192
 
2180
2193
  "temMALFORMED": -299,
2181
2194
  "temBAD_AMOUNT": -298,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ripple-binary-codec",
3
- "version": "1.6.0",
3
+ "version": "1.7.0",
4
4
  "description": "XRP Ledger binary codec",
5
5
  "files": [
6
6
  "dist/*",
@@ -40,5 +40,5 @@
40
40
  "engines": {
41
41
  "node": ">= 10"
42
42
  },
43
- "gitHead": "3791c6292cee7e6d6ff46a17fcd26aae2d323439"
43
+ "gitHead": "c523a7c80b43a6e0faa5ec2a54b27c21b722497e"
44
44
  }
@@ -1,39 +0,0 @@
1
- import { BinaryParser } from '../serdes/binary-parser';
2
- import { JsonObject, SerializedType } from './serialized-type';
3
- import { Buffer } from 'buffer/';
4
- /**
5
- * Interface for JSON objects that represent amounts
6
- */
7
- interface IssueObject extends JsonObject {
8
- currency: string;
9
- issuer?: string;
10
- }
11
- /**
12
- * Class for serializing/Deserializing Amounts
13
- */
14
- declare class Issue extends SerializedType {
15
- static readonly ZERO_ISSUED_CURRENCY: Issue;
16
- constructor(bytes: Buffer);
17
- /**
18
- * Construct an amount from an IOU or string amount
19
- *
20
- * @param value An Amount, object representing an IOU, or a string
21
- * representing an integer amount
22
- * @returns An Amount object
23
- */
24
- static from<T extends Issue | IssueObject>(value: T): Issue;
25
- /**
26
- * Read an amount from a BinaryParser
27
- *
28
- * @param parser BinaryParser to read the Amount from
29
- * @returns An Amount object
30
- */
31
- static fromParser(parser: BinaryParser): Issue;
32
- /**
33
- * Get the JSON representation of this Amount
34
- *
35
- * @returns the JSON interpretation of this.bytes
36
- */
37
- toJSON(): IssueObject;
38
- }
39
- export { Issue, IssueObject };
@@ -1,81 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Issue = void 0;
4
- const binary_parser_1 = require("../serdes/binary-parser");
5
- const account_id_1 = require("./account-id");
6
- const currency_1 = require("./currency");
7
- const serialized_type_1 = require("./serialized-type");
8
- const buffer_1 = require("buffer/");
9
- /**
10
- * Type guard for AmountObject
11
- */
12
- function isIssueObject(arg) {
13
- const keys = Object.keys(arg).sort();
14
- if (keys.length === 1) {
15
- return keys[0] === 'currency';
16
- }
17
- return keys.length === 2 && keys[0] === 'currency' && keys[1] === 'issuer';
18
- }
19
- /**
20
- * Class for serializing/Deserializing Amounts
21
- */
22
- class Issue extends serialized_type_1.SerializedType {
23
- constructor(bytes) {
24
- super(bytes !== null && bytes !== void 0 ? bytes : Issue.ZERO_ISSUED_CURRENCY.bytes);
25
- }
26
- /**
27
- * Construct an amount from an IOU or string amount
28
- *
29
- * @param value An Amount, object representing an IOU, or a string
30
- * representing an integer amount
31
- * @returns An Amount object
32
- */
33
- static from(value) {
34
- if (value instanceof Issue) {
35
- return value;
36
- }
37
- if (isIssueObject(value)) {
38
- const currency = currency_1.Currency.from(value.currency).toBytes();
39
- if (value.issuer == null) {
40
- return new Issue(currency);
41
- }
42
- const issuer = account_id_1.AccountID.from(value.issuer).toBytes();
43
- return new Issue(buffer_1.Buffer.concat([currency, issuer]));
44
- }
45
- throw new Error('Invalid type to construct an Amount');
46
- }
47
- /**
48
- * Read an amount from a BinaryParser
49
- *
50
- * @param parser BinaryParser to read the Amount from
51
- * @returns An Amount object
52
- */
53
- static fromParser(parser) {
54
- const currency = parser.read(20);
55
- if (new currency_1.Currency(currency).toJSON() === 'XRP') {
56
- return new Issue(currency);
57
- }
58
- const currencyAndIssuer = [currency, parser.read(20)];
59
- return new Issue(buffer_1.Buffer.concat(currencyAndIssuer));
60
- }
61
- /**
62
- * Get the JSON representation of this Amount
63
- *
64
- * @returns the JSON interpretation of this.bytes
65
- */
66
- toJSON() {
67
- const parser = new binary_parser_1.BinaryParser(this.toString());
68
- const currency = currency_1.Currency.fromParser(parser);
69
- if (currency.toJSON() === 'XRP') {
70
- return { currency: currency.toJSON() };
71
- }
72
- const issuer = account_id_1.AccountID.fromParser(parser);
73
- return {
74
- currency: currency.toJSON(),
75
- issuer: issuer.toJSON(),
76
- };
77
- }
78
- }
79
- exports.Issue = Issue;
80
- Issue.ZERO_ISSUED_CURRENCY = new Issue(buffer_1.Buffer.alloc(20));
81
- //# sourceMappingURL=issue.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"issue.js","sourceRoot":"","sources":["../../src/types/issue.ts"],"names":[],"mappings":";;;AAAA,2DAAsD;AAEtD,6CAAwC;AACxC,yCAAqC;AACrC,uDAA8D;AAC9D,oCAAgC;AAUhC;;GAEG;AACH,SAAS,aAAa,CAAC,GAAG;IACxB,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAA;IACpC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE;QACrB,OAAO,IAAI,CAAC,CAAC,CAAC,KAAK,UAAU,CAAA;KAC9B;IACD,OAAO,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,UAAU,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAA;AAC5E,CAAC;AAED;;GAEG;AACH,MAAM,KAAM,SAAQ,gCAAc;IAGhC,YAAY,KAAa;QACvB,KAAK,CAAC,KAAK,aAAL,KAAK,cAAL,KAAK,GAAI,KAAK,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAA;IAClD,CAAC;IAED;;;;;;OAMG;IACH,MAAM,CAAC,IAAI,CAAgC,KAAQ;QACjD,IAAI,KAAK,YAAY,KAAK,EAAE;YAC1B,OAAO,KAAK,CAAA;SACb;QAED,IAAI,aAAa,CAAC,KAAK,CAAC,EAAE;YACxB,MAAM,QAAQ,GAAG,mBAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,OAAO,EAAE,CAAA;YACxD,IAAI,KAAK,CAAC,MAAM,IAAI,IAAI,EAAE;gBACxB,OAAO,IAAI,KAAK,CAAC,QAAQ,CAAC,CAAA;aAC3B;YACD,MAAM,MAAM,GAAG,sBAAS,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,CAAA;YACrD,OAAO,IAAI,KAAK,CAAC,eAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,CAAA;SACpD;QAED,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAA;IACxD,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,UAAU,CAAC,MAAoB;QACpC,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QAChC,IAAI,IAAI,mBAAQ,CAAC,QAAQ,CAAC,CAAC,MAAM,EAAE,KAAK,KAAK,EAAE;YAC7C,OAAO,IAAI,KAAK,CAAC,QAAQ,CAAC,CAAA;SAC3B;QACD,MAAM,iBAAiB,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAA;QACrD,OAAO,IAAI,KAAK,CAAC,eAAM,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAA;IACpD,CAAC;IAED;;;;OAIG;IACH,MAAM;QACJ,MAAM,MAAM,GAAG,IAAI,4BAAY,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAA;QAChD,MAAM,QAAQ,GAAG,mBAAQ,CAAC,UAAU,CAAC,MAAM,CAAa,CAAA;QACxD,IAAI,QAAQ,CAAC,MAAM,EAAE,KAAK,KAAK,EAAE;YAC/B,OAAO,EAAE,QAAQ,EAAE,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAA;SACvC;QACD,MAAM,MAAM,GAAG,sBAAS,CAAC,UAAU,CAAC,MAAM,CAAc,CAAA;QAExD,OAAO;YACL,QAAQ,EAAE,QAAQ,CAAC,MAAM,EAAE;YAC3B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE;SACxB,CAAA;IACH,CAAC;;AAGM,sBAAK;AAjEI,0BAAoB,GAAU,IAAI,KAAK,CAAC,eAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAA"}
@@ -1,45 +0,0 @@
1
- import { BinaryParser } from '../serdes/binary-parser';
2
- import { JsonObject, SerializedType } from './serialized-type';
3
- import { Buffer } from 'buffer/';
4
- import { IssueObject } from './issue';
5
- /**
6
- * Interface for JSON objects that represent cross-chain bridges
7
- */
8
- interface XChainBridgeObject extends JsonObject {
9
- LockingChainDoor: string;
10
- LockingChainIssue: IssueObject | string;
11
- IssuingChainDoor: string;
12
- IssuingChainIssue: IssueObject | string;
13
- }
14
- /**
15
- * Class for serializing/deserializing XChainBridges
16
- */
17
- declare class XChainBridge extends SerializedType {
18
- static readonly ZERO_XCHAIN_BRIDGE: XChainBridge;
19
- static readonly TYPE_ORDER: {
20
- name: string;
21
- type: typeof SerializedType;
22
- }[];
23
- constructor(bytes: Buffer);
24
- /**
25
- * Construct a cross-chain bridge from a JSON
26
- *
27
- * @param value XChainBridge or JSON to parse into a XChainBridge
28
- * @returns A XChainBridge object
29
- */
30
- static from<T extends XChainBridge | XChainBridgeObject>(value: T): XChainBridge;
31
- /**
32
- * Read a XChainBridge from a BinaryParser
33
- *
34
- * @param parser BinaryParser to read the XChainBridge from
35
- * @returns A XChainBridge object
36
- */
37
- static fromParser(parser: BinaryParser): XChainBridge;
38
- /**
39
- * Get the JSON representation of this XChainBridge
40
- *
41
- * @returns the JSON interpretation of this.bytes
42
- */
43
- toJSON(): XChainBridgeObject;
44
- }
45
- export { XChainBridge, XChainBridgeObject };
@@ -1,102 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.XChainBridge = void 0;
4
- const binary_parser_1 = require("../serdes/binary-parser");
5
- const account_id_1 = require("./account-id");
6
- const serialized_type_1 = require("./serialized-type");
7
- const buffer_1 = require("buffer/");
8
- const issue_1 = require("./issue");
9
- /**
10
- * Type guard for XChainBridgeObject
11
- */
12
- function isXChainBridgeObject(arg) {
13
- const keys = Object.keys(arg).sort();
14
- return (keys.length === 4 &&
15
- keys[0] === 'IssuingChainDoor' &&
16
- keys[1] === 'IssuingChainIssue' &&
17
- keys[2] === 'LockingChainDoor' &&
18
- keys[3] === 'LockingChainIssue');
19
- }
20
- /**
21
- * Class for serializing/deserializing XChainBridges
22
- */
23
- class XChainBridge extends serialized_type_1.SerializedType {
24
- constructor(bytes) {
25
- super(bytes !== null && bytes !== void 0 ? bytes : XChainBridge.ZERO_XCHAIN_BRIDGE.bytes);
26
- }
27
- /**
28
- * Construct a cross-chain bridge from a JSON
29
- *
30
- * @param value XChainBridge or JSON to parse into a XChainBridge
31
- * @returns A XChainBridge object
32
- */
33
- static from(value) {
34
- if (value instanceof XChainBridge) {
35
- return value;
36
- }
37
- if (isXChainBridgeObject(value)) {
38
- const bytes = [];
39
- this.TYPE_ORDER.forEach((item) => {
40
- const { name, type } = item;
41
- if (type === account_id_1.AccountID) {
42
- bytes.push(buffer_1.Buffer.from([0x14]));
43
- }
44
- const object = type.from(value[name]);
45
- bytes.push(object.toBytes());
46
- });
47
- return new XChainBridge(buffer_1.Buffer.concat(bytes));
48
- }
49
- throw new Error('Invalid type to construct a XChainBridge');
50
- }
51
- /**
52
- * Read a XChainBridge from a BinaryParser
53
- *
54
- * @param parser BinaryParser to read the XChainBridge from
55
- * @returns A XChainBridge object
56
- */
57
- static fromParser(parser) {
58
- const bytes = [];
59
- this.TYPE_ORDER.forEach((item) => {
60
- const { type } = item;
61
- if (type === account_id_1.AccountID) {
62
- parser.skip(1);
63
- bytes.push(buffer_1.Buffer.from([0x14]));
64
- }
65
- const object = type.fromParser(parser);
66
- bytes.push(object.toBytes());
67
- });
68
- return new XChainBridge(buffer_1.Buffer.concat(bytes));
69
- }
70
- /**
71
- * Get the JSON representation of this XChainBridge
72
- *
73
- * @returns the JSON interpretation of this.bytes
74
- */
75
- toJSON() {
76
- const parser = new binary_parser_1.BinaryParser(this.toString());
77
- const json = {};
78
- XChainBridge.TYPE_ORDER.forEach((item) => {
79
- const { name, type } = item;
80
- if (type === account_id_1.AccountID) {
81
- parser.skip(1);
82
- }
83
- const object = type.fromParser(parser).toJSON();
84
- json[name] = object;
85
- });
86
- return json;
87
- }
88
- }
89
- exports.XChainBridge = XChainBridge;
90
- XChainBridge.ZERO_XCHAIN_BRIDGE = new XChainBridge(buffer_1.Buffer.concat([
91
- buffer_1.Buffer.from([0x14]),
92
- buffer_1.Buffer.alloc(40),
93
- buffer_1.Buffer.from([0x14]),
94
- buffer_1.Buffer.alloc(40),
95
- ]));
96
- XChainBridge.TYPE_ORDER = [
97
- { name: 'LockingChainDoor', type: account_id_1.AccountID },
98
- { name: 'LockingChainIssue', type: issue_1.Issue },
99
- { name: 'IssuingChainDoor', type: account_id_1.AccountID },
100
- { name: 'IssuingChainIssue', type: issue_1.Issue },
101
- ];
102
- //# sourceMappingURL=xchain-bridge.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"xchain-bridge.js","sourceRoot":"","sources":["../../src/types/xchain-bridge.ts"],"names":[],"mappings":"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"}