@secux/app-eth
Version:
SecuX Hardware Wallet ETH API
18 lines (15 loc) • 11.2 kB
JavaScript
;
/*!
Copyright 2022 SecuX Technology Inc
Copyright Chen Wei-En
Copyright Wu Tsung-Yu
Licensed under the Apache License, Version 2.0 (the License);
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an AS IS BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/var __importDefault=this&&this.__importDefault||function(mod){return mod&&mod.__esModule?mod:{default:mod}};Object.defineProperty(exports,"__esModule",{value:!0}),exports.prepareSign=exports.ETHTransactionBuilder=exports.SecuxETH=void 0;const js_sha3_1=require("js-sha3"),secp256k1=require("secp256k1/elliptic"),ow_1=__importDefault(require("ow")),utility_1=require("@secux/utility"),protocol_transaction_1=require("@secux/protocol-transaction"),interface_1=require("@secux/protocol-transaction/lib/interface"),interface_2=require("./interface"),transaction_1=require("./transaction");Object.defineProperty(exports,"ETHTransactionBuilder",{enumerable:!0,get:function(){return transaction_1.ETHTransactionBuilder}});const eth_sig_util_1=require("eth-sig-util"),communication_1=require("@secux/utility/lib/communication"),erc20_1=require("./erc20"),erc721_1=require("./erc721"),erc1155_1=require("./erc1155"),transport_1=require("@secux/transport"),logger=null===utility_1.Logger||void 0===utility_1.Logger?void 0:utility_1.Logger.child({id:"ethereum"}),ow_path=(0,utility_1.ow_strictPath)(60,44),mcu={crypto:"2.12",nifty:"0.02.1"};class SecuxETH{static get ERC20(){return erc20_1.ERC20}static get ERC721(){return erc721_1.ERC721}static get ERC1155(){return erc1155_1.ERC1155}static addressConvert(publickey){const pk=function(data){(0,ow_1.default)(data,ow_1.default.any(utility_1.owTool.hexString,ow_1.default.buffer));const pk="string"==typeof data?Buffer.from(data,"hex"):data;if((0,ow_1.default)(pk,ow_1.default.buffer.is((x=>33===x.length||65===x.length))),!secp256k1.publicKeyVerify(pk))throw Error(`ArgumentError: invalid secp256k1 publickey, got "${pk.toString("hex")}"`);return pk}(publickey),uncompressed=secp256k1.publicKeyConvert(pk,!1),encodedAddr=function(address){address=address.toLowerCase().replace(/^0x/,"");const hash=(0,js_sha3_1.keccak256)(address);let ret="0x";for(let i=0;i<address.length;i++)parseInt(hash[i],16)>=8?ret+=address[i].toUpperCase():ret+=address[i];return ret}((0,js_sha3_1.keccak256)(uncompressed.slice(1)).slice(-40));return encodedAddr}static prepareAddress(path){return this.preparePublickey(path)}static resolveAddress(response){(0,ow_1.default)(response,communication_1.ow_communicationData);const pk=SecuxETH.resolvePublickey(response);return SecuxETH.addressConvert(pk)}static preparePublickey(path){return(0,ow_1.default)(path,ow_path),protocol_transaction_1.SecuxTransactionTool.getPublickey(path,interface_1.EllipticCurve.SECP256K1)}static resolvePublickey(response){const pk=protocol_transaction_1.SecuxTransactionTool.resolvePublickey(response,interface_1.EllipticCurve.SECP256K1);return Buffer.from(pk,"base64").toString("hex")}static prepareXPublickey(path){return(0,ow_1.default)(path,ow_path),protocol_transaction_1.SecuxTransactionTool.getXPublickey(path)}static resolveXPublickey(response,path){return(0,ow_1.default)(path,ow_path),protocol_transaction_1.SecuxTransactionTool.resolveXPublickey(response,path)}static prepareSignSerialized(path,serialized,txType){(0,ow_1.default)(serialized,communication_1.ow_communicationData);const buf=(0,communication_1.getBuffer)(serialized);null==logger||logger.debug(`- prepareSignSerialized\ninput serialized tx: ${buf.toString("hex")}`);return prepareSign(path,transaction_1.ETHTransactionBuilder.deserialize(buf),txType)}static resolveSignature(response){return Buffer.from(protocol_transaction_1.SecuxTransactionTool.resolveSignature(response),"base64").toString("hex")}static resolveTransaction(response,serialized){(0,ow_1.default)(response,communication_1.ow_communicationData),(0,ow_1.default)(serialized,communication_1.ow_communicationData);const buf=(0,communication_1.getBuffer)(serialized),builder=transaction_1.ETHTransactionBuilder.deserialize(buf),signature=Buffer.from(SecuxETH.resolveSignature(response),"hex");return null==logger||logger.debug(`- resolveTransaction\ninput serialized tx: ${buf.toString("hex")}`),`0x${builder.withSignature(signature).toString("hex")}`}static prepareSignEIP155(path,content,txType){(0,ow_1.default)(content,interface_2.ow_tx155);return prepareSign(path,(0,transaction_1.getBuilder)(content),txType)}static resolveSignatureEIP155(response,chainId){(0,ow_1.default)(response,communication_1.ow_communicationData),(0,ow_1.default)(chainId,ow_1.default.optional.number.positive);const signature=Buffer.from(SecuxETH.resolveSignature(response),"hex"),v=signature[64];return void 0===chainId?signature.writeUInt8(27+v,64):signature.writeUInt8(35+2*chainId+v,64),signature.toString("hex")}static prepareSignEIP1559(path,content,txType){(0,ow_1.default)(content,interface_2.ow_tx1559);return prepareSign(path,(0,transaction_1.getBuilder)(content),txType)}static prepareSignMessage(path,message){let buffer;return(0,utility_1.checkFWVersion)("mcu",mcu[transport_1.ITransport.deviceType],transport_1.ITransport.mcuVersion),(0,ow_1.default)(path,ow_path),(0,ow_1.default)(message,ow_1.default.any(ow_1.default.string.nonEmpty,ow_1.default.buffer)),"string"==typeof message&&(buffer=message.startsWith("0x")?Buffer.from(message.slice(2),"hex"):Buffer.from(message)),protocol_transaction_1.SecuxTransactionTool.signMessage(path,null!=buffer?buffer:message)}static prepareSignTypedData(path,typedData){(0,utility_1.checkFWVersion)("mcu",mcu[transport_1.ITransport.deviceType],transport_1.ITransport.mcuVersion),(0,ow_1.default)(path,ow_path),(0,ow_1.default)(typedData,ow_1.default.string);const data=JSON.parse(typedData),sanitizedData=eth_sig_util_1.TypedDataUtils.sanitizeData(data);if(0===Object.keys(sanitizedData).length){(0,ow_1.default)(data,ow_1.default.array.ofType(interface_2.ow_TypedDataV1).nonEmpty);const hash=(0,eth_sig_util_1.typedSignatureHash)(data),buf=Buffer.from(hash.slice(2),"hex");return protocol_transaction_1.SecuxTransactionTool.signTransaction(path,buf)}const parts=[];parts.push(eth_sig_util_1.TypedDataUtils.hashStruct("EIP712Domain",sanitizedData.domain,sanitizedData.types,!0)),"EIP712Domain"!==sanitizedData.primaryType&&parts.push(eth_sig_util_1.TypedDataUtils.hashStruct(sanitizedData.primaryType.toString(),sanitizedData.message,sanitizedData.types,!0));const buf=Buffer.concat(parts);return protocol_transaction_1.SecuxTransactionTool.signTypedMessage(path,buf)}static prepareSignWalletConnectTransaction(path,content){(0,ow_1.default)(path,ow_path),(0,ow_1.default)(content,ow_1.default.any(interface_2.ow_tx155,interface_2.ow_tx1559));const builder=(0,transaction_1.getBuilder)(content),chainId=builder.chainId||1,data=protocol_transaction_1.SecuxTransactionTool.signTransaction(path,builder.serialize(!0),{tp:interface_1.TransactionType.NORMAL,curve:interface_1.EllipticCurve.SECP256K1,chainId:chainId>65535?65535:chainId});return(0,communication_1.wrapResult)({commandData:data,rawTx:(0,communication_1.toCommunicationData)(builder.serialize())})}static async getAddress(path){const buffer=SecuxETH.prepareAddress(path),response=await this.Exchange((0,communication_1.getBuffer)(buffer));return SecuxETH.resolveAddress(response)}static async getPublickey(path){const buffer=SecuxETH.preparePublickey(path),response=await this.Exchange((0,communication_1.getBuffer)(buffer));return SecuxETH.resolvePublickey(response)}static async getXPublickey(path){const buffer=SecuxETH.prepareXPublickey(path),response=await this.Exchange((0,communication_1.getBuffer)(buffer));return SecuxETH.resolveXPublickey(response,path)}static async sign(path,args,option){const signSerialized=async()=>{const{commandData}=SecuxETH.prepareSignSerialized(path,args,option),rsp=await this.Exchange((0,communication_1.getBuffer)(commandData));let signature=Buffer.from(SecuxETH.resolveSignature(rsp),"hex");return signature=transaction_1.ETHTransactionBuilder.deserialize((0,communication_1.getBuffer)(args)).getSignature(signature),{raw_tx:SecuxETH.resolveTransaction(rsp,args),signature:`0x${signature.toString("hex")}`}};if("string"==typeof args){if(args.match(communication_1.base64_regexp))return signSerialized();const data=((0,interface_2.isJsonString)(args)?SecuxETH.prepareSignTypedData:SecuxETH.prepareSignMessage)(path,args),rsp=await this.Exchange((0,communication_1.getBuffer)(data));return{raw_tx:void 0,signature:`0x${SecuxETH.resolveSignatureEIP155(rsp,option)}`}}if(Buffer.isBuffer(args))return signSerialized();let func=SecuxETH.prepareSignEIP155;(args.accessList||args.maxPriorityFeePerGas||args.maxFeePerGas)&&(func=SecuxETH.prepareSignEIP1559),"boolean"==typeof option&&option&&(func=SecuxETH.prepareSignWalletConnectTransaction);const{commandData,rawTx}=func(path,args,option),rsp=await this.Exchange((0,communication_1.getBuffer)(commandData));let signature=Buffer.from(SecuxETH.resolveSignature(rsp),"hex");return signature=transaction_1.ETHTransactionBuilder.deserialize((0,communication_1.getBuffer)(rawTx)).getSignature(signature),{raw_tx:SecuxETH.resolveTransaction(rsp,rawTx),signature:`0x${signature.toString("hex")}`}}}function prepareSign(path,builder,tp){(0,utility_1.checkFWVersion)("mcu",mcu[transport_1.ITransport.deviceType],transport_1.ITransport.mcuVersion),(0,ow_1.default)(path,ow_path),tp||(tp=builder.tx.value?interface_1.TransactionType.NORMAL:function(data){const abiData=Buffer.isBuffer(data)?data.toString("hex"):null==data?void 0:data.replace(/^0x/,"");if(!abiData)return!1;const abiNFT=["23b872dd","42842e0e","f242432a"];for(const abi of abiNFT)if(abiData.startsWith(abi))return!0;return!1}(builder.tx.data)?interface_1.TransactionType.NFT:interface_1.TransactionType.TOKEN);const isBlind=function(data){const abiSupported=[{identify:"a9059cbb",length:136},{identify:"23b872dd",length:200},{identify:"095ea7b3",length:136},{identify:"42842e0e",length:200},{identify:"f242432a",length:392}],abiData=Buffer.isBuffer(data)?data.toString("hex"):null==data?void 0:data.replace(/^0x/,"");if(!abiData)return!1;for(const abi of abiSupported)if(abiData.startsWith(abi.identify)&&abiData.length===abi.length)return!1;return!0}(builder.tx.data);isBlind&&(tp=interface_1.TransactionType.NORMAL);const option={tp,curve:interface_1.EllipticCurve.SECP256K1,chainId:builder.chainId||1};option.chainId>65535&&(option.chainId=65535);const buf=isBlind?protocol_transaction_1.SecuxTransactionTool.signTransaction(path,builder.serialize(!0),option):protocol_transaction_1.SecuxTransactionTool.signRawTransaction(path,builder.serialize(),option);return(0,communication_1.wrapResult)({commandData:buf,rawTx:(0,communication_1.toCommunicationData)(builder.serialize())})}exports.SecuxETH=SecuxETH,(0,utility_1.loadPlugin)(SecuxETH,"SecuxETH"),exports.prepareSign=prepareSign;