Skip to content

Commit

Permalink
send payload to ledger
Browse files Browse the repository at this point in the history
  • Loading branch information
michaeljscript committed Oct 6, 2023
1 parent 834dbcc commit 6e0a9ec
Show file tree
Hide file tree
Showing 4 changed files with 158 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {CardanoMobile} from '../../../../../yoroi-wallets/wallets'
import {bech32} from 'bech32'

import {
AddressType,

Check failure on line 22 in apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/ListOrders/helpers.ts

View workflow job for this annotation

GitHub Actions / check

'AddressType' is defined but never used. Allowed unused vars must match /^_/u
AddressType as LedgerAddressType,
AssetGroup as LedgerAssetGroup,
DeviceOwnedAddress as LedgerDeviceOwnedAddress,
Expand All @@ -32,6 +33,7 @@ import {
TxRequiredSignerType,
} from '@cardano-foundation/ledgerjs-hw-app-cardano'
import {Addressing, AddressingAddress, Bip44DerivationLevels} from '@emurgo/yoroi-lib'
import {str_to_path} from '@cardano-foundation/ledgerjs-hw-app-cardano/dist/utils/address'

Check failure on line 36 in apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/ListOrders/helpers.ts

View workflow job for this annotation

GitHub Actions / check

'str_to_path' is defined but never used. Allowed unused vars must match /^_/u

type Options = {
bech32Address: string
Expand Down Expand Up @@ -681,11 +683,12 @@ export const createSwapCancellationLedgerPayload = async (
}
return collateralArray
}),
ttl: await tx
.body()
.then((b) => b.ttl())
.then((n) => n?.toString()),
requiredSigners: [{type: TxRequiredSignerType.PATH, path: [harden(1825), harden(1815), harden(0), 0, 0]}],
ttl:
(await tx
.body()
.then((b) => b.ttl())
.then((n) => n?.toString())) || 10,
requiredSigners: [{type: TxRequiredSignerType.PATH, path: [harden(1852), harden(1815), harden(0), 0, 0]}],
outputs: await transformToLedgerOutputs(CardanoMobile, {
networkId,
txOutputs: await tx.body().then((b) => b.outputs()),
Expand Down Expand Up @@ -735,6 +738,25 @@ export const transformToLedgerOutputs = async (

const dataHash = (await output.hasDataHash()) ? (await output.dataHash().then((x) => x?.toHex())) ?? '' : undefined

// result.push({
// amount: await output
// .amount()
// .then((x) => x.coin())
// .then((x) => x.toStr()),
// tokenBundle: await toLedgerTokenBundle(await output.amount().then((x) => x.multiasset())),
// datumHashHex: dataHash,
// destination: {
// type: TxOutputDestinationType.DEVICE_OWNED,
// params: {
// type: AddressType.BASE_PAYMENT_KEY_STAKE_KEY,
// params: {
// spendingPath: str_to_path("1852'/1815'/0'/0/0"),
// stakingPath: str_to_path("1852'/1815'/0'/2/0"),
// },
// },
// },
// })

if (changeAddr != null) {
verifyFromBip44Root(changeAddr.addressing)
const addressParams = await toLedgerAddressParameters(wasm, {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import {PrivateKey} from '@emurgo/cross-csl-core'
import {Bip32PublicKey, PrivateKey} from '@emurgo/cross-csl-core'
import blake2b from 'blake2b'

import {CardanoMobile} from '../../wallets'
import {Addressing, RemoteUnspentOutput} from '@emurgo/yoroi-lib'

export const signRawTransaction = async (txHex: string, pKeys: PrivateKey[]): Promise<Uint8Array> => {
const fixedTx = await CardanoMobile.FixedTransaction.fromHex(txHex)
export const signRawTransaction = async (cbor: string, pKeys: PrivateKey[]): Promise<Uint8Array> => {
const fixedTx = await CardanoMobile.FixedTransaction.fromHex(cbor)
if (!fixedTx) throw new Error('invalid tx hex')
const rawBody = await fixedTx.rawBody()
const txHash = await CardanoMobile.TransactionHash.fromBytes(blake2b(32).update(rawBody).digest('binary'))
Expand All @@ -24,3 +25,74 @@ export const signRawTransaction = async (txHex: string, pKeys: PrivateKey[]): Pr

return fixedTx.toBytes()
}

export const createSignedLedgerSwapCancellationTx = async (
cbor: string,
witnesses: Array<{path: number[]; witnessSignatureHex: string}>,
purpose: number,
publicKeyHex: string,
): Promise<Uint8Array> => {
console.log('trying to get fixed tx')
const fixedTx = await CardanoMobile.FixedTransaction.fromHex(cbor)
if (!fixedTx) throw new Error('invalid tx hex')
const rawBody = await fixedTx.rawBody()
const txHash = await CardanoMobile.TransactionHash.fromBytes(blake2b(32).update(rawBody).digest('binary'))
if (!txHash) throw new Error('invalid tx hex, could not generate tx hash')

const witSet = await fixedTx.witnessSet()
const vkeys = await CardanoMobile.Vkeywitnesses.new()

const addressing = {
path: [
purpose,
2147485463, // CARDANO
2147483648,
],
startLevel: 1,
}

const key = await CardanoMobile.Bip32PublicKey.fromBytes(Buffer.from(publicKeyHex, 'hex'))
const keyLevel = addressing.startLevel + addressing.path.length - 1

for (let i = 0; i < witnesses.length; i++) {
console.log('getting witness', witnesses[i].path)
const addressKey = await derivePublicByAddressing(
{startLevel: 1, path: witnesses[i].path},
{
level: keyLevel,
key,
},
)
const witness = await CardanoMobile.Vkeywitness.new(
await CardanoMobile.Vkey.new(await addressKey.toRawKey()),
await CardanoMobile.Ed25519Signature.fromBytes(Buffer.from(witnesses[i].witnessSignatureHex, 'hex')),
)
if (!witness) throw new Error('invalid tx hex, could not generate vkey witness')
await vkeys.add(witness)
}

await witSet.setVkeys(vkeys)
await fixedTx.setWitnessSet(await witSet.toBytes())

return fixedTx.toBytes()
}

export const derivePublicByAddressing = async (
addressing: Addressing,
startingFrom: {
key: Bip32PublicKey
level: number
},
) => {
if (startingFrom.level + 1 < addressing.startLevel) {
throw new Error('derivePublicByAddressing: keyLevel < startLevel')
}

let derivedKey = startingFrom.key

for (let i = startingFrom.level - addressing.startLevel + 1; i < addressing.path.length; i++) {
derivedKey = await derivedKey.derive(addressing.path[i])
}

return derivedKey
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import {PrivateKey} from '@emurgo/cross-csl-core'
import {Datum} from '@emurgo/yoroi-lib'
import {CardanoAddressedUtxo, Datum, RemoteUnspentOutput} from '@emurgo/yoroi-lib'
import {parseSafe} from '@yoroi/common'
import {App, Balance} from '@yoroi/types'
import assert from 'assert'
Expand Down Expand Up @@ -39,7 +39,7 @@ import * as api from '../api'
import {encryptWithPassword} from '../catalyst/catalystCipher'
import {generatePrivateKeyForCatalyst} from '../catalyst/catalystUtils'
import {AddressChain, AddressChainJSON, Addresses, AddressGenerator} from '../chain'
import {signRawTransaction} from '../common/signatureUtils'
import {createSignedLedgerSwapCancellationTx, signRawTransaction} from '../common/signatureUtils'
import * as MAINNET from '../constants/mainnet/constants'
import * as TESTNET from '../constants/testnet/constants'
import {CardanoError} from '../errors'
Expand Down Expand Up @@ -879,7 +879,59 @@ export const makeShelleyWallet = (constants: typeof MAINNET | typeof TESTNET) =>

const signedLedgerTx = await signTxWithLedger(payload, this.hwDeviceInfo, useUSB)

// TODO: handle signedLedgerTx
console.log('received signature', signedLedgerTx)

// const tx = await CardanoMobile.Transaction.fromHex(cbor)
//
// const allUtxos = await this.getAddressedUtxos()
// const addressingMap = new Map<RemoteUnspentOutput, CardanoAddressedUtxo>()
// console.log('allUtxos', allUtxos)
// for (const utxo of allUtxos) {
// addressingMap.set(
// {
// amount: utxo.amount,
// receiver: utxo.receiver,
// txHash: utxo.txHash,
// txIndex: utxo.txIndex,
// utxoId: utxo.utxoId,
// assets: utxo.assets,
// },
// utxo,
// )
// }
//
// const senderUtxos = allUtxos
// try {
// const signedTx = await Cardano.buildLedgerSignedTx(
// {senderUtxos, txBuilder: {build: () => tx.body()}} as any,
// signedLedgerTx,
// PURPOSE,
// this.publicKeyHex,
// true,
// )
//
// console.log('signedTx', signedTx)
// // await this.submitTransaction(base64)
// const base64 = Buffer.from(signedTx.encodedTx).toString('base64')
// console.log('got base64', base64)
// await this.submitTransaction(base64)
// } catch (e) {
// if (e instanceof Error) {
// console.log('error', e)
// console.log('error', e.stack)
// }
// }

const bytes = await createSignedLedgerSwapCancellationTx(
cbor,
signedLedgerTx.witnesses,
PURPOSE,
this.publicKeyHex,
)

const base64 = Buffer.from(bytes).toString('base64')
console.log('got base64', base64)
await this.submitTransaction(base64)
}

async signTxWithLedger(unsignedTx: YoroiUnsignedTx, useUSB: boolean): Promise<YoroiSignedTx> {
Expand Down
2 changes: 1 addition & 1 deletion apps/wallet-mobile/src/yoroi-wallets/cardano/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ export const createRawTxSigningKey = async (rootKey: string, derivationPath: num
const rawKey = await accountPrivateKey.toRawKey()
const bech32 = await rawKey.toBech32()

const pkey = await CardanoMobile.PrivateKey.fromBech32(bech32) // TODO: Check this
const pkey = await CardanoMobile.PrivateKey.fromBech32(bech32)
if (!pkey) throw new Error('Invalid private key')
return pkey
}

0 comments on commit 6e0a9ec

Please sign in to comment.