Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
200 additions
and
3 deletions.
There are no files selected for viewing
6 changes: 3 additions & 3 deletions
6
app/frontend/wallet/shelley/shelley-crypto-provider-factory.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
197 changes: 197 additions & 0 deletions
197
app/frontend/wallet/shelley/shelley-trezor-crypto-provider.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,197 @@ | ||
// eslint-disable-next-line import/no-unresolved | ||
import CachedDeriveXpubFactory from '../helpers/CachedDeriveXpubFactory' | ||
import {ADALITE_SUPPORT_EMAIL} from '../constants' | ||
import derivationSchemes from '../helpers/derivation-schemes' | ||
import NamedError from '../../helpers/NamedError' | ||
import debugLog from '../../helpers/debugLog' | ||
|
||
const CardanoTrezorCryptoProvider = ({network, config}) => { | ||
const derivationScheme = derivationSchemes.v2 | ||
|
||
const TrezorConnect = config.ADALITE_TREZOR_CONNECT_URL | ||
? (window as any).TrezorConnect | ||
: require('trezor-connect').default | ||
|
||
TrezorConnect.manifest({ | ||
email: ADALITE_SUPPORT_EMAIL, | ||
appUrl: config.ADALITE_SERVER_URL, | ||
}) | ||
|
||
const isHwWallet = () => true | ||
const getHwWalletName = () => 'Trezor' | ||
|
||
const deriveXpub = CachedDeriveXpubFactory(derivationScheme, async (absDerivationPath) => { | ||
const response = await TrezorConnect.cardanoGetPublicKey({ | ||
path: absDerivationPath, | ||
showOnTrezor: false, | ||
}) | ||
throwIfNotSuccess(response) | ||
return Buffer.from(response.payload.publicKey, 'hex') | ||
}) | ||
|
||
function deriveHdNode(childIndex) { | ||
throw NamedError( | ||
'UnsupportedOperationError', | ||
'This operation is not supported on TrezorCryptoProvider!' | ||
) | ||
} | ||
|
||
function sign(message, absDerivationPath) { | ||
throw NamedError('UnsupportedOperationError', 'Operation not supported') | ||
} | ||
|
||
async function displayAddressForPath(absDerivationPath) { | ||
const response = await TrezorConnect.cardanoGetAddress({ | ||
path: absDerivationPath, | ||
showOnTrezor: true, | ||
}) | ||
|
||
throwIfNotSuccess(response) | ||
} | ||
|
||
type CardanoTxInputType = { | ||
address_n: Array<number> | ||
prev_hash: Buffer | ||
prev_index: number | ||
} | ||
|
||
type CardanoAddressParametersType = { | ||
address_type: number // 0 for base address etc. | ||
address_n: Array<number> // BIP32 | ||
address_n_staking: Array<number> | ||
staking_key_hash?: Buffer | ||
certificate_pointer?: any // TODO: CardanoBlockchainPointerType | ||
} | ||
|
||
type CardanoTxOutputType = { | ||
address: string | ||
amount: number | ||
address_parameters?: CardanoAddressParametersType | ||
} | ||
|
||
type CardanoTxCertificateType = { | ||
type: number | ||
path: Array<number> | ||
pool: Buffer | ||
} | ||
|
||
function prepareInput(input, addressToAbsPathMapper): CardanoTxInputType { | ||
const data = { | ||
address_n: addressToAbsPathMapper(input.address), | ||
prev_hash: Buffer.from(input.txHash, 'hex'), | ||
prev_index: input.outputIndex, | ||
} | ||
|
||
return data | ||
} | ||
|
||
function prepareOutput(output, addressToAbsPathMapper): CardanoTxOutputType { | ||
const data: CardanoTxOutputType = { | ||
address: output.address, | ||
amount: output.coins, | ||
} | ||
let addressParameters: CardanoAddressParametersType | ||
if (output.isChange) { | ||
addressParameters = { | ||
address_type: 0, // TODO: 0 for base address | ||
address_n: output.spendingPath, | ||
address_n_staking: output.stakingPath, | ||
} | ||
data.address_parameters = addressParameters | ||
} | ||
return data | ||
} | ||
|
||
function prepareCertificate(cert, addressToAbsPathMapper): CardanoTxCertificateType { | ||
return { | ||
type: cert.type, | ||
path: addressToAbsPathMapper(cert.accountAddress), | ||
pool: Buffer.from(cert.poolHash, 'hex'), | ||
} | ||
} | ||
|
||
async function signTx(unsignedTx, rawInputTxs, addressToAbsPathMapper) { | ||
const inputs = [] | ||
for (const input of unsignedTx.inputs) { | ||
inputs.push(await prepareInput(input, addressToAbsPathMapper)) | ||
} | ||
|
||
const outputs = [] | ||
for (const output of unsignedTx.outputs) { | ||
const data = await prepareOutput(output, addressToAbsPathMapper) | ||
outputs.push(data) | ||
} | ||
|
||
const certificates = [] | ||
for (const cert of unsignedTx.certs) { | ||
const data = await prepareCertificate(cert) | ||
certificates.push(data) | ||
} | ||
const withdrawals = [] | ||
const metadata = null | ||
|
||
// inputs: List[CardanoTxInputType] = None, | ||
// outputs: List[CardanoTxOutputType] = None, | ||
// protocol_magic: int = None, | ||
// fee: int = None, | ||
// ttl: int = None, | ||
// network_id: int = None, | ||
// certificates: List[CardanoTxCertificateType] = None, | ||
// withdrawals: List[CardanoTxWithdrawalType] = None, | ||
// metadata: bytes = None, | ||
|
||
const response = await TrezorConnect.cardanoSignTransaction({ | ||
inputs, | ||
outputs, | ||
protocol_magic: network.protocolMagic, | ||
fee: unsignedTx.fee, | ||
ttl: unsignedTx.ttl, | ||
network_id: network.networkId, | ||
certificates, | ||
withdrawals, | ||
metadata, | ||
}) | ||
|
||
if (response.error || !response.success) { | ||
debugLog(response) | ||
throw NamedError('TrezorSignTxError', response.payload.error) | ||
} | ||
|
||
return { | ||
txHash: response.payload.hash, | ||
txBody: response.payload.body, | ||
} | ||
} | ||
|
||
function getWalletSecret() { | ||
throw NamedError('UnsupportedOperationError', 'Unsupported operation!') | ||
} | ||
|
||
function getDerivationScheme() { | ||
return derivationScheme | ||
} | ||
|
||
function throwIfNotSuccess(response) { | ||
if (response.error || !response.success) { | ||
debugLog(response) | ||
throw NamedError( | ||
'TrezorError', | ||
'Trezor operation failed, please make sure ad blockers are switched off for this site' | ||
) | ||
} | ||
} | ||
|
||
return { | ||
getWalletSecret, | ||
getDerivationScheme, | ||
signTx, | ||
displayAddressForPath, | ||
deriveXpub, | ||
isHwWallet, | ||
getHwWalletName, | ||
_sign: sign, | ||
_deriveHdNode: deriveHdNode, | ||
} | ||
} | ||
|
||
export default CardanoTrezorCryptoProvider |