starknet 3.9.0 → 3.10.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 +11 -0
- package/__mocks__/ArgentAccount.json +32022 -38726
- package/__tests__/accountContract.test.ts +42 -32
- package/__tests__/contract.test.ts +20 -6
- package/__tests__/utils/__snapshots__/utils.browser.test.ts.snap +2 -2
- package/__tests__/utils/__snapshots__/utils.test.ts.snap +2 -2
- package/__tests__/utils/ellipticalCurve.test.ts +26 -8
- package/__tests__/utils/transactionHash.test.ts +17 -0
- package/account/default.js +10 -21
- package/constants.d.ts +9 -0
- package/constants.js +13 -0
- package/dist/account/default.js +9 -5
- package/dist/constants.d.ts +9 -0
- package/dist/constants.js +12 -1
- package/dist/provider/default.d.ts +3 -0
- package/dist/provider/default.js +18 -0
- package/dist/provider/interface.d.ts +2 -0
- package/dist/signer/default.js +4 -2
- package/dist/signer/ledger.js +4 -2
- package/dist/types/signer.d.ts +2 -0
- package/dist/utils/hash.d.ts +4 -3
- package/dist/utils/hash.js +24 -24
- package/dist/utils/transaction.d.ts +2 -0
- package/dist/utils/transaction.js +5 -1
- package/dist/utils/typedData/index.d.ts +2 -2
- package/dist/utils/typedData/types.d.ts +3 -3
- package/dist/utils/typedData/utils.d.ts +1 -1
- package/package.json +1 -1
- package/provider/default.d.ts +3 -0
- package/provider/default.js +19 -0
- package/provider/interface.d.ts +2 -0
- package/signer/default.js +12 -6
- package/signer/ledger.js +12 -5
- package/src/account/default.ts +16 -9
- package/src/constants.ts +10 -0
- package/src/provider/default.ts +19 -0
- package/src/provider/interface.ts +3 -0
- package/src/signer/default.ts +10 -6
- package/src/signer/ledger.ts +10 -5
- package/src/types/signer.ts +2 -0
- package/src/utils/hash.ts +68 -26
- package/src/utils/transaction.ts +7 -0
- package/types/signer.d.ts +2 -0
- package/utils/hash.d.ts +24 -8
- package/utils/hash.js +55 -28
- package/utils/transaction.d.ts +5 -0
- package/utils/transaction.js +12 -1
- package/utils/typedData/index.d.ts +2 -2
- package/utils/typedData/types.d.ts +3 -3
- package/utils/typedData/utils.d.ts +1 -1
- package/__tests__/constancts.ts +0 -2
package/provider/default.js
CHANGED
|
@@ -175,6 +175,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
175
175
|
exports.Provider = void 0;
|
|
176
176
|
var axios_1 = __importDefault(require('axios'));
|
|
177
177
|
var url_join_1 = __importDefault(require('url-join'));
|
|
178
|
+
var constants_1 = require('../constants');
|
|
178
179
|
var hash_1 = require('../utils/hash');
|
|
179
180
|
var json_1 = require('../utils/json');
|
|
180
181
|
var number_1 = require('../utils/number');
|
|
@@ -203,16 +204,22 @@ var Provider = /** @class */ (function () {
|
|
|
203
204
|
if (optionsOrProvider === void 0) {
|
|
204
205
|
optionsOrProvider = { network: 'goerli-alpha' };
|
|
205
206
|
}
|
|
207
|
+
var _a;
|
|
206
208
|
if (optionsOrProvider instanceof Provider) {
|
|
207
209
|
this.baseUrl = optionsOrProvider.baseUrl;
|
|
208
210
|
this.feederGatewayUrl = optionsOrProvider.feederGatewayUrl;
|
|
209
211
|
this.gatewayUrl = optionsOrProvider.gatewayUrl;
|
|
212
|
+
this.chainId =
|
|
213
|
+
(_a = optionsOrProvider.chainId) !== null && _a !== void 0
|
|
214
|
+
? _a
|
|
215
|
+
: Provider.getChainIdFromBaseUrl(optionsOrProvider.baseUrl);
|
|
210
216
|
} else {
|
|
211
217
|
var baseUrl =
|
|
212
218
|
'baseUrl' in optionsOrProvider
|
|
213
219
|
? optionsOrProvider.baseUrl
|
|
214
220
|
: Provider.getNetworkFromName(optionsOrProvider.network);
|
|
215
221
|
this.baseUrl = baseUrl;
|
|
222
|
+
this.chainId = Provider.getChainIdFromBaseUrl(baseUrl);
|
|
216
223
|
this.feederGatewayUrl = (0, url_join_1.default)(baseUrl, 'feeder_gateway');
|
|
217
224
|
this.gatewayUrl = (0, url_join_1.default)(baseUrl, 'gateway');
|
|
218
225
|
}
|
|
@@ -226,6 +233,18 @@ var Provider = /** @class */ (function () {
|
|
|
226
233
|
return 'https://alpha4.starknet.io';
|
|
227
234
|
}
|
|
228
235
|
};
|
|
236
|
+
Provider.getChainIdFromBaseUrl = function (baseUrl) {
|
|
237
|
+
try {
|
|
238
|
+
var url = new URL(baseUrl);
|
|
239
|
+
if (url.host.includes('mainnet.starknet.io')) {
|
|
240
|
+
return constants_1.StarknetChainId.MAINNET;
|
|
241
|
+
}
|
|
242
|
+
} catch (_a) {
|
|
243
|
+
// eslint-disable-next-line no-console
|
|
244
|
+
console.error('Could not parse baseUrl: ' + baseUrl);
|
|
245
|
+
}
|
|
246
|
+
return constants_1.StarknetChainId.TESTNET;
|
|
247
|
+
};
|
|
229
248
|
Provider.prototype.getFetchUrl = function (endpoint) {
|
|
230
249
|
var gatewayUrlEndpoints = ['add_transaction'];
|
|
231
250
|
return gatewayUrlEndpoints.includes(endpoint) ? this.gatewayUrl : this.feederGatewayUrl;
|
package/provider/interface.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { StarknetChainId } from '../constants';
|
|
1
2
|
import type {
|
|
2
3
|
AddTransactionResponse,
|
|
3
4
|
Call,
|
|
@@ -17,6 +18,7 @@ export declare abstract class ProviderInterface {
|
|
|
17
18
|
abstract baseUrl: string;
|
|
18
19
|
abstract feederGatewayUrl: string;
|
|
19
20
|
abstract gatewayUrl: string;
|
|
21
|
+
abstract chainId: StarknetChainId;
|
|
20
22
|
/**
|
|
21
23
|
* Gets the smart contract address on the goerli testnet.
|
|
22
24
|
*
|
package/signer/default.js
CHANGED
|
@@ -134,6 +134,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
134
134
|
exports.Signer = void 0;
|
|
135
135
|
var ellipticCurve_1 = require('../utils/ellipticCurve');
|
|
136
136
|
var hash_1 = require('../utils/hash');
|
|
137
|
+
var transaction_1 = require('../utils/transaction');
|
|
137
138
|
var typedData_1 = require('../utils/typedData');
|
|
138
139
|
var Signer = /** @class */ (function () {
|
|
139
140
|
function Signer(keyPair) {
|
|
@@ -148,17 +149,22 @@ var Signer = /** @class */ (function () {
|
|
|
148
149
|
};
|
|
149
150
|
Signer.prototype.signTransaction = function (transactions, transactionsDetail, abis) {
|
|
150
151
|
return __awaiter(this, void 0, void 0, function () {
|
|
151
|
-
var msgHash;
|
|
152
|
+
var calldata, msgHash;
|
|
152
153
|
return __generator(this, function (_a) {
|
|
153
154
|
if (abis && abis.length !== transactions.length) {
|
|
154
155
|
throw new Error('ABI must be provided for each transaction or no transaction');
|
|
155
156
|
}
|
|
156
|
-
|
|
157
|
-
transactionsDetail.walletAddress,
|
|
157
|
+
calldata = (0, transaction_1.fromCallsToExecuteCalldataWithNonce)(
|
|
158
158
|
transactions,
|
|
159
|
-
transactionsDetail.nonce
|
|
160
|
-
|
|
161
|
-
|
|
159
|
+
transactionsDetail.nonce
|
|
160
|
+
);
|
|
161
|
+
msgHash = (0, hash_1.calculcateTransactionHash)(
|
|
162
|
+
transactionsDetail.walletAddress,
|
|
163
|
+
transactionsDetail.version,
|
|
164
|
+
(0, hash_1.getSelectorFromName)('__execute__'),
|
|
165
|
+
calldata,
|
|
166
|
+
transactionsDetail.maxFee,
|
|
167
|
+
transactionsDetail.chainId
|
|
162
168
|
);
|
|
163
169
|
return [2 /*return*/, (0, ellipticCurve_1.sign)(this.keyPair, msgHash)];
|
|
164
170
|
});
|
package/signer/ledger.js
CHANGED
|
@@ -141,6 +141,7 @@ var hw_app_eth_1 = __importDefault(require('@ledgerhq/hw-app-eth'));
|
|
|
141
141
|
var hw_transport_webhid_1 = __importDefault(require('@ledgerhq/hw-transport-webhid'));
|
|
142
142
|
var encode_1 = require('../utils/encode');
|
|
143
143
|
var hash_1 = require('../utils/hash');
|
|
144
|
+
var transaction_1 = require('../utils/transaction');
|
|
144
145
|
var typedData_1 = require('../utils/typedData');
|
|
145
146
|
function hexZeroPad(hash, length) {
|
|
146
147
|
var value = hash;
|
|
@@ -200,13 +201,19 @@ var LedgerBlindSigner = /** @class */ (function () {
|
|
|
200
201
|
};
|
|
201
202
|
LedgerBlindSigner.prototype.signTransaction = function (transactions, transactionsDetail) {
|
|
202
203
|
return __awaiter(this, void 0, void 0, function () {
|
|
203
|
-
var msgHash;
|
|
204
|
+
var calldata, msgHash;
|
|
204
205
|
return __generator(this, function (_a) {
|
|
205
|
-
|
|
206
|
-
transactionsDetail.walletAddress,
|
|
206
|
+
calldata = (0, transaction_1.fromCallsToExecuteCalldataWithNonce)(
|
|
207
207
|
transactions,
|
|
208
|
-
transactionsDetail.nonce
|
|
209
|
-
|
|
208
|
+
transactionsDetail.nonce
|
|
209
|
+
);
|
|
210
|
+
msgHash = (0, hash_1.calculcateTransactionHash)(
|
|
211
|
+
transactionsDetail.walletAddress,
|
|
212
|
+
transactionsDetail.version,
|
|
213
|
+
(0, hash_1.getSelectorFromName)('__execute__'),
|
|
214
|
+
calldata,
|
|
215
|
+
transactionsDetail.maxFee,
|
|
216
|
+
transactionsDetail.chainId
|
|
210
217
|
);
|
|
211
218
|
return [2 /*return*/, this.sign(msgHash)];
|
|
212
219
|
});
|
package/src/account/default.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import assert from 'minimalistic-assert';
|
|
2
2
|
|
|
3
|
+
import { ZERO } from '../constants';
|
|
3
4
|
import { Provider } from '../provider';
|
|
4
5
|
import { BlockIdentifier } from '../provider/utils';
|
|
5
6
|
import { Signer, SignerInterface } from '../signer';
|
|
@@ -9,6 +10,7 @@ import {
|
|
|
9
10
|
Call,
|
|
10
11
|
EstimateFeeResponse,
|
|
11
12
|
InvocationsDetails,
|
|
13
|
+
InvocationsSignerDetails,
|
|
12
14
|
InvokeFunctionTransaction,
|
|
13
15
|
KeyPair,
|
|
14
16
|
Signature,
|
|
@@ -19,12 +21,12 @@ import {
|
|
|
19
21
|
computeHashOnElements,
|
|
20
22
|
feeTransactionVersion,
|
|
21
23
|
getSelectorFromName,
|
|
22
|
-
transactionPrefix,
|
|
23
24
|
transactionVersion,
|
|
24
25
|
} from '../utils/hash';
|
|
25
26
|
import { BigNumberish, bigNumberishArrayToDecimalStringArray, toBN, toHex } from '../utils/number';
|
|
27
|
+
import { encodeShortString } from '../utils/shortString';
|
|
26
28
|
import { compileCalldata, estimatedFeeToMaxFee } from '../utils/stark';
|
|
27
|
-
import {
|
|
29
|
+
import { fromCallsToExecuteCalldataWithNonce } from '../utils/transaction';
|
|
28
30
|
import { TypedData, getMessageHash } from '../utils/typedData';
|
|
29
31
|
import { AccountInterface } from './interface';
|
|
30
32
|
|
|
@@ -58,15 +60,18 @@ export class Account extends Provider implements AccountInterface {
|
|
|
58
60
|
const transactions = Array.isArray(calls) ? calls : [calls];
|
|
59
61
|
const nonce = providedNonce ?? (await this.getNonce());
|
|
60
62
|
const version = toBN(feeTransactionVersion);
|
|
61
|
-
|
|
63
|
+
|
|
64
|
+
const signerDetails: InvocationsSignerDetails = {
|
|
62
65
|
walletAddress: this.address,
|
|
63
66
|
nonce: toBN(nonce),
|
|
64
|
-
maxFee:
|
|
67
|
+
maxFee: ZERO,
|
|
65
68
|
version,
|
|
69
|
+
chainId: this.chainId,
|
|
66
70
|
};
|
|
71
|
+
|
|
67
72
|
const signature = await this.signer.signTransaction(transactions, signerDetails);
|
|
68
73
|
|
|
69
|
-
const calldata =
|
|
74
|
+
const calldata = fromCallsToExecuteCalldataWithNonce(transactions, nonce);
|
|
70
75
|
return this.fetchEndpoint(
|
|
71
76
|
'estimate_fee',
|
|
72
77
|
{ blockIdentifier },
|
|
@@ -96,22 +101,24 @@ export class Account extends Provider implements AccountInterface {
|
|
|
96
101
|
const transactions = Array.isArray(calls) ? calls : [calls];
|
|
97
102
|
const nonce = toBN(transactionsDetail.nonce ?? (await this.getNonce()));
|
|
98
103
|
let maxFee: BigNumberish = '0';
|
|
99
|
-
if (transactionsDetail.maxFee) {
|
|
104
|
+
if (transactionsDetail.maxFee || transactionsDetail.maxFee === 0) {
|
|
100
105
|
maxFee = transactionsDetail.maxFee;
|
|
101
106
|
} else {
|
|
102
107
|
const estimatedFee = (await this.estimateFee(transactions, { nonce })).amount;
|
|
103
108
|
maxFee = estimatedFeeToMaxFee(estimatedFee).toString();
|
|
104
109
|
}
|
|
105
|
-
|
|
110
|
+
|
|
111
|
+
const signerDetails: InvocationsSignerDetails = {
|
|
106
112
|
walletAddress: this.address,
|
|
107
113
|
nonce,
|
|
108
114
|
maxFee,
|
|
109
115
|
version: toBN(transactionVersion),
|
|
116
|
+
chainId: this.chainId,
|
|
110
117
|
};
|
|
111
118
|
|
|
112
119
|
const signature = await this.signer.signTransaction(transactions, signerDetails, abis);
|
|
113
120
|
|
|
114
|
-
const calldata =
|
|
121
|
+
const calldata = fromCallsToExecuteCalldataWithNonce(transactions, nonce);
|
|
115
122
|
return this.fetchEndpoint('add_transaction', undefined, {
|
|
116
123
|
type: 'INVOKE_FUNCTION',
|
|
117
124
|
contract_address: this.address,
|
|
@@ -161,7 +168,7 @@ export class Account extends Provider implements AccountInterface {
|
|
|
161
168
|
.map(computeHashOnElements);
|
|
162
169
|
|
|
163
170
|
return computeHashOnElements([
|
|
164
|
-
|
|
171
|
+
encodeShortString('StarkNet Transaction'),
|
|
165
172
|
account,
|
|
166
173
|
computeHashOnElements(hashArray),
|
|
167
174
|
nonce,
|
package/src/constants.ts
CHANGED
|
@@ -8,6 +8,16 @@ export const TWO = toBN(2);
|
|
|
8
8
|
export const MASK_250 = TWO.pow(toBN(250)).sub(ONE); // 2 ** 250 - 1
|
|
9
9
|
export const MASK_251 = TWO.pow(toBN(251));
|
|
10
10
|
|
|
11
|
+
export enum StarknetChainId {
|
|
12
|
+
MAINNET = '0x534e5f4d41494e', // encodeShortString('SN_MAIN'),
|
|
13
|
+
TESTNET = '0x534e5f474f45524c49', // encodeShortString('SN_GOERLI'),
|
|
14
|
+
}
|
|
15
|
+
export enum TransactionHashPrefix {
|
|
16
|
+
DEPLOY = '0x6465706c6f79', // encodeShortString('deploy'),
|
|
17
|
+
INVOKE = '0x696e766f6b65', // encodeShortString('invoke'),
|
|
18
|
+
L1_HANDLER = '0x6c315f68616e646c6572', // encodeShortString('l1_handler'),
|
|
19
|
+
}
|
|
20
|
+
|
|
11
21
|
/**
|
|
12
22
|
* The following is taken from https://github.com/starkware-libs/starkex-resources/blob/master/crypto/starkware/crypto/signature/pedersen_params.json but converted to hex, because JS is very bad handling big integers by default
|
|
13
23
|
* Please do not edit until the JSON changes.
|
package/src/provider/default.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import axios, { AxiosRequestHeaders } from 'axios';
|
|
2
2
|
import urljoin from 'url-join';
|
|
3
3
|
|
|
4
|
+
import { StarknetChainId } from '../constants';
|
|
4
5
|
import {
|
|
5
6
|
Abi,
|
|
6
7
|
AddTransactionResponse,
|
|
@@ -49,17 +50,22 @@ export class Provider implements ProviderInterface {
|
|
|
49
50
|
|
|
50
51
|
public gatewayUrl: string;
|
|
51
52
|
|
|
53
|
+
public chainId: StarknetChainId;
|
|
54
|
+
|
|
52
55
|
constructor(optionsOrProvider: ProviderOptions | Provider = { network: 'goerli-alpha' }) {
|
|
53
56
|
if (optionsOrProvider instanceof Provider) {
|
|
54
57
|
this.baseUrl = optionsOrProvider.baseUrl;
|
|
55
58
|
this.feederGatewayUrl = optionsOrProvider.feederGatewayUrl;
|
|
56
59
|
this.gatewayUrl = optionsOrProvider.gatewayUrl;
|
|
60
|
+
this.chainId =
|
|
61
|
+
optionsOrProvider.chainId ?? Provider.getChainIdFromBaseUrl(optionsOrProvider.baseUrl);
|
|
57
62
|
} else {
|
|
58
63
|
const baseUrl =
|
|
59
64
|
'baseUrl' in optionsOrProvider
|
|
60
65
|
? optionsOrProvider.baseUrl
|
|
61
66
|
: Provider.getNetworkFromName(optionsOrProvider.network);
|
|
62
67
|
this.baseUrl = baseUrl;
|
|
68
|
+
this.chainId = Provider.getChainIdFromBaseUrl(baseUrl);
|
|
63
69
|
this.feederGatewayUrl = urljoin(baseUrl, 'feeder_gateway');
|
|
64
70
|
this.gatewayUrl = urljoin(baseUrl, 'gateway');
|
|
65
71
|
}
|
|
@@ -75,6 +81,19 @@ export class Provider implements ProviderInterface {
|
|
|
75
81
|
}
|
|
76
82
|
}
|
|
77
83
|
|
|
84
|
+
protected static getChainIdFromBaseUrl(baseUrl: string): StarknetChainId {
|
|
85
|
+
try {
|
|
86
|
+
const url = new URL(baseUrl);
|
|
87
|
+
if (url.host.includes('mainnet.starknet.io')) {
|
|
88
|
+
return StarknetChainId.MAINNET;
|
|
89
|
+
}
|
|
90
|
+
} catch {
|
|
91
|
+
// eslint-disable-next-line no-console
|
|
92
|
+
console.error(`Could not parse baseUrl: ${baseUrl}`);
|
|
93
|
+
}
|
|
94
|
+
return StarknetChainId.TESTNET;
|
|
95
|
+
}
|
|
96
|
+
|
|
78
97
|
private getFetchUrl(endpoint: keyof Endpoints) {
|
|
79
98
|
const gatewayUrlEndpoints = ['add_transaction'];
|
|
80
99
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { StarknetChainId } from '../constants';
|
|
1
2
|
import type {
|
|
2
3
|
AddTransactionResponse,
|
|
3
4
|
Call,
|
|
@@ -21,6 +22,8 @@ export abstract class ProviderInterface {
|
|
|
21
22
|
|
|
22
23
|
public abstract gatewayUrl: string;
|
|
23
24
|
|
|
25
|
+
public abstract chainId: StarknetChainId;
|
|
26
|
+
|
|
24
27
|
/**
|
|
25
28
|
* Gets the smart contract address on the goerli testnet.
|
|
26
29
|
*
|
package/src/signer/default.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Abi, Invocation, InvocationsSignerDetails, KeyPair, Signature } from '../types';
|
|
2
2
|
import { getStarkKey, sign } from '../utils/ellipticCurve';
|
|
3
|
-
import {
|
|
3
|
+
import { calculcateTransactionHash, getSelectorFromName } from '../utils/hash';
|
|
4
|
+
import { fromCallsToExecuteCalldataWithNonce } from '../utils/transaction';
|
|
4
5
|
import { TypedData, getMessageHash } from '../utils/typedData';
|
|
5
6
|
import { SignerInterface } from './interface';
|
|
6
7
|
|
|
@@ -25,12 +26,15 @@ export class Signer implements SignerInterface {
|
|
|
25
26
|
}
|
|
26
27
|
// now use abi to display decoded data somewhere, but as this signer is headless, we can't do that
|
|
27
28
|
|
|
28
|
-
const
|
|
29
|
+
const calldata = fromCallsToExecuteCalldataWithNonce(transactions, transactionsDetail.nonce);
|
|
30
|
+
|
|
31
|
+
const msgHash = calculcateTransactionHash(
|
|
29
32
|
transactionsDetail.walletAddress,
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
transactionsDetail.
|
|
33
|
+
transactionsDetail.version,
|
|
34
|
+
getSelectorFromName('__execute__'),
|
|
35
|
+
calldata,
|
|
36
|
+
transactionsDetail.maxFee,
|
|
37
|
+
transactionsDetail.chainId
|
|
34
38
|
);
|
|
35
39
|
|
|
36
40
|
return sign(this.keyPair, msgHash);
|
package/src/signer/ledger.ts
CHANGED
|
@@ -4,7 +4,8 @@ import TransportWebHID from '@ledgerhq/hw-transport-webhid';
|
|
|
4
4
|
|
|
5
5
|
import { Invocation, InvocationsSignerDetails, Signature } from '../types';
|
|
6
6
|
import { addHexPrefix } from '../utils/encode';
|
|
7
|
-
import {
|
|
7
|
+
import { calculcateTransactionHash, getSelectorFromName } from '../utils/hash';
|
|
8
|
+
import { fromCallsToExecuteCalldataWithNonce } from '../utils/transaction';
|
|
8
9
|
import { TypedData, getMessageHash } from '../utils/typedData';
|
|
9
10
|
import { SignerInterface } from './interface';
|
|
10
11
|
|
|
@@ -46,11 +47,15 @@ export class LedgerBlindSigner implements SignerInterface {
|
|
|
46
47
|
transactions: Invocation[],
|
|
47
48
|
transactionsDetail: InvocationsSignerDetails
|
|
48
49
|
): Promise<Signature> {
|
|
49
|
-
const
|
|
50
|
+
const calldata = fromCallsToExecuteCalldataWithNonce(transactions, transactionsDetail.nonce);
|
|
51
|
+
|
|
52
|
+
const msgHash = calculcateTransactionHash(
|
|
50
53
|
transactionsDetail.walletAddress,
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
+
transactionsDetail.version,
|
|
55
|
+
getSelectorFromName('__execute__'),
|
|
56
|
+
calldata,
|
|
57
|
+
transactionsDetail.maxFee,
|
|
58
|
+
transactionsDetail.chainId
|
|
54
59
|
);
|
|
55
60
|
|
|
56
61
|
return this.sign(msgHash);
|
package/src/types/signer.ts
CHANGED
package/src/utils/hash.ts
CHANGED
|
@@ -2,14 +2,19 @@ import BN from 'bn.js';
|
|
|
2
2
|
import { keccak256 } from 'ethereum-cryptography/keccak';
|
|
3
3
|
import assert from 'minimalistic-assert';
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
|
|
5
|
+
import {
|
|
6
|
+
CONSTANT_POINTS,
|
|
7
|
+
FIELD_PRIME,
|
|
8
|
+
MASK_250,
|
|
9
|
+
ONE,
|
|
10
|
+
StarknetChainId,
|
|
11
|
+
TransactionHashPrefix,
|
|
12
|
+
ZERO,
|
|
13
|
+
} from '../constants';
|
|
7
14
|
import { ec } from './ellipticCurve';
|
|
8
15
|
import { addHexPrefix, buf2hex, utf8ToArray } from './encode';
|
|
9
|
-
import { BigNumberish,
|
|
10
|
-
import { encodeShortString } from './shortString';
|
|
16
|
+
import { BigNumberish, toBN, toHex } from './number';
|
|
11
17
|
|
|
12
|
-
export const transactionPrefix = encodeShortString('StarkNet Transaction');
|
|
13
18
|
export const transactionVersion = 0;
|
|
14
19
|
export const feeTransactionVersion = toBN(2).pow(toBN(128)).add(toBN(transactionVersion));
|
|
15
20
|
|
|
@@ -65,28 +70,65 @@ export function computeHashOnElements(data: BigNumberish[]) {
|
|
|
65
70
|
return [...data, data.length].reduce((x, y) => pedersen([x, y]), 0).toString();
|
|
66
71
|
}
|
|
67
72
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
transactions: Call[],
|
|
71
|
-
nonce: string,
|
|
72
|
-
maxFee: string,
|
|
73
|
-
version: string | number = transactionVersion
|
|
74
|
-
) {
|
|
75
|
-
const hashArray = transactions
|
|
76
|
-
.map(({ contractAddress, entrypoint, calldata }) => [
|
|
77
|
-
contractAddress,
|
|
78
|
-
getSelectorFromName(entrypoint),
|
|
79
|
-
computeHashOnElements(calldata || []),
|
|
80
|
-
])
|
|
81
|
-
.map(bigNumberishArrayToDecimalStringArray)
|
|
82
|
-
.map(computeHashOnElements);
|
|
73
|
+
// following implementation is based on this python implementation:
|
|
74
|
+
// https://github.com/starkware-libs/cairo-lang/blob/b614d1867c64f3fb2cf4a4879348cfcf87c3a5a7/src/starkware/starknet/core/os/transaction_hash/transaction_hash.py
|
|
83
75
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
76
|
+
export function calculateTransactionHashCommon(
|
|
77
|
+
txHashPrefix: TransactionHashPrefix,
|
|
78
|
+
version: BigNumberish,
|
|
79
|
+
contractAddress: BigNumberish,
|
|
80
|
+
entryPointSelector: BigNumberish,
|
|
81
|
+
calldata: BigNumberish[],
|
|
82
|
+
maxFee: BigNumberish,
|
|
83
|
+
chainId: StarknetChainId,
|
|
84
|
+
additionalData: BigNumberish[] = []
|
|
85
|
+
): string {
|
|
86
|
+
const calldataHash = computeHashOnElements(calldata);
|
|
87
|
+
const dataToHash = [
|
|
88
|
+
txHashPrefix,
|
|
89
|
+
version,
|
|
90
|
+
contractAddress,
|
|
91
|
+
entryPointSelector,
|
|
92
|
+
calldataHash,
|
|
89
93
|
maxFee,
|
|
94
|
+
chainId,
|
|
95
|
+
...additionalData,
|
|
96
|
+
];
|
|
97
|
+
return computeHashOnElements(dataToHash);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function calculateDeployTransactionHash(
|
|
101
|
+
contractAddress: BigNumberish,
|
|
102
|
+
constructorCalldata: BigNumberish[],
|
|
103
|
+
version: BigNumberish,
|
|
104
|
+
chainId: StarknetChainId
|
|
105
|
+
): string {
|
|
106
|
+
return calculateTransactionHashCommon(
|
|
107
|
+
TransactionHashPrefix.DEPLOY,
|
|
90
108
|
version,
|
|
91
|
-
|
|
109
|
+
contractAddress,
|
|
110
|
+
getSelectorFromName('constructor'),
|
|
111
|
+
constructorCalldata,
|
|
112
|
+
ZERO,
|
|
113
|
+
chainId
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export function calculcateTransactionHash(
|
|
118
|
+
contractAddress: BigNumberish,
|
|
119
|
+
version: BigNumberish,
|
|
120
|
+
entryPointSelector: BigNumberish,
|
|
121
|
+
calldata: BigNumberish[],
|
|
122
|
+
maxFee: BigNumberish,
|
|
123
|
+
chainId: StarknetChainId
|
|
124
|
+
): string {
|
|
125
|
+
return calculateTransactionHashCommon(
|
|
126
|
+
TransactionHashPrefix.INVOKE,
|
|
127
|
+
version,
|
|
128
|
+
contractAddress,
|
|
129
|
+
entryPointSelector,
|
|
130
|
+
calldata,
|
|
131
|
+
maxFee,
|
|
132
|
+
chainId
|
|
133
|
+
);
|
|
92
134
|
}
|
package/src/utils/transaction.ts
CHANGED
|
@@ -47,3 +47,10 @@ export const fromCallsToExecuteCalldata = (calls: Call[]): string[] => {
|
|
|
47
47
|
...calldata,
|
|
48
48
|
];
|
|
49
49
|
};
|
|
50
|
+
|
|
51
|
+
export const fromCallsToExecuteCalldataWithNonce = (
|
|
52
|
+
calls: Call[],
|
|
53
|
+
nonce: BigNumberish
|
|
54
|
+
): string[] => {
|
|
55
|
+
return [...fromCallsToExecuteCalldata(calls), toBN(nonce).toString()];
|
|
56
|
+
};
|
package/types/signer.d.ts
CHANGED
package/utils/hash.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import BN from 'bn.js';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { StarknetChainId, TransactionHashPrefix } from '../constants';
|
|
4
4
|
import { BigNumberish } from './number';
|
|
5
|
-
export declare const transactionPrefix: string;
|
|
6
5
|
export declare const transactionVersion = 0;
|
|
7
6
|
export declare const feeTransactionVersion: BN;
|
|
8
7
|
/**
|
|
@@ -23,10 +22,27 @@ export declare function starknetKeccak(value: string): BN;
|
|
|
23
22
|
export declare function getSelectorFromName(funcName: string): string;
|
|
24
23
|
export declare function pedersen(input: [BigNumberish, BigNumberish]): string;
|
|
25
24
|
export declare function computeHashOnElements(data: BigNumberish[]): string;
|
|
26
|
-
export declare function
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
25
|
+
export declare function calculateTransactionHashCommon(
|
|
26
|
+
txHashPrefix: TransactionHashPrefix,
|
|
27
|
+
version: BigNumberish,
|
|
28
|
+
contractAddress: BigNumberish,
|
|
29
|
+
entryPointSelector: BigNumberish,
|
|
30
|
+
calldata: BigNumberish[],
|
|
31
|
+
maxFee: BigNumberish,
|
|
32
|
+
chainId: StarknetChainId,
|
|
33
|
+
additionalData?: BigNumberish[]
|
|
34
|
+
): string;
|
|
35
|
+
export declare function calculateDeployTransactionHash(
|
|
36
|
+
contractAddress: BigNumberish,
|
|
37
|
+
constructorCalldata: BigNumberish[],
|
|
38
|
+
version: BigNumberish,
|
|
39
|
+
chainId: StarknetChainId
|
|
40
|
+
): string;
|
|
41
|
+
export declare function calculcateTransactionHash(
|
|
42
|
+
contractAddress: BigNumberish,
|
|
43
|
+
version: BigNumberish,
|
|
44
|
+
entryPointSelector: BigNumberish,
|
|
45
|
+
calldata: BigNumberish[],
|
|
46
|
+
maxFee: BigNumberish,
|
|
47
|
+
chainId: StarknetChainId
|
|
32
48
|
): string;
|
package/utils/hash.js
CHANGED
|
@@ -39,14 +39,15 @@ var __importDefault =
|
|
|
39
39
|
return mod && mod.__esModule ? mod : { default: mod };
|
|
40
40
|
};
|
|
41
41
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
42
|
-
exports.
|
|
42
|
+
exports.calculcateTransactionHash =
|
|
43
|
+
exports.calculateDeployTransactionHash =
|
|
44
|
+
exports.calculateTransactionHashCommon =
|
|
43
45
|
exports.computeHashOnElements =
|
|
44
46
|
exports.pedersen =
|
|
45
47
|
exports.getSelectorFromName =
|
|
46
48
|
exports.starknetKeccak =
|
|
47
49
|
exports.feeTransactionVersion =
|
|
48
50
|
exports.transactionVersion =
|
|
49
|
-
exports.transactionPrefix =
|
|
50
51
|
void 0;
|
|
51
52
|
var keccak_1 = require('ethereum-cryptography/keccak');
|
|
52
53
|
var minimalistic_assert_1 = __importDefault(require('minimalistic-assert'));
|
|
@@ -54,8 +55,6 @@ var constants_1 = require('../constants');
|
|
|
54
55
|
var ellipticCurve_1 = require('./ellipticCurve');
|
|
55
56
|
var encode_1 = require('./encode');
|
|
56
57
|
var number_1 = require('./number');
|
|
57
|
-
var shortString_1 = require('./shortString');
|
|
58
|
-
exports.transactionPrefix = (0, shortString_1.encodeShortString)('StarkNet Transaction');
|
|
59
58
|
exports.transactionVersion = 0;
|
|
60
59
|
exports.feeTransactionVersion = (0, number_1.toBN)(2)
|
|
61
60
|
.pow((0, number_1.toBN)(128))
|
|
@@ -120,30 +119,58 @@ function computeHashOnElements(data) {
|
|
|
120
119
|
.toString();
|
|
121
120
|
}
|
|
122
121
|
exports.computeHashOnElements = computeHashOnElements;
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
122
|
+
// following implementation is based on this python implementation:
|
|
123
|
+
// https://github.com/starkware-libs/cairo-lang/blob/b614d1867c64f3fb2cf4a4879348cfcf87c3a5a7/src/starkware/starknet/core/os/transaction_hash/transaction_hash.py
|
|
124
|
+
function calculateTransactionHashCommon(
|
|
125
|
+
txHashPrefix,
|
|
126
|
+
version,
|
|
127
|
+
contractAddress,
|
|
128
|
+
entryPointSelector,
|
|
129
|
+
calldata,
|
|
130
|
+
maxFee,
|
|
131
|
+
chainId,
|
|
132
|
+
additionalData
|
|
133
|
+
) {
|
|
134
|
+
if (additionalData === void 0) {
|
|
135
|
+
additionalData = [];
|
|
126
136
|
}
|
|
127
|
-
var
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
.
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
137
|
+
var calldataHash = computeHashOnElements(calldata);
|
|
138
|
+
var dataToHash = __spreadArray(
|
|
139
|
+
[txHashPrefix, version, contractAddress, entryPointSelector, calldataHash, maxFee, chainId],
|
|
140
|
+
__read(additionalData),
|
|
141
|
+
false
|
|
142
|
+
);
|
|
143
|
+
return computeHashOnElements(dataToHash);
|
|
144
|
+
}
|
|
145
|
+
exports.calculateTransactionHashCommon = calculateTransactionHashCommon;
|
|
146
|
+
function calculateDeployTransactionHash(contractAddress, constructorCalldata, version, chainId) {
|
|
147
|
+
return calculateTransactionHashCommon(
|
|
148
|
+
constants_1.TransactionHashPrefix.DEPLOY,
|
|
149
|
+
version,
|
|
150
|
+
contractAddress,
|
|
151
|
+
getSelectorFromName('constructor'),
|
|
152
|
+
constructorCalldata,
|
|
153
|
+
constants_1.ZERO,
|
|
154
|
+
chainId
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
exports.calculateDeployTransactionHash = calculateDeployTransactionHash;
|
|
158
|
+
function calculcateTransactionHash(
|
|
159
|
+
contractAddress,
|
|
160
|
+
version,
|
|
161
|
+
entryPointSelector,
|
|
162
|
+
calldata,
|
|
163
|
+
maxFee,
|
|
164
|
+
chainId
|
|
165
|
+
) {
|
|
166
|
+
return calculateTransactionHashCommon(
|
|
167
|
+
constants_1.TransactionHashPrefix.INVOKE,
|
|
146
168
|
version,
|
|
147
|
-
|
|
169
|
+
contractAddress,
|
|
170
|
+
entryPointSelector,
|
|
171
|
+
calldata,
|
|
172
|
+
maxFee,
|
|
173
|
+
chainId
|
|
174
|
+
);
|
|
148
175
|
}
|
|
149
|
-
exports.
|
|
176
|
+
exports.calculcateTransactionHash = calculcateTransactionHash;
|