@caict/bop-typescript-sdk 1.0.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.
Files changed (115) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/LICENSE +202 -0
  3. package/NOTICE +5 -0
  4. package/README.md +112 -0
  5. package/package.json +90 -0
  6. package/src/bop/bop-base/README.md +5 -0
  7. package/src/bop/bop-base/base.ts +366 -0
  8. package/src/bop/bop-base/index.ts +83 -0
  9. package/src/bop/bop-base/permit.ts +116 -0
  10. package/src/bop/bop-base/test/base.test.ts +867 -0
  11. package/src/bop/bop-base/test/index.test.ts +69 -0
  12. package/src/bop/bop-base/test/permit.test.ts +125 -0
  13. package/src/bop/bop-base/tsconfig.json +8 -0
  14. package/src/bop/bop-proto/README.md +2 -0
  15. package/src/bop/bop-proto/bop-ws.proto +266 -0
  16. package/src/bop/bop-proto/bop-ws.ts +4447 -0
  17. package/src/bop/bop-proto/bop.proto +898 -0
  18. package/src/bop/bop-proto/bop.ts +12890 -0
  19. package/src/bop/bop-proto/tsconfig.json +8 -0
  20. package/src/bop/bop-ws/index.ts +315 -0
  21. package/src/bop/bop-ws/sample/sample.ts +107 -0
  22. package/src/bop/bop-ws/tsconfig.json +8 -0
  23. package/src/bop/index.ts +14 -0
  24. package/src/bop-sdk/index.ts +22 -0
  25. package/src/bop-sdk/interface/abstract-service/abstract-account.ts +23 -0
  26. package/src/bop-sdk/interface/abstract-service/abstract-chain.ts +9 -0
  27. package/src/bop-sdk/interface/abstract-service/abstract-contract.ts +16 -0
  28. package/src/bop-sdk/interface/abstract-service/abstract-ledger.ts +15 -0
  29. package/src/bop-sdk/interface/abstract-service/abstract-provider.ts +13 -0
  30. package/src/bop-sdk/interface/abstract-service/abstract-signer.ts +133 -0
  31. package/src/bop-sdk/interface/abstract-service/abstract-transaction.ts +86 -0
  32. package/src/bop-sdk/interface/provider-ws.ts +10 -0
  33. package/src/bop-sdk/interface/provider.ts +22 -0
  34. package/src/bop-sdk/interface/service/3rd.ts +54 -0
  35. package/src/bop-sdk/interface/service/account.ts +86 -0
  36. package/src/bop-sdk/interface/service/chain.ts +27 -0
  37. package/src/bop-sdk/interface/service/contract.ts +51 -0
  38. package/src/bop-sdk/interface/service/helper.ts +426 -0
  39. package/src/bop-sdk/interface/service/ledger.ts +75 -0
  40. package/src/bop-sdk/interface/service/offline/check/index.js +138 -0
  41. package/src/bop-sdk/interface/service/offline/common/constant.js +6 -0
  42. package/src/bop-sdk/interface/service/offline/common/snowFlakeUtils.js +192 -0
  43. package/src/bop-sdk/interface/service/offline/common/util.js +511 -0
  44. package/src/bop-sdk/interface/service/offline/exception/customErrors.js +29 -0
  45. package/src/bop-sdk/interface/service/offline/exception/errors.js +90 -0
  46. package/src/bop-sdk/interface/service/offline/exception/index.js +5 -0
  47. package/src/bop-sdk/interface/service/offline/operation/accountCreateOperation.js +28 -0
  48. package/src/bop-sdk/interface/service/offline/operation/accountSetMetadataOperation.js +44 -0
  49. package/src/bop-sdk/interface/service/offline/operation/accountSetPrivilegeOperation.js +49 -0
  50. package/src/bop-sdk/interface/service/offline/operation/contractCreateOperation.js +43 -0
  51. package/src/bop-sdk/interface/service/offline/operation/contractInvokeOperation.js +42 -0
  52. package/src/bop-sdk/interface/service/offline/operation/contractInvokeRequestOperation.js +69 -0
  53. package/src/bop-sdk/interface/service/offline/operation/gasSendOperation.js +29 -0
  54. package/src/bop-sdk/interface/service/offline/operation/gasSendRequestOperation.js +61 -0
  55. package/src/bop-sdk/interface/service/offline/operation/index.js +20 -0
  56. package/src/bop-sdk/interface/service/offline/proto/chain_pb.js +12079 -0
  57. package/src/bop-sdk/interface/service/offline/proto/common_pb.js +2867 -0
  58. package/src/bop-sdk/interface/service/offline/transaction/index.js +988 -0
  59. package/src/bop-sdk/interface/service/offline/transaction/operations.js +188 -0
  60. package/src/bop-sdk/interface/service/offline/validate/account.js +152 -0
  61. package/src/bop-sdk/interface/service/offline/validate/contract.js +101 -0
  62. package/src/bop-sdk/interface/service/offline/validate/index.js +10 -0
  63. package/src/bop-sdk/interface/service/offline/validate/transaction.js +51 -0
  64. package/src/bop-sdk/interface/service/transaction.ts +731 -0
  65. package/src/bop-sdk/interface/signer.ts +46 -0
  66. package/src/bop-sdk/interface/test/3rd.test.ts +1571 -0
  67. package/src/bop-sdk/interface/test/account.test.ts +284 -0
  68. package/src/bop-sdk/interface/test/chain.test.ts +45 -0
  69. package/src/bop-sdk/interface/test/contract.test.ts +283 -0
  70. package/src/bop-sdk/interface/test/ledger.test.ts +166 -0
  71. package/src/bop-sdk/interface/test/provider.test.ts +407 -0
  72. package/src/bop-sdk/interface/test/signer.test.ts +105 -0
  73. package/src/bop-sdk/interface/test/transaction.test.ts +713 -0
  74. package/src/bop-sdk/proto/bop-sdk-common.proto +159 -0
  75. package/src/bop-sdk/proto/bop-sdk-common.ts +829 -0
  76. package/src/bop-sdk/proto/bop-sdk-interface.proto +581 -0
  77. package/src/bop-sdk/proto/bop-sdk-interface.ts +10839 -0
  78. package/src/bop-sdk/proto/bop-sdk-utils.proto +86 -0
  79. package/src/bop-sdk/proto/bop-sdk-utils.ts +1495 -0
  80. package/src/bop-sdk/utils/abi/abi-coder.ts +147 -0
  81. package/src/bop-sdk/utils/abi/address.ts +109 -0
  82. package/src/bop-sdk/utils/abi/bignumber.ts +403 -0
  83. package/src/bop-sdk/utils/abi/bytes.ts +565 -0
  84. package/src/bop-sdk/utils/abi/coders/abstract-coder.ts +239 -0
  85. package/src/bop-sdk/utils/abi/coders/address.ts +58 -0
  86. package/src/bop-sdk/utils/abi/coders/anonymous.ts +25 -0
  87. package/src/bop-sdk/utils/abi/coders/array.ts +275 -0
  88. package/src/bop-sdk/utils/abi/coders/boolean.ts +21 -0
  89. package/src/bop-sdk/utils/abi/coders/bytes.ts +36 -0
  90. package/src/bop-sdk/utils/abi/coders/fixed-bytes.ts +35 -0
  91. package/src/bop-sdk/utils/abi/coders/null.ts +25 -0
  92. package/src/bop-sdk/utils/abi/coders/number.ts +56 -0
  93. package/src/bop-sdk/utils/abi/coders/string.ts +24 -0
  94. package/src/bop-sdk/utils/abi/coders/tuple.ts +73 -0
  95. package/src/bop-sdk/utils/abi/constants/addresses.ts +1 -0
  96. package/src/bop-sdk/utils/abi/constants/bignumbers.ts +30 -0
  97. package/src/bop-sdk/utils/abi/constants/hashes.ts +2 -0
  98. package/src/bop-sdk/utils/abi/constants/index.ts +15 -0
  99. package/src/bop-sdk/utils/abi/constants/strings.ts +2 -0
  100. package/src/bop-sdk/utils/abi/fragments.ts +1243 -0
  101. package/src/bop-sdk/utils/abi/id.ts +6 -0
  102. package/src/bop-sdk/utils/abi/index.ts +46 -0
  103. package/src/bop-sdk/utils/abi/interface.ts +921 -0
  104. package/src/bop-sdk/utils/abi/keccak256.ts +9 -0
  105. package/src/bop-sdk/utils/abi/properties.ts +172 -0
  106. package/src/bop-sdk/utils/abi/strings/bytes32.ts +40 -0
  107. package/src/bop-sdk/utils/abi/strings/idna.ts +258 -0
  108. package/src/bop-sdk/utils/abi/strings/index.ts +28 -0
  109. package/src/bop-sdk/utils/abi/strings/utf8.ts +373 -0
  110. package/src/bop-sdk/utils/encryption-address.ts +501 -0
  111. package/src/bop-sdk/utils/encryption-crypto.ts +427 -0
  112. package/src/bop-sdk/utils/encryption-mnemonics.ts +120 -0
  113. package/src/bop-sdk/utils/index.ts +27 -0
  114. package/src/bop-sdk/utils/logger.ts +480 -0
  115. package/src/index.ts +35 -0
