@alephium/ledger-app 0.5.1 → 0.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.
@@ -1,11 +1,12 @@
1
- import AlephiumApp, { GROUP_NUM } from '../src/ledger-app'
1
+ import { AlephiumApp, GROUP_NUM } from '../src/ledger-app'
2
2
  import { ALPH_TOKEN_ID, Address, DUST_AMOUNT, NodeProvider, ONE_ALPH, binToHex, codec, groupOfAddress, node, sleep, transactionVerifySignature, waitForTxConfirmation, web3 } from '@alephium/web3'
3
3
  import { getSigner, mintToken, transfer } from '@alephium/web3-test'
4
4
  import { PrivateKeyWallet } from '@alephium/web3-wallet'
5
5
  import blake from 'blakejs'
6
- import { approveAddress, approveHash, approveTx, createTransport, enableBlindSigning, getRandomInt, needToAutoApprove, OutputType, skipBlindSigningWarning, staxFlexApproveOnce } from './utils'
6
+ import { approveAddress, approveHash, approveTx, createTransport, enableBlindSigning, getRandomInt, isNanos, needToAutoApprove, OutputType, skipBlindSigningWarning, staxFlexApproveOnce } from './utils'
7
7
  import { TokenMetadata } from '../src/types'
8
- import { randomInt } from 'crypto'
8
+ import { randomBytes } from 'crypto'
9
+ import { merkleTokens, tokenMerkleProofs } from '../src/merkle'
9
10
 
