import { coin as COIN , setting , apdu , Transport } from '@coolwallet/core' ; import * as ethSign from './sign' ; import { pubKeyToAddress } from './utils/ethUtils' ; import * as types from './config/types' ; import * as scriptUtils from './utils/scriptUtils' ; import * as scriptUtilsEIP1559 from './utils/scriptUtilsEIP1559' ; import * as params from './config/params' ; import { TOKENTYPE } from './config/tokenType' ; export { TOKENTYPE } ; const convertEIP1559IntoLegacyTx = ( eip1559Tx ) : types . signTx => { const tx = { chainId : 1 , gasPrice : eip1559Tx . transaction . gasFeeCap , ... eip1559Tx . transaction , } ; return { ... eip1559Tx , transaction : tx } ; } ; export default class ETH extends COIN . ECDSACoin implements COIN . Coin { constructor ( ) { super ( params . COIN_TYPE ) ; } async getAddress ( transport , appPrivateKey , appId , addressIndex ) { const publicKey = await this . getPublicKey ( transport , appPrivateKey , appId , addressIndex ) ; return pubKeyToAddress ( publicKey ) ; } async getAddressByAccountKey ( accPublicKey , accChainCode , addressIndex ) { const publicKey = await this . getAddressPublicKey ( accPublicKey , accChainCode , addressIndex ) ; return pubKeyToAddress ( publicKey ) ; } async signEIP1559Transaction ( signTxData ) { const { value , data , to } = signTxData . transaction ; if ( value && ! data ) { return this . signEIP1559Transfer ( signTxData ) ; } const functionHash = data . startsWith ( '0x' ) ? data . slice ( 2 , 10 ) : data . slice ( 0 , 8 ) ; if ( ( ! value || value === '0x0' ) && data && functionHash === 'a9059cbb' ) { const upperCaseAddress = to . toUpperCase ( ) ; for ( const tokenInfo of TOKENTYPE ) { if ( tokenInfo . contractAddress . toUpperCase ( ) === upperCaseAddress ) { signTxData . transaction . option = { info : { symbol : tokenInfo . symbol , decimals : tokenInfo . unit , } , } ; return this . signEIP1559ERC20 ( signTxData , tokenInfo . signature ) ; } } if ( signTxData . transaction . option && signTxData . transaction . option . info ) { const { symbol , decimals } = signTxData . transaction . option . info ; if ( symbol && decimals ) { return this . signEIP1559ERC20 ( signTxData ) ; } } } return this . signEIP1559Smart ( signTxData ) ; } async signEIP1559Transfer ( signTxData ) { const version = await apdu . general . getSEVersion ( signTxData . transport ) ; if ( version < 311 ) { const data = convertEIP1559IntoLegacyTx ( signTxData ) ; return this . signTransferTransaction ( data ) ; } const { transport , appPrivateKey , appId , addressIndex , transaction } = signTxData ; const publicKey = await this . getPublicKey ( transport , appPrivateKey , appId , addressIndex ) ; const argument = await scriptUtilsEIP1559 . getTransferArgument ( transaction , addressIndex ) ; const script = params . EIP1559Transfer . scriptWithSignature ; return ethSign . signEIP1559Transaction ( signTxData , script , argument , publicKey ) ; } async signEIP1559ERC20 ( signTxData , tokenSignature = '' ) { const version = await apdu . general . getSEVersion ( signTxData . transport ) ; if ( version < 311 ) { const data = convertEIP1559IntoLegacyTx ( signTxData ) ; return this . signERC20Transaction ( data , tokenSignature ) ; } const { transport , appPrivateKey , appId , addressIndex , transaction } = signTxData ; const publicKey = await this . getPublicKey ( transport , appPrivateKey , appId , addressIndex ) ; const argument = await scriptUtilsEIP1559 . getERC20Argument ( transaction , tokenSignature , addressIndex ) ; const script = params . EIP1559ERC20 . scriptWithSignature ; return ethSign . signEIP1559Transaction ( signTxData , script , argument , publicKey ) ; } async signEIP1559Smart ( signTxData ) { const version = await apdu . general . getSEVersion ( signTxData . transport ) ; if ( version < 311 ) { const data = convertEIP1559IntoLegacyTx ( signTxData ) ; return this . signSmartContractTransaction ( data ) ; } const { transport , appPrivateKey , appId , addressIndex , transaction } = signTxData ; const publicKey = await this . getPublicKey ( transport , appPrivateKey , appId , addressIndex ) ; const argument = await scriptUtilsEIP1559 . getSmartArgument ( transaction , addressIndex ) ; const script = params . EIP1559SmartContract . scriptWithSignature ; return ethSign . signEIP1559SmartContractTransaction ( signTxData , script , argument , publicKey ) ; } async signTransaction ( signTxData ) { const { value , data , to } = signTxData . transaction ; if ( value && ! data ) { return this . signTransferTransaction ( signTxData ) ; } const functionHash = data . startsWith ( '0x' ) ? data . slice ( 2 , 10 ) : data . slice ( 0 , 8 ) ; if ( data && functionHash === 'a9059cbb' ) { const upperCaseAddress = to . toUpperCase ( ) ; let tokenSignature ; for ( const tokenInfo of TOKENTYPE ) { if ( tokenInfo . contractAddress . toUpperCase ( ) === upperCaseAddress ) { tokenSignature = tokenInfo . signature ; signTxData . transaction . option . info . symbol = tokenInfo . symbol ; signTxData . transaction . option . info . decimals = tokenInfo . unit ; break ; } } const { symbol , decimals } = signTxData . transaction . option . info ; if ( symbol && decimals ) { if ( tokenSignature ) { return this . signERC20Transaction ( signTxData , tokenSignature ) ; } return this . signERC20Transaction ( signTxData ) ; } } return this . signSmartContractTransaction ( signTxData ) ; } async signTransferTransaction ( signTxData ) { const { transport , appPrivateKey , appId , addressIndex , transaction } = signTxData ; const publicKey = await this . getPublicKey ( transport , appPrivateKey , appId , addressIndex ) ; const argument = await scriptUtils . getTransferArgument ( transaction , addressIndex ) ; const script = params . TRANSFER . scriptWithSignature ; return ethSign . signTransaction ( signTxData , script , argument , publicKey ) ; } async signERC20Transaction ( signTxData , tokenSignature = '' ) { const { transport , appPrivateKey , appId , addressIndex , transaction } = signTxData ; const publicKey = await this . getPublicKey ( transport , appPrivateKey , appId , addressIndex ) ; const argument = await scriptUtils . getERC20Argument ( transaction , tokenSignature , addressIndex ) ; const script = params . ERC20 . scriptWithSignature ; return ethSign . signTransaction ( signTxData , script , argument , publicKey ) ; } async signSmartContractTransaction ( signTxData ) { const { transport , appPrivateKey , appId , addressIndex , transaction } = signTxData ; const publicKey = await this . getPublicKey ( transport , appPrivateKey , appId , addressIndex ) ; const argument = await scriptUtils . getSmartContractArgument ( transaction , addressIndex ) ; const script = params . SmartContract . scriptWithSignature ; return ethSign . signSmartContractTransaction ( signTxData , script , argument , publicKey ) ; } async signMessage ( signMsgData ) { await setting . auth . versionCheck ( signMsgData . transport , 81 ) ; const { transport , appPrivateKey , appId , addressIndex , message } = signMsgData ; const publicKey = await this . getPublicKey ( transport , appPrivateKey , appId , addressIndex ) ; const argument = await scriptUtils . getSignMessageArgument ( message , addressIndex ) ; const script = params . SIGN_MESSAGE . scriptWithSignature ; return ethSign . signMessage ( signMsgData , script , argument , publicKey ) ; } async signTypedData ( typedData ) { await setting . auth . versionCheck ( typedData . transport , 84 ) ; const { transport , appPrivateKey , appId , addressIndex } = typedData ; const publicKey = await this . getPublicKey ( transport , appPrivateKey , appId , addressIndex ) ; const script = params . SIGN_TYPED_DATA . scriptWithSignature ; return ethSign . signTypedData ( typedData , script , publicKey ) ; } }