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.
- package/CHANGELOG.md +16 -0
- package/__tests__/account.test.ts +3 -3
- package/__tests__/utils/ellipticalCurve.test.ts +1 -1
- package/__tests__/utils/typedData.test.ts +72 -0
- package/contract.d.ts +2 -2
- package/dist/contract.d.ts +2 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -1
- package/dist/provider/default.d.ts +2 -2
- package/dist/provider/default.js +10 -9
- package/dist/provider/interface.d.ts +2 -2
- package/dist/signer/default.d.ts +18 -1
- package/dist/signer/default.js +43 -7
- package/dist/signer/interface.d.ts +20 -1
- package/dist/types.d.ts +3 -3
- package/dist/utils/ellipticCurve.d.ts +8 -1
- package/dist/utils/ellipticCurve.js +48 -9
- package/dist/utils/stark.d.ts +2 -3
- package/dist/utils/typedData/index.d.ts +91 -0
- package/dist/utils/typedData/index.js +183 -0
- package/dist/utils/typedData/types.d.ts +82 -0
- package/dist/utils/typedData/types.js +47 -0
- package/dist/utils/typedData/utils.d.ts +24 -0
- package/dist/utils/typedData/utils.js +15 -0
- package/index.d.ts +1 -0
- package/index.js +3 -1
- package/package.json +2 -1
- package/provider/default.d.ts +2 -1
- package/provider/default.js +10 -10
- package/provider/interface.d.ts +2 -1
- package/signer/default.d.ts +18 -1
- package/signer/default.js +44 -7
- package/signer/interface.d.ts +20 -1
- package/src/contract.ts +2 -2
- package/src/index.ts +1 -0
- package/src/provider/default.ts +5 -5
- package/src/provider/interface.ts +2 -1
- package/src/signer/default.ts +26 -3
- package/src/signer/interface.ts +22 -1
- package/src/types.ts +9 -3
- package/src/utils/ellipticCurve.ts +31 -9
- package/src/utils/stark.ts +4 -4
- package/src/utils/typedData/index.ts +176 -0
- package/src/utils/typedData/types.ts +82 -0
- package/src/utils/typedData/utils.ts +13 -0
- package/types.d.ts +5 -4
- package/utils/ellipticCurve.d.ts +12 -1
- package/utils/ellipticCurve.js +72 -23
- package/utils/stark.d.ts +2 -3
- package/utils/typedData/index.d.ts +113 -0
- package/utils/typedData/index.js +247 -0
- package/utils/typedData/types.d.ts +103 -0
- package/utils/typedData/types.js +57 -0
- package/utils/typedData/utils.d.ts +27 -0
- package/utils/typedData/utils.js +15 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
# [2.5.0](https://github.com/seanjameshan/starknet.js/compare/v2.4.0...v2.5.0) (2021-12-13)
|
|
2
|
+
|
|
3
|
+
### Bug Fixes
|
|
4
|
+
|
|
5
|
+
- add jsdoc comment ([4cd969f](https://github.com/seanjameshan/starknet.js/commit/4cd969f82eb4a5d8c08feb59c42fb3e7195af50e))
|
|
6
|
+
- remove eip712 reference ([039a360](https://github.com/seanjameshan/starknet.js/commit/039a360873f9a1cdedc7a498b6e1732183957143))
|
|
7
|
+
- remove unused types ([e528f7d](https://github.com/seanjameshan/starknet.js/commit/e528f7d75f4560d2affe3ca99426e01fbee6dfb5))
|
|
8
|
+
- review ([a3813c9](https://github.com/seanjameshan/starknet.js/commit/a3813c9931c178d58c2521b926fb3fdff6944635))
|
|
9
|
+
|
|
10
|
+
### Features
|
|
11
|
+
|
|
12
|
+
- add `getKeyPairFromPublicKey` method ([66d543d](https://github.com/seanjameshan/starknet.js/commit/66d543dca1bb302654f0f1588a27f7794bfa49be))
|
|
13
|
+
- add tests ([b414a83](https://github.com/seanjameshan/starknet.js/commit/b414a839a1fdd56084a58d6efb4747e8f5455628))
|
|
14
|
+
- allow multi sig ([fc1e086](https://github.com/seanjameshan/starknet.js/commit/fc1e0866154d2bf29f26374639a34fec438bae5e))
|
|
15
|
+
- support eip712 for starknet ([d597082](https://github.com/seanjameshan/starknet.js/commit/d59708211fc497d801699a7168dad1a5cc9648fd))
|
|
16
|
+
|
|
1
17
|
# [2.4.0](https://github.com/seanjameshan/starknet.js/compare/v2.3.1...v2.4.0) (2021-12-09)
|
|
2
18
|
|
|
3
19
|
### Features
|
|
@@ -104,7 +104,7 @@ describe('deploy and test Wallet', () => {
|
|
|
104
104
|
)
|
|
105
105
|
);
|
|
106
106
|
|
|
107
|
-
const
|
|
107
|
+
const signature = ec.sign(starkKeyPair, msgHash);
|
|
108
108
|
const { code, transaction_hash } = await wallet.invoke(
|
|
109
109
|
'execute',
|
|
110
110
|
{
|
|
@@ -113,7 +113,7 @@ describe('deploy and test Wallet', () => {
|
|
|
113
113
|
calldata: [erc20Address, '10'],
|
|
114
114
|
nonce: nonce.toString(),
|
|
115
115
|
},
|
|
116
|
-
|
|
116
|
+
signature
|
|
117
117
|
);
|
|
118
118
|
|
|
119
119
|
expect(code).toBe('TRANSACTION_RECEIVED');
|
|
@@ -151,7 +151,7 @@ test('build tx', async () => {
|
|
|
151
151
|
.toString()
|
|
152
152
|
);
|
|
153
153
|
|
|
154
|
-
const
|
|
154
|
+
const [r, s] = ec.sign(keyPair, msgHash);
|
|
155
155
|
expect(r.toString()).toBe(
|
|
156
156
|
'706800951915233622090196542158919402159816118214143837213294331713137614072'
|
|
157
157
|
);
|
|
@@ -40,7 +40,7 @@ test('hashMessage()', () => {
|
|
|
40
40
|
);
|
|
41
41
|
expect(hashMsg).toBe('0x7f15c38ea577a26f4f553282fcfe4f1feeb8ecfaad8f221ae41abf8224cbddd');
|
|
42
42
|
const keyPair = getKeyPair(privateKey);
|
|
43
|
-
const
|
|
43
|
+
const [r, s] = sign(keyPair, removeHexPrefix(hashMsg));
|
|
44
44
|
expect(r.toString()).toStrictEqual(
|
|
45
45
|
toBN('2458502865976494910213617956670505342647705497324144349552978333078363662855').toString()
|
|
46
46
|
);
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { encodeType, getMessageHash, getStructHash, getTypeHash } from '../../src/utils/typedData';
|
|
2
|
+
|
|
3
|
+
const typedDataExample = {
|
|
4
|
+
types: {
|
|
5
|
+
StarkNetDomain: [
|
|
6
|
+
{ name: 'name', type: 'felt' },
|
|
7
|
+
{ name: 'version', type: 'felt' },
|
|
8
|
+
{ name: 'chainId', type: 'felt' },
|
|
9
|
+
],
|
|
10
|
+
Person: [
|
|
11
|
+
{ name: 'name', type: 'felt' },
|
|
12
|
+
{ name: 'wallet', type: 'felt' },
|
|
13
|
+
],
|
|
14
|
+
Mail: [
|
|
15
|
+
{ name: 'from', type: 'Person' },
|
|
16
|
+
{ name: 'to', type: 'Person' },
|
|
17
|
+
{ name: 'contents', type: 'felt' },
|
|
18
|
+
],
|
|
19
|
+
},
|
|
20
|
+
primaryType: 'Mail',
|
|
21
|
+
domain: {
|
|
22
|
+
name: 'StarkNet Mail',
|
|
23
|
+
version: '1',
|
|
24
|
+
chainId: 1,
|
|
25
|
+
},
|
|
26
|
+
message: {
|
|
27
|
+
from: {
|
|
28
|
+
name: 'Cow',
|
|
29
|
+
wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826',
|
|
30
|
+
},
|
|
31
|
+
to: {
|
|
32
|
+
name: 'Bob',
|
|
33
|
+
wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB',
|
|
34
|
+
},
|
|
35
|
+
contents: 'Hello, Bob!',
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
describe('typedData', () => {
|
|
40
|
+
test('should get right type encoding', () => {
|
|
41
|
+
const typeEncoding = encodeType(typedDataExample, 'Mail');
|
|
42
|
+
expect(typeEncoding).toMatchInlineSnapshot(
|
|
43
|
+
`"Mail(from:Person,to:Person,contents:felt)Person(name:felt,wallet:felt)"`
|
|
44
|
+
);
|
|
45
|
+
});
|
|
46
|
+
test('should get right type hash', () => {
|
|
47
|
+
const typeHashDomain = getTypeHash(typedDataExample, 'StarkNetDomain');
|
|
48
|
+
expect(typeHashDomain).toMatchInlineSnapshot(
|
|
49
|
+
`"0x1bfc207425a47a5dfa1a50a4f5241203f50624ca5fdf5e18755765416b8e288"`
|
|
50
|
+
);
|
|
51
|
+
const typeHashPerson = getTypeHash(typedDataExample, 'Person');
|
|
52
|
+
expect(typeHashPerson).toMatchInlineSnapshot(
|
|
53
|
+
`"0x2896dbe4b96a67110f454c01e5336edc5bbc3635537efd690f122f4809cc855"`
|
|
54
|
+
);
|
|
55
|
+
const typeHashMail = getTypeHash(typedDataExample, 'Mail');
|
|
56
|
+
expect(typeHashMail).toMatchInlineSnapshot(
|
|
57
|
+
`"0x13d89452df9512bf750f539ba3001b945576243288137ddb6c788457d4b2f79"`
|
|
58
|
+
);
|
|
59
|
+
});
|
|
60
|
+
test('should get right hash for StarkNetDomain', () => {
|
|
61
|
+
const hash = getStructHash(typedDataExample, 'StarkNetDomain', typedDataExample.domain as any);
|
|
62
|
+
expect(hash).toMatchInlineSnapshot(
|
|
63
|
+
`"0x54833b121883a3e3aebff48ec08a962f5742e5f7b973469c1f8f4f55d470b07"`
|
|
64
|
+
);
|
|
65
|
+
});
|
|
66
|
+
test('should get right hash for entire message', () => {
|
|
67
|
+
const hash = getMessageHash(typedDataExample, '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826');
|
|
68
|
+
expect(hash).toMatchInlineSnapshot(
|
|
69
|
+
`"0x6fcff244f63e38b9d88b9e3378d44757710d1b244282b435cb472053c8d78d0"`
|
|
70
|
+
);
|
|
71
|
+
});
|
|
72
|
+
});
|
package/contract.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Provider } from './provider';
|
|
2
|
-
import { Abi, StructAbi } from './types';
|
|
2
|
+
import { Abi, Signature, StructAbi } from './types';
|
|
3
3
|
import { BigNumberish } from './utils/number';
|
|
4
4
|
export declare type Args = {
|
|
5
5
|
[inputName: string]:
|
|
@@ -33,7 +33,7 @@ export declare class Contract {
|
|
|
33
33
|
invoke(
|
|
34
34
|
method: string,
|
|
35
35
|
args?: Args,
|
|
36
|
-
signature?:
|
|
36
|
+
signature?: Signature
|
|
37
37
|
): Promise<import('./types').AddTransactionResponse>;
|
|
38
38
|
call(method: string, args?: Args): Promise<Args>;
|
|
39
39
|
}
|
package/dist/contract.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Provider } from './provider';
|
|
2
|
-
import { Abi, StructAbi } from './types';
|
|
2
|
+
import { Abi, Signature, StructAbi } from './types';
|
|
3
3
|
import { BigNumberish } from './utils/number';
|
|
4
4
|
export declare type Args = {
|
|
5
5
|
[inputName: string]: string | string[] | {
|
|
@@ -27,6 +27,6 @@ export declare class Contract {
|
|
|
27
27
|
private validateMethodAndArgs;
|
|
28
28
|
private parseResponseField;
|
|
29
29
|
private parseResponse;
|
|
30
|
-
invoke(method: string, args?: Args, signature?:
|
|
30
|
+
invoke(method: string, args?: Args, signature?: Signature): Promise<import("./types").AddTransactionResponse>;
|
|
31
31
|
call(method: string, args?: Args): Promise<Args>;
|
|
32
32
|
}
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -22,7 +22,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
22
22
|
return result;
|
|
23
23
|
};
|
|
24
24
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
-
exports.shortString = exports.uint256 = exports.ec = exports.stark = exports.number = exports.json = exports.hash = exports.encode = exports.constants = void 0;
|
|
25
|
+
exports.typedData = exports.shortString = exports.uint256 = exports.ec = exports.stark = exports.number = exports.json = exports.hash = exports.encode = exports.constants = void 0;
|
|
26
26
|
/**
|
|
27
27
|
* Main
|
|
28
28
|
*/
|
|
@@ -42,3 +42,4 @@ exports.stark = __importStar(require("./utils/stark"));
|
|
|
42
42
|
exports.ec = __importStar(require("./utils/ellipticCurve"));
|
|
43
43
|
exports.uint256 = __importStar(require("./utils/uint256"));
|
|
44
44
|
exports.shortString = __importStar(require("./utils/shortString"));
|
|
45
|
+
exports.typedData = __importStar(require("./utils/typedData"));
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AddTransactionResponse, CallContractResponse, CallContractTransaction, CompiledContract, GetBlockResponse, GetCodeResponse, GetContractAddressesResponse, GetTransactionResponse, GetTransactionStatusResponse, Transaction } from '../types';
|
|
1
|
+
import { AddTransactionResponse, CallContractResponse, CallContractTransaction, CompiledContract, GetBlockResponse, GetCodeResponse, GetContractAddressesResponse, GetTransactionResponse, GetTransactionStatusResponse, Signature, Transaction } from '../types';
|
|
2
2
|
import { BigNumberish } from '../utils/number';
|
|
3
3
|
import { ProviderInterface } from './interface';
|
|
4
4
|
declare type NetworkName = 'mainnet-alpha' | 'georli-alpha';
|
|
@@ -104,7 +104,7 @@ export declare class Provider implements ProviderInterface {
|
|
|
104
104
|
* @param signature - (optional) signature to send along
|
|
105
105
|
* @returns response from addTransaction
|
|
106
106
|
*/
|
|
107
|
-
invokeFunction(contractAddress: string, entrypointSelector: string, calldata?: string[], signature?:
|
|
107
|
+
invokeFunction(contractAddress: string, entrypointSelector: string, calldata?: string[], signature?: Signature): Promise<AddTransactionResponse>;
|
|
108
108
|
waitForTx(txHash: BigNumberish, retryInterval?: number): Promise<void>;
|
|
109
109
|
}
|
|
110
110
|
export {};
|
package/dist/provider/default.js
CHANGED
|
@@ -308,20 +308,21 @@ var Provider = /** @class */ (function () {
|
|
|
308
308
|
switch (_a.label) {
|
|
309
309
|
case 0:
|
|
310
310
|
onchain = false;
|
|
311
|
-
|
|
311
|
+
return [4 /*yield*/, wait(retryInterval)];
|
|
312
312
|
case 1:
|
|
313
|
-
|
|
313
|
+
_a.sent();
|
|
314
|
+
_a.label = 2;
|
|
315
|
+
case 2:
|
|
316
|
+
if (!!onchain) return [3 /*break*/, 5];
|
|
314
317
|
// eslint-disable-next-line no-await-in-loop
|
|
315
318
|
return [4 /*yield*/, wait(retryInterval)];
|
|
316
|
-
case
|
|
319
|
+
case 3:
|
|
317
320
|
// eslint-disable-next-line no-await-in-loop
|
|
318
321
|
_a.sent();
|
|
319
322
|
return [4 /*yield*/, this.getTransactionStatus(txHash)];
|
|
320
|
-
case
|
|
323
|
+
case 4:
|
|
321
324
|
res = _a.sent();
|
|
322
|
-
if (res.tx_status === '
|
|
323
|
-
(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.
|
|
324
|
-
) {
|
|
325
|
+
if (res.tx_status === 'ACCEPTED_ON_L1' || res.tx_status === 'ACCEPTED_ON_L2') {
|
|
325
326
|
onchain = true;
|
|
326
327
|
}
|
|
327
328
|
else if (res.tx_status === 'REJECTED') {
|
|
@@ -330,8 +331,8 @@ var Provider = /** @class */ (function () {
|
|
|
330
331
|
else if (res.tx_status === 'NOT_RECEIVED') {
|
|
331
332
|
throw Error('NOT_RECEIVED');
|
|
332
333
|
}
|
|
333
|
-
return [3 /*break*/,
|
|
334
|
-
case
|
|
334
|
+
return [3 /*break*/, 2];
|
|
335
|
+
case 5: return [2 /*return*/];
|
|
335
336
|
}
|
|
336
337
|
});
|
|
337
338
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AddTransactionResponse, CallContractResponse, CallContractTransaction, CompiledContract, GetBlockResponse, GetCodeResponse, GetContractAddressesResponse, GetTransactionResponse, GetTransactionStatusResponse, Transaction } from '../types';
|
|
1
|
+
import type { AddTransactionResponse, CallContractResponse, CallContractTransaction, CompiledContract, GetBlockResponse, GetCodeResponse, GetContractAddressesResponse, GetTransactionResponse, GetTransactionStatusResponse, Signature, Transaction } from '../types';
|
|
2
2
|
import type { BigNumberish } from '../utils/number';
|
|
3
3
|
export declare abstract class ProviderInterface {
|
|
4
4
|
abstract baseUrl: string;
|
|
@@ -95,6 +95,6 @@ export declare abstract class ProviderInterface {
|
|
|
95
95
|
* @param signature - (optional) signature to send along
|
|
96
96
|
* @returns response from addTransaction
|
|
97
97
|
*/
|
|
98
|
-
abstract invokeFunction(contractAddress: string, entrypointSelector: string, calldata?: string[], signature?:
|
|
98
|
+
abstract invokeFunction(contractAddress: string, entrypointSelector: string, calldata?: string[], signature?: Signature): Promise<AddTransactionResponse>;
|
|
99
99
|
abstract waitForTx(txHash: BigNumberish, retryInterval?: number): Promise<void>;
|
|
100
100
|
}
|
package/dist/signer/default.d.ts
CHANGED
|
@@ -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/dist/signer/default.js
CHANGED
|
@@ -87,6 +87,7 @@ var encode_1 = require("../utils/encode");
|
|
|
87
87
|
var hash_1 = require("../utils/hash");
|
|
88
88
|
var number_1 = require("../utils/number");
|
|
89
89
|
var stark_1 = require("../utils/stark");
|
|
90
|
+
var typedData_1 = require("../utils/typedData");
|
|
90
91
|
var Signer = /** @class */ (function (_super) {
|
|
91
92
|
__extends(Signer, _super);
|
|
92
93
|
function Signer(provider, address, keyPair) {
|
|
@@ -105,9 +106,9 @@ var Signer = /** @class */ (function (_super) {
|
|
|
105
106
|
*/
|
|
106
107
|
Signer.prototype.addTransaction = function (transaction) {
|
|
107
108
|
return __awaiter(this, void 0, void 0, function () {
|
|
108
|
-
var nonceBn, result, calldataDecimal, msgHash,
|
|
109
|
-
return __generator(this, function (
|
|
110
|
-
switch (
|
|
109
|
+
var nonceBn, result, calldataDecimal, msgHash, signature;
|
|
110
|
+
return __generator(this, function (_a) {
|
|
111
|
+
switch (_a.label) {
|
|
111
112
|
case 0:
|
|
112
113
|
if (transaction.type === 'DEPLOY')
|
|
113
114
|
return [2 /*return*/, _super.prototype.addTransaction.call(this, transaction)];
|
|
@@ -120,13 +121,13 @@ var Signer = /** @class */ (function (_super) {
|
|
|
120
121
|
entry_point_selector: (0, stark_1.getSelectorFromName)('get_nonce'),
|
|
121
122
|
})];
|
|
122
123
|
case 2:
|
|
123
|
-
result = (
|
|
124
|
+
result = (_a.sent()).result;
|
|
124
125
|
nonceBn = (0, number_1.toBN)(result[0]);
|
|
125
|
-
|
|
126
|
+
_a.label = 3;
|
|
126
127
|
case 3:
|
|
127
128
|
calldataDecimal = (transaction.calldata || []).map(function (x) { return (0, number_1.toBN)(x).toString(); });
|
|
128
129
|
msgHash = (0, encode_1.addHexPrefix)((0, hash_1.hashMessage)(this.address, transaction.contract_address, transaction.entry_point_selector, calldataDecimal, nonceBn.toString()));
|
|
129
|
-
|
|
130
|
+
signature = (0, ellipticCurve_1.sign)(this.keyPair, msgHash);
|
|
130
131
|
return [2 /*return*/, _super.prototype.addTransaction.call(this, {
|
|
131
132
|
type: 'INVOKE_FUNCTION',
|
|
132
133
|
entry_point_selector: (0, stark_1.getSelectorFromName)('execute'),
|
|
@@ -138,12 +139,47 @@ var Signer = /** @class */ (function (_super) {
|
|
|
138
139
|
nonceBn.toString(),
|
|
139
140
|
], false).map(function (x) { return (0, number_1.toBN)(x).toString(); }),
|
|
140
141
|
contract_address: this.address,
|
|
141
|
-
signature:
|
|
142
|
+
signature: signature,
|
|
142
143
|
})];
|
|
143
144
|
}
|
|
144
145
|
});
|
|
145
146
|
});
|
|
146
147
|
};
|
|
148
|
+
/**
|
|
149
|
+
* Sign an JSON object with the starknet private key and return the signature
|
|
150
|
+
*
|
|
151
|
+
* @param json - JSON object to be signed
|
|
152
|
+
* @returns the signature of the JSON object
|
|
153
|
+
* @throws {Error} if the JSON object is not a valid JSON
|
|
154
|
+
*/
|
|
155
|
+
Signer.prototype.signMessage = function (typedData) {
|
|
156
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
157
|
+
var _a, _b;
|
|
158
|
+
return __generator(this, function (_c) {
|
|
159
|
+
switch (_c.label) {
|
|
160
|
+
case 0:
|
|
161
|
+
_a = ellipticCurve_1.sign;
|
|
162
|
+
_b = [this.keyPair];
|
|
163
|
+
return [4 /*yield*/, this.hashMessage(typedData)];
|
|
164
|
+
case 1: return [2 /*return*/, _a.apply(void 0, _b.concat([_c.sent()]))];
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
};
|
|
169
|
+
/**
|
|
170
|
+
* Hash a JSON object with pederson hash and return the hash
|
|
171
|
+
*
|
|
172
|
+
* @param json - JSON object to be hashed
|
|
173
|
+
* @returns the hash of the JSON object
|
|
174
|
+
* @throws {Error} if the JSON object is not a valid JSON
|
|
175
|
+
*/
|
|
176
|
+
Signer.prototype.hashMessage = function (typedData) {
|
|
177
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
178
|
+
return __generator(this, function (_a) {
|
|
179
|
+
return [2 /*return*/, (0, typedData_1.getMessageHash)(typedData, this.address)];
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
};
|
|
147
183
|
return Signer;
|
|
148
184
|
}(provider_1.Provider));
|
|
149
185
|
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/dist/types.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type { ec as EC } from 'elliptic';
|
|
2
2
|
import type { BigNumberish } from './utils/number';
|
|
3
3
|
export declare type KeyPair = EC.KeyPair;
|
|
4
|
-
export declare type Signature =
|
|
4
|
+
export declare type Signature = BigNumberish[];
|
|
5
5
|
export declare type GetContractAddressesResponse = {
|
|
6
6
|
Starknet: string;
|
|
7
7
|
GpsStatementVerifier: string;
|
|
8
8
|
};
|
|
9
|
-
export declare type Status = 'NOT_RECEIVED' | 'RECEIVED' | 'PENDING' | '
|
|
9
|
+
export declare type Status = 'NOT_RECEIVED' | 'RECEIVED' | 'PENDING' | 'ACCEPTED_ON_L2' | 'ACCEPTED_ON_L1' | 'REJECTED';
|
|
10
10
|
export declare type TransactionStatus = 'TRANSACTION_RECEIVED';
|
|
11
11
|
export declare type Type = 'DEPLOY' | 'INVOKE_FUNCTION';
|
|
12
12
|
export declare type EntryPointType = 'EXTERNAL';
|
|
@@ -49,7 +49,7 @@ export declare type DeployTransaction = {
|
|
|
49
49
|
export declare type InvokeFunctionTransaction = {
|
|
50
50
|
type: 'INVOKE_FUNCTION';
|
|
51
51
|
contract_address: string;
|
|
52
|
-
signature?:
|
|
52
|
+
signature?: Signature;
|
|
53
53
|
entry_point_type?: EntryPointType;
|
|
54
54
|
entry_point_selector: string;
|
|
55
55
|
calldata?: string[];
|
|
@@ -5,5 +5,12 @@ export declare const ec: EC;
|
|
|
5
5
|
export declare const genKeyPair: (options?: EC.GenKeyPairOptions | undefined) => EC.KeyPair;
|
|
6
6
|
export declare function getKeyPair(pk: BigNumberish): KeyPair;
|
|
7
7
|
export declare function getStarkKey(keyPair: KeyPair): string;
|
|
8
|
+
/**
|
|
9
|
+
* Takes a public key and casts it into `elliptic` KeyPair format.
|
|
10
|
+
*
|
|
11
|
+
* @param publicKey - public key which should get casted to a KeyPair
|
|
12
|
+
* @returns keyPair with public key only, which can be used to verify signatures, but cant sign anything
|
|
13
|
+
*/
|
|
14
|
+
export declare function getKeyPairFromPublicKey(publicKey: BigNumberish): KeyPair;
|
|
8
15
|
export declare function sign(keyPair: KeyPair, msgHash: string): Signature;
|
|
9
|
-
export declare function verify(keyPair: KeyPair, msgHash: string, sig: Signature): boolean;
|
|
16
|
+
export declare function verify(keyPair: KeyPair | KeyPair[], msgHash: string, sig: Signature): boolean;
|
|
@@ -1,9 +1,25 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __read = (this && this.__read) || function (o, n) {
|
|
3
|
+
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
|
4
|
+
if (!m) return o;
|
|
5
|
+
var i = m.call(o), r, ar = [], e;
|
|
6
|
+
try {
|
|
7
|
+
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
|
|
8
|
+
}
|
|
9
|
+
catch (error) { e = { error: error }; }
|
|
10
|
+
finally {
|
|
11
|
+
try {
|
|
12
|
+
if (r && !r.done && (m = i["return"])) m.call(i);
|
|
13
|
+
}
|
|
14
|
+
finally { if (e) throw e.error; }
|
|
15
|
+
}
|
|
16
|
+
return ar;
|
|
17
|
+
};
|
|
2
18
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
19
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
20
|
};
|
|
5
21
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.verify = exports.sign = exports.getStarkKey = exports.getKeyPair = exports.genKeyPair = exports.ec = void 0;
|
|
22
|
+
exports.verify = exports.sign = exports.getKeyPairFromPublicKey = exports.getStarkKey = exports.getKeyPair = exports.genKeyPair = exports.ec = void 0;
|
|
7
23
|
var elliptic_1 = require("elliptic");
|
|
8
24
|
var hash_js_1 = __importDefault(require("hash.js"));
|
|
9
25
|
var minimalistic_assert_1 = __importDefault(require("minimalistic-assert"));
|
|
@@ -50,6 +66,17 @@ function getStarkKey(keyPair) {
|
|
|
50
66
|
return (0, encode_1.addHexPrefix)((0, encode_1.sanitizeBytes)(keyPair.pub.getX().toString(16), 2));
|
|
51
67
|
}
|
|
52
68
|
exports.getStarkKey = getStarkKey;
|
|
69
|
+
/**
|
|
70
|
+
* Takes a public key and casts it into `elliptic` KeyPair format.
|
|
71
|
+
*
|
|
72
|
+
* @param publicKey - public key which should get casted to a KeyPair
|
|
73
|
+
* @returns keyPair with public key only, which can be used to verify signatures, but cant sign anything
|
|
74
|
+
*/
|
|
75
|
+
function getKeyPairFromPublicKey(publicKey) {
|
|
76
|
+
var publicKeyBn = (0, number_1.toBN)(publicKey);
|
|
77
|
+
return exports.ec.keyFromPublic((0, encode_1.removeHexPrefix)((0, number_1.toHex)(publicKeyBn)), 'hex');
|
|
78
|
+
}
|
|
79
|
+
exports.getKeyPairFromPublicKey = getKeyPairFromPublicKey;
|
|
53
80
|
/*
|
|
54
81
|
Signs a message using the provided key.
|
|
55
82
|
key should be an KeyPair with a valid private key.
|
|
@@ -66,9 +93,14 @@ function sign(keyPair, msgHash) {
|
|
|
66
93
|
(0, number_1.assertInRange)(r, constants_1.ONE, (0, number_1.toBN)((0, encode_1.addHexPrefix)(constants_1.MAX_ECDSA_VAL)), 'r');
|
|
67
94
|
(0, number_1.assertInRange)(s, constants_1.ONE, (0, number_1.toBN)((0, encode_1.addHexPrefix)(constants_1.EC_ORDER)), 's');
|
|
68
95
|
(0, number_1.assertInRange)(w, constants_1.ONE, (0, number_1.toBN)((0, encode_1.addHexPrefix)(constants_1.MAX_ECDSA_VAL)), 'w');
|
|
69
|
-
return
|
|
96
|
+
return [r, s];
|
|
70
97
|
}
|
|
71
98
|
exports.sign = sign;
|
|
99
|
+
function chunkArray(arr, n) {
|
|
100
|
+
return Array(Math.ceil(arr.length / n))
|
|
101
|
+
.fill('')
|
|
102
|
+
.map(function (_, i) { return arr.slice(i * n, i * n + n); });
|
|
103
|
+
}
|
|
72
104
|
/*
|
|
73
105
|
Verifies a message using the provided key.
|
|
74
106
|
key should be an KeyPair with a valid public key.
|
|
@@ -76,14 +108,21 @@ exports.sign = sign;
|
|
|
76
108
|
Returns a boolean true if the verification succeeds.
|
|
77
109
|
*/
|
|
78
110
|
function verify(keyPair, msgHash, sig) {
|
|
111
|
+
var keyPairArray = Array.isArray(keyPair) ? keyPair : [keyPair];
|
|
79
112
|
var msgHashBN = (0, number_1.toBN)((0, encode_1.addHexPrefix)(msgHash));
|
|
113
|
+
(0, minimalistic_assert_1.default)(sig.length % 2 === 0, 'Signature must be an array of length dividable by 2');
|
|
80
114
|
(0, number_1.assertInRange)(msgHashBN, constants_1.ZERO, (0, number_1.toBN)((0, encode_1.addHexPrefix)(constants_1.MAX_ECDSA_VAL)), 'msgHash');
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
115
|
+
(0, minimalistic_assert_1.default)(keyPairArray.length === sig.length / 2, 'Signature and keyPair length must be equal');
|
|
116
|
+
return chunkArray(sig, 2).every(function (_a, i) {
|
|
117
|
+
var _b;
|
|
118
|
+
var _c = __read(_a, 2), r = _c[0], s = _c[1];
|
|
119
|
+
var rBN = (0, number_1.toBN)(r);
|
|
120
|
+
var sBN = (0, number_1.toBN)(s);
|
|
121
|
+
var w = sBN.invm(exports.ec.n);
|
|
122
|
+
(0, number_1.assertInRange)(rBN, constants_1.ONE, (0, number_1.toBN)((0, encode_1.addHexPrefix)(constants_1.MAX_ECDSA_VAL)), 'r');
|
|
123
|
+
(0, number_1.assertInRange)(sBN, constants_1.ONE, (0, number_1.toBN)((0, encode_1.addHexPrefix)(constants_1.EC_ORDER)), 's');
|
|
124
|
+
(0, number_1.assertInRange)(w, constants_1.ONE, (0, number_1.toBN)((0, encode_1.addHexPrefix)(constants_1.MAX_ECDSA_VAL)), 'w');
|
|
125
|
+
return (_b = exports.ec.verify(fixMessage(msgHash), { r: rBN, s: sBN }, keyPairArray[i])) !== null && _b !== void 0 ? _b : false;
|
|
126
|
+
});
|
|
88
127
|
}
|
|
89
128
|
exports.verify = verify;
|
package/dist/utils/stark.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { CompressedProgram, Program } from '../types';
|
|
2
|
-
import { BigNumberish } from './number';
|
|
1
|
+
import { CompressedProgram, Program, Signature } from '../types';
|
|
3
2
|
/**
|
|
4
3
|
* Function to compress compiled cairo program
|
|
5
4
|
*
|
|
@@ -18,4 +17,4 @@ export declare function compressProgram(jsonProgram: Program | string): Compress
|
|
|
18
17
|
export declare function getSelectorFromName(funcName: string): string;
|
|
19
18
|
export declare function randomAddress(): string;
|
|
20
19
|
export declare function makeAddress(input: string): string;
|
|
21
|
-
export declare function formatSignature(sig?:
|
|
20
|
+
export declare function formatSignature(sig?: Signature): string[];
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { BigNumberish } from '../number';
|
|
2
|
+
import { TypedData } from './types';
|
|
3
|
+
export * from './types';
|
|
4
|
+
/**
|
|
5
|
+
* Get the dependencies of a struct type. If a struct has the same dependency multiple times, it's only included once
|
|
6
|
+
* in the resulting array.
|
|
7
|
+
*
|
|
8
|
+
* @param {TypedData} typedData
|
|
9
|
+
* @param {string} type
|
|
10
|
+
* @param {string[]} [dependencies]
|
|
11
|
+
* @return {string[]}
|
|
12
|
+
*/
|
|
13
|
+
export declare const getDependencies: (typedData: TypedData, type: string, dependencies?: string[]) => string[];
|
|
14
|
+
/**
|
|
15
|
+
* Encode a type to a string. All dependant types are alphabetically sorted.
|
|
16
|
+
*
|
|
17
|
+
* @param {TypedData} typedData
|
|
18
|
+
* @param {string} type
|
|
19
|
+
* @return {string}
|
|
20
|
+
*/
|
|
21
|
+
export declare const encodeType: (typedData: TypedData, type: string) => string;
|
|
22
|
+
/**
|
|
23
|
+
* Get a type string as hash.
|
|
24
|
+
*
|
|
25
|
+
* @param {TypedData} typedData
|
|
26
|
+
* @param {string} type
|
|
27
|
+
* @return {string}
|
|
28
|
+
*/
|
|
29
|
+
export declare const getTypeHash: (typedData: TypedData, type: string) => string;
|
|
30
|
+
/**
|
|
31
|
+
* Encode the data to an ABI encoded Buffer. The data should be a key -> value object with all the required values. All
|
|
32
|
+
* dependant types are automatically encoded.
|
|
33
|
+
*
|
|
34
|
+
* @param {TypedData} typedData
|
|
35
|
+
* @param {string} type
|
|
36
|
+
* @param {Record<string, any>} data
|
|
37
|
+
*/
|
|
38
|
+
export declare const encodeData: <T extends {
|
|
39
|
+
types: {
|
|
40
|
+
StarkNetDomain: {
|
|
41
|
+
type: string;
|
|
42
|
+
name: string;
|
|
43
|
+
}[];
|
|
44
|
+
} & Record<string, {
|
|
45
|
+
type: string;
|
|
46
|
+
name: string;
|
|
47
|
+
}[]>;
|
|
48
|
+
primaryType: string;
|
|
49
|
+
domain: {
|
|
50
|
+
name?: string | undefined;
|
|
51
|
+
version?: string | undefined;
|
|
52
|
+
chainId?: string | number | undefined;
|
|
53
|
+
};
|
|
54
|
+
message: Record<string, unknown>;
|
|
55
|
+
}>(typedData: T, type: string, data: T["message"]) => string[][];
|
|
56
|
+
/**
|
|
57
|
+
* Get encoded data as a hash. The data should be a key -> value object with all the required values. All dependant
|
|
58
|
+
* types are automatically encoded.
|
|
59
|
+
*
|
|
60
|
+
* @param {TypedData} typedData
|
|
61
|
+
* @param {string} type
|
|
62
|
+
* @param {Record<string, any>} data
|
|
63
|
+
* @return {Buffer}
|
|
64
|
+
*/
|
|
65
|
+
export declare const getStructHash: <T extends {
|
|
66
|
+
types: {
|
|
67
|
+
StarkNetDomain: {
|
|
68
|
+
type: string;
|
|
69
|
+
name: string;
|
|
70
|
+
}[];
|
|
71
|
+
} & Record<string, {
|
|
72
|
+
type: string;
|
|
73
|
+
name: string;
|
|
74
|
+
}[]>;
|
|
75
|
+
primaryType: string;
|
|
76
|
+
domain: {
|
|
77
|
+
name?: string | undefined;
|
|
78
|
+
version?: string | undefined;
|
|
79
|
+
chainId?: string | number | undefined;
|
|
80
|
+
};
|
|
81
|
+
message: Record<string, unknown>;
|
|
82
|
+
}>(typedData: T, type: string, data: T["message"]) => string;
|
|
83
|
+
/**
|
|
84
|
+
* Get the EIP-191 encoded message to sign, from the typedData object. If `hash` is enabled, the message will be hashed
|
|
85
|
+
* with Keccak256.
|
|
86
|
+
*
|
|
87
|
+
* @param {TypedData} typedData
|
|
88
|
+
* @param {boolean} hash
|
|
89
|
+
* @return {string}
|
|
90
|
+
*/
|
|
91
|
+
export declare const getMessageHash: (typedData: TypedData, account: BigNumberish) => string;
|