starknet 3.5.1 → 3.6.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 +18 -0
- package/__tests__/account.test.ts +38 -20
- package/__tests__/accountContract.test.ts +0 -31
- package/__tests__/constancts.ts +2 -0
- package/__tests__/contract.test.ts +14 -21
- package/__tests__/provider.test.ts +8 -0
- package/account/default.d.ts +2 -0
- package/account/default.js +60 -12
- package/account/interface.d.ts +14 -0
- package/contract/default.d.ts +1 -1
- package/contract/default.js +27 -11
- package/dist/account/default.d.ts +2 -1
- package/dist/account/default.js +47 -9
- package/dist/account/interface.d.ts +13 -1
- package/dist/contract/default.d.ts +1 -1
- package/dist/contract/default.js +22 -10
- package/dist/provider/default.d.ts +9 -2
- package/dist/provider/default.js +16 -11
- package/dist/signer/index.d.ts +1 -0
- package/dist/signer/index.js +1 -0
- package/dist/signer/ledger.d.ts +12 -0
- package/dist/signer/ledger.js +138 -0
- package/dist/types/api.d.ts +57 -2
- package/package.json +5 -2
- package/provider/default.d.ts +9 -1
- package/provider/default.js +19 -15
- package/signer/index.d.ts +1 -0
- package/signer/index.js +1 -0
- package/signer/ledger.d.ts +15 -0
- package/signer/ledger.js +243 -0
- package/src/account/default.ts +25 -4
- package/src/account/interface.ts +15 -0
- package/src/contract/default.ts +23 -22
- package/src/provider/default.ts +13 -11
- package/src/signer/index.ts +1 -0
- package/src/signer/ledger.ts +81 -0
- package/src/types/api.ts +62 -3
- package/tsconfig.json +1 -10
- package/types/api.d.ts +57 -2
- package/www/README.md +41 -0
- package/www/babel.config.js +3 -0
- package/www/code-examples/account.js +62 -0
- package/www/code-examples/amm.js +49 -0
- package/www/code-examples/erc20.js +10 -0
- package/www/code-examples/package-lock.json +336 -0
- package/www/code-examples/package.json +15 -0
- package/www/docs/API/_category_.json +5 -0
- package/www/docs/API/account.md +11 -0
- package/www/docs/API/contract.md +14 -0
- package/www/docs/API/index.md +4 -0
- package/www/docs/API/provider.md +10 -0
- package/www/docs/API/signer.md +8 -0
- package/www/docusaurus.config.js +131 -0
- package/www/guides/account.md +60 -0
- package/www/guides/cra.md +3 -0
- package/www/guides/erc20.md +88 -0
- package/www/guides/intro.md +20 -0
- package/www/package-lock.json +22285 -0
- package/www/package.json +43 -0
- package/www/sidebars.js +31 -0
- package/www/src/components/HomepageFeatures/index.tsx +67 -0
- package/www/src/components/HomepageFeatures/styles.module.css +10 -0
- package/www/src/css/custom.css +39 -0
- package/www/src/pages/index.module.css +23 -0
- package/www/src/pages/index.tsx +40 -0
- package/www/src/pages/markdown-page.md +7 -0
- package/www/static/.nojekyll +0 -0
- package/www/static/img/docusaurus.png +0 -0
- package/www/static/img/favicon.ico +0 -0
- package/www/static/img/logo.svg +17 -0
- package/www/static/img/starknet-1.png +0 -0
- package/www/static/img/starknet-2.png +0 -0
- package/www/static/img/starknet-3.png +0 -0
- package/www/static/img/tutorial/docsVersionDropdown.png +0 -0
- package/www/static/img/tutorial/localeDropdown.png +0 -0
- package/www/tsconfig.json +8 -0
package/signer/ledger.js
ADDED
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
var __awaiter =
|
|
3
|
+
(this && this.__awaiter) ||
|
|
4
|
+
function (thisArg, _arguments, P, generator) {
|
|
5
|
+
function adopt(value) {
|
|
6
|
+
return value instanceof P
|
|
7
|
+
? value
|
|
8
|
+
: new P(function (resolve) {
|
|
9
|
+
resolve(value);
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
13
|
+
function fulfilled(value) {
|
|
14
|
+
try {
|
|
15
|
+
step(generator.next(value));
|
|
16
|
+
} catch (e) {
|
|
17
|
+
reject(e);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function rejected(value) {
|
|
21
|
+
try {
|
|
22
|
+
step(generator['throw'](value));
|
|
23
|
+
} catch (e) {
|
|
24
|
+
reject(e);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function step(result) {
|
|
28
|
+
result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
|
|
29
|
+
}
|
|
30
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
31
|
+
});
|
|
32
|
+
};
|
|
33
|
+
var __generator =
|
|
34
|
+
(this && this.__generator) ||
|
|
35
|
+
function (thisArg, body) {
|
|
36
|
+
var _ = {
|
|
37
|
+
label: 0,
|
|
38
|
+
sent: function () {
|
|
39
|
+
if (t[0] & 1) throw t[1];
|
|
40
|
+
return t[1];
|
|
41
|
+
},
|
|
42
|
+
trys: [],
|
|
43
|
+
ops: [],
|
|
44
|
+
},
|
|
45
|
+
f,
|
|
46
|
+
y,
|
|
47
|
+
t,
|
|
48
|
+
g;
|
|
49
|
+
return (
|
|
50
|
+
(g = { next: verb(0), throw: verb(1), return: verb(2) }),
|
|
51
|
+
typeof Symbol === 'function' &&
|
|
52
|
+
(g[Symbol.iterator] = function () {
|
|
53
|
+
return this;
|
|
54
|
+
}),
|
|
55
|
+
g
|
|
56
|
+
);
|
|
57
|
+
function verb(n) {
|
|
58
|
+
return function (v) {
|
|
59
|
+
return step([n, v]);
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
function step(op) {
|
|
63
|
+
if (f) throw new TypeError('Generator is already executing.');
|
|
64
|
+
while (_)
|
|
65
|
+
try {
|
|
66
|
+
if (
|
|
67
|
+
((f = 1),
|
|
68
|
+
y &&
|
|
69
|
+
(t =
|
|
70
|
+
op[0] & 2
|
|
71
|
+
? y['return']
|
|
72
|
+
: op[0]
|
|
73
|
+
? y['throw'] || ((t = y['return']) && t.call(y), 0)
|
|
74
|
+
: y.next) &&
|
|
75
|
+
!(t = t.call(y, op[1])).done)
|
|
76
|
+
)
|
|
77
|
+
return t;
|
|
78
|
+
if (((y = 0), t)) op = [op[0] & 2, t.value];
|
|
79
|
+
switch (op[0]) {
|
|
80
|
+
case 0:
|
|
81
|
+
case 1:
|
|
82
|
+
t = op;
|
|
83
|
+
break;
|
|
84
|
+
case 4:
|
|
85
|
+
_.label++;
|
|
86
|
+
return { value: op[1], done: false };
|
|
87
|
+
case 5:
|
|
88
|
+
_.label++;
|
|
89
|
+
y = op[1];
|
|
90
|
+
op = [0];
|
|
91
|
+
continue;
|
|
92
|
+
case 7:
|
|
93
|
+
op = _.ops.pop();
|
|
94
|
+
_.trys.pop();
|
|
95
|
+
continue;
|
|
96
|
+
default:
|
|
97
|
+
if (
|
|
98
|
+
!((t = _.trys), (t = t.length > 0 && t[t.length - 1])) &&
|
|
99
|
+
(op[0] === 6 || op[0] === 2)
|
|
100
|
+
) {
|
|
101
|
+
_ = 0;
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) {
|
|
105
|
+
_.label = op[1];
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
if (op[0] === 6 && _.label < t[1]) {
|
|
109
|
+
_.label = t[1];
|
|
110
|
+
t = op;
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
if (t && _.label < t[2]) {
|
|
114
|
+
_.label = t[2];
|
|
115
|
+
_.ops.push(op);
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
if (t[2]) _.ops.pop();
|
|
119
|
+
_.trys.pop();
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
op = body.call(thisArg, _);
|
|
123
|
+
} catch (e) {
|
|
124
|
+
op = [6, e];
|
|
125
|
+
y = 0;
|
|
126
|
+
} finally {
|
|
127
|
+
f = t = 0;
|
|
128
|
+
}
|
|
129
|
+
if (op[0] & 5) throw op[1];
|
|
130
|
+
return { value: op[0] ? op[1] : void 0, done: true };
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
var __importDefault =
|
|
134
|
+
(this && this.__importDefault) ||
|
|
135
|
+
function (mod) {
|
|
136
|
+
return mod && mod.__esModule ? mod : { default: mod };
|
|
137
|
+
};
|
|
138
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
139
|
+
exports.LedgerBlindSigner = void 0;
|
|
140
|
+
var hw_app_eth_1 = __importDefault(require('@ledgerhq/hw-app-eth'));
|
|
141
|
+
var hw_transport_webhid_1 = __importDefault(require('@ledgerhq/hw-transport-webhid'));
|
|
142
|
+
var encode_1 = require('../utils/encode');
|
|
143
|
+
var hash_1 = require('../utils/hash');
|
|
144
|
+
var typedData_1 = require('../utils/typedData');
|
|
145
|
+
function hexZeroPad(hash, length) {
|
|
146
|
+
var value = hash;
|
|
147
|
+
if (value.length > 2 * length + 2) {
|
|
148
|
+
throw new Error('value out of range');
|
|
149
|
+
}
|
|
150
|
+
while (value.length < 2 * length + 2) {
|
|
151
|
+
value = '0x0' + value.substring(2);
|
|
152
|
+
}
|
|
153
|
+
return value;
|
|
154
|
+
}
|
|
155
|
+
var LedgerBlindSigner = /** @class */ (function () {
|
|
156
|
+
function LedgerBlindSigner() {
|
|
157
|
+
this.derivationPath = "/2645'/579218131'/1148870696'/0'/0'/0";
|
|
158
|
+
}
|
|
159
|
+
LedgerBlindSigner.prototype.getEthApp = function () {
|
|
160
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
161
|
+
var _a, _b;
|
|
162
|
+
return __generator(this, function (_c) {
|
|
163
|
+
switch (_c.label) {
|
|
164
|
+
case 0:
|
|
165
|
+
if (!!this.transport) return [3 /*break*/, 4];
|
|
166
|
+
_c.label = 1;
|
|
167
|
+
case 1:
|
|
168
|
+
_c.trys.push([1, 3, , 4]);
|
|
169
|
+
_a = this;
|
|
170
|
+
return [4 /*yield*/, hw_transport_webhid_1.default.create()];
|
|
171
|
+
case 2:
|
|
172
|
+
_a.transport = _c.sent();
|
|
173
|
+
return [3 /*break*/, 4];
|
|
174
|
+
case 3:
|
|
175
|
+
_b = _c.sent();
|
|
176
|
+
throw new Error('Device connection error');
|
|
177
|
+
case 4:
|
|
178
|
+
return [2 /*return*/, new hw_app_eth_1.default(this.transport)];
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
};
|
|
183
|
+
LedgerBlindSigner.prototype.getPubKey = function () {
|
|
184
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
185
|
+
var eth, response, starkPub;
|
|
186
|
+
return __generator(this, function (_a) {
|
|
187
|
+
switch (_a.label) {
|
|
188
|
+
case 0:
|
|
189
|
+
return [4 /*yield*/, this.getEthApp()];
|
|
190
|
+
case 1:
|
|
191
|
+
eth = _a.sent();
|
|
192
|
+
return [4 /*yield*/, eth.starkGetPublicKey(this.derivationPath)];
|
|
193
|
+
case 2:
|
|
194
|
+
response = _a.sent();
|
|
195
|
+
starkPub = '0x' + response.slice(1, 1 + 32).toString('hex');
|
|
196
|
+
return [2 /*return*/, starkPub];
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
};
|
|
201
|
+
LedgerBlindSigner.prototype.signTransaction = function (transactions, transactionsDetail) {
|
|
202
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
203
|
+
var msgHash;
|
|
204
|
+
return __generator(this, function (_a) {
|
|
205
|
+
msgHash = (0, hash_1.hashMulticall)(
|
|
206
|
+
transactionsDetail.walletAddress,
|
|
207
|
+
transactions,
|
|
208
|
+
transactionsDetail.nonce.toString(),
|
|
209
|
+
transactionsDetail.maxFee.toString()
|
|
210
|
+
);
|
|
211
|
+
return [2 /*return*/, this.sign(msgHash)];
|
|
212
|
+
});
|
|
213
|
+
});
|
|
214
|
+
};
|
|
215
|
+
LedgerBlindSigner.prototype.signMessage = function (typedData, accountAddress) {
|
|
216
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
217
|
+
var msgHash;
|
|
218
|
+
return __generator(this, function (_a) {
|
|
219
|
+
msgHash = (0, typedData_1.getMessageHash)(typedData, accountAddress);
|
|
220
|
+
return [2 /*return*/, this.sign(msgHash)];
|
|
221
|
+
});
|
|
222
|
+
});
|
|
223
|
+
};
|
|
224
|
+
LedgerBlindSigner.prototype.sign = function (msgHash) {
|
|
225
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
226
|
+
var eth, _a, r, s;
|
|
227
|
+
return __generator(this, function (_b) {
|
|
228
|
+
switch (_b.label) {
|
|
229
|
+
case 0:
|
|
230
|
+
return [4 /*yield*/, this.getEthApp()];
|
|
231
|
+
case 1:
|
|
232
|
+
eth = _b.sent();
|
|
233
|
+
return [4 /*yield*/, eth.starkUnsafeSign(this.derivationPath, hexZeroPad(msgHash, 32))];
|
|
234
|
+
case 2:
|
|
235
|
+
(_a = _b.sent()), (r = _a.r), (s = _a.s);
|
|
236
|
+
return [2 /*return*/, [(0, encode_1.addHexPrefix)(r), (0, encode_1.addHexPrefix)(s)]];
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
});
|
|
240
|
+
};
|
|
241
|
+
return LedgerBlindSigner;
|
|
242
|
+
})();
|
|
243
|
+
exports.LedgerBlindSigner = LedgerBlindSigner;
|
package/src/account/default.ts
CHANGED
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
Abi,
|
|
7
7
|
AddTransactionResponse,
|
|
8
8
|
Call,
|
|
9
|
+
EstimateFeeResponse,
|
|
9
10
|
InvocationsDetails,
|
|
10
11
|
InvokeFunctionTransaction,
|
|
11
12
|
KeyPair,
|
|
@@ -44,6 +45,25 @@ export class Account extends Provider implements AccountInterface {
|
|
|
44
45
|
return toHex(toBN(result[0]));
|
|
45
46
|
}
|
|
46
47
|
|
|
48
|
+
public async estimateFee(calls: Call | Call[]): Promise<EstimateFeeResponse> {
|
|
49
|
+
const transactions = Array.isArray(calls) ? calls : [calls];
|
|
50
|
+
const nonce = await this.getNonce();
|
|
51
|
+
const signerDetails = {
|
|
52
|
+
walletAddress: this.address,
|
|
53
|
+
nonce: toBN(nonce),
|
|
54
|
+
maxFee: toBN('0'),
|
|
55
|
+
};
|
|
56
|
+
const signature = await this.signer.signTransaction(transactions, signerDetails);
|
|
57
|
+
|
|
58
|
+
const calldata = [...fromCallsToExecuteCalldata(transactions), signerDetails.nonce.toString()];
|
|
59
|
+
return this.fetchEndpoint('estimate_fee', undefined, {
|
|
60
|
+
contract_address: this.address,
|
|
61
|
+
entry_point_selector: getSelectorFromName('__execute__'),
|
|
62
|
+
calldata,
|
|
63
|
+
signature: bigNumberishArrayToDecimalStringArray(signature),
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
47
67
|
/**
|
|
48
68
|
* Invoke execute function in account contract
|
|
49
69
|
*
|
|
@@ -58,23 +78,24 @@ export class Account extends Provider implements AccountInterface {
|
|
|
58
78
|
transactionsDetail: InvocationsDetails = {}
|
|
59
79
|
): Promise<AddTransactionResponse> {
|
|
60
80
|
const transactions = Array.isArray(calls) ? calls : [calls];
|
|
61
|
-
|
|
81
|
+
const nonce = toBN(transactionsDetail.nonce ?? (await this.getNonce()));
|
|
82
|
+
const maxFee = transactionsDetail.maxFee ?? (await this.estimateFee(transactions)).amount;
|
|
62
83
|
const signerDetails = {
|
|
63
84
|
walletAddress: this.address,
|
|
64
|
-
nonce
|
|
65
|
-
maxFee
|
|
85
|
+
nonce,
|
|
86
|
+
maxFee,
|
|
66
87
|
};
|
|
67
88
|
|
|
68
89
|
const signature = await this.signer.signTransaction(transactions, signerDetails, abis);
|
|
69
90
|
|
|
70
91
|
const calldata = [...fromCallsToExecuteCalldata(transactions), signerDetails.nonce.toString()];
|
|
71
|
-
|
|
72
92
|
return this.fetchEndpoint('add_transaction', undefined, {
|
|
73
93
|
type: 'INVOKE_FUNCTION',
|
|
74
94
|
contract_address: this.address,
|
|
75
95
|
entry_point_selector: getSelectorFromName('__execute__'),
|
|
76
96
|
calldata,
|
|
77
97
|
signature: bigNumberishArrayToDecimalStringArray(signature),
|
|
98
|
+
max_fee: toHex(toBN(maxFee)),
|
|
78
99
|
});
|
|
79
100
|
}
|
|
80
101
|
|
package/src/account/interface.ts
CHANGED
|
@@ -4,6 +4,8 @@ import {
|
|
|
4
4
|
AddTransactionResponse,
|
|
5
5
|
Call,
|
|
6
6
|
DeployContractPayload,
|
|
7
|
+
EstimateFeeResponse,
|
|
8
|
+
Invocation,
|
|
7
9
|
InvocationsDetails,
|
|
8
10
|
Signature,
|
|
9
11
|
} from '../types';
|
|
@@ -28,6 +30,19 @@ export abstract class AccountInterface extends ProviderInterface {
|
|
|
28
30
|
abi?: Abi
|
|
29
31
|
): Promise<AddTransactionResponse>;
|
|
30
32
|
|
|
33
|
+
/**
|
|
34
|
+
* Estimate Fee for a method on starknet
|
|
35
|
+
*
|
|
36
|
+
* @param invocation the invocation object containing:
|
|
37
|
+
* - contractAddress - the address of the contract
|
|
38
|
+
* - entrypoint - the entrypoint of the contract
|
|
39
|
+
* - calldata - (defaults to []) the calldata
|
|
40
|
+
* - signature - (defaults to []) the signature
|
|
41
|
+
*
|
|
42
|
+
* @returns response from addTransaction
|
|
43
|
+
*/
|
|
44
|
+
public abstract estimateFee(invocation: Invocation): Promise<EstimateFeeResponse>;
|
|
45
|
+
|
|
31
46
|
/**
|
|
32
47
|
* Invoke execute function in account contract
|
|
33
48
|
*
|
package/src/contract/default.ts
CHANGED
|
@@ -13,11 +13,11 @@ import {
|
|
|
13
13
|
ContractFunction,
|
|
14
14
|
FunctionAbi,
|
|
15
15
|
Invocation,
|
|
16
|
+
Overrides,
|
|
16
17
|
ParsedStruct,
|
|
17
18
|
Result,
|
|
18
19
|
StructAbi,
|
|
19
20
|
} from '../types';
|
|
20
|
-
import { getSelectorFromName } from '../utils/hash';
|
|
21
21
|
import { BigNumberish, toBN, toFelt } from '../utils/number';
|
|
22
22
|
import { ContractInterface } from './interface';
|
|
23
23
|
|
|
@@ -541,10 +541,12 @@ export class Contract implements ContractInterface {
|
|
|
541
541
|
}
|
|
542
542
|
return acc;
|
|
543
543
|
}, 0);
|
|
544
|
-
|
|
544
|
+
|
|
545
|
+
const overrides: Overrides = {};
|
|
545
546
|
if (args.length === inputsLength + 1 && Array.isArray(args[args.length - 1])) {
|
|
546
|
-
|
|
547
|
+
Object.assign(overrides, args.pop());
|
|
547
548
|
}
|
|
549
|
+
|
|
548
550
|
if (args.length !== inputsLength) {
|
|
549
551
|
throw Error(
|
|
550
552
|
`Invalid number of arguments, expected ${inputsLength} arguments, but got ${args.length}`
|
|
@@ -559,11 +561,15 @@ export class Contract implements ContractInterface {
|
|
|
559
561
|
entrypoint: method,
|
|
560
562
|
};
|
|
561
563
|
if ('execute' in this.providerOrAccount) {
|
|
562
|
-
return this.providerOrAccount.execute(invocation
|
|
564
|
+
return this.providerOrAccount.execute(invocation, undefined, {
|
|
565
|
+
maxFee: overrides.maxFee,
|
|
566
|
+
nonce: overrides.nonce,
|
|
567
|
+
});
|
|
563
568
|
}
|
|
569
|
+
|
|
564
570
|
return this.providerOrAccount.invokeFunction({
|
|
565
571
|
...invocation,
|
|
566
|
-
signature,
|
|
572
|
+
signature: overrides.signature || [],
|
|
567
573
|
});
|
|
568
574
|
}
|
|
569
575
|
|
|
@@ -595,30 +601,25 @@ export class Contract implements ContractInterface {
|
|
|
595
601
|
.then((x) => this.parseResponse(method, x.result));
|
|
596
602
|
}
|
|
597
603
|
|
|
598
|
-
public async estimate(
|
|
604
|
+
public async estimate(method: string, args: Array<any> = []) {
|
|
599
605
|
// TODO; remove error as soon as estimate fees are supported
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
// return this.providerOrAccount.estimateFee({
|
|
611
|
-
// contractAddress: this.address as string,
|
|
612
|
-
// calldata,
|
|
613
|
-
// entrypoint: method,
|
|
614
|
-
// });
|
|
606
|
+
// ensure contract is connected
|
|
607
|
+
assert(this.address !== null, 'contract isnt connected to an address');
|
|
608
|
+
|
|
609
|
+
// validate method and args
|
|
610
|
+
this.validateMethodAndArgs('INVOKE', method, args);
|
|
611
|
+
const invocation = this.populateTransaction[method](...args);
|
|
612
|
+
if ('estimateFee' in this.providerOrAccount) {
|
|
613
|
+
return this.providerOrAccount.estimateFee(invocation);
|
|
614
|
+
}
|
|
615
|
+
throw Error('Contract must be connected to the account contract to estimate');
|
|
615
616
|
}
|
|
616
617
|
|
|
617
618
|
public populate(method: string, args: Array<any> = []): Invocation {
|
|
618
619
|
const { inputs } = this.abi.find((abi) => abi.name === method) as FunctionAbi;
|
|
619
620
|
return {
|
|
620
621
|
contractAddress: this.address,
|
|
621
|
-
entrypoint:
|
|
622
|
+
entrypoint: method,
|
|
622
623
|
calldata: this.compileCalldata(args, inputs),
|
|
623
624
|
signature: [],
|
|
624
625
|
};
|
package/src/provider/default.ts
CHANGED
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
GetContractAddressesResponse,
|
|
15
15
|
GetTransactionResponse,
|
|
16
16
|
GetTransactionStatusResponse,
|
|
17
|
+
GetTransactionTraceResponse,
|
|
17
18
|
Invocation,
|
|
18
19
|
TransactionReceipt,
|
|
19
20
|
} from '../types';
|
|
@@ -277,6 +278,18 @@ export class Provider implements ProviderInterface {
|
|
|
277
278
|
return this.fetchEndpoint('get_transaction', { transactionHash: txHashHex });
|
|
278
279
|
}
|
|
279
280
|
|
|
281
|
+
/**
|
|
282
|
+
* Gets the transaction trace from a tx id.
|
|
283
|
+
*
|
|
284
|
+
*
|
|
285
|
+
* @param txHash
|
|
286
|
+
* @returns the transaction trace
|
|
287
|
+
*/
|
|
288
|
+
public async getTransactionTrace(txHash: BigNumberish): Promise<GetTransactionTraceResponse> {
|
|
289
|
+
const txHashHex = toHex(toBN(txHash));
|
|
290
|
+
return this.fetchEndpoint('get_transaction_trace', { transactionHash: txHashHex });
|
|
291
|
+
}
|
|
292
|
+
|
|
280
293
|
/**
|
|
281
294
|
* Deploys a given compiled contract (json) to starknet
|
|
282
295
|
*
|
|
@@ -325,17 +338,6 @@ export class Provider implements ProviderInterface {
|
|
|
325
338
|
});
|
|
326
339
|
}
|
|
327
340
|
|
|
328
|
-
public estimateFee(invocation: Invocation): Promise<any> {
|
|
329
|
-
return this.fetchEndpoint('estimate_fee', undefined, {
|
|
330
|
-
// TODO: change the TYPE of the call
|
|
331
|
-
type: 'INVOKE_FUNCTION',
|
|
332
|
-
contract_address: invocation.contractAddress,
|
|
333
|
-
entry_point_selector: getSelectorFromName(invocation.entrypoint),
|
|
334
|
-
calldata: bigNumberishArrayToDecimalStringArray(invocation.calldata ?? []),
|
|
335
|
-
signature: bigNumberishArrayToDecimalStringArray(invocation.signature ?? []),
|
|
336
|
-
});
|
|
337
|
-
}
|
|
338
|
-
|
|
339
341
|
public async waitForTransaction(txHash: BigNumberish, retryInterval: number = 8000) {
|
|
340
342
|
let onchain = false;
|
|
341
343
|
await wait(retryInterval);
|
package/src/signer/index.ts
CHANGED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import Eth from '@ledgerhq/hw-app-eth';
|
|
2
|
+
import Transport from '@ledgerhq/hw-transport';
|
|
3
|
+
import TransportWebHID from '@ledgerhq/hw-transport-webhid';
|
|
4
|
+
|
|
5
|
+
import { Invocation, InvocationsSignerDetails, Signature } from '../types';
|
|
6
|
+
import { addHexPrefix } from '../utils/encode';
|
|
7
|
+
import { hashMulticall } from '../utils/hash';
|
|
8
|
+
import { TypedData, getMessageHash } from '../utils/typedData';
|
|
9
|
+
import { SignerInterface } from './interface';
|
|
10
|
+
|
|
11
|
+
function hexZeroPad(hash: string, length: number): string {
|
|
12
|
+
let value = hash;
|
|
13
|
+
if (value.length > 2 * length + 2) {
|
|
14
|
+
throw new Error('value out of range');
|
|
15
|
+
}
|
|
16
|
+
while (value.length < 2 * length + 2) {
|
|
17
|
+
value = `0x0${value.substring(2)}`;
|
|
18
|
+
}
|
|
19
|
+
return value;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export class LedgerBlindSigner implements SignerInterface {
|
|
23
|
+
public derivationPath = "/2645'/579218131'/1148870696'/0'/0'/0";
|
|
24
|
+
|
|
25
|
+
private transport: Transport | undefined;
|
|
26
|
+
|
|
27
|
+
private async getEthApp(): Promise<Eth> {
|
|
28
|
+
if (!this.transport) {
|
|
29
|
+
try {
|
|
30
|
+
this.transport = await TransportWebHID.create();
|
|
31
|
+
} catch {
|
|
32
|
+
throw new Error('Device connection error');
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return new Eth(this.transport);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
public async getPubKey(): Promise<string> {
|
|
39
|
+
const eth = await this.getEthApp();
|
|
40
|
+
const response = await eth.starkGetPublicKey(this.derivationPath);
|
|
41
|
+
const starkPub = `0x${response.slice(1, 1 + 32).toString('hex')}`;
|
|
42
|
+
return starkPub;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
public async signTransaction(
|
|
46
|
+
transactions: Invocation[],
|
|
47
|
+
transactionsDetail: InvocationsSignerDetails
|
|
48
|
+
): Promise<Signature> {
|
|
49
|
+
const msgHash = hashMulticall(
|
|
50
|
+
transactionsDetail.walletAddress,
|
|
51
|
+
transactions,
|
|
52
|
+
transactionsDetail.nonce.toString(),
|
|
53
|
+
transactionsDetail.maxFee.toString()
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
return this.sign(msgHash);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
public async signMessage(typedData: TypedData, accountAddress: string): Promise<Signature> {
|
|
60
|
+
const msgHash = getMessageHash(typedData, accountAddress);
|
|
61
|
+
|
|
62
|
+
return this.sign(msgHash);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
protected async sign(msgHash: string): Promise<Signature> {
|
|
66
|
+
const eth = await this.getEthApp();
|
|
67
|
+
|
|
68
|
+
const {
|
|
69
|
+
r,
|
|
70
|
+
s,
|
|
71
|
+
}: {
|
|
72
|
+
r: string;
|
|
73
|
+
s: string;
|
|
74
|
+
} = (await eth.starkUnsafeSign(this.derivationPath, hexZeroPad(msgHash, 32))) as {
|
|
75
|
+
r: string;
|
|
76
|
+
s: string;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
return [addHexPrefix(r), addHexPrefix(s)];
|
|
80
|
+
}
|
|
81
|
+
}
|
package/src/types/api.ts
CHANGED
|
@@ -36,6 +36,13 @@ export type Endpoints = {
|
|
|
36
36
|
REQUEST: never;
|
|
37
37
|
RESPONSE: GetTransactionStatusResponse;
|
|
38
38
|
};
|
|
39
|
+
get_transaction_trace: {
|
|
40
|
+
QUERY: {
|
|
41
|
+
transactionHash: string;
|
|
42
|
+
};
|
|
43
|
+
REQUEST: never;
|
|
44
|
+
RESPONSE: GetTransactionTraceResponse;
|
|
45
|
+
};
|
|
39
46
|
get_storage_at: {
|
|
40
47
|
QUERY: {
|
|
41
48
|
contractAddress: string;
|
|
@@ -69,7 +76,7 @@ export type Endpoints = {
|
|
|
69
76
|
};
|
|
70
77
|
estimate_fee: {
|
|
71
78
|
QUERY: never;
|
|
72
|
-
REQUEST:
|
|
79
|
+
REQUEST: CallContractTransaction;
|
|
73
80
|
RESPONSE: EstimateFeeResponse;
|
|
74
81
|
};
|
|
75
82
|
};
|
|
@@ -95,6 +102,33 @@ export type InvokeFunctionTransaction = {
|
|
|
95
102
|
entry_point_selector: string;
|
|
96
103
|
calldata?: RawCalldata;
|
|
97
104
|
nonce?: BigNumberish;
|
|
105
|
+
max_fee?: BigNumberish;
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
export type InvokeFunctionTrace = {
|
|
109
|
+
caller_address: string;
|
|
110
|
+
contract_address: string;
|
|
111
|
+
code_address: string;
|
|
112
|
+
selector: string;
|
|
113
|
+
calldata: RawCalldata;
|
|
114
|
+
result: Array<any>;
|
|
115
|
+
execution_resources: ExecutionResources;
|
|
116
|
+
internal_call: Array<InvokeFunctionTrace>;
|
|
117
|
+
events: Array<any>;
|
|
118
|
+
messages: Array<any>;
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
export type ExecutionResources = {
|
|
122
|
+
n_steps: number;
|
|
123
|
+
builtin_instance_counter: {
|
|
124
|
+
pedersen_builtin: number;
|
|
125
|
+
range_check_builtin: number;
|
|
126
|
+
bitwise_builtin: number;
|
|
127
|
+
output_builtin: number;
|
|
128
|
+
ecdsa_builtin: number;
|
|
129
|
+
ec_op_builtin: number;
|
|
130
|
+
};
|
|
131
|
+
n_memory_holes: number;
|
|
98
132
|
};
|
|
99
133
|
|
|
100
134
|
export type CallContractTransaction = Omit<
|
|
@@ -149,6 +183,22 @@ export type GetTransactionStatusResponse = {
|
|
|
149
183
|
};
|
|
150
184
|
};
|
|
151
185
|
|
|
186
|
+
export type GetTransactionTraceResponse = {
|
|
187
|
+
function_invocation: {
|
|
188
|
+
caller_address: string;
|
|
189
|
+
contract_address: string;
|
|
190
|
+
code_address: string;
|
|
191
|
+
selector: string;
|
|
192
|
+
calldata: RawArgs;
|
|
193
|
+
result: Array<any>;
|
|
194
|
+
execution_resources: any;
|
|
195
|
+
internal_call: Array<any>;
|
|
196
|
+
events: Array<any>;
|
|
197
|
+
messages: Array<any>;
|
|
198
|
+
};
|
|
199
|
+
signature: Signature;
|
|
200
|
+
};
|
|
201
|
+
|
|
152
202
|
export type GetTransactionResponse = {
|
|
153
203
|
status: Status;
|
|
154
204
|
transaction: Transaction;
|
|
@@ -173,11 +223,20 @@ export type TransactionReceipt = {
|
|
|
173
223
|
l2_to_l1_messages: string[];
|
|
174
224
|
events: string[];
|
|
175
225
|
};
|
|
176
|
-
|
|
177
|
-
export type EstimateFeeResponse = {
|
|
226
|
+
|
|
227
|
+
export type EstimateFeeResponse = {
|
|
228
|
+
amount: number;
|
|
229
|
+
unit: string;
|
|
230
|
+
};
|
|
178
231
|
|
|
179
232
|
export type RawArgs = {
|
|
180
233
|
[inputName: string]: string | string[] | { type: 'struct'; [k: string]: BigNumberish };
|
|
181
234
|
};
|
|
182
235
|
|
|
183
236
|
export type Calldata = string[];
|
|
237
|
+
|
|
238
|
+
export type Overrides = {
|
|
239
|
+
maxFee?: BigNumberish;
|
|
240
|
+
nonce?: BigNumberish;
|
|
241
|
+
signature?: Signature;
|
|
242
|
+
};
|
package/tsconfig.json
CHANGED
|
@@ -103,14 +103,5 @@
|
|
|
103
103
|
"skipLibCheck": true /* Skip type checking all .d.ts files. */
|
|
104
104
|
},
|
|
105
105
|
"include": ["src/**/*"],
|
|
106
|
-
"exclude": ["node_modules"]
|
|
107
|
-
"typedocOptions": {
|
|
108
|
-
"entryPoints": "src/index.ts",
|
|
109
|
-
"entryPointStrategy": "expand",
|
|
110
|
-
"out": "docs",
|
|
111
|
-
"githubPages": false,
|
|
112
|
-
"readme": "./README.md",
|
|
113
|
-
"name": "StarkNet.js Docs",
|
|
114
|
-
"sort": "required-first"
|
|
115
|
-
}
|
|
106
|
+
"exclude": ["node_modules"]
|
|
116
107
|
}
|