starknet 2.4.0 → 2.5.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 (55) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/__tests__/account.test.ts +3 -3
  3. package/__tests__/utils/ellipticalCurve.test.ts +1 -1
  4. package/__tests__/utils/typedData.test.ts +72 -0
  5. package/contract.d.ts +2 -2
  6. package/dist/contract.d.ts +2 -2
  7. package/dist/index.d.ts +1 -0
  8. package/dist/index.js +2 -1
  9. package/dist/provider/default.d.ts +2 -2
  10. package/dist/provider/default.js +10 -9
  11. package/dist/provider/interface.d.ts +2 -2
  12. package/dist/signer/default.d.ts +18 -1
  13. package/dist/signer/default.js +43 -7
  14. package/dist/signer/interface.d.ts +20 -1
  15. package/dist/types.d.ts +3 -3
  16. package/dist/utils/ellipticCurve.d.ts +8 -1
  17. package/dist/utils/ellipticCurve.js +48 -9
  18. package/dist/utils/stark.d.ts +2 -3
  19. package/dist/utils/typedData/index.d.ts +91 -0
  20. package/dist/utils/typedData/index.js +183 -0
  21. package/dist/utils/typedData/types.d.ts +82 -0
  22. package/dist/utils/typedData/types.js +47 -0
  23. package/dist/utils/typedData/utils.d.ts +24 -0
  24. package/dist/utils/typedData/utils.js +15 -0
  25. package/index.d.ts +1 -0
  26. package/index.js +3 -1
  27. package/package.json +2 -1
  28. package/provider/default.d.ts +2 -1
  29. package/provider/default.js +10 -10
  30. package/provider/interface.d.ts +2 -1
  31. package/signer/default.d.ts +18 -1
  32. package/signer/default.js +44 -7
  33. package/signer/interface.d.ts +20 -1
  34. package/src/contract.ts +2 -2
  35. package/src/index.ts +1 -0
  36. package/src/provider/default.ts +5 -5
  37. package/src/provider/interface.ts +2 -1
  38. package/src/signer/default.ts +26 -3
  39. package/src/signer/interface.ts +22 -1
  40. package/src/types.ts +9 -3
  41. package/src/utils/ellipticCurve.ts +31 -9
  42. package/src/utils/stark.ts +4 -4
  43. package/src/utils/typedData/index.ts +176 -0
  44. package/src/utils/typedData/types.ts +82 -0
  45. package/src/utils/typedData/utils.ts +13 -0
  46. package/types.d.ts +5 -4
  47. package/utils/ellipticCurve.d.ts +12 -1
  48. package/utils/ellipticCurve.js +72 -23
  49. package/utils/stark.d.ts +2 -3
  50. package/utils/typedData/index.d.ts +113 -0
  51. package/utils/typedData/index.js +247 -0
  52. package/utils/typedData/types.d.ts +103 -0
  53. package/utils/typedData/types.js +57 -0
  54. package/utils/typedData/utils.d.ts +27 -0
  55. package/utils/typedData/utils.js +15 -0
