@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.
- package/dist/src/index.d.ts +4 -2
- package/dist/src/index.js +15 -4
- package/dist/test/utils.d.ts +16 -0
- package/dist/test/utils.js +215 -0
- package/dist/test/{speculos.test.js → wallet.test.js} +140 -174
- package/package.json +7 -7
- package/src/index.ts +18 -4
- package/test/utils.ts +222 -0
- package/test/{speculos.test.ts → wallet.test.ts} +156 -166
- package/dist/test/release.test.js +0 -132
- package/dist/test/speculos.test.d.ts +0 -1
- package/test/release.test.ts +0 -152
- /package/dist/test/{release.test.d.ts → wallet.test.d.ts} +0 -0
|
@@ -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
|
-
|
|
36
|
-
|
|
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
|
|
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.
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
95
|
-
const
|
|
96
|
-
const
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
}
|
|
106
|
-
async
|
|
107
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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 *
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
339
|
-
const transport = await
|
|
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:
|
|
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
|
-
|
|
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(
|
|
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
|
+
"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
|
-
"@
|
|
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": "
|
|
36
|
-
"@ledgerhq/hw-transport-node-speculos": "
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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)
|