10
11
  describe('ledger wallet', () => {
11
12
  const nodeProvider = new NodeProvider("http://127.0.0.1:22973")
@@ -272,37 +273,87 @@ describe('ledger wallet', () => {
272
273
  return { tokens, destinations }
273
274
  }
274
275
 
275
- it('should transfer token with metadata', async () => {
276
+ it('should transfer tokens with proof', async () => {
276
277
  const transport = await createTransport()
277
278
  const app = new AlephiumApp(transport)
278
279
  const [testAccount] = await app.getAccount(path)
279
280
  await transferToAddress(testAccount.address)
281
+ const newAccount = await getSigner()
282
+
283
+ const selectedTokens = [
284
+ merkleTokens[5], // decimals is 0
285
+ merkleTokens[6], // decimals is 18
286
+ merkleTokens[8], // decimals is 9
287
+ merkleTokens[11], // decimals is 8
288
+ merkleTokens[13], // decimals is 6
289
+ ]
290
+ const outputs: node.FixedAssetOutput[] = selectedTokens.map((token, index) => {
291
+ return {
292
+ hint:0,
293
+ key: '',
294
+ attoAlphAmount: DUST_AMOUNT.toString(),
295
+ address: newAccount.address,
296
+ tokens: [{ id: token.tokenId, amount: (BigInt(index + 1) * ONE_ALPH).toString() }],
297
+ lockTime: 0,
298
+ message: ''
299
+ }
300
+ })
301
+ const unsignedTx: node.UnsignedTx = {
302
+ txId: '',
303
+ version: 0,
304
+ networkId: 4,
305
+ gasAmount: 100000,
306
+ gasPrice: (ONE_ALPH / 10000000n).toString(),
307
+ inputs: [{ outputRef: { hint: 0, key: binToHex(randomBytes(32)) }, unlockScript: '00' + testAccount.publicKey }],
308
+ fixedOutputs: outputs
309
+ }
310
+ const encodedUnsignedTx = codec.unsignedTxCodec.encodeApiUnsignedTx(unsignedTx)
280
311
 
281
- const toAddress = '1BmVCLrjttchZMW7i6df7mTdCKzHpy38bgDbVL1GqV6P7';
282
- const transferAmount = 1234567890123456789012345n
283
- const mintAmount = 2222222222222222222222222n
284
- const { tokens, destinations } = await genTokensAndDestinations(testAccount.address, toAddress, mintAmount, transferAmount)
312
+ if (isNanos()) {
313
+ approveTx([OutputType.Nanos11, OutputType.Nanos10, OutputType.Nanos10, OutputType.Nanos10, OutputType.Nanos11])
314
+ } else {
315
+ approveTx(Array(5).fill(OutputType.BaseAndToken))
316
+ }
317
+ const signature = await app.signUnsignedTx(path, Buffer.from(encodedUnsignedTx))
318
+ const txId = blake.blake2b(encodedUnsignedTx, undefined, 32)
319
+ expect(transactionVerifySignature(binToHex(txId), testAccount.publicKey, signature)).toBe(true)
285
320
 
286
- const randomOrderTokens = tokens.sort((a, b) => b.tokenId.localeCompare(a.tokenId))
287
- const buildTxResult = await nodeProvider.transactions.postTransactionsBuild({
288
- fromPublicKey: testAccount.publicKey,
289
- destinations: destinations
290
- })
321
+ await app.close()
322
+ }, 120000)
291
323
 
292
- approveTx(Array(5).fill(OutputType.BaseAndToken))
293
- const signature = await app.signUnsignedTx(path, Buffer.from(buildTxResult.unsignedTx, 'hex'), randomOrderTokens)
294
- expect(transactionVerifySignature(buildTxResult.txId, testAccount.publicKey, signature)).toBe(true)
324
+ it('should reject tx if the token proof is invalid', async () => {
325
+ const transport = await createTransport()
326
+ const app = new AlephiumApp(transport)
327
+ const [testAccount] = await app.getAccount(path)
328
+ await transferToAddress(testAccount.address)
295
329
 
296
- const submitResult = await nodeProvider.transactions.postTransactionsSubmit({
297
- unsignedTx: buildTxResult.unsignedTx,
298
- signature: signature
299
- })
300
- await waitForTxConfirmation(submitResult.txId, 1, 1000)
301
- const balances = await nodeProvider.addresses.getAddressesAddressBalance(toAddress)
302
- tokens.forEach((metadata) => {
303
- const tokenBalance = balances.tokenBalances!.find((t) => t.id === metadata.tokenId)!
304
- expect(BigInt(tokenBalance.amount)).toEqual(transferAmount)
305
- })
330
+ const toAddress = '1BmVCLrjttchZMW7i6df7mTdCKzHpy38bgDbVL1GqV6P7'
331
+ const selectedToken = merkleTokens[6] // the decimals is 18
332
+ const output: node.FixedAssetOutput = {
333
+ hint: 0,
334
+ key: '',
335
+ attoAlphAmount: DUST_AMOUNT.toString(),
336
+ address: toAddress,
337
+ tokens: [{ id: selectedToken.tokenId, amount: ONE_ALPH.toString() }],
338
+ lockTime: 0,
339
+ message: ''
340
+ }
341
+ const unsignedTx: node.UnsignedTx = {
342
+ txId: '',
343
+ version: 0,
344
+ networkId: 4,
345
+ gasAmount: 100000,
346
+ gasPrice: (ONE_ALPH / 10000000n).toString(),
347
+ inputs: [{ outputRef: { hint: 0, key: binToHex(randomBytes(32)) }, unlockScript: '00' + testAccount.publicKey }],
348
+ fixedOutputs: [output]
349
+ }
350
+ const encodedUnsignedTx = codec.unsignedTxCodec.encodeApiUnsignedTx(unsignedTx)
351
+
352
+ const originalProof = tokenMerkleProofs[selectedToken.tokenId]
353
+ const invalidProof = originalProof.slice(0, originalProof.length - 64)
354
+ tokenMerkleProofs[selectedToken.tokenId] = invalidProof
355
+ await expect(app.signUnsignedTx(path, Buffer.from(encodedUnsignedTx))).rejects.toThrow()
356
+ tokenMerkleProofs[selectedToken.tokenId] = originalProof
306
357
 
307
358
  await app.close()
308
359
  }, 120000)
@@ -313,19 +364,31 @@ describe('ledger wallet', () => {
313
364
  const [testAccount] = await app.getAccount(path)
314
365
  await transferToAddress(testAccount.address)
315
366
 
316
- const toAddress = '1BmVCLrjttchZMW7i6df7mTdCKzHpy38bgDbVL1GqV6P7';
317
- const transferAmount = 1234567890123456789012345n
318
- const mintAmount = 2222222222222222222222222n
319
- const { tokens, destinations } = await genTokensAndDestinations(testAccount.address, toAddress, mintAmount, transferAmount)
320
-
321
- const invalidTokenIndex = randomInt(5)
322
- tokens[invalidTokenIndex] = { ...tokens[invalidTokenIndex], version: 1 }
323
- const buildTxResult = await nodeProvider.transactions.postTransactionsBuild({
324
- fromPublicKey: testAccount.publicKey,
325
- destinations: destinations
326
- })
327
-
328
- await expect(app.signUnsignedTx(path, Buffer.from(buildTxResult.unsignedTx, 'hex'), tokens)).rejects.toThrow()
367
+ const toAddress = '1BmVCLrjttchZMW7i6df7mTdCKzHpy38bgDbVL1GqV6P7'
368
+ const tokenIndex = 6
369
+ const selectedToken = merkleTokens[tokenIndex]
370
+ const output: node.FixedAssetOutput = {
371
+ hint: 0,
372
+ key: '',
373
+ attoAlphAmount: DUST_AMOUNT.toString(),
374
+ address: toAddress,
375
+ tokens: [{ id: selectedToken.tokenId, amount: ONE_ALPH.toString() }],
376
+ lockTime: 0,
377
+ message: ''
378
+ }
379
+ const unsignedTx: node.UnsignedTx = {
380
+ txId: '',
381
+ version: 0,
382
+ networkId: 4,
383
+ gasAmount: 100000,
384
+ gasPrice: (ONE_ALPH / 10000000n).toString(),
385
+ inputs: [{ outputRef: { hint: 0, key: binToHex(randomBytes(32)) }, unlockScript: '00' + testAccount.publicKey }],
386
+ fixedOutputs: [output]
387
+ }
388
+ const encodedUnsignedTx = codec.unsignedTxCodec.encodeApiUnsignedTx(unsignedTx)
389
+ merkleTokens[tokenIndex] = { ...selectedToken, version: 1 }
390
+ await expect(app.signUnsignedTx(path, Buffer.from(encodedUnsignedTx))).rejects.toThrow()
391
+ merkleTokens[tokenIndex] = selectedToken
329
392
 
330
393
  await app.close()
331
394
  }, 120000)