UNPKG

@secux/transport

Version:

SecuX Hardware Wallet transport API for communication layer

18 lines (15 loc) 13.8 kB
"use strict"; /*! 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 _ITransport_instances,_ITransport_lock,_ITransport_version,_ITransport_fillup,_ITransport_appendL0,_ITransport_resolver,_ITransport_isRunning,_ITransport_resovled,_ITransport_error,_ITransport_packetSize,_ITransport_timeout,_ITransport_sendImage,_ITransport_Read,_ITransport_ReceiveData,_ITransport_Exchange,_ITransport_Send,_ITransport_buildPacketBuffer,_ITransport_appendL0V2,_ITransport_disableTimeout,__classPrivateFieldSet=this&&this.__classPrivateFieldSet||function(receiver,state,value,kind,f){if("m"===kind)throw new TypeError("Private method is not writable");if("a"===kind&&!f)throw new TypeError("Private accessor was defined without a setter");if("function"==typeof state?receiver!==state||!f:!state.has(receiver))throw new TypeError("Cannot write private member to an object whose class did not declare it");return"a"===kind?f.call(receiver,value):f?f.value=value:state.set(receiver,value),value},__classPrivateFieldGet=this&&this.__classPrivateFieldGet||function(receiver,state,kind,f){if("a"===kind&&!f)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof state?receiver!==state||!f:!state.has(receiver))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===kind?f:"a"===kind?f.call(receiver):f?f.value:state.get(receiver)};Object.defineProperty(exports,"__esModule",{value:!0}),exports.loadPlugin=exports.staticImplements=exports.ITransport=void 0;const interface_1=require("./interface"),resolver_1=require("./resolver"),utility_1=require("@secux/utility"),communication_1=require("@secux/utility/lib/communication"),bs58_1=require("@secux/utility/lib/bs58"),AsyncLock=require("async-lock"),ow_1=require("ow"),NotImplemented=Error("abstract method need to be implemented.");class ITransport{constructor(config){var _a;_ITransport_instances.add(this),this.autoApplyL1=!0,_ITransport_lock.set(this,new AsyncLock),_ITransport_version.set(this,void 0),_ITransport_fillup.set(this,void 0),_ITransport_appendL0.set(this,void 0),_ITransport_resolver.set(this,void 0),_ITransport_isRunning.set(this,!1),_ITransport_resovled.set(this,null),_ITransport_error.set(this,null),_ITransport_packetSize.set(this,void 0),_ITransport_timeout.set(this,void 0),_ITransport_sendImage.set(this,!1),__classPrivateFieldSet(this,_ITransport_fillup,!0,"f"),__classPrivateFieldSet(this,_ITransport_timeout,null!==(_a=null==config?void 0:config.timeout)&&void 0!==_a?_a:2e4,"f"),__classPrivateFieldSet(this,_ITransport_resolver,new resolver_1.CommandResolver(new resolver_1.BaseResolver),"f"),__classPrivateFieldSet(this,_ITransport_appendL0,(data=>data),"f")}async Connect(){throw NotImplemented}async Disconnect(){throw NotImplemented}async Write(data){throw NotImplemented}get Read(){return __classPrivateFieldGet(this,_ITransport_instances,"m",_ITransport_Read)}get ReceiveData(){return __classPrivateFieldGet(this,_ITransport_instances,"m",_ITransport_ReceiveData)}get Exchange(){return __classPrivateFieldGet(this,_ITransport_instances,"m",_ITransport_Exchange)}get Send(){return __classPrivateFieldGet(this,_ITransport_instances,"m",_ITransport_Send)}async getAddress(path,...args){return getPlugin(path).getAddress.call(this,path,...args)}async getPublickey(path,...args){return getPlugin(path).getPublickey.call(this,path,...args)}async getXPublickey(path,...args){return getPlugin(path).getXPublickey.call(this,path,...args)}async sign(...args){if("object"==typeof args[0]){return getPlugin(Array.isArray(args[0])?args[0][0].path:args[0].path).sign.call(this,...args)}return args[0].length>=43&&args[0].length<=44&&bs58_1.Base58.decodeUnsafe(args[0])?getModule(utility_1.supported_coin.find((x=>"solana"===x.name))).sign.call(this,...args):getPlugin(args[0]).sign.call(this,...args)}async signWithImage(imageName,imageData,metadata,...args){var _a;let SecuxDeviceNifty;try{({SecuxDeviceNifty}=require("@secux/protocol-device"))}catch(error){}if(!SecuxDeviceNifty)throw Error('The package "@secux/protocol-device" of verison above 3.1.0 needed.');const{AttachmentType,FileDestination}=require("@secux/protocol-device/lib/interface"),_metadata=Object.assign({contractAddress:" ",tokenId:" ",type:null!==(_a=metadata.type)&&void 0!==_a?_a:AttachmentType.Ethereum,tokenStandard:" "},metadata),dataList=SecuxDeviceNifty.prepareSendImage(imageName,imageData,_metadata,FileDestination.CONFIRM);__classPrivateFieldSet(this,_ITransport_sendImage,!1,"f");const task=this.sign(...args);await new Promise((resolve=>{const timer=setInterval((()=>{__classPrivateFieldGet(this,_ITransport_sendImage,"f")&&(resolve(1),clearInterval(timer))}),100)}));for(const data of dataList)await this.Exchange((0,communication_1.getBuffer)(data));const{raw_tx,signature}=await task;return{raw_tx,signature}}get version(){var _a;return null!==(_a=__classPrivateFieldGet(this,_ITransport_version,"f"))&&void 0!==_a?_a:ITransport.PROTOCOLv1}set version(value){if(__classPrivateFieldGet(this,_ITransport_version,"f")&&__classPrivateFieldGet(this,_ITransport_version,"f")!==value)throw Error("Protocol cannot change after setup.");if(__classPrivateFieldSet(this,_ITransport_version,value,"f"),value===ITransport.PROTOCOLv2)__classPrivateFieldSet(this,_ITransport_resolver,new resolver_1.NotifyResolver(new resolver_1.APDUResolver(new resolver_1.BaseResolverV2)),"f"),__classPrivateFieldSet(this,_ITransport_appendL0,__classPrivateFieldGet(this,_ITransport_instances,"m",_ITransport_appendL0V2),"f"),__classPrivateFieldSet(this,_ITransport_fillup,!1,"f")}get packetSize(){var _a;return null!==(_a=__classPrivateFieldGet(this,_ITransport_packetSize,"f"))&&void 0!==_a?_a:64}set packetSize(value){if(__classPrivateFieldGet(this,_ITransport_packetSize,"f")&&__classPrivateFieldGet(this,_ITransport_packetSize,"f")!==value)throw Error("Packet size cannot change after setup.");__classPrivateFieldSet(this,_ITransport_packetSize,value,"f")}get CustomerId(){return""}get DeviceType(){return""}get DeviceId(){return""}get Model(){return""}get MCU(){return""}get SE(){return""}}function getPlugin(path){(0,ow_1.default)(path,utility_1.owTool.bip32String);const split=path.match(/\d+/g),cointype=parseInt(split[1],10),item=utility_1.supported_coin.find((x=>x.cointype===cointype));if(!item)throw Error(`ArgumentError: unsupport cointype of path, got "${path}"`);return getModule(item)}function getModule(info){const m=ITransport[info.module];if(!m)throw Error(`Cannot find plugin, please install npm package "${info.npm}" and import into your code.`);return m}exports.ITransport=ITransport,_ITransport_lock=new WeakMap,_ITransport_version=new WeakMap,_ITransport_fillup=new WeakMap,_ITransport_appendL0=new WeakMap,_ITransport_resolver=new WeakMap,_ITransport_isRunning=new WeakMap,_ITransport_resovled=new WeakMap,_ITransport_error=new WeakMap,_ITransport_packetSize=new WeakMap,_ITransport_timeout=new WeakMap,_ITransport_sendImage=new WeakMap,_ITransport_instances=new WeakSet,_ITransport_Read=async function(){return await __classPrivateFieldGet(this,_ITransport_lock,"f").acquire("read_lock",(async()=>{let isTerminated=!1;return setTimeout((()=>{var _a;isTerminated=!(null===(_a=__classPrivateFieldGet(this,_ITransport_resovled,"f"))||void 0===_a?void 0:_a.data)}),__classPrivateFieldGet(this,_ITransport_timeout,"f")),await new Promise(((resolve,reject)=>{const timer=setInterval((()=>{var _a;(null===(_a=__classPrivateFieldGet(this,_ITransport_resovled,"f"))||void 0===_a?void 0:_a.data)?(resolve(__classPrivateFieldGet(this,_ITransport_resovled,"f").data),__classPrivateFieldSet(this,_ITransport_resovled,null,"f"),clearInterval(timer)):isTerminated&&(reject(`TransferError: timeout (${__classPrivateFieldGet(this,_ITransport_timeout,"f")} ms)`),clearInterval(timer))}),1)}))}))},_ITransport_ReceiveData=function(data){var _a;if(0!==data.length)if(resolver_1.IResolver.isRunning.call(__classPrivateFieldGet(this,_ITransport_resolver,"f"))){try{if(__classPrivateFieldSet(this,_ITransport_resovled,resolver_1.IResolver.handleData.call(__classPrivateFieldGet(this,_ITransport_resolver,"f"),data),"f"),__classPrivateFieldGet(this,_ITransport_resovled,"f").type===resolver_1.ResponseType.NOTIFY)return __classPrivateFieldSet(this,_ITransport_sendImage,!0,"f"),void(null===(_a=this.OnNotification)||void 0===_a||_a.call(void 0,__classPrivateFieldGet(this,_ITransport_resovled,"f").data));if(0===__classPrivateFieldGet(this,_ITransport_resovled,"f").data.length)return;__classPrivateFieldSet(this,_ITransport_error,null,"f")}catch(error){resolver_1.IResolver.resetAll.call(__classPrivateFieldGet(this,_ITransport_resolver,"f")),__classPrivateFieldSet(this,_ITransport_resovled,null,"f"),__classPrivateFieldSet(this,_ITransport_error,error,"f")}__classPrivateFieldSet(this,_ITransport_isRunning,!1,"f")}else __classPrivateFieldSet(this,_ITransport_resovled,{data,type:resolver_1.ResponseType.UNKNOWN},"f")},_ITransport_Exchange=async function(data){__classPrivateFieldSet(this,_ITransport_isRunning,!0,"f");let L1=data,isAPDU=!1;__classPrivateFieldGet(this,_ITransport_version,"f")===ITransport.PROTOCOLv2&&this.autoApplyL1&&248!==data[0]&&(L1=(0,communication_1.getBuffer)((0,communication_1.to_L1_APDU)(data)),isAPDU=!0),__classPrivateFieldGet(this,_ITransport_resolver,"f").Sent=L1;const L0=__classPrivateFieldGet(this,_ITransport_appendL0,"f").call(this,L1),packetBufferArray=__classPrivateFieldGet(this,_ITransport_instances,"m",_ITransport_buildPacketBuffer).call(this,L0);for(const packetBuffer of packetBufferArray)await this.Write(packetBuffer);let isTerminated=!1;if(__classPrivateFieldGet(this,_ITransport_instances,"m",_ITransport_disableTimeout).call(this)||setTimeout((()=>{isTerminated=!0}),__classPrivateFieldGet(this,_ITransport_timeout,"f")),await new Promise(((resolve,reject)=>{const timer=setInterval((()=>{__classPrivateFieldGet(this,_ITransport_isRunning,"f")?isTerminated&&(reject(`TransferError: timeout (${__classPrivateFieldGet(this,_ITransport_timeout,"f")} ms)`),clearInterval(timer)):(resolve(1),clearInterval(timer))}),1)})),__classPrivateFieldGet(this,_ITransport_version,"f")===ITransport.PROTOCOLv2&&isAPDU&&await new Promise(((resolve,reject)=>{const timer=setInterval((()=>{var _a;(null===(_a=__classPrivateFieldGet(this,_ITransport_resovled,"f"))||void 0===_a?void 0:_a.type)===resolver_1.ResponseType.APDU||__classPrivateFieldGet(this,_ITransport_error,"f")?(resolve(1),clearInterval(timer)):isTerminated&&(reject(`TransferError: timeout (${__classPrivateFieldGet(this,_ITransport_timeout,"f")} ms)`),clearInterval(timer))}),1)})),__classPrivateFieldGet(this,_ITransport_error,"f"))throw __classPrivateFieldGet(this,_ITransport_error,"f");if(!__classPrivateFieldGet(this,_ITransport_resovled,"f"))throw Error("TransferError: empty response");return __classPrivateFieldGet(this,_ITransport_version,"f")===ITransport.PROTOCOLv2&&__classPrivateFieldGet(this,_ITransport_resovled,"f").type===resolver_1.ResponseType.APDU?__classPrivateFieldGet(this,_ITransport_resovled,"f").data.slice(4):__classPrivateFieldGet(this,_ITransport_resovled,"f").data},_ITransport_Send=async function(cla,ins,p1=0,p2=0,data=Buffer.alloc(0)){let buf=(0,communication_1.Send)(cla,ins,p1,p2,data);return __classPrivateFieldGet(this,_ITransport_version,"f")===ITransport.PROTOCOLv2&&(buf=(0,communication_1.to_L1_APDU)(buf)),await this.Exchange((0,communication_1.getBuffer)(buf)),__classPrivateFieldGet(this,_ITransport_resovled,"f").response},_ITransport_buildPacketBuffer=function(buffer){const packet=this.packetSize,nBlocks=Math.ceil(buffer.length/packet),blocks=[];let offset=0;for(let i=0;i<nBlocks-1;i++){const chunkData=buffer.slice(offset,offset+packet);blocks.push(chunkData),offset+=packet}const last=buffer.slice(offset);if(!__classPrivateFieldGet(this,_ITransport_fillup,"f"))return blocks.push(last),blocks;const remain=Buffer.alloc(packet);return last.copy(remain),blocks.push(remain),blocks},_ITransport_appendL0V2=function(data){const packet=this.packetSize-1,slices=Math.ceil(data.length/packet),L0=Buffer.allocUnsafe(data.length+slices);let offset=0,serial=interface_1.ProtocolV2.SERIAL_START;for(let i=0;i<slices-1;i++)L0[offset++]=serial,++serial>interface_1.ProtocolV2.SERIAL_END&&(serial=interface_1.ProtocolV2.SERIAL_START),offset+=data.copy(L0,offset,i*packet,(i+1)*packet);const remain=data.length%packet;return L0[offset++]=remain,data.slice(-remain).copy(L0,offset),L0[0]+=interface_1.ProtocolV2.HEAD_PREFIX,L0},_ITransport_disableTimeout=function(){if(112===__classPrivateFieldGet(this,_ITransport_resolver,"f").cla)switch(__classPrivateFieldGet(this,_ITransport_resolver,"f").ins){case 163:case 164:case 165:case 166:case 134:return!0}return this.version===ITransport.PROTOCOLv2&&248===__classPrivateFieldGet(this,_ITransport_resolver,"f").Sent[0]&&4===__classPrivateFieldGet(this,_ITransport_resolver,"f").Sent[1]&&1===__classPrivateFieldGet(this,_ITransport_resolver,"f").Sent[2]},ITransport.PROTOCOLv1=1,ITransport.PROTOCOLv2=2,exports.staticImplements=function(){return constructor=>{}},exports.loadPlugin=function(plugin,name){void 0===ITransport[name]&&Object.defineProperty(ITransport,name,{enumerable:!0,configurable:!1,writable:!1,value:plugin})};