@alephium/ledger-app 0.3.0 → 0.4.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.
@@ -26,54 +26,59 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
26
26
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
27
  };
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
- const hw_transport_node_speculos_1 = __importDefault(require("@ledgerhq/hw-transport-node-speculos"));
30
29
  const src_1 = __importStar(require("../src"));
31
- const node_fetch_1 = __importDefault(require("node-fetch"));
32
30
  const web3_1 = require("@alephium/web3");
33
31
  const web3_test_1 = require("@alephium/web3-test");
34
32
  const web3_wallet_1 = require("@alephium/web3-wallet");
35
- function sleep(ms) {
36
- return new Promise((resolve) => setTimeout(resolve, ms));
37
- }
38
- async function pressButton(button) {
39
- await sleep(500);
40
- return (0, node_fetch_1.default)(`http://localhost:25000/button/${button}`, {
41
- method: 'POST',
42
- body: JSON.stringify({ action: 'press-and-release' })
43
- });
44
- }
45
- function getRandomInt(min, max) {
46
- min = Math.ceil(min);
47
- max = Math.floor(max);
48
- return Math.floor(Math.random() * (max - min) + min); // The maximum is exclusive and the minimum is inclusive
49
- }
50
- describe('sdk', () => {
51
- const apduPort = 9999;
33
+ const blakejs_1 = __importDefault(require("blakejs"));
34
+ const utils_1 = require("./utils");
35
+ describe('ledger wallet', () => {
52
36
  const nodeProvider = new web3_1.NodeProvider("http://127.0.0.1:22973");
53
37
  web3_1.web3.setCurrentNodeProvider(nodeProvider);
54
38
  let pathIndex;
55
39
  let path;
56
40
  beforeEach(() => {
57
- pathIndex = getRandomInt(0, 1000000);
41
+ pathIndex = (0, utils_1.getRandomInt)(0, 1000000);
58
42
  path = `m/44'/1234'/0'/0/` + pathIndex;
59
43
  });
44
+ async function transferToAddress(address, amount = web3_1.ONE_ALPH * 10n) {
45
+ const balance0 = await getALPHBalance(address);
46
+ const fromAccount = await (0, web3_test_1.getSigner)();
47
+ const transferResult = await (0, web3_test_1.transfer)(fromAccount, address, web3_1.ALPH_TOKEN_ID, amount);
48
+ await (0, web3_1.waitForTxConfirmation)(transferResult.txId, 1, 1000);
49
+ const balance1 = await getALPHBalance(address);
50
+ expect(balance1 - balance0).toEqual(amount);
51
+ }
52
+ async function getALPHBalance(address) {
53
+ const balances = await nodeProvider.addresses.getAddressesAddressBalance(address);
54
+ return BigInt(balances.balance);
55
+ }
60
56
  it('should get version', async () => {
61
- const transport = await hw_transport_node_speculos_1.default.open({ apduPort });
57
+ const transport = await (0, utils_1.createTransport)();
62
58
  const app = new src_1.default(transport);
63
59
  const version = await app.getVersion();
64
- expect(version).toBe('0.2.0');
60
+ expect(version).toBe('0.4.0');
65
61
  await app.close();
66
62
  });
67
63
  it('should get public key', async () => {
68
- const transport = await hw_transport_node_speculos_1.default.open({ apduPort });
64
+ const transport = await (0, utils_1.createTransport)();
69
65
  const app = new src_1.default(transport);
70
66
  const [account, hdIndex] = await app.getAccount(path);
71
67
  expect(hdIndex).toBe(pathIndex);
72
68
  console.log(account);
73
69
  await app.close();
74
70
  });
71
+ it('should get public key and confirm address', async () => {
72
+ const transport = await (0, utils_1.createTransport)();
73
+ const app = new src_1.default(transport);
74
+ (0, utils_1.approveAddress)();
75
+ const [account, hdIndex] = await app.getAccount(path, undefined, undefined, true);
76
+ expect(hdIndex).toBe(pathIndex);
77
+ console.log(account);
78
+ await app.close();
79
+ }, 30000);
75
80
  it('should get public key for group', async () => {
76
- const transport = await hw_transport_node_speculos_1.default.open({ apduPort });
81
+ const transport = await (0, utils_1.createTransport)();
77
82
  const app = new src_1.default(transport);
78
83
  for (let group = 0; group < src_1.GROUP_NUM; group++) {
79
84
  const [account, hdIndex] = await app.getAccount(path, group);
@@ -84,33 +89,27 @@ describe('sdk', () => {
84
89
  await app.close();
85
90
  });
86
91
  it('should get public key for group for Schnorr signature', async () => {
87
- const transport = await hw_transport_node_speculos_1.default.open({ apduPort });
92
+ const transport = await (0, utils_1.createTransport)();
88
93
  const app = new src_1.default(transport);
89
94
  for (let group = 0; group < src_1.GROUP_NUM; group++) {
90
95
  await expect(app.getAccount(path, group, 'bip340-schnorr')).rejects.toThrow('BIP340-Schnorr is not supported yet');
91
96
  }
92
97
  await app.close();
93
98
  });
94
- async function transferToAddress(address, amount = web3_1.ONE_ALPH * 10n) {
95
- const balance0 = await getALPHBalance(address);
96
- const fromAccount = await (0, web3_test_1.getSigner)();
97
- const transferResult = await (0, web3_test_1.transfer)(fromAccount, address, web3_1.ALPH_TOKEN_ID, amount);
98
- await (0, web3_1.waitForTxConfirmation)(transferResult.txId, 1, 1000);
99
- const balance1 = await getALPHBalance(address);
100
- expect(balance1 - balance0).toEqual(amount);
101
- }
102
- async function getALPHBalance(address) {
103
- const balances = await nodeProvider.addresses.getAddressesAddressBalance(address);
104
- return BigInt(balances.balance);
105
- }
106
- async function clickAndApprove(times) {
107
- for (let i = 0; i < times; i++) {
108
- await pressButton('right');
109
- }
110
- await pressButton('both');
111
- }
112
- it('should transfer alph to p2pkh address', async () => {
113
- const transport = await hw_transport_node_speculos_1.default.open({ apduPort });
99
+ it('should sign hash', async () => {
100
+ const transport = await (0, utils_1.createTransport)();
101
+ const app = new src_1.default(transport);
102
+ const [account] = await app.getAccount(path);
103
+ console.log(account);
104
+ const hash = Buffer.from(blakejs_1.default.blake2b(Buffer.from([0, 1, 2, 3, 4]), undefined, 32));
105
+ (0, utils_1.approveHash)();
106
+ const signature = await app.signHash(path, hash);
107
+ console.log(signature);
108
+ await app.close();
109
+ expect((0, web3_1.transactionVerifySignature)(hash.toString('hex'), account.publicKey, signature)).toBe(true);
110
+ }, 10000);
111
+ it('shoudl transfer alph to one address', async () => {
112
+ const transport = await (0, utils_1.createTransport)();
114
113
  const app = new src_1.default(transport);
115
114
  const [testAccount] = await app.getAccount(path);
116
115
  await transferToAddress(testAccount.address);
@@ -120,30 +119,40 @@ describe('sdk', () => {
120
119
  {
121
120
  address: '1BmVCLrjttchZMW7i6df7mTdCKzHpy38bgDbVL1GqV6P7',
122
121
  attoAlphAmount: (web3_1.ONE_ALPH * 2n).toString(),
123
- },
122
+ }
123
+ ]
124
+ });
125
+ (0, utils_1.approveTx)([utils_1.OutputType.Base]);
126
+ const signature = await app.signUnsignedTx(path, Buffer.from(buildTxResult.unsignedTx, 'hex'));
127
+ expect((0, web3_1.transactionVerifySignature)(buildTxResult.txId, testAccount.publicKey, signature)).toBe(true);
128
+ const submitResult = await nodeProvider.transactions.postTransactionsSubmit({
129
+ unsignedTx: buildTxResult.unsignedTx,
130
+ signature: signature
131
+ });
132
+ await (0, web3_1.waitForTxConfirmation)(submitResult.txId, 1, 1000);
133
+ const balance = await getALPHBalance(testAccount.address);
134
+ expect(balance < (web3_1.ONE_ALPH * 8n)).toEqual(true);
135
+ await app.close();
136
+ }, 120000);
137
+ it('should transfer alph to multiple addresses', async () => {
138
+ const transport = await (0, utils_1.createTransport)();
139
+ const app = new src_1.default(transport);
140
+ const [testAccount] = await app.getAccount(path);
141
+ await transferToAddress(testAccount.address);
142
+ const buildTxResult = await nodeProvider.transactions.postTransactionsBuild({
143
+ fromPublicKey: testAccount.publicKey,
144
+ destinations: [
124
145
  {
125
146
  address: '1BmVCLrjttchZMW7i6df7mTdCKzHpy38bgDbVL1GqV6P7',
147
+ attoAlphAmount: (web3_1.ONE_ALPH * 2n).toString(),
148
+ },
149
+ {
150
+ address: '1F1fu6GjuN9yUVRFVcgQKWwiTg8RMzKFv1BZFDwFcfWJq',
126
151
  attoAlphAmount: (web3_1.ONE_ALPH * 3n).toString(),
127
152
  },
128
153
  ]
129
154
  });
130
- function approve(index) {
131
- if (index >= 7)
132
- return;
133
- if (index >= 3) { // outputs and signature
134
- setTimeout(async () => {
135
- await clickAndApprove(6);
136
- approve(index + 1);
137
- }, 1000);
138
- }
139
- else {
140
- setTimeout(async () => {
141
- await clickAndApprove(3);
142
- approve(index + 1);
143
- }, 1000);
144
- }
145
- }
146
- approve(0);
155
+ (0, utils_1.approveTx)(Array(2).fill(utils_1.OutputType.Base));
147
156
  const signature = await app.signUnsignedTx(path, Buffer.from(buildTxResult.unsignedTx, 'hex'));
148
157
  expect((0, web3_1.transactionVerifySignature)(buildTxResult.txId, testAccount.publicKey, signature)).toBe(true);
149
158
  const submitResult = await nodeProvider.transactions.postTransactionsSubmit({
@@ -156,7 +165,7 @@ describe('sdk', () => {
156
165
  await app.close();
157
166
  }, 120000);
158
167
  it('should transfer alph to multisig address', async () => {
159
- const transport = await hw_transport_node_speculos_1.default.open({ apduPort });
168
+ const transport = await (0, utils_1.createTransport)();
160
169
  const app = new src_1.default(transport);
161
170
  const [testAccount] = await app.getAccount(path);
162
171
  await transferToAddress(testAccount.address);
@@ -167,36 +176,10 @@ describe('sdk', () => {
167
176
  {
168
177
  address: multiSigAddress,
169
178
  attoAlphAmount: (web3_1.ONE_ALPH * 2n).toString(),
170
- },
171
- {
172
- address: multiSigAddress,
173
- attoAlphAmount: (web3_1.ONE_ALPH * 3n).toString(),
174
- },
179
+ }
175
180
  ]
176
181
  });
177
- function approve(index) {
178
- if (index >= 7)
179
- return;
180
- if (index == 3 || index == 4) { // multi-sig outputs
181
- setTimeout(async () => {
182
- await clickAndApprove(11);
183
- approve(index + 1);
184
- }, 1000);
185
- }
186
- else if (index > 4) { // change output and signature
187
- setTimeout(async () => {
188
- await clickAndApprove(6);
189
- approve(index + 1);
190
- }, 1000);
191
- }
192
- else {
193
- setTimeout(async () => {
194
- await clickAndApprove(3);
195
- approve(index + 1);
196
- }, 1000);
197
- }
198
- }
199
- approve(0);
182
+ (0, utils_1.approveTx)([utils_1.OutputType.Multisig]);
200
183
  const signature = await app.signUnsignedTx(path, Buffer.from(buildTxResult.unsignedTx, 'hex'));
201
184
  expect((0, web3_1.transactionVerifySignature)(buildTxResult.txId, testAccount.publicKey, signature)).toBe(true);
202
185
  const submitResult = await nodeProvider.transactions.postTransactionsSubmit({
@@ -205,11 +188,11 @@ describe('sdk', () => {
205
188
  });
206
189
  await (0, web3_1.waitForTxConfirmation)(submitResult.txId, 1, 1000);
207
190
  const balance1 = await getALPHBalance(testAccount.address);
208
- expect(balance1 < (web3_1.ONE_ALPH * 5n)).toEqual(true);
191
+ expect(balance1 < (web3_1.ONE_ALPH * 8n)).toEqual(true);
209
192
  await app.close();
210
193
  }, 120000);
211
194
  it('should transfer token to multisig address', async () => {
212
- const transport = await hw_transport_node_speculos_1.default.open({ apduPort });
195
+ const transport = await (0, utils_1.createTransport)();
213
196
  const app = new src_1.default(transport);
214
197
  const [testAccount] = await app.getAccount(path);
215
198
  await transferToAddress(testAccount.address);
@@ -230,41 +213,7 @@ describe('sdk', () => {
230
213
  }
231
214
  ]
232
215
  });
233
- function approve(index) {
234
- if (index > 7)
235
- return;
236
- if (index <= 2) {
237
- setTimeout(async () => {
238
- await clickAndApprove(3);
239
- approve(index + 1);
240
- }, 1000);
241
- }
242
- else if (index === 3) { // multi-sig token output
243
- setTimeout(async () => {
244
- await clickAndApprove(17);
245
- approve(index + 1);
246
- }, 1000);
247
- }
248
- else if (index === 4) { // multi-sig alph output
249
- setTimeout(async () => {
250
- await clickAndApprove(11);
251
- approve(index + 1);
252
- }, 1000);
253
- }
254
- else if (index === 5) { // token change output
255
- setTimeout(async () => {
256
- await clickAndApprove(12);
257
- approve(index + 1);
258
- }, 1000);
259
- }
260
- else if (index >= 6) { // alph change output and signature
261
- setTimeout(async () => {
262
- await clickAndApprove(6);
263
- approve(index + 1);
264
- }, 1000);
265
- }
266
- }
267
- approve(0);
216
+ (0, utils_1.approveTx)([utils_1.OutputType.MultisigAndToken, utils_1.OutputType.Multisig]);
268
217
  const signature = await app.signUnsignedTx(path, Buffer.from(buildTxResult.unsignedTx, 'hex'));
269
218
  expect((0, web3_1.transactionVerifySignature)(buildTxResult.txId, testAccount.publicKey, signature)).toBe(true);
270
219
  const submitResult = await nodeProvider.transactions.postTransactionsSubmit({
@@ -282,7 +231,7 @@ describe('sdk', () => {
282
231
  await app.close();
283
232
  }, 120000);
284
233
  it('should transfer from multiple inputs', async () => {
285
- const transport = await hw_transport_node_speculos_1.default.open({ apduPort });
234
+ const transport = await (0, utils_1.createTransport)();
286
235
  const app = new src_1.default(transport);
287
236
  const [testAccount] = await app.getAccount(path);
288
237
  for (let i = 0; i < 20; i += 1) {
@@ -297,23 +246,7 @@ describe('sdk', () => {
297
246
  }
298
247
  ]
299
248
  });
300
- function approve(index) {
301
- if (index >= 6)
302
- return;
303
- if (index >= 3) { // outputs and signature
304
- setTimeout(async () => {
305
- await clickAndApprove(6);
306
- approve(index + 1);
307
- }, 1000);
308
- }
309
- else {
310
- setTimeout(async () => {
311
- await clickAndApprove(3);
312
- approve(index + 1);
313
- }, 1000);
314
- }
315
- }
316
- approve(0);
249
+ (0, utils_1.approveTx)([utils_1.OutputType.Base]);
317
250
  const signature = await app.signUnsignedTx(path, Buffer.from(buildTxResult.unsignedTx, 'hex'));
318
251
  expect((0, web3_1.transactionVerifySignature)(buildTxResult.txId, testAccount.publicKey, signature)).toBe(true);
319
252
  const submitResult = await nodeProvider.transactions.postTransactionsSubmit({
@@ -335,8 +268,8 @@ describe('sdk', () => {
335
268
  const unlockScript = '02' + `0101000000000458144020${account.publicKey}8685` + '00';
336
269
  return { account, unlockScript };
337
270
  }
338
- it('should transfer from different input addresses', async () => {
339
- const transport = await hw_transport_node_speculos_1.default.open({ apduPort });
271
+ it('should test external inputs', async () => {
272
+ const transport = await (0, utils_1.createTransport)();
340
273
  const app = new src_1.default(transport);
341
274
  const [testAccount] = await app.getAccount(path);
342
275
  const { account: newAccount, unlockScript: unlockScript0 } = getAccount(testAccount.group);
@@ -369,7 +302,7 @@ describe('sdk', () => {
369
302
  hint: 0,
370
303
  key: '',
371
304
  attoAlphAmount: (web3_1.ONE_ALPH * 3n).toString(),
372
- address: testAccount.address,
305
+ address: newAccount.address,
373
306
  tokens: [],
374
307
  lockTime: 0,
375
308
  message: ''
@@ -380,29 +313,7 @@ describe('sdk', () => {
380
313
  signerAddress: newAccount.address,
381
314
  unsignedTx: (0, web3_1.binToHex)(txBytes)
382
315
  });
383
- function approve(index) {
384
- if (index > 6)
385
- return;
386
- if (index === 3 || index === 4) { // inputs
387
- setTimeout(async () => {
388
- await clickAndApprove(5);
389
- approve(index + 1);
390
- }, 1000);
391
- }
392
- else if (index >= 5) { // outputs and tx id
393
- setTimeout(async () => {
394
- await clickAndApprove(6);
395
- approve(index + 1);
396
- }, 1000);
397
- }
398
- else {
399
- setTimeout(async () => {
400
- await clickAndApprove(3);
401
- approve(index + 1);
402
- }, 1000);
403
- }
404
- }
405
- approve(0);
316
+ (0, utils_1.approveTx)([utils_1.OutputType.Base], true);
406
317
  const signature1 = await app.signUnsignedTx(path, Buffer.from(txBytes));
407
318
  expect((0, web3_1.transactionVerifySignature)(signResult0.txId, testAccount.publicKey, signature1)).toBe(true);
408
319
  const submitResult = await nodeProvider.multisig.postMultisigSubmit({
@@ -410,8 +321,63 @@ describe('sdk', () => {
410
321
  signatures: [signResult0.signature, signature1]
411
322
  });
412
323
  await (0, web3_1.waitForTxConfirmation)(submitResult.txId, 1, 1000);
413
- const balance = await getALPHBalance(testAccount.address);
324
+ const balance = await getALPHBalance(newAccount.address);
414
325
  expect(balance).toEqual(web3_1.ONE_ALPH * 3n);
415
326
  await app.close();
416
327
  }, 120000);
328
+ it('should test self transfer tx', async () => {
329
+ const transport = await (0, utils_1.createTransport)();
330
+ const app = new src_1.default(transport);
331
+ const [testAccount] = await app.getAccount(path);
332
+ await transferToAddress(testAccount.address);
333
+ const buildTxResult = await nodeProvider.transactions.postTransactionsBuild({
334
+ fromPublicKey: testAccount.publicKey,
335
+ destinations: [
336
+ {
337
+ address: testAccount.address,
338
+ attoAlphAmount: (web3_1.ONE_ALPH * 2n).toString(),
339
+ }
340
+ ]
341
+ });
342
+ (0, utils_1.approveTx)([]);
343
+ const signature = await app.signUnsignedTx(path, Buffer.from(buildTxResult.unsignedTx, 'hex'));
344
+ expect((0, web3_1.transactionVerifySignature)(buildTxResult.txId, testAccount.publicKey, signature)).toBe(true);
345
+ const submitResult = await nodeProvider.transactions.postTransactionsSubmit({
346
+ unsignedTx: buildTxResult.unsignedTx,
347
+ signature: signature
348
+ });
349
+ await (0, web3_1.waitForTxConfirmation)(submitResult.txId, 1, 1000);
350
+ const balance = await getALPHBalance(testAccount.address);
351
+ expect(balance > (web3_1.ONE_ALPH * 9n)).toEqual(true);
352
+ await app.close();
353
+ }, 12000);
354
+ it('should test script execution tx', async () => {
355
+ const transport = await (0, utils_1.createTransport)();
356
+ const app = new src_1.default(transport);
357
+ const [testAccount] = await app.getAccount(path);
358
+ await transferToAddress(testAccount.address);
359
+ const buildTxResult = await nodeProvider.contracts.postContractsUnsignedTxDeployContract({
360
+ fromPublicKey: testAccount.publicKey,
361
+ bytecode: '00010c010000000002d38d0b3636020000'
362
+ });
363
+ setTimeout(() => (0, utils_1.skipBlindSigningWarning)(), 1000);
364
+ await expect(app.signUnsignedTx(path, Buffer.from(buildTxResult.unsignedTx, 'hex'))).rejects.toThrow();
365
+ await (0, utils_1.enableBlindSigning)();
366
+ if ((0, utils_1.needToAutoApprove)()) {
367
+ (0, utils_1.staxFlexApproveOnce)().then(() => (0, utils_1.approveTx)([]));
368
+ }
369
+ else {
370
+ // waiting for blind signing setting to be enabled
371
+ await (0, web3_1.sleep)(20000);
372
+ }
373
+ const signature = await app.signUnsignedTx(path, Buffer.from(buildTxResult.unsignedTx, 'hex'));
374
+ const submitResult = await nodeProvider.transactions.postTransactionsSubmit({
375
+ unsignedTx: buildTxResult.unsignedTx,
376
+ signature: signature
377
+ });
378
+ await (0, web3_1.waitForTxConfirmation)(submitResult.txId, 1, 1000);
379
+ const details = await nodeProvider.transactions.getTransactionsDetailsTxid(submitResult.txId);
380
+ expect(details.scriptExecutionOk).toEqual(true);
381
+ await app.close();
382
+ }, 120000);
417
383
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alephium/ledger-app",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "license": "GPL",
5
5
  "types": "dist/src/index.d.ts",
6
6
  "exports": {
@@ -12,7 +12,8 @@
12
12
  "clean:windows": "node -e \"if (process.platform === 'win32') process.exit(1)\" || , if exist dist rmdir /Q /S dist",
13
13
  "lint": "eslint . --ext ts",
14
14
  "lint:fix": "eslint . --fix --ext ts",
15
- "test": "jest -i --config ./jest-config.json",
15
+ "speculos-test": "BACKEND=speculos jest -i --config ./jest-config.json",
16
+ "device-test": "BACKEND=device jest -i --config ./jest-config.json",
16
17
  "pub": "npm run build && npm publish --access public"
17
18
  },
18
19
  "prettier": {
@@ -26,15 +27,14 @@
26
27
  },
27
28
  "dependencies": {
28
29
  "@alephium/web3": "^1.2.0",
29
- "@alephium/web3-wallet": "^1.2.0",
30
- "@ledgerhq/hw-transport": "^6.31.0"
30
+ "@ledgerhq/hw-transport": "6.31.0"
31
31
  },
32
32
  "devDependencies": {
33
33
  "@alephium/web3-test": "^1.2.0",
34
+ "@alephium/web3-wallet": "^1.2.0",
34
35
  "@alephium/cli": "^1.2.0",
35
- "@ledgerhq/hw-transport-node-hid": "^6.29.1",
36
- "@ledgerhq/hw-transport-node-speculos": "^6.29.0",
37
- "@ledgerhq/logs": "^6.10.1",
36
+ "@ledgerhq/hw-transport-node-hid": "6.29.1",
37
+ "@ledgerhq/hw-transport-node-speculos": "6.29.0",
38
38
  "@types/elliptic": "^6.4.13",
39
39
  "@types/jest": "^27.5.1",
40
40
  "@types/node": "^20.8.10",
package/src/index.ts CHANGED
@@ -9,7 +9,8 @@ export const CLA = 0x80
9
9
  export enum INS {
10
10
  GET_VERSION = 0x00,
11
11
  GET_PUBLIC_KEY = 0x01,
12
- SIGN_TX = 0x02
12
+ SIGN_HASH = 0x02,
13
+ SIGN_TX = 0x03
13
14
  }
14
15
 
15
16
  export const GROUP_NUM = 4
@@ -32,8 +33,7 @@ export default class AlephiumApp {
32
33
  return `${response[0]}.${response[1]}.${response[2]}`
33
34
  }
34
35
 
35
- // TODO: make address display optional
36
- async getAccount(startPath: string, targetGroup?: number, keyType?: KeyType): Promise<readonly [Account, number]> {
36
+ async getAccount(startPath: string, targetGroup?: number, keyType?: KeyType, display = false): Promise<readonly [Account, number]> {
37
37
  if ((targetGroup ?? 0) >= GROUP_NUM) {
38
38
  throw Error(`Invalid targetGroup: ${targetGroup}`)
39
39
  }
@@ -44,7 +44,8 @@ export default class AlephiumApp {
44
44
 
45
45
  const p1 = targetGroup === undefined ? 0x00 : GROUP_NUM
46
46
  const p2 = targetGroup === undefined ? 0x00 : targetGroup
47
- const response = await this.transport.send(CLA, INS.GET_PUBLIC_KEY, p1, p2, serde.serializePath(startPath))
47
+ const payload = Buffer.concat([serde.serializePath(startPath), Buffer.from([display ? 1 : 0])]);
48
+ const response = await this.transport.send(CLA, INS.GET_PUBLIC_KEY, p1, p2, payload)
48
49
  const publicKey = ec.keyFromPublic(response.slice(0, 65)).getPublic(true, 'hex')
49
50
  const address = addressFromPublicKey(publicKey)
50
51
  const group = groupOfAddress(address)
@@ -53,6 +54,19 @@ export default class AlephiumApp {
53
54
  return [{ publicKey: publicKey, address: address, group: group, keyType: keyType ?? 'default' }, hdIndex] as const
54
55
  }
55
56
 
57
+ async signHash(path: string, hash: Buffer): Promise<string> {
58
+ if (hash.length !== HASH_LEN) {
59
+ throw new Error('Invalid hash length')
60
+ }
61
+
62
+ const data = Buffer.concat([serde.serializePath(path), hash])
63
+ console.log(`data ${data.length}`)
64
+ const response = await this.transport.send(CLA, INS.SIGN_HASH, 0x00, 0x00, data, [StatusCodes.OK])
65
+ console.log(`response ${response.length} - ${response.toString('hex')}`)
66
+
67
+ return decodeSignature(response)
68
+ }
69
+
56
70
  async signUnsignedTx(path: string, unsignedTx: Buffer): Promise<string> {
57
71
  console.log(`unsigned tx size: ${unsignedTx.length}`)
58
72
  const encodedPath = serde.serializePath(path)