Skip to content

Commit

Permalink
bitbox02: add types for the bitbox02-api dependency
Browse files Browse the repository at this point in the history
They will eventually be upstreamed.

Excluded from eslint because eslint expects Javascript, not pure
Typescript (e.g. it can't parse the constructor type without a body).
  • Loading branch information
benma authored and refi93 committed Nov 22, 2021
1 parent 7b456c2 commit 22ac22b
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 14 deletions.
1 change: 1 addition & 0 deletions .eslintignore
@@ -1,4 +1,5 @@
node_modules/
app/bitbox02-api.d.ts
app/dist/
app/tests/dist/
app/node_modules/
Expand Down
105 changes: 105 additions & 0 deletions app/bitbox02-api.d.ts
@@ -0,0 +1,105 @@
declare module 'bitbox02-api' {
export function getDevicePath(options?: {forceBridge: boolean}): string

type CardanoNetwork = 0 | 1

export const constants = {
Status: {
PairingFailed: string,
},
Product: {
BitBox02Multi: string,
BitBox02BTCOnly: string,
},
messages: {
CardanoNetwork: {
CardanoMainnet: CardanoNetwork,
CardanoTestnet: CardanoNetwork,
},
},
}

declare class Firmware {
Product(): string
}

type Keypath = number[]
type ScriptConfig = {
pkhSkh: {
keypathPayment: Keypath
keypathStake: Keypath
}
}

type CardanoInput = {
keypath: Keypath
prevOutHash: Uint8Array
prevOutIndex: number
}

type CardanoOutput = {
encodedAddress: string
value: string
scriptConfig?: ScriptConfig
}

type CardanoCertificate =
| {
stakeRegistration: {
keypath: Keypath
}
}
| {
stakeDeregistration: {
keypath: Keypath
}
}
| {
stakeDelegation: {
keypath: Keypath
poolKeyhash: Uint8Array
}
}

type CardanoWithdrawal = {
keypath: Keypath
value: string
}

type CardanoShelleyWitness = {
signature: Uint8Array
publicKey: Uint8Array
}

export declare class BitBox02API {
constructor(devicePath: string)
connect(
showPairingCb: (string) => void,
userVerify: () => Promise<void>,
handleAttestationCb: (bool) => void,
onCloseCb: () => void,
setStatusCb: (string) => void
)
close(): boolean
firmware(): Firmware
version(): string
cardanoXPubs(keypaths: Keypath[]): Promise<Uint8Array[]>
cardanoAddress(
network: CardanoNetwork,
scriptConfig: ScriptConfig,
display?: boolean
): Promise<string>
cardanoSignTransaction(params: {
network: CardanoNetwork
inputs: CardanoInput[]
outputs: CardanoOutput[]
fee: string
ttl: string
certificates: CardanoCertificate[]
withdrawals: CardanoWithdrawal[]
validityIntervalStart: string
}): Promise<{
shelleyWitnesses: CardanoShelleyWitness[]
}>
}
}
37 changes: 23 additions & 14 deletions app/frontend/wallet/shelley/shelley-bitbox02-crypto-provider.ts
@@ -1,4 +1,12 @@
import {BitBox02API, getDevicePath, constants as bitbox02Constants} from 'bitbox02-api'
import {
CardanoInput,
CardanoOutput,
CardanoCertificate,
CardanoShelleyWitness,
BitBox02API,
getDevicePath,
constants as bitbox02Constants,
} from 'bitbox02-api'
import * as cbor from 'borc'
import CachedDeriveXpubFactory from '../helpers/CachedDeriveXpubFactory'
import {ShelleySignedTransactionStructured, cborizeTxWitnesses} from './shelley-transaction'
Expand Down Expand Up @@ -43,8 +51,8 @@ const ShelleyBitBox02CryptoProvider = async ({
network,
config,
}: CryptoProviderParams): Promise<CryptoProvider> => {
let bitbox02
const withDevice = async (f) => {
let bitbox02: BitBox02API | undefined
async function withDevice<T>(f: (BitBox02API) => Promise<T>): Promise<T> {
if (bitbox02 !== undefined) {
return await f(bitbox02)
}
Expand All @@ -57,6 +65,7 @@ const ShelleyBitBox02CryptoProvider = async ({
},
() => {
config.bitbox02OnPairingCode(null)
return Promise.resolve()
},
(attestationResult) => {
debugLog(`BitBox02 attestation: ${attestationResult}`)
Expand Down Expand Up @@ -95,13 +104,13 @@ const ShelleyBitBox02CryptoProvider = async ({
[NetworkId.TESTNET]: bitbox02Constants.messages.CardanoNetwork.CardanoTestnet,
}[network.networkId]

const version = await withDevice((bitbox02) => {
const version = await withDevice((bitbox02: BitBox02API) => {
const version = bitbox02.version().split('.')
return {
return Promise.resolve({
major: version[0],
minor: version[1],
patch: version[2],
}
})
})

const getVersion = (): string => `${version.major}.${version.minor}.${version.patch}`
Expand All @@ -115,8 +124,8 @@ const ShelleyBitBox02CryptoProvider = async ({
derivationScheme,
config.shouldExportPubKeyBulk && isFeatureSupported(CryptoProviderFeature.BULK_EXPORT),
async (derivationPaths: BIP32Path[]) => {
return await withDevice(async (bitbox02) => {
const xpubs = await bitbox02.cardanoXPubs(derivationPaths)
return await withDevice(async (bitbox02: BitBox02API) => {
const xpubs: Uint8Array[] = await bitbox02.cardanoXPubs(derivationPaths)
return xpubs.map(Buffer.from)
})
},
Expand Down Expand Up @@ -161,7 +170,7 @@ const ShelleyBitBox02CryptoProvider = async ({
absDerivationPath: BIP32Path,
stakingPath: BIP32Path
): Promise<void> {
await withDevice(async (bitbox02) => {
await withDevice(async (bitbox02: BitBox02API) => {
await bitbox02.cardanoAddress(bb02Network, {
pkhSkh: {
keypathPayment: absDerivationPath,
Expand All @@ -181,15 +190,15 @@ const ShelleyBitBox02CryptoProvider = async ({
return derivationScheme
}

function prepareInput(input: TxInput, addressToAbsPathMapper: AddressToPathMapper) {
function prepareInput(input: TxInput, addressToAbsPathMapper: AddressToPathMapper): CardanoInput {
return {
keypath: addressToAbsPathMapper(input.address),
prevOutHash: Buffer.from(input.txHash, 'hex'),
prevOutIndex: input.outputIndex,
}
}

function prepareOutput(output: TxOutput) {
function prepareOutput(output: TxOutput): CardanoOutput {
return {
encodedAddress: output.address,
value: output.coins.toString(),
Expand All @@ -207,7 +216,7 @@ const ShelleyBitBox02CryptoProvider = async ({
function prepareCertificate(
certificate: TxCertificate,
addressToAbsPathMapper: AddressToPathMapper
) {
): CardanoCertificate {
switch (certificate.type) {
case CertificateType.STAKING_KEY_REGISTRATION:
return {
Expand Down Expand Up @@ -237,7 +246,7 @@ const ShelleyBitBox02CryptoProvider = async ({
}
}

function prepareShelleyWitness(witness): TxShelleyWitness {
function prepareShelleyWitness(witness: CardanoShelleyWitness): TxShelleyWitness {
return {
publicKey: Buffer.from(witness.publicKey),
signature: Buffer.from(witness.signature),
Expand All @@ -261,7 +270,7 @@ const ShelleyBitBox02CryptoProvider = async ({
? `${txAux.validityIntervalStart}`
: null

const response = await withDevice(async (bitbox02) => {
const response = await withDevice(async (bitbox02: BitBox02API) => {
return await bitbox02.cardanoSignTransaction({
network: bb02Network,
inputs,
Expand Down

0 comments on commit 22ac22b

Please sign in to comment.