@@ -0,0 +1,183 @@
1
+ "use strict";
2
+ var __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
+ }));
9
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
10
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
11
+ };
12
+ var __read = (this && this.__read) || function (o, n) {
13
+ var m = typeof Symbol === "function" && o[Symbol.iterator];
14
+ if (!m) return o;
15
+ var i = m.call(o), r, ar = [], e;
16
+ try {
17
+ while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
18
+ }
19
+ catch (error) { e = { error: error }; }
20
+ finally {
21
+ try {
22
+ if (r && !r.done && (m = i["return"])) m.call(i);
23
+ }
24
+ finally { if (e) throw e.error; }
25
+ }
26
+ return ar;
27
+ };
28
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
29
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
30
+ if (ar || !(i in from)) {
31
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
32
+ ar[i] = from[i];
33
+ }
34
+ }
35
+ return to.concat(ar || Array.prototype.slice.call(from));
36
+ };
37
+ Object.defineProperty(exports, "__esModule", { value: true });
38
+ exports.getMessageHash = exports.getStructHash = exports.encodeData = exports.getTypeHash = exports.encodeType = exports.getDependencies = void 0;
39
+ var hash_1 = require("../hash");
40
+ var number_1 = require("../number");
41
+ var shortString_1 = require("../shortString");
42
+ var stark_1 = require("../stark");
43
+ var utils_1 = require("./utils");
44
+ __exportStar(require("./types"), exports);
45
+ function getHex(value) {
46
+ try {
47
+ return (0, number_1.toHex)((0, number_1.toBN)(value));
48
+ }
49
+ catch (e) {
50
+ if (typeof value === 'string') {
51
+ return (0, number_1.toHex)((0, number_1.toBN)((0, shortString_1.encodeShortString)(value)));
52
+ }
53
+ throw new Error("Invalid BigNumberish: " + value);
54
+ }
55
+ }
56
+ /**
57
+ * Get the dependencies of a struct type. If a struct has the same dependency multiple times, it's only included once
58
+ * in the resulting array.
59
+ *
60
+ * @param {TypedData} typedData
61
+ * @param {string} type
62
+ * @param {string[]} [dependencies]
63
+ * @return {string[]}
64
+ */
65
+ var getDependencies = function (typedData, type, dependencies) {
66
+ if (dependencies === void 0) { dependencies = []; }
67
+ // `getDependencies` is called by most other functions, so we validate the JSON schema here
68
+ if (!(0, utils_1.validateTypedData)(typedData)) {
69
+ throw new Error('Typed data does not match JSON schema');
70
+ }
71
+ if (dependencies.includes(type)) {
72
+ return dependencies;
73
+ }
74
+ if (!typedData.types[type]) {
75
+ return dependencies;
76
+ }
77
+ return __spreadArray([
78
+ type
79
+ ], __read(typedData.types[type].reduce(function (previous, t) { return __spreadArray(__spreadArray([], __read(previous), false), __read((0, exports.getDependencies)(typedData, t.type, previous).filter(function (dependency) { return !previous.includes(dependency); })), false); }, [])), false);
80
+ };
81
+ exports.getDependencies = getDependencies;
82
+ /**
83
+ * Encode a type to a string. All dependant types are alphabetically sorted.
84
+ *
85
+ * @param {TypedData} typedData
86
+ * @param {string} type
87
+ * @return {string}
88
+ */
89
+ var encodeType = function (typedData, type) {
90
+ var _a = __read((0, exports.getDependencies)(typedData, type)), primary = _a[0], dependencies = _a.slice(1);
91
+ var types = __spreadArray([primary], __read(dependencies.sort()), false);
92
+ return types
93
+ .map(function (dependency) {
94
+ return dependency + "(" + typedData.types[dependency].map(function (t) { return t.name + ":" + t.type; }) + ")";
95
+ })
96
+ .join('');
97
+ };
98
+ exports.encodeType = encodeType;
99
+ /**
100
+ * Get a type string as hash.
101
+ *
102
+ * @param {TypedData} typedData
103
+ * @param {string} type
104
+ * @return {string}
105
+ */
106
+ var getTypeHash = function (typedData, type) {
107
+ return (0, stark_1.getSelectorFromName)((0, exports.encodeType)(typedData, type));
108
+ };
109
+ exports.getTypeHash = getTypeHash;
110
+ /**
111
+ * Encodes a single value to an ABI serialisable string, number or Buffer. Returns the data as tuple, which consists of
112
+ * an array of ABI compatible types, and an array of corresponding values.
113
+ *
114
+ * @param {TypedData} typedData
115
+ * @param {string} type
116
+ * @param {any} data
117
+ * @returns {[string, string]}
118
+ */
119
+ var encodeValue = function (typedData, type, data) {
120
+ if (typedData.types[type]) {
121
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
122
+ return [type, (0, exports.getStructHash)(typedData, type, data)];
123
+ }
124
+ if (type === 'felt*') {
125
+ return ['felt*', (0, hash_1.computeHashOnElements)(data)];
126
+ }
127
+ return [type, getHex(data)];
128
+ };
129
+ /**
130
+ * Encode the data to an ABI encoded Buffer. The data should be a key -> value object with all the required values. All
131
+ * dependant types are automatically encoded.
132
+ *
133
+ * @param {TypedData} typedData
134
+ * @param {string} type
135
+ * @param {Record<string, any>} data
136
+ */
137
+ var encodeData = function (typedData, type, data) {
138
+ var _a = __read(typedData.types[type].reduce(function (_a, field) {
139
+ var _b = __read(_a, 2), ts = _b[0], vs = _b[1];
140
+ if (data[field.name] === undefined || data[field.name] === null) {
141
+ throw new Error("Cannot encode data: missing data for '" + field.name + "'");
142
+ }
143
+ var value = data[field.name];
144
+ var _c = __read(encodeValue(typedData, field.type, value), 2), t = _c[0], encodedValue = _c[1];
145
+ return [
146
+ __spreadArray(__spreadArray([], __read(ts), false), [t], false),
147
+ __spreadArray(__spreadArray([], __read(vs), false), [encodedValue], false),
148
+ ];
149
+ }, [['felt'], [(0, exports.getTypeHash)(typedData, type)]]), 2), types = _a[0], values = _a[1];
150
+ return [types, values];
151
+ };
152
+ exports.encodeData = encodeData;
153
+ /**
154
+ * Get encoded data as a hash. The data should be a key -> value object with all the required values. All dependant
155
+ * types are automatically encoded.
156
+ *
157
+ * @param {TypedData} typedData
158
+ * @param {string} type
159
+ * @param {Record<string, any>} data
160
+ * @return {Buffer}
161
+ */
162
+ var getStructHash = function (typedData, type, data) {
163
+ return (0, hash_1.computeHashOnElements)((0, exports.encodeData)(typedData, type, data)[1]);
164
+ };
165
+ exports.getStructHash = getStructHash;
166
+ /**
167
+ * Get the EIP-191 encoded message to sign, from the typedData object. If `hash` is enabled, the message will be hashed
168
+ * with Keccak256.
169
+ *
170
+ * @param {TypedData} typedData
171
+ * @param {boolean} hash
172
+ * @return {string}
173
+ */
174
+ var getMessageHash = function (typedData, account) {
175
+ var message = [
176
+ (0, shortString_1.encodeShortString)('StarkNet Message'),
177
+ (0, exports.getStructHash)(typedData, 'StarkNetDomain', typedData.domain),
178
+ account,
179
+ (0, exports.getStructHash)(typedData, typedData.primaryType, typedData.message),
180
+ ];
181
+ return (0, hash_1.computeHashOnElements)(message);
182
+ };
183
+ exports.getMessageHash = getMessageHash;
@@ -0,0 +1,82 @@
1
+ import { Infer } from 'superstruct';
2
+ export declare const ATOMIC_TYPES: string[];
3
+ /**
4
+ * Checks if a type is valid with the given `typedData`. The following types are valid:
5
+ * - Atomic types: felt, felt*
6
+ * - Reference types: struct type (e.g. SomeStruct)
7
+ *
8
+ * @param {Record<string, unknown>} types
9
+ * @param {string} type
10
+ * @return {boolean}
11
+ */
12
+ export declare const isValidType: (types: Record<string, unknown>, type: string) => boolean;
13
+ export declare const STARKNET_TYPE: import("superstruct").Struct<{
14
+ type: string;
15
+ name: string;
16
+ }, {
17
+ name: import("superstruct").Struct<string, null>;
18
+ type: import("superstruct").Struct<string, null>;
19
+ }>;
20
+ /**
21
+ * A single type, as part of a struct. The `type` field can be any of the EIP-712 supported types.
22
+ *
23
+ * Note that the `uint` and `int` aliases like in Solidity, and fixed point numbers are not supported by the EIP-712
24
+ * standard.
25
+ */
26
+ export declare type StarkNetType = Infer<typeof STARKNET_TYPE>;
27
+ export declare const STARKNET_DOMAIN_TYPE: import("superstruct").Struct<{
28
+ name?: string | undefined;
29
+ version?: string | undefined;
30
+ chainId?: string | number | undefined;
31
+ }, {
32
+ name: import("superstruct").Struct<string | undefined, null>;
33
+ version: import("superstruct").Struct<string | undefined, null>;
34
+ chainId: import("superstruct").Struct<string | number | undefined, null>;
35
+ }>;
36
+ /**
37
+ * The EIP712 domain struct. Any of these fields are optional, but it must contain at least one field.
38
+ */
39
+ export declare type StarkNetDomain = Infer<typeof STARKNET_DOMAIN_TYPE>;
40
+ export declare const STARKNET_TYPED_DATA_TYPE: import("superstruct").Struct<{
41
+ types: {
42
+ StarkNetDomain: {
43
+ type: string;
44
+ name: string;
45
+ }[];
46
+ } & Record<string, {
47
+ type: string;
48
+ name: string;
49
+ }[]>;
50
+ primaryType: string;
51
+ domain: {
52
+ name?: string | undefined;
53
+ version?: string | undefined;
54
+ chainId?: string | number | undefined;
55
+ };
56
+ message: Record<string, unknown>;
57
+ }, {
58
+ types: import("superstruct").Struct<{
59
+ StarkNetDomain: {
60
+ type: string;
61
+ name: string;
62
+ }[];
63
+ } & Record<string, {
64
+ type: string;
65
+ name: string;
66
+ }[]>, null>;
67
+ primaryType: import("superstruct").Struct<string, null>;
68
+ domain: import("superstruct").Struct<{
69
+ name?: string | undefined;
70
+ version?: string | undefined;
71
+ chainId?: string | number | undefined;
72
+ }, {
73
+ name: import("superstruct").Struct<string | undefined, null>;
74
+ version: import("superstruct").Struct<string | undefined, null>;
75
+ chainId: import("superstruct").Struct<string | number | undefined, null>;
76
+ }>;
77
+ message: import("superstruct").Struct<Record<string, unknown>, null>;
78
+ }>;
79
+ /**
80
+ * The complete typed data, with all the structs, domain data, primary type of the message, and the message itself.
81
+ */
82
+ export declare type TypedData = Infer<typeof STARKNET_TYPED_DATA_TYPE>;
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.STARKNET_TYPED_DATA_TYPE = exports.STARKNET_DOMAIN_TYPE = exports.STARKNET_TYPE = exports.isValidType = exports.ATOMIC_TYPES = void 0;
4
+ var superstruct_1 = require("superstruct");
5
+ exports.ATOMIC_TYPES = ['felt', 'felt*'];
6
+ // Source: https://github.com/Mrtenz/eip-712/blob/master/src/eip-712.ts
7
+ // and modified to support starknet types
8
+ /**
9
+ * Checks if a type is valid with the given `typedData`. The following types are valid:
10
+ * - Atomic types: felt, felt*
11
+ * - Reference types: struct type (e.g. SomeStruct)
12
+ *
13
+ * @param {Record<string, unknown>} types
14
+ * @param {string} type
15
+ * @return {boolean}
16
+ */
17
+ var isValidType = function (types, type) {
18
+ if (exports.ATOMIC_TYPES.includes(type)) {
19
+ return true;
20
+ }
21
+ if (types[type]) {
22
+ return true;
23
+ }
24
+ return false;
25
+ };
26
+ exports.isValidType = isValidType;
27
+ var TYPE = (0, superstruct_1.refine)((0, superstruct_1.string)(), 'Type', function (type, context) {
28
+ return (0, exports.isValidType)(context.branch[0].types, type);
29
+ });
30
+ exports.STARKNET_TYPE = (0, superstruct_1.object)({
31
+ name: (0, superstruct_1.string)(),
32
+ type: TYPE,
33
+ });
34
+ exports.STARKNET_DOMAIN_TYPE = (0, superstruct_1.object)({
35
+ name: (0, superstruct_1.optional)((0, superstruct_1.string)()),
36
+ version: (0, superstruct_1.optional)((0, superstruct_1.string)()),
37
+ chainId: (0, superstruct_1.optional)((0, superstruct_1.union)([(0, superstruct_1.string)(), (0, superstruct_1.number)()])),
38
+ });
39
+ exports.STARKNET_TYPED_DATA_TYPE = (0, superstruct_1.object)({
40
+ types: (0, superstruct_1.intersection)([
41
+ (0, superstruct_1.type)({ StarkNetDomain: (0, superstruct_1.array)(exports.STARKNET_TYPE) }),
42
+ (0, superstruct_1.record)((0, superstruct_1.string)(), (0, superstruct_1.array)(exports.STARKNET_TYPE)),
43
+ ]),
44
+ primaryType: (0, superstruct_1.string)(),
45
+ domain: exports.STARKNET_DOMAIN_TYPE,
46
+ message: (0, superstruct_1.object)(),
47
+ });
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Validates that `data` matches the EIP-712 JSON schema.
3
+ *
4
+ * @param {any} data
5
+ * @return {boolean}
6
+ */
7
+ export declare const validateTypedData: (data: unknown) => data is {
8
+ types: {
9
+ StarkNetDomain: {
10
+ type: string;
11
+ name: string;
12
+ }[];
13
+ } & Record<string, {
14
+ type: string;
15
+ name: string;
16
+ }[]>;
17
+ primaryType: string;
18
+ domain: {
19
+ name?: string | undefined;
20
+ version?: string | undefined;
21
+ chainId?: string | number | undefined;
22
+ };
23
+ message: Record<string, unknown>;
24
+ };
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.validateTypedData = void 0;
4
+ var superstruct_1 = require("superstruct");
5
+ var types_1 = require("./types");
6
+ /**
7
+ * Validates that `data` matches the EIP-712 JSON schema.
8
+ *
9
+ * @param {any} data
10
+ * @return {boolean}
11
+ */
12
+ var validateTypedData = function (data) {
13
+ return (0, superstruct_1.is)(data, types_1.STARKNET_TYPED_DATA_TYPE);
14
+ };
15
+ exports.validateTypedData = validateTypedData;
package/index.d.ts CHANGED
@@ -17,3 +17,4 @@ export * as stark from './utils/stark';
17
17
  export * as ec from './utils/ellipticCurve';