@@ -0,0 +1,565 @@
1
+ "use strict";
2
+
3
+ import { Logger } from "../logger";
4
+ const version = "bytes/5.7.0";
5
+ const logger = new Logger(version);
6
+
7
+ ///////////////////////////////
8
+ // Exported Types
9
+
10
+ export type Bytes = ArrayLike<number>;
11
+
12
+ export type BytesLike = Bytes | string;
13
+
14
+ export type DataOptions = {
15
+ allowMissingPrefix?: boolean;
16
+ hexPad?: "left" | "right" | null;
17
+ };
18
+
19
+ export interface Hexable {
20
+ toHexString(): string;
21
+ }
22
+
23
+ export type SignatureLike =
24
+ | {
25
+ r: string;
26
+ s?: string;
27
+ _vs?: string;
28
+ recoveryParam?: number;
29
+ v?: number;
30
+ }
31
+ | BytesLike;
32
+
33
+ export interface Signature {
34
+ r: string;
35
+
36
+ s: string;
37
+ _vs: string;
38
+
39
+ recoveryParam: number;
40
+ v: number;
41
+
42
+ yParityAndS: string;
43
+ compact: string;
44
+ }
45
+
46
+ ///////////////////////////////
47
+
48
+ function isHexable(value: any): value is Hexable {
49
+ return !!value.toHexString;
50
+ }
51
+
52
+ function addSlice(array: Uint8Array): Uint8Array {
53
+ if (array.slice) {
54
+ return array;
55
+ }
56
+
57
+ array.slice = function () {
58
+ const args = Array.prototype.slice.call(arguments);
59
+ return addSlice(new Uint8Array(Array.prototype.slice.apply(array, args)));
60
+ };
61
+
62
+ return array;
63
+ }
64
+
65
+ export function isBytesLike(value: any): value is BytesLike {
66
+ return (isHexString(value) && !(value.length % 2)) || isBytes(value);
67
+ }
68
+
69
+ function isInteger(value: number) {
70
+ return typeof value === "number" && value == value && value % 1 === 0;
71
+ }
72
+
73
+ export function isBytes(value: any): value is Bytes {
74
+ if (value == null) {
75
+ return false;
76
+ }
77
+
78
+ if (value.constructor === Uint8Array) {
79
+ return true;
80
+ }
81
+ if (typeof value === "string") {
82
+ return false;
83
+ }
84
+ if (!isInteger(value.length) || value.length < 0) {
85
+ return false;
86
+ }
87
+
88
+ for (let i = 0; i < value.length; i++) {
89
+ const v = value[i];
90
+ if (!isInteger(v) || v < 0 || v >= 256) {
91
+ return false;
92
+ }
93
+ }
94
+ return true;
95
+ }
96
+
97
+ export function arrayify(
98
+ value: BytesLike | Hexable | number,
99
+ options?: DataOptions,
100
+ ): Uint8Array {
101
+ if (!options) {
102
+ options = {};
103
+ }
104
+
105
+ if (typeof value === "number") {
106
+ logger.checkSafeUint53(value, "invalid arrayify value");
107
+
108
+ const result = [];
109
+ while (value) {
110
+ result.unshift(value & 0xff);
111
+ value = parseInt(String(value / 256));
112
+ }
113
+ if (result.length === 0) {
114
+ result.push(0);
115
+ }
116
+
117
+ return addSlice(new Uint8Array(result));
118
+ }
119
+
120
+ if (
121
+ options.allowMissingPrefix &&
122
+ typeof value === "string" &&
123
+ value.substring(0, 2) !== "0x"
124
+ ) {
125
+ value = "0x" + value;
126
+ }
127
+
128
+ if (isHexable(value)) {
129
+ value = value.toHexString();
130
+ }
131
+
132
+ if (isHexString(value)) {
133
+ let hex = (<string>value).substring(2);
134
+ if (hex.length % 2) {
135
+ if (options.hexPad === "left") {
136
+ hex = "0" + hex;
137
+ } else if (options.hexPad === "right") {
138
+ hex += "0";
139
+ } else {
140
+ logger.throwArgumentError("hex data is odd-length", "value", value);
141
+ }
142
+ }
143
+
144
+ const result = [];
145
+ for (let i = 0; i < hex.length; i += 2) {
146
+ result.push(parseInt(hex.substring(i, i + 2), 16));
147
+ }
148
+
149
+ return addSlice(new Uint8Array(result));
150
+ }
151
+
152
+ if (isBytes(value)) {
153
+ return addSlice(new Uint8Array(value));
154
+ }
155
+
156
+ return logger.throwArgumentError("invalid arrayify value", "value", value);
157
+ }
158
+
159
+ export function concat(items: ReadonlyArray<BytesLike>): Uint8Array {
160
+ const objects = items.map((item) => arrayify(item));
161
+ const length = objects.reduce((accum, item) => accum + item.length, 0);
162
+
163
+ const result = new Uint8Array(length);
164
+
165
+ objects.reduce((offset, object) => {
166
+ result.set(object, offset);
167
+ return offset + object.length;
168
+ }, 0);
169
+
170
+ return addSlice(result);
171
+ }
172
+
173
+ export function stripZeros(value: BytesLike): Uint8Array {
174
+ let result: Uint8Array = arrayify(value);
175
+
176
+ if (result.length === 0) {
177
+ return result;
178
+ }
179
+
180
+ // Find the first non-zero entry
181
+ let start = 0;
182
+ while (start < result.length && result[start] === 0) {
183
+ start++;
184
+ }
185
+
186
+ // If we started with zeros, strip them
187
+ if (start) {
188
+ result = result.slice(start);
189
+ }
190
+
191
+ return result;
192
+ }
193
+
194
+ export function zeroPad(value: BytesLike, length: number): Uint8Array {
195
+ value = arrayify(value);
196
+
197
+ if (value.length > length) {
198
+ logger.throwArgumentError("value out of range", "value", arguments[0]);
199
+ }
200
+
201
+ const result = new Uint8Array(length);
202
+ result.set(value, length - value.length);
203
+ return addSlice(result);
204
+ }
205
+
206
+ export function isHexString(value: any, length?: number): boolean {
207
+ if (typeof value !== "string" || !value.match(/^0x[0-9A-Fa-f]*$/)) {
208
+ return false;
209
+ }
210
+ if (length && value.length !== 2 + 2 * length) {
211
+ return false;
212
+ }
213
+ return true;
214
+ }
215
+
216
+ const HexCharacters: string = "0123456789abcdef";
217
+
218
+ export function hexlify(
219
+ value: BytesLike | Hexable | number | bigint,
220
+ options?: DataOptions,
221
+ ): string {
222
+ if (!options) {
223
+ options = {};
224
+ }
225
+
226
+ if (typeof value === "number") {
227
+ logger.checkSafeUint53(value, "invalid hexlify value");
228
+
229
+ let hex = "";
230
+ while (value) {
231
+ hex = HexCharacters[value & 0xf] + hex;
232
+ value = Math.floor(value / 16);
233
+ }
234
+
235
+ if (hex.length) {
236
+ if (hex.length % 2) {
237
+ hex = "0" + hex;
238
+ }
239
+ return "0x" + hex;
240
+ }
241
+
242
+ return "0x00";
243
+ }
244
+
245
+ if (typeof value === "bigint") {
246
+ value = value.toString(16);
247
+ if (value.length % 2) {
248
+ return "0x0" + value;
249
+ }
250
+ return "0x" + value;
251
+ }
252
+
253
+ if (
254
+ options.allowMissingPrefix &&
255
+ typeof value === "string" &&
256
+ value.substring(0, 2) !== "0x"
257
+ ) {
258
+ value = "0x" + value;
259
+ }
260
+
261
+ if (isHexable(value)) {
262
+ return value.toHexString();
263
+ }
264
+
265
+ if (isHexString(value)) {
266
+ if ((<string>value).length % 2) {
267
+ if (options.hexPad === "left") {
268
+ value = "0x0" + (<string>value).substring(2);
269
+ } else if (options.hexPad === "right") {
270
+ value += "0";
271
+ } else {
272
+ logger.throwArgumentError("hex data is odd-length", "value", value);
273
+ }
274
+ }
275
+ return (<string>value).toLowerCase();
276
+ }
277
+
278
+ if (isBytes(value)) {
279
+ let result = "0x";
280
+ for (let i = 0; i < value.length; i++) {
281
+ let v = value[i];
282
+ result += HexCharacters[(v & 0xf0) >> 4] + HexCharacters[v & 0x0f];
283
+ }
284
+ return result;
285
+ }
286
+
287
+ return logger.throwArgumentError("invalid hexlify value", "value", value);
288
+ }
289
+
290
+ export function hexDataLength(data: BytesLike) {
291
+ if (typeof data !== "string") {
292
+ data = hexlify(data);
293
+ } else if (!isHexString(data) || data.length % 2) {
294
+ return null;
295
+ }
296
+
297
+ return (data.length - 2) / 2;
298
+ }
299
+
300
+ export function hexDataSlice(
301
+ data: BytesLike,
302
+ offset: number,
303
+ endOffset?: number,
304
+ ): string {
305
+ if (typeof data !== "string") {
306
+ data = hexlify(data);
307
+ } else if (!isHexString(data) || data.length % 2) {
308
+ logger.throwArgumentError("invalid hexData", "value", data);
309
+ }
310
+
311
+ offset = 2 + 2 * offset;
312
+
313
+ if (endOffset != null) {
314
+ return "0x" + data.substring(offset, 2 + 2 * endOffset);
315
+ }
316
+
317
+ return "0x" + data.substring(offset);
318
+ }
319
+
320
+ export function hexConcat(items: ReadonlyArray<BytesLike>): string {
321
+ let result = "0x";
322
+ items.forEach((item) => {
323
+ result += hexlify(item).substring(2);
324
+ });
325
+ return result;
326
+ }
327
+
328
+ export function hexValue(value: BytesLike | Hexable | number | bigint): string {
329
+ const trimmed = hexStripZeros(hexlify(value, { hexPad: "left" }));
330
+ if (trimmed === "0x") {
331
+ return "0x0";
332
+ }
333
+ return trimmed;
334
+ }
335
+
336
+ export function hexStripZeros(value: BytesLike): string {
337
+ if (typeof value !== "string") {
338
+ value = hexlify(value);
339
+ }
340
+
341
+ if (!isHexString(value)) {
342
+ logger.throwArgumentError("invalid hex string", "value", value);
343
+ }
344
+ value = value.substring(2);
345
+ let offset = 0;
346
+ while (offset < value.length && value[offset] === "0") {
347
+ offset++;
348
+ }
349
+ return "0x" + value.substring(offset);
350
+ }
351
+
352
+ export function hexZeroPad(value: BytesLike, length: number): string {
353
+ if (typeof value !== "string") {
354
+ value = hexlify(value);
355
+ } else if (!isHexString(value)) {
356
+ logger.throwArgumentError("invalid hex string", "value", value);
357
+ }
358
+
359
+ if (value.length > 2 * length + 2) {
360
+ logger.throwArgumentError("value out of range", "value", arguments[1]);
361
+ }
362
+
363
+ while (value.length < 2 * length + 2) {
364
+ value = "0x0" + value.substring(2);
365
+ }
366
+
367
+ return value;
368
+ }
369
+
370
+ export function splitSignature(signature: SignatureLike): Signature {
371
+ const result = {
372
+ r: "0x",
373
+ s: "0x",
374
+ _vs: "0x",
375
+ recoveryParam: 0,
376
+ v: 0,
377
+ yParityAndS: "0x",
378
+ compact: "0x",
379
+ };
380
+
381
+ if (isBytesLike(signature)) {
382
+ let bytes: Uint8Array = arrayify(signature);
383
+
384
+ // Get the r, s and v
385
+ if (bytes.length === 64) {
386
+ // EIP-2098; pull the v from the top bit of s and clear it
387
+ result.v = 27 + (bytes[32] >> 7);
388
+ bytes[32] &= 0x7f;
389
+
390
+ result.r = hexlify(bytes.slice(0, 32));
391
+ result.s = hexlify(bytes.slice(32, 64));
392
+ } else if (bytes.length === 65) {
393
+ result.r = hexlify(bytes.slice(0, 32));
394
+ result.s = hexlify(bytes.slice(32, 64));
395
+ result.v = bytes[64];
396
+ } else {
397
+ logger.throwArgumentError(
398
+ "invalid signature string",
399
+ "signature",
400
+ signature,
401
+ );
402
+ }
403
+
404
+ // Allow a recid to be used as the v
405
+ if (result.v < 27) {
406
+ if (result.v === 0 || result.v === 1) {
407
+ result.v += 27;
408
+ } else {
409
+ logger.throwArgumentError(
410
+ "signature invalid v byte",
411
+ "signature",
412
+ signature,
413
+ );
414
+ }
415
+ }
416
+
417
+ // Compute recoveryParam from v
418
+ result.recoveryParam = 1 - (result.v % 2);
419
+
420
+ // Compute _vs from recoveryParam and s
421
+ if (result.recoveryParam) {
422
+ bytes[32] |= 0x80;
423
+ }
424
+ result._vs = hexlify(bytes.slice(32, 64));
425
+ } else {
426
+ result.r = signature.r;
427
+ result.s = signature.s;
428
+ result.v = signature.v;
429
+ result.recoveryParam = signature.recoveryParam;
430
+ result._vs = signature._vs;
431
+
432
+ // If the _vs is available, use it to populate missing s, v and recoveryParam
433
+ // and verify non-missing s, v and recoveryParam
434
+ if (result._vs != null) {
435
+ const vs = zeroPad(arrayify(result._vs), 32);
436
+ result._vs = hexlify(vs);
437
+
438
+ // Set or check the recid
439
+ const recoveryParam = vs[0] >= 128 ? 1 : 0;
440
+ if (result.recoveryParam == null) {
441
+ result.recoveryParam = recoveryParam;
442
+ } else if (result.recoveryParam !== recoveryParam) {
443
+ logger.throwArgumentError(
444
+ "signature recoveryParam mismatch _vs",
445
+ "signature",
446
+ signature,
447
+ );
448
+ }
449
+
450
+ // Set or check the s
451
+ vs[0] &= 0x7f;
452
+ const s = hexlify(vs);
453
+ if (result.s == null) {
454
+ result.s = s;
455
+ } else if (result.s !== s) {
456
+ logger.throwArgumentError(
457
+ "signature v mismatch _vs",
458
+ "signature",
459
+ signature,
460
+ );
461
+ }
462
+ }
463
+
464
+ // Use recid and v to populate each other
465
+ if (result.recoveryParam == null) {
466
+ if (result.v == null) {
467
+ logger.throwArgumentError(
468
+ "signature missing v and recoveryParam",
469
+ "signature",
470
+ signature,
471
+ );
472
+ } else if (result.v === 0 || result.v === 1) {
473
+ result.recoveryParam = result.v;
474
+ } else {
475
+ result.recoveryParam = 1 - (result.v % 2);
476
+ }
477
+ } else {
478
+ if (result.v == null) {
479
+ result.v = 27 + result.recoveryParam;
480
+ } else {
481
+ const recId =
482
+ result.v === 0 || result.v === 1 ? result.v : 1 - (result.v % 2);
483
+ if (result.recoveryParam !== recId) {
484
+ logger.throwArgumentError(
485
+ "signature recoveryParam mismatch v",
486
+ "signature",
487
+ signature,
488
+ );
489
+ }
490
+ }
491
+ }
492
+
493
+ if (result.r == null || !isHexString(result.r)) {
494
+ logger.throwArgumentError(
495
+ "signature missing or invalid r",
496
+ "signature",
497
+ signature,
498
+ );
499
+ } else {
500
+ result.r = hexZeroPad(result.r, 32);
501
+ }
502
+
503
+ if (result.s == null || !isHexString(result.s)) {
504
+ logger.throwArgumentError(
505
+ "signature missing or invalid s",
506
+ "signature",
507
+ signature,
508
+ );
509
+ } else {
510
+ result.s = hexZeroPad(result.s, 32);
511
+ }
512
+
513
+ const vs = arrayify(result.s);
514
+ if (vs[0] >= 128) {
515
+ logger.throwArgumentError(
516
+ "signature s out of range",
517
+ "signature",
518
+ signature,
519
+ );
520
+ }
521
+ if (result.recoveryParam) {
522
+ vs[0] |= 0x80;
523
+ }
524
+ const _vs = hexlify(vs);
525
+
526
+ if (result._vs) {
527
+ if (!isHexString(result._vs)) {
528
+ logger.throwArgumentError(
529
+ "signature invalid _vs",
530
+ "signature",
531
+ signature,
532
+ );
533
+ }
534
+ result._vs = hexZeroPad(result._vs, 32);
535
+ }
536
+
537
+ // Set or check the _vs
538
+ if (result._vs == null) {
539
+ result._vs = _vs;
540
+ } else if (result._vs !== _vs) {
541
+ logger.throwArgumentError(
542
+ "signature _vs mismatch v and s",
543
+ "signature",
544
+ signature,
545
+ );
546
+ }
547
+ }
548
+
549
+ result.yParityAndS = result._vs;
550
+ result.compact = result.r + result.yParityAndS.substring(2);
551
+
552
+ return result;
553
+ }
554
+
555
+ export function joinSignature(signature: SignatureLike): string {
556
+ signature = splitSignature(signature);
557
+
558
+ return hexlify(
559
+ concat([
560
+ signature.r,
561
+ signature.s,
562
+ signature.recoveryParam ? "0x1c" : "0x1b",
563
+ ]),
564
+ );
565
+ }