@callcium/sdk 0.10.0 → 0.11.1

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.
package/src/signature.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { keccak_256 } from "@noble/hashes/sha3.js";
2
+ import { utf8ToBytes } from "@noble/hashes/utils.js";
2
3
 
3
4
  import { bytesToHex } from "./bytes";
4
5
  import { CallciumError } from "./errors";
@@ -18,13 +19,13 @@ export type ParsedSignature = {
18
19
  };
19
20
 
20
21
  /** Return true if the char code is an ASCII letter. */
21
- function isAlpha(c: number): boolean {
22
- return (c >= 0x41 && c <= 0x5a) || (c >= 0x61 && c <= 0x7a);
22
+ function isAlpha(char: number): boolean {
23
+ return (char >= 0x41 && char <= 0x5a) || (char >= 0x61 && char <= 0x7a);
23
24
  }
24
25
 
25
26
  /** Return true if the char code is an ASCII alphanumeric character. */
26
- function isAlphanum(c: number): boolean {
27
- return isAlpha(c) || (c >= 0x30 && c <= 0x39);
27
+ function isAlphanum(char: number): boolean {
28
+ return isAlpha(char) || (char >= 0x30 && char <= 0x39);
28
29
  }
29
30
 
30
31
  /**
@@ -36,29 +37,27 @@ function isAlphanum(c: number): boolean {
36
37
  * @param signature - A function signature string, e.g. `"transfer(address,uint256)"`.
37
38
  * @returns The 4-byte selector and the comma-separated types string.
38
39
  * @throws {CallciumError} with code `"MALFORMED_SIGNATURE"`, `"SIGNATURE_CONTAINS_WHITESPACE"`, or
39
- * `"INVALID_FUNCTION_NAME"` if the signature is malformed.
40
+ * `"INVALID_FUNCTION_NAME"` if the signature is malformed. The types between the parentheses are
41
+ * returned unread; whether they name types is for the type parser to say.
40
42
  */
41
43
  function parse(signature: string): ParsedSignature {
42
44
  if (signature.length < 3) {
43
45
  throw new CallciumError("MALFORMED_SIGNATURE", `Invalid signature: too short, got "${signature}"`);
44
46
  }
45
47
 
46
- // Scan for whitespace, non-ASCII, and the opening parenthesis in one pass.
48
+ // Scan for whitespace and the opening parenthesis in one pass.
47
49
  let openParen = -1;
48
50
  for (let i = 0; i < signature.length; i++) {
49
- const c = signature.charCodeAt(i);
50
- if (c === 0x20 || c === 0x09 || c === 0x0a || c === 0x0d) {
51
+ const char = signature.charCodeAt(i);
52
+ if (char === 0x20 || char === 0x09 || char === 0x0a || char === 0x0d) {
51
53
  throw new CallciumError("SIGNATURE_CONTAINS_WHITESPACE", "Signature must not contain whitespace");
52
54
  }
53
- if (c > 0x7e) {
54
- throw new CallciumError("MALFORMED_SIGNATURE", "Signature must contain only ASCII characters");
55
- }
56
- if (openParen === -1 && c === 0x28) {
55
+ if (openParen === -1 && char === 0x28) {
57
56
  openParen = i;
58
57
  }
59
58
  }
60
59
 
61
- if (openParen < 1) {
60
+ if (openParen === -1) {
62
61
  throw new CallciumError(
63
62
  "MALFORMED_SIGNATURE",
64
63
  `Invalid signature: must have a function name followed by parentheses, got "${signature}"`,
@@ -69,14 +68,19 @@ function parse(signature: string): ParsedSignature {
69
68
  throw new CallciumError("MALFORMED_SIGNATURE", `Invalid signature: must end with ")", got "${signature}"`);
70
69
  }
71
70
 
72
- // Validate function name: [A-Za-z_][A-Za-z0-9_]*.
71
+ if (openParen === 0) {
72
+ throw new CallciumError("INVALID_FUNCTION_NAME", "Function name must not be empty");
73
+ }
74
+
75
+ // Validate function name: [A-Za-z_][A-Za-z0-9_]*. Every character outside ASCII carries a code
76
+ // unit above the alphanumeric ranges, so the same test rejects it.
73
77
  const firstChar = signature.charCodeAt(0);
74
78
  if (!isAlpha(firstChar) && firstChar !== 0x5f) {
75
79
  throw new CallciumError("INVALID_FUNCTION_NAME", "Function name must start with a letter or underscore");
76
80
  }
77
81
  for (let i = 1; i < openParen; i++) {
78
- const c = signature.charCodeAt(i);
79
- if (!isAlphanum(c) && c !== 0x5f) {
82
+ const char = signature.charCodeAt(i);
83
+ if (!isAlphanum(char) && char !== 0x5f) {
80
84
  throw new CallciumError(
81
85
  "INVALID_FUNCTION_NAME",
82
86
  "Function name must contain only alphanumeric characters or underscores",
@@ -84,9 +88,7 @@ function parse(signature: string): ParsedSignature {
84
88
  }
85
89
  }
86
90
 
87
- const encoded = new Uint8Array(signature.length);
88
- for (let i = 0; i < signature.length; i++) encoded[i] = signature.charCodeAt(i);
89
- const hash = keccak_256(encoded);
91
+ const hash = keccak_256(utf8ToBytes(signature));
90
92
 
91
93
  const selector = bytesToHex(hash.subarray(0, 4));
92
94
  const types = signature.slice(openParen + 1, signature.length - 1);
package/src/type-desc.ts CHANGED
@@ -77,14 +77,14 @@ export function string_(): Uint8Array {
77
77
 
78
78
  /**
79
79
  * Build a descriptor node for `bytesN`.
80
- * @param n - Byte width, 1–32.
81
- * @throws {CallciumError} With code `UNKNOWN_TYPE` if n is out of range.
80
+ * @param length - Byte width, 1–32.
81
+ * @throws {CallciumError} With code `UNKNOWN_TYPE` if length is out of range.
82
82
  */
83
- export function bytesN(n: number): Uint8Array {
84
- if (n < 1 || n > 32) {
85
- throw new CallciumError("UNKNOWN_TYPE", `Invalid bytesN size: ${n}. Must be 1–32`);
83
+ export function bytesN(length: number): Uint8Array {
84
+ if (length < 1 || length > 32) {
85
+ throw new CallciumError("UNKNOWN_TYPE", `Invalid bytesN size: ${length}. Must be 1–32`);
86
86
  }
87
- return new Uint8Array([TypeCode.FIXED_BYTES_MIN + (n - 1)]);
87
+ return new Uint8Array([TypeCode.FIXED_BYTES_MIN + (length - 1)]);
88
88
  }
89
89
 
90
90
  ///////////////////////////////////////////////////////////////////////////