UNPKG

6.73 kBJavaScriptView Raw
1"use strict";
2var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3 if (k2 === undefined) k2 = k;
4 Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5}) : (function(o, m, k, k2) {
6 if (k2 === undefined) k2 = k;
7 o[k2] = m[k];
8}));
9var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
10 Object.defineProperty(o, "default", { enumerable: true, value: v });
11}) : function(o, v) {
12 o["default"] = v;
13});
14var __importStar = (this && this.__importStar) || function (mod) {
15 if (mod && mod.__esModule) return mod;
16 var result = {};
17 if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
18 __setModuleDefault(result, mod);
19 return result;
20};
21var __importDefault = (this && this.__importDefault) || function (mod) {
22 return (mod && mod.__esModule) ? mod : { "default": mod };
23};
24Object.defineProperty(exports, "__esModule", { value: true });
25const lodash_1 = __importDefault(require("lodash"));
26const utils = __importStar(require("./utils"));
27const ripple_keypairs_1 = __importDefault(require("ripple-keypairs"));
28const ripple_binary_codec_1 = __importDefault(require("ripple-binary-codec"));
29const hashes_1 = require("../common/hashes");
30const bignumber_js_1 = __importDefault(require("bignumber.js"));
31const common_1 = require("../common");
32const validate = utils.common.validate;
33function computeSignature(tx, privateKey, signAs) {
34 const signingData = signAs
35 ? ripple_binary_codec_1.default.encodeForMultisigning(tx, signAs)
36 : ripple_binary_codec_1.default.encodeForSigning(tx);
37 return ripple_keypairs_1.default.sign(signingData, privateKey);
38}
39function signWithKeypair(api, txJSON, keypair, options = {
40 signAs: ''
41}) {
42 validate.sign({ txJSON, keypair });
43 const tx = JSON.parse(txJSON);
44 if (tx.TxnSignature || tx.Signers) {
45 throw new utils.common.errors.ValidationError('txJSON must not contain "TxnSignature" or "Signers" properties');
46 }
47 checkFee(api, tx.Fee);
48 const txToSignAndEncode = Object.assign({}, tx);
49 txToSignAndEncode.SigningPubKey = options.signAs ? '' : keypair.publicKey;
50 if (options.signAs) {
51 const signer = {
52 Account: options.signAs,
53 SigningPubKey: keypair.publicKey,
54 TxnSignature: computeSignature(txToSignAndEncode, keypair.privateKey, options.signAs)
55 };
56 txToSignAndEncode.Signers = [{ Signer: signer }];
57 }
58 else {
59 txToSignAndEncode.TxnSignature = computeSignature(txToSignAndEncode, keypair.privateKey);
60 }
61 const serialized = ripple_binary_codec_1.default.encode(txToSignAndEncode);
62 checkTxSerialization(serialized, tx);
63 return {
64 signedTransaction: serialized,
65 id: hashes_1.computeBinaryTransactionHash(serialized)
66 };
67}
68function objectDiff(a, b) {
69 const diffs = {};
70 const compare = function (i1, i2, k) {
71 const type1 = Object.prototype.toString.call(i1);
72 const type2 = Object.prototype.toString.call(i2);
73 if (type2 === '[object Undefined]') {
74 diffs[k] = null;
75 return;
76 }
77 if (type1 !== type2) {
78 diffs[k] = i2;
79 return;
80 }
81 if (type1 === '[object Object]') {
82 const objDiff = objectDiff(i1, i2);
83 if (Object.keys(objDiff).length > 0) {
84 diffs[k] = objDiff;
85 }
86 return;
87 }
88 if (type1 === '[object Array]') {
89 if (!lodash_1.default.isEqual(i1, i2)) {
90 diffs[k] = i2;
91 }
92 return;
93 }
94 if (type1 === '[object Function]') {
95 if (i1.toString() !== i2.toString()) {
96 diffs[k] = i2;
97 }
98 return;
99 }
100 if (i1 !== i2) {
101 diffs[k] = i2;
102 }
103 };
104 for (const key in a) {
105 if (a.hasOwnProperty(key)) {
106 compare(a[key], b[key], key);
107 }
108 }
109 for (const key in b) {
110 if (b.hasOwnProperty(key)) {
111 if (!a[key] && a[key] !== b[key]) {
112 diffs[key] = b[key];
113 }
114 }
115 }
116 return diffs;
117}
118function checkTxSerialization(serialized, tx) {
119 var _a;
120 const decoded = ripple_binary_codec_1.default.decode(serialized);
121 if (!decoded.TxnSignature && !decoded.Signers) {
122 throw new utils.common.errors.ValidationError('Serialized transaction must have a TxnSignature or Signers property');
123 }
124 delete decoded.TxnSignature;
125 delete decoded.Signers;
126 if (!tx.SigningPubKey) {
127 delete decoded.SigningPubKey;
128 }
129 (_a = tx.Memos) === null || _a === void 0 ? void 0 : _a.map(memo => {
130 var _a, _b, _c;
131 if ((_a = memo === null || memo === void 0 ? void 0 : memo.Memo) === null || _a === void 0 ? void 0 : _a.MemoData) {
132 memo.Memo.MemoData = memo.Memo.MemoData.toUpperCase();
133 }
134 if ((_b = memo === null || memo === void 0 ? void 0 : memo.Memo) === null || _b === void 0 ? void 0 : _b.MemoType) {
135 memo.Memo.MemoType = memo.Memo.MemoType.toUpperCase();
136 }
137 if ((_c = memo === null || memo === void 0 ? void 0 : memo.Memo) === null || _c === void 0 ? void 0 : _c.MemoFormat) {
138 memo.Memo.MemoFormat = memo.Memo.MemoFormat.toUpperCase();
139 }
140 return memo;
141 });
142 if (!lodash_1.default.isEqual(decoded, tx)) {
143 const error = new utils.common.errors.ValidationError('Serialized transaction does not match original txJSON. See `error.data`');
144 error.data = {
145 decoded,
146 tx,
147 diff: objectDiff(tx, decoded)
148 };
149 throw error;
150 }
151}
152function checkFee(api, txFee) {
153 const fee = new bignumber_js_1.default(txFee);
154 const maxFeeDrops = common_1.xrpToDrops(api._maxFeeXRP);
155 if (fee.isGreaterThan(maxFeeDrops)) {
156 throw new utils.common.errors.ValidationError(`"Fee" should not exceed "${maxFeeDrops}". ` +
157 'To use a higher fee, set `maxFeeXRP` in the RippleAPI constructor.');
158 }
159}
160function sign(txJSON, secret, options, keypair) {
161 if (typeof secret === 'string') {
162 validate.sign({ txJSON, secret });
163 return signWithKeypair(this, txJSON, ripple_keypairs_1.default.deriveKeypair(secret), options);
164 }
165 else {
166 if (!keypair && !secret) {
167 throw new utils.common.errors.ValidationError('sign: Missing secret or keypair.');
168 }
169 return signWithKeypair(this, txJSON, keypair ? keypair : secret, options);
170 }
171}
172exports.default = sign;
173//# sourceMappingURL=sign.js.map
\No newline at end of file