18
18
  export * as uint256 from './utils/uint256';
19
19
  export * as shortString from './utils/shortString';
20
+ export * as typedData from './utils/typedData';
package/index.js CHANGED
@@ -44,7 +44,8 @@ var __importStar =
44
44
  return result;
45
45
  };
46
46
  Object.defineProperty(exports, '__esModule', { value: true });
47
- exports.shortString =
47
+ exports.typedData =
48
+ exports.shortString =
48
49
  exports.uint256 =
49
50
  exports.ec =
50
51
  exports.stark =
@@ -73,3 +74,4 @@ exports.stark = __importStar(require('./utils/stark'));
73
74
  exports.ec = __importStar(require('./utils/ellipticCurve'));
74
75
  exports.uint256 = __importStar(require('./utils/uint256'));
75
76
  exports.shortString = __importStar(require('./utils/shortString'));
77
+ exports.typedData = __importStar(require('./utils/typedData'));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "starknet",
3
- "version": "2.4.0",
3
+ "version": "2.5.0",
4
4
  "description": "JavaScript library for StarkNet",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -68,6 +68,7 @@
68
68
  "json-bigint": "^1.0.0",
69
69
  "minimalistic-assert": "^1.0.1",
70
70
  "pako": "^2.0.4",
71
+ "superstruct": "^0.15.3",
71
72
  "url-join": "^4.0.1"
