Repository: 0xs34n/starknet.js
Pull request #572 (2023-04-03 16:06:47)

fix: implement custom ts error localy
Due to the bundling issue, reimplemented custom-ts-errors locally.
Please test for chrome ext. @dhruvkelawala, on node imp., this works fine.


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e3f7de8f..cacb5299 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,10 +1,3 @@
-## [5.4.1](https://github.com/0xs34n/starknet.js/compare/v5.4.0...v5.4.1) (2023-04-03)
-
-### Bug Fixes
-
-- remove AnySignatureType and parseSignature method ([358bfad](https://github.com/0xs34n/starknet.js/commit/358bfad8e70ab3d4b2c784e0444780c4d7c5f71a))
-- signature tight flexible resolution ([4990cd8](https://github.com/0xs34n/starknet.js/commit/4990cd8a4d6fd8b87c3016fd27c7eb1b2d5a4a8a))
-
 # [5.4.0](https://github.com/0xs34n/starknet.js/compare/v5.3.0...v5.4.0) (2023-04-03)
 
 ### Bug Fixes
diff --git a/package-lock.json b/package-lock.json
index 71035496..074581eb 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
 {
   "name": "starknet",
-  "version": "5.4.1",
+  "version": "5.4.0",
   "lockfileVersion": 3,
   "requires": true,
   "packages": {
     "": {
       "name": "starknet",
-      "version": "5.4.1",
+      "version": "5.4.0",
       "license": "MIT",
       "dependencies": {
         "@noble/curves": "^0.8.2",
@@ -14,7 +14,6 @@
         "lossless-json": "^2.0.8",
         "micro-starknet": "^0.2.1",
         "pako": "^2.0.4",
-        "ts-custom-error": "^3.3.1",
         "url-join": "^4.0.1"
       },
       "devDependencies": {
@@ -20077,14 +20076,6 @@
         "node": ">=8"
       }
     },
-    "node_modules/ts-custom-error": {
-      "version": "3.3.1",
-      "resolved": "https://registry.npmjs.org/ts-custom-error/-/ts-custom-error-3.3.1.tgz",
-      "integrity": "sha512-5OX1tzOjxWEgsr/YEUWSuPrQ00deKLh6D7OTWcvNHm12/7QPyRh8SYpyWvA4IZv8H/+GQWQEh/kwo95Q9OVW1A==",
-      "engines": {
-        "node": ">=14.0.0"
-      }
-    },
     "node_modules/ts-interface-checker": {
       "version": "0.1.13",
       "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
diff --git a/package.json b/package.json
index f33ffde3..e91ae652 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "starknet",
-  "version": "5.4.1",
+  "version": "5.4.0",
   "description": "JavaScript library for Starknet",
   "main": "dist/index.js",
   "module": "dist/index.mjs",
@@ -92,7 +92,6 @@
     "lossless-json": "^2.0.8",
     "micro-starknet": "^0.2.1",
     "pako": "^2.0.4",
-    "ts-custom-error": "^3.3.1",
     "url-join": "^4.0.1"
   },
   "lint-staged": {
diff --git a/src/account/default.ts b/src/account/default.ts
index 73a38788..9aa21983 100644
--- a/src/account/default.ts
+++ b/src/account/default.ts
@@ -42,14 +42,9 @@ import {
   transactionVersion,
   transactionVersion_2,
 } from '../utils/hash';
-import { BigNumberish, toBigInt, toCairoBool } from '../utils/num';
+import { BigNumberish, toBigInt, toCairoBool, toHex } from '../utils/num';
 import { parseContract } from '../utils/provider';
-import {
-  compileCalldata,
-  estimatedFeeToMaxFee,
-  formatSignature,
-  randomAddress,
-} from '../utils/stark';
+import { compileCalldata, estimatedFeeToMaxFee, randomAddress } from '../utils/stark';
 import { getExecuteCalldata } from '../utils/transaction';
 import { TypedData, getMessageHash } from '../utils/typedData';
 import { AccountInterface } from './interface';
@@ -496,7 +491,7 @@ export class Account extends Provider implements AccountInterface {
         entrypoint: 'isValidSignature',
         calldata: compileCalldata({
           hash: toBigInt(hash).toString(),
-          signature: formatSignature(signature),
+          signature: [toHex(signature.r), toHex(signature.s)],
         }),
       });
       return true;
diff --git a/src/contract/default.ts b/src/contract/default.ts
index 4df043b6..b04b333a 100644
--- a/src/contract/default.ts
+++ b/src/contract/default.ts
@@ -8,7 +8,6 @@ import {
   FunctionAbi,
   InvokeFunctionResponse,
   Overrides,
-  Result,
   StructAbi,
 } from '../types';
 import assert from '../utils/assert';
@@ -191,7 +190,7 @@ export class Contract implements ContractInterface {
     method: string,
     args: Array<any> = [],
     options: CallOptions = { parseRequest: true, parseResponse: true, formatResponse: undefined }
-  ): Promise<Result> {
+  ): Promise<object> {
     assert(this.address !== null, 'contract is not connected to an address');
     const blockIdentifier = options?.blockIdentifier || undefined;
     let calldata = args[0];
diff --git a/src/provider/errors.ts b/src/provider/errors.ts
index 7d798d1c..14367144 100644
--- a/src/provider/errors.ts
+++ b/src/provider/errors.ts
@@ -1,5 +1,38 @@
+// eslint-disable-next-line max-classes-per-file
+export function fixStack(target: Error, fn: Function = target.constructor) {
+  const { captureStackTrace } = Error as any;
+  // eslint-disable-next-line @typescript-eslint/no-unused-expressions
+  captureStackTrace && captureStackTrace(target, fn);
+}
+
+export function fixProto(target: Error, prototype: {}) {
+  const { setPrototypeOf } = Object as any;
+  // eslint-disable-next-line @typescript-eslint/no-unused-expressions, no-proto, no-param-reassign
+  setPrototypeOf ? setPrototypeOf(target, prototype) : ((target as any).__proto__ = prototype);
+}
+
 /* eslint-disable max-classes-per-file */
-import { CustomError } from 'ts-custom-error/dist/custom-error';
+export class CustomError extends Error {
+  name!: string;
+
+  constructor(message?: string) {
+    super(message);
+    // set error name as constructor name, make it not enumerable to keep native Error behavior
+    // see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new.target#new.target_in_constructors
+    // see https://github.com/adriengibrat/ts-custom-error/issues/30
+    Object.defineProperty(this, 'name', {
+      value: new.target.name,
+      enumerable: false,
+      configurable: true,
+    });
+    // fix the extended error prototype chain
+    // because typescript __extends implementation can't
+    // see https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work
+    fixProto(this, new.target.prototype);
+    // try to remove contructor from stack trace
+    fixStack(this);
+  }
+}
 
 export class LibraryError extends CustomError {}
 
diff --git a/src/types/contract.ts b/src/types/contract.ts
index 8513a616..84bbd894 100644
--- a/src/types/contract.ts
+++ b/src/types/contract.ts
@@ -1,5 +1,2 @@
 export type AsyncContractFunction<T = any> = (...args: Array<any>) => Promise<T>;
 export type ContractFunction = (...args: Array<any>) => any;
-export type Result = {
-  [key: string]: any;
-};
diff --git a/src/types/lib/index.ts b/src/types/lib/index.ts
index 685ccddb..04431570 100644
--- a/src/types/lib/index.ts
+++ b/src/types/lib/index.ts
@@ -3,9 +3,10 @@ import { weierstrass } from '../../utils/ec';
 import type { BigNumberish } from '../../utils/num';
 import { CompiledContract, CompiledSierraCasm, ContractClass } from './contract';
 
-export type WeierstrassSignatureType = weierstrass.SignatureType;
-export type ArraySignatureType = string[];
-export type Signature = ArraySignatureType | WeierstrassSignatureType;
+// Common Signature Type which needs to be imported from weierstrass
+// and imported at many places
+// This is because stark.ts doesn't export SignatureType
+export type Signature = weierstrass.SignatureType;
 
 export type RawCalldata = BigNumberish[];
 export type AllowArray<T> = T | T[];
diff --git a/src/utils/responseParser/sequencer.ts b/src/utils/responseParser/sequencer.ts
index 70b17f11..d3644d16 100644
--- a/src/utils/responseParser/sequencer.ts
+++ b/src/utils/responseParser/sequencer.ts
@@ -17,6 +17,7 @@ import {
   TransactionSimulationResponse,
 } from '../../types';
 import { toBigInt } from '../num';
+import { parseSignature } from '../stark';
 import { ResponseParser } from '.';
 
 export class SequencerAPIResponseParser extends ResponseParser {
@@ -49,7 +50,8 @@ export class SequencerAPIResponseParser extends ResponseParser {
         'sender_address' in res.transaction
           ? (res.transaction.sender_address as string)
           : undefined,
-      signature: 'signature' in res.transaction ? res.transaction.signature : undefined,
+      signature:
+        'signature' in res.transaction ? parseSignature(res.transaction.signature) : undefined,
       transaction_hash:
         'transaction_hash' in res.transaction ? res.transaction.transaction_hash : undefined,
       version: 'version' in res.transaction ? (res.transaction.version as string) : undefined,
diff --git a/src/utils/stark.ts b/src/utils/stark.ts
index 87860d84..5e07ad00 100644
--- a/src/utils/stark.ts
+++ b/src/utils/stark.ts
@@ -1,13 +1,12 @@
-import { getStarkKey, utils } from 'micro-starknet';
+import { Signature, getStarkKey, utils } from 'micro-starknet';
 import { gzip } from 'pako';
 
 import {
-  ArraySignatureType,
   Calldata,
   CompressedProgram,
   Program,
   RawArgs,
-  Signature,
+  Signature as SignatureType,
 } from '../types';
 import { addHexPrefix, btoaUniversal } from './encode';
 import { stringify } from './json';
@@ -41,27 +40,31 @@ export function makeAddress(input: string): string {
   return addHexPrefix(input).toLowerCase();
 }
 
-export function formatSignature(sig?: Signature): ArraySignatureType {
-  if (!sig) throw Error('formatSignature: provided signature is undefined');
-  if (Array.isArray(sig)) {
-    return sig.map((it) => toHex(it));
-  }
+export function formatSignature(sig?: SignatureType): string[] {
+  if (!sig) return [];
   try {
     const { r, s } = sig;
     return [toHex(r), toHex(s)];
   } catch (e) {
-    throw new Error('Signature need to be weierstrass.SignatureType or an array for custom');
+    return [];
   }
 }
 
-export function signatureToDecimalArray(sig?: Signature): ArraySignatureType {
+export function signatureToDecimalArray(sig?: SignatureType): string[] {
   return bigNumberishArrayToDecimalStringArray(formatSignature(sig));
 }
 
-export function signatureToHexArray(sig?: Signature): ArraySignatureType {
+export function signatureToHexArray(sig?: SignatureType): string[] {
   return bigNumberishArrayToHexadecimalStringArray(formatSignature(sig));
 }
 
+export function parseSignature(sig?: string[]) {
+  if (!sig) return undefined;
+
+  const [r, s] = sig;
+  return new Signature(toBigInt(r), toBigInt(s));
+}
+
 /**
  * @deprecated this function is deprecated use callData instead from calldata.ts
  */


Test patch:
diff --git a/__tests__/account.test.ts b/__tests__/account.test.ts
index f7d87a8b..f8d37aed 100644
--- a/__tests__/account.test.ts
+++ b/__tests__/account.test.ts
@@ -1,5 +1,3 @@
-import { Signature } from 'micro-starknet';
-
 import typedDataExample from '../__mocks__/typedDataExample.json';
 import { Account, Contract, Provider, TransactionStatus, ec, stark } from '../src';
 import { uint256 } from '../src/utils/calldata/cairo';
@@ -186,7 +184,7 @@ describe('deploy and test Wallet', () => {
     // change the signature to make it invalid
     const r2 = toBigInt(r) + 123n;
 
-    const signature2 = new Signature(toBigInt(r2.toString()), toBigInt(s));
+    const signature2 = stark.parseSignature([r2.toString(), s]);
 
     if (!signature2) return;