UNPKG

@radixdlt/hardware-ledger

Version:
304 lines (264 loc) 7.89 kB
/** * @group integration */ /* eslint-disable */ import { SemVerT, SignTXOutput } from '@radixdlt/hardware-wallet' import { log } from '@radixdlt/util' import { Subscription } from 'rxjs' import { LedgerNanoT, LedgerNano, HardwareWalletLedger } from '../../src' import { ECPointOnCurveT, HDPathRadix, PublicKey, PublicKeyT, sha256Twice, SignatureT, } from '@radixdlt/crypto' import { BuiltTransactionReadyToSign, Network, uint256FromUnsafe, } from '@radixdlt/primitives' import { Transaction, stringifyUInt256, TransactionT, } from '@radixdlt/tx-parser' import { AccountAddress } from '@radixdlt/account' import { sendAPDU } from './utils' describe('hw_ledger_integration', () => { let ledgerNano: LedgerNanoT beforeAll(() => { log.setLevel('debug') }) afterEach(done => { if (!ledgerNano) { done() return } }) afterAll(() => { log.setLevel('warn') }) it('getVersion_integration', async done => { ledgerNano = await LedgerNano.connect({ send: sendAPDU, }) const hardwareWallet = HardwareWalletLedger.from(ledgerNano) const subs = new Subscription() subs.add( hardwareWallet.getVersion().subscribe({ next: (semVer: SemVerT) => { expect(semVer.toString()).toBe('0.3.7') done() }, error: e => { done(e) }, }), ) }) it('getPublicKey_integration', async done => { ledgerNano = await LedgerNano.connect({ send: sendAPDU, }) const hardwareWallet = HardwareWalletLedger.from(ledgerNano) const subs = new Subscription() const path = HDPathRadix.fromString( `m/44'/1022'/2'/1/3`, )._unsafeUnwrap() const displayAddress = true const expectedPubKeyHex = '03d79039c428a6b835e136fbb582e9259df23f8660f928367c3f0d6912728a8444' const expectedPubKey = PublicKey.fromBuffer( Buffer.from(expectedPubKeyHex, 'hex'), )._unsafeUnwrap() if (displayAddress) { console.log(`🔮 expected path: ${path.toString()}`) const accountAddress = AccountAddress.fromPublicKeyAndNetwork({ publicKey: expectedPubKey, network: Network.MAINNET, }) const wrongAccountAddress = AccountAddress.fromPublicKeyAndNetwork({ publicKey: expectedPubKey, network: Network.MAINNET, }) console.log( `🔮 expected address: '${accountAddress.toString()}' ([wrong]mainnet: '${wrongAccountAddress.toString()}')`, ) } subs.add( hardwareWallet .getPublicKey({ path, display: displayAddress, }) .subscribe( (publicKey: PublicKeyT) => { expect(publicKey.toString(true)).toBe(expectedPubKeyHex) done() }, e => { done(e) }, ), ) }) it('doKeyExchange_integration', async done => { ledgerNano = await LedgerNano.connect({ send: sendAPDU, }) const hardwareWallet = HardwareWalletLedger.from(ledgerNano) const subs = new Subscription() const publicKeyOfOtherParty = PublicKey.fromBuffer( Buffer.from( '0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8', 'hex', ), )._unsafeUnwrap() const displayBIPAndPubKeyOtherParty = true if (displayBIPAndPubKeyOtherParty) { console.log( `🔮 publicKeyOfOtherParty: ${publicKeyOfOtherParty.toString( false, )}`, ) const accountAddressOfOtherParty = AccountAddress.fromPublicKeyAndNetwork( { publicKey: publicKeyOfOtherParty, network: Network.MAINNET, }, ) console.log( `🔮 other party address: ${accountAddressOfOtherParty.toString()}`, ) } subs.add( hardwareWallet .doKeyExchange({ // both Account and Address will be hardened. path: HDPathRadix.fromString( `m/44'/1022'/2'/1/3`, )._unsafeUnwrap(), publicKeyOfOtherParty, display: 'encrypt', }) .subscribe( (ecPointOnCurve: ECPointOnCurveT) => { expect(ecPointOnCurve.toString()).toBe( 'd79039c428a6b835e136fbb582e9259df23f8660f928367c3f0d6912728a8444a87d3a07191942666ca3d0396374531fe669e451bae6eeb79fb0884ef78a2f9d', ) done() }, e => { done(e) }, ), ) }, 20_000) it( 'doSignTX_integration', async done => { ledgerNano = await LedgerNano.connect({ send: sendAPDU, }) const hardwareWallet = HardwareWalletLedger.from(ledgerNano) const subs = new Subscription() const path = HDPathRadix.fromString( `m/44'/1022'/2'/1/3`, )._unsafeUnwrap() const expectedPubKeyHex = '03d79039c428a6b835e136fbb582e9259df23f8660f928367c3f0d6912728a8444' const expectedPubKey = PublicKey.fromBuffer( Buffer.from(expectedPubKeyHex, 'hex'), )._unsafeUnwrap() const blobHex = '0d000107a0686a487f9d3adf4892a358e4460cda432068f069e5e9f4c815af21bc3dd1d600000000012100000000000000000000000000000000000000000000000abbade0b6b3a76400000206000402935deebcad35bcf27d05b431276be8fcba26312cd1d54c33ac6748a72fe427ca0100000000000000000000000000000000000000000000d3c1e44bf21f037000000008000000000206000402935deebcad35bcf27d05b431276be8fcba26312cd1d54c33ac6748a72fe427ca0100000000000000000000000000000000000000000000d38bae82445924d00000020600040356959464545aa2787984fe4ac76496721a22f150c0076724ad7190fe3a597bb70100000000000000000000000000000000000000000000003635c9adc5dea00000000121010000000000000000000000000000000000000000000000000de0b6b3a76400000206000402935deebcad35bcf27d05b431276be8fcba26312cd1d54c33ac6748a72fe427ca010000000000000000000000000000000000000000000000000de0b6b3a764000000' const blob = Buffer.from(blobHex, 'hex') const txRes = Transaction.fromBuffer(blob) if (txRes.isErr()) { throw txRes.error } const parsedTx: TransactionT = txRes.value const expectedHash = sha256Twice(Buffer.from(blobHex, 'hex')) const tx: BuiltTransactionReadyToSign = { blob: blobHex, hashOfBlobToSign: expectedHash.toString('hex'), } console.log(`🔮 Path: ${path.toString()}`) console.log(`🔮 Expected Hash: ${expectedHash.toString('hex')}`) console.log(`🔮 Signing tx:\n${parsedTx.toString()}`) const totalCostDecATTOString = '2048463735185526206758912' const totalCost = uint256FromUnsafe( totalCostDecATTOString, )._unsafeUnwrap() console.log( `🔮 Expected total cost incl tx fee in XRD: ${stringifyUInt256( totalCost, )} (atto: ${totalCost.toString(10)})`, ) subs.add( hardwareWallet .doSignTransaction({ path, nonXrdHRP: 'btc', tx, }) .subscribe( (result: SignTXOutput) => { const hashCalculatedByLedger = result.hashCalculatedByLedger const signature = result.signature expect(hashCalculatedByLedger.toString('hex')).toBe( expectedHash.toString('hex'), ) expect( expectedPubKey.isValidSignature({ signature, hashedMessage: hashCalculatedByLedger, }), ).toBe(true) done() }, e => { done(e) }, ), ) }, 10 * 60 * 1_000, ) // 10 min it('doSignHash_integration', async done => { ledgerNano = await LedgerNano.connect({ send: sendAPDU, }) const hardwareWallet = HardwareWalletLedger.from(ledgerNano) const subs = new Subscription() const hashToSign = sha256Twice( `I'm testing Radix awesome hardware wallet!`, ) const path = HDPathRadix.fromString( `m/44'/1022'/2'/1/3`, )._unsafeUnwrap() console.log(`🔮 Path: ${path.toString()}`) console.log(`🔮 Hash: ${hashToSign.toString('hex')}`) subs.add( hardwareWallet .doSignHash({ path, hashToSign, }) .subscribe( (signature: SignatureT) => { expect(signature.toDER()).toBe( '3045022100de5f8c5a92cc5bea386d7a5321d0aa1b46fc7d90c5d07098346252aacd59e52302202bbaeef1256d0185b550a7b661557eea11bb98b99ccc7e01d19fd931e617e824', ) done() }, e => { done(e) }, ), ) }, 40_000) })