72
73
  },
73
74
  "lint-staged": {
@@ -8,6 +8,7 @@ import {
8
8
  GetContractAddressesResponse,
9
9
  GetTransactionResponse,
10
10
  GetTransactionStatusResponse,
11
+ Signature,
11
12
  Transaction,
12
13
  } from '../types';
13
14
  import { BigNumberish } from '../utils/number';
@@ -130,7 +131,7 @@ export declare class Provider implements ProviderInterface {
130
131
  contractAddress: string,
131
132
  entrypointSelector: string,
132
133
  calldata?: string[],
133
- signature?: [BigNumberish, BigNumberish]
134
+ signature?: Signature
134
135
  ): Promise<AddTransactionResponse>;
135
136
  waitForTx(txHash: BigNumberish, retryInterval?: number): Promise<void>;
136
137
  }
@@ -517,29 +517,29 @@ var Provider = /** @class */ (function () {
517
517
  switch (_a.label) {
518
518
  case 0:
519
519
  onchain = false;
520
- _a.label = 1;
520
+ return [4 /*yield*/, wait(retryInterval)];
521
521
  case 1:
522
- if (!!onchain) return [3 /*break*/, 4];
522
+ _a.sent();
523
+ _a.label = 2;
524
+ case 2:
525
+ if (!!onchain) return [3 /*break*/, 5];
523
526
  // eslint-disable-next-line no-await-in-loop
524
527
  return [4 /*yield*/, wait(retryInterval)];
525
- case 2:
528
+ case 3:
526
529
  // eslint-disable-next-line no-await-in-loop
527
530
  _a.sent();
528
531
  return [4 /*yield*/, this.getTransactionStatus(txHash)];
529
- case 3:
532
+ case 4:
530
533
  res = _a.sent();
531
- if (
532
- res.tx_status === 'ACCEPTED_ONCHAIN' ||
533
- (res.tx_status === 'PENDING' && res.block_hash !== 'pending') // This is needed as of today. In the future there will be a different status for pending transactions.
534
- ) {
534
+ if (res.tx_status === 'ACCEPTED_ON_L1' || res.tx_status === 'ACCEPTED_ON_L2') {
535
535
  onchain = true;
536
536
  } else if (res.tx_status === 'REJECTED') {
537
537
  throw Error('REJECTED');
538
538
  } else if (res.tx_status === 'NOT_RECEIVED') {
539
539
  throw Error('NOT_RECEIVED');
540
540
  }
541
- return [3 /*break*/, 1];
542
- case 4:
541
+ return [3 /*break*/, 2];
542
+ case 5:
543
543
  return [2 /*return*/];
544
544
  }
545
545
  });
@@ -8,6 +8,7 @@ import type {
8
8
  GetContractAddressesResponse,
9
9
  GetTransactionResponse,
10
10
  GetTransactionStatusResponse,
11
+ Signature,
11
12
  Transaction,
12
13
  } from '../types';
13
14
  import type { BigNumberish } from '../utils/number';
@@ -117,7 +118,7 @@ export declare abstract class ProviderInterface {
117
118
  contractAddress: string,
118
119
  entrypointSelector: string,
119
120
  calldata?: string[],
120
- signature?: [BigNumberish, BigNumberish]
121
+ signature?: Signature
121
122
  ): Promise<AddTransactionResponse>;
122
123
  abstract waitForTx(txHash: BigNumberish, retryInterval?: number): Promise<void>;
123
124
  }
@@ -1,5 +1,6 @@
1
1
  import { Provider } from '../provider';
2
- import { AddTransactionResponse, KeyPair, Transaction } from '../types';
2
+ import { AddTransactionResponse, KeyPair, Signature, Transaction } from '../types';
3
+ import { TypedData } from '../utils/typedData';
3
4
  import { SignerInterface } from './interface';
4
5
  export declare class Signer extends Provider implements SignerInterface {
5
6
  address: string;
@@ -14,4 +15,20 @@ export declare class Signer extends Provider implements SignerInterface {
14
15
  * @returns a confirmation of invoking a function on the starknet contract
15
16
  */
16
17
  addTransaction(transaction: Transaction): Promise<AddTransactionResponse>;
18
+ /**
19
+ * Sign an JSON object with the starknet private key and return the signature
20
+ *
21
+ * @param json - JSON object to be signed
22
+ * @returns the signature of the JSON object
23
+ * @throws {Error} if the JSON object is not a valid JSON
24
+ */
25
+ signMessage(typedData: TypedData): Promise<Signature>;
26
+ /**
27
+ * Hash a JSON object with pederson hash and return the hash
28
+ *
29
+ * @param json - JSON object to be hashed
30
+ * @returns the hash of the JSON object
31
+ * @throws {Error} if the JSON object is not a valid JSON
32
+ */
33
+ hashMessage(typedData: TypedData): Promise<string>;
17
34
  }
package/signer/default.js CHANGED
@@ -203,6 +203,7 @@ var encode_1 = require('../utils/encode');
203
203
  var hash_1 = require('../utils/hash');
204
204
  var number_1 = require('../utils/number');
205
205
  var stark_1 = require('../utils/stark');
206
+ var typedData_1 = require('../utils/typedData');
206
207
  var Signer = /** @class */ (function (_super) {
207
208
  __extends(Signer, _super);
208
209
  function Signer(provider, address, keyPair) {
@@ -221,9 +222,9 @@ var Signer = /** @class */ (function (_super) {
221
222
  */
222
223
  Signer.prototype.addTransaction = function (transaction) {
223
224
  return __awaiter(this, void 0, void 0, function () {
224
- var nonceBn, result, calldataDecimal, msgHash, _a, r, s;
225
- return __generator(this, function (_b) {
226
- switch (_b.label) {
225
+ var nonceBn, result, calldataDecimal, msgHash, signature;
226
+ return __generator(this, function (_a) {
227
+ switch (_a.label) {
227
228
  case 0:
228
229
  if (transaction.type === 'DEPLOY')
229
230
  return [2 /*return*/, _super.prototype.addTransaction.call(this, transaction)];
@@ -241,9 +242,9 @@ var Signer = /** @class */ (function (_super) {
241
242
  }),
242
243
  ];
243
244
  case 2:
244
- result = _b.sent().result;
245
+ result = _a.sent().result;
245
246
  nonceBn = (0, number_1.toBN)(result[0]);
246
- _b.label = 3;
247
+ _a.label = 3;
247
248
  case 3:
248
249
  calldataDecimal = (transaction.calldata || []).map(function (x) {
249
250
  return (0, number_1.toBN)(x).toString();
@@ -257,7 +258,7 @@ var Signer = /** @class */ (function (_super) {
257
258
  nonceBn.toString()
258
259
  )
259
260
  );
260
- (_a = (0, ellipticCurve_1.sign)(this.keyPair, msgHash)), (r = _a.r), (s = _a.s);
261
+ signature = (0, ellipticCurve_1.sign)(this.keyPair, msgHash);
261
262
  return [
262
263
  2 /*return*/,
263
264
  _super.prototype.addTransaction.call(this, {
@@ -279,13 +280,49 @@ var Signer = /** @class */ (function (_super) {
279
280
  return (0, number_1.toBN)(x).toString();
280
281
  }),
281
282
  contract_address: this.address,
282
- signature: [r, s],
283
+ signature: signature,
283
284
  }),
284
285
  ];
285
286
  }
286
287
  });
287
288
  });
288
289
  };
290
+ /**
291
+ * Sign an JSON object with the starknet private key and return the signature
292
+ *
293
+ * @param json - JSON object to be signed
294
+ * @returns the signature of the JSON object
295
+ * @throws {Error} if the JSON object is not a valid JSON
296
+ */
297
+ Signer.prototype.signMessage = function (typedData) {
298
+ return __awaiter(this, void 0, void 0, function () {
299
+ var _a, _b;
300
+ return __generator(this, function (_c) {
301
+ switch (_c.label) {
302
+ case 0:
303
+ _a = ellipticCurve_1.sign;
304
+ _b = [this.keyPair];
305
+ return [4 /*yield*/, this.hashMessage(typedData)];
306
+ case 1:
307
+ return [2 /*return*/, _a.apply(void 0, _b.concat([_c.sent()]))];
308
+ }
309
+ });
310
+ });
311
+ };
312
+ /**
313
+ * Hash a JSON object with pederson hash and return the hash
314
+ *
315
+ * @param json - JSON object to be hashed
316
+ * @returns the hash of the JSON object
317
+ * @throws {Error} if the JSON object is not a valid JSON
318
+ */
319
+ Signer.prototype.hashMessage = function (typedData) {
320
+ return __awaiter(this, void 0, void 0, function () {
321
+ return __generator(this, function (_a) {
322
+ return [2 /*return*/, (0, typedData_1.getMessageHash)(typedData, this.address)];
323
+ });
324
+ });
325
+ };
289
326
  return Signer;
290
327
  })(provider_1.Provider);
291
328
  exports.Signer = Signer;
@@ -1,5 +1,6 @@
1
1
  import { Provider } from '../provider';
2
- import { AddTransactionResponse, Transaction } from '../types';
2
+ import { AddTransactionResponse, Signature, Transaction } from '../types';
3
+ import { TypedData } from '../utils/typedData/types';
3
4
  export declare abstract class SignerInterface extends Provider {
4
5
  abstract address: string;
5
6
  /**
@@ -11,4 +12,22 @@ export declare abstract class SignerInterface extends Provider {
11
12
  * @returns a confirmation of invoking a function on the starknet contract
12
13
  */
13
14
  abstract addTransaction(transaction: Transaction): Promise<AddTransactionResponse>;
15
+ /**
16
+ * Sign an JSON object for off-chain usage with the starknet private key and return the signature
17
+ * This adds a message prefix so it cant be interchanged with transactions
18
+ *
19
+ * @param json - JSON object to be signed
20
+ * @returns the signature of the JSON object
21
+ * @throws {Error} if the JSON object is not a valid JSON
22
+ */
23
+ abstract signMessage(typedData: TypedData): Promise<Signature>;
24
+ /**
25
+ * Hash a JSON object with pederson hash and return the hash
26
+ * This adds a message prefix so it cant be interchanged with transactions
27
+ *
28
+ * @param json - JSON object to be hashed
29
+ * @returns the hash of the JSON object
30
+ * @throws {Error} if the JSON object is not a valid JSON
31
+ */
32
+ abstract hashMessage(typedData: TypedData): Promise<string>;
14
33
  }
package/src/contract.ts CHANGED
@@ -2,7 +2,7 @@ import BN from 'bn.js';
2
2
  import assert from 'minimalistic-assert';
3
3
 
4
4
  import { Provider, defaultProvider } from './provider';
5
- import { Abi, AbiEntry, FunctionAbi, StructAbi } from './types';
5
+ import { Abi, AbiEntry, FunctionAbi, Signature, StructAbi } from './types';
6
6
  import { BigNumberish, toBN } from './utils/number';
7
7
  import { getSelectorFromName } from './utils/stark';
8
8
 
@@ -146,7 +146,7 @@ export class Contract {
146
146
  return this.parseResponseField(methodAbi, responseIterator);
147
147
  }
148
148
 
149
- public invoke(method: string, args: Args = {}, signature?: [BigNumberish, BigNumberish]) {
149
+ public invoke(method: string, args: Args = {}, signature?: Signature) {
150
150
  // ensure contract is connected
151
151
  assert(this.connectedTo !== null, 'contract isnt connected to an address');
152
152
 
package/src/index.ts CHANGED
@@ -18,3 +18,4 @@ export * as stark from './utils/stark';
18
18
  export * as ec from './utils/ellipticCurve';
19
19
  export * as uint256 from './utils/uint256';
20
20
  export * as shortString from './utils/shortString';
21
+ export * as typedData from './utils/